]> git.saurik.com Git - apple/mdnsresponder.git/commitdiff
mDNSResponder-212.1.tar.gz mac-os-x-106 mac-os-x-1061 v212.1
authorApple <opensource@apple.com>
Thu, 23 Jul 2009 23:54:29 +0000 (23:54 +0000)
committerApple <opensource@apple.com>
Thu, 23 Jul 2009 23:54:29 +0000 (23:54 +0000)
215 files changed:
Clients/ClientCommon.c [new file with mode: 0644]
Clients/ClientCommon.h [new file with mode: 0644]
Clients/DNS-SD.VisualStudio/DNS-SD.manifest [new file with mode: 0644]
Clients/DNS-SD.VisualStudio/DNS-SD64.manifest [new file with mode: 0644]
Clients/DNS-SD.VisualStudio/dns-sd.vcproj
Clients/DNS-SD.xcodeproj/project.pbxproj
Clients/DNSServiceBrowser.NET/DNSServiceBrowser.NET.csproj
Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs
Clients/DNSServiceBrowser.VB/DNSServiceBrowser.Designer.vb [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/DNSServiceBrowser.VB.vbproj [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/DNSServiceBrowser.resx [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/DNSServiceBrowser.vb [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/My Project/Application.Designer.vb [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/My Project/Application.myapp [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/My Project/AssemblyInfo.vb [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/My Project/Resources.Designer.vb [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/My Project/Resources.resx [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/My Project/Settings.Designer.vb [new file with mode: 0644]
Clients/DNSServiceBrowser.VB/My Project/Settings.settings [new file with mode: 0644]
Clients/ExplorerPlugin/About.cpp
Clients/ExplorerPlugin/ExplorerBar.cpp
Clients/ExplorerPlugin/ExplorerBar.h
Clients/ExplorerPlugin/ExplorerBarWindow.cpp
Clients/ExplorerPlugin/ExplorerBarWindow.h
Clients/ExplorerPlugin/ExplorerPlugin.cpp
Clients/ExplorerPlugin/ExplorerPlugin.h
Clients/ExplorerPlugin/ExplorerPlugin.vcproj
Clients/ExplorerPlugin/ExplorerPluginLocRes.rc
Clients/ExplorerPlugin/ExplorerPluginLocRes.vcproj
Clients/ExplorerPlugin/ExplorerPluginRes.vcproj
Clients/ExplorerPlugin/res/ExplorerPlugin.manifest [new file with mode: 0644]
Clients/ExplorerPlugin/res/ExplorerPlugin64.manifest [new file with mode: 0644]
Clients/ExplorerPlugin/resource_dll.h
Clients/ExplorerPlugin/resource_loc_res.h
Clients/ExplorerPlugin/resource_res.h
Clients/Java/BrowserApp.java
Clients/Java/JavaSamples.vcproj
Clients/Java/SwingResolveListener.java [deleted file]
Clients/Java/nmakefile
Clients/Makefile
Clients/PrinterSetupWizard/Logger.cpp [new file with mode: 0644]
Clients/PrinterSetupWizard/Logger.h [new file with mode: 0644]
Clients/PrinterSetupWizard/PrinterSetupWizard.rc
Clients/PrinterSetupWizard/PrinterSetupWizard.vcproj
Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp
Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc
Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj
Clients/PrinterSetupWizard/PrinterSetupWizardRes.vcproj
Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp
Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h
Clients/PrinterSetupWizard/SecondPage.cpp
Clients/PrinterSetupWizard/ThirdPage.cpp
Clients/PrinterSetupWizard/ThirdPage.h
Clients/PrinterSetupWizard/UtilTypes.h
Clients/PrinterSetupWizard/res/PrinterSetupWizard.manifest
Clients/PrinterSetupWizard/res/PrinterSetupWizard64.manifest [new file with mode: 0644]
Clients/PrinterSetupWizard/resource_exe.h
Clients/PrinterSetupWizard/resource_loc_res.h
Clients/PrinterSetupWizard/resource_res.h
Clients/SimpleChat.NET/SimpleChat.NET.csproj
Clients/SimpleChat.NET/SimpleChat.cs
Clients/SimpleChat.NET/SimpleChat.resx
Clients/SimpleChat.VB/My Project/Application.Designer.vb [new file with mode: 0644]
Clients/SimpleChat.VB/My Project/Application.myapp [new file with mode: 0644]
Clients/SimpleChat.VB/My Project/AssemblyInfo.vb [new file with mode: 0644]
Clients/SimpleChat.VB/My Project/Resources.Designer.vb [new file with mode: 0644]
Clients/SimpleChat.VB/My Project/Resources.resx [new file with mode: 0644]
Clients/SimpleChat.VB/My Project/Settings.Designer.vb [new file with mode: 0644]
Clients/SimpleChat.VB/My Project/Settings.settings [new file with mode: 0644]
Clients/SimpleChat.VB/SimpleChat.Designer.vb [new file with mode: 0644]
Clients/SimpleChat.VB/SimpleChat.VB.vbproj [new file with mode: 0644]
Clients/SimpleChat.VB/SimpleChat.resx [new file with mode: 0644]
Clients/SimpleChat.VB/SimpleChat.vb [new file with mode: 0644]
Clients/dns-sd.c
Makefile
PrivateDNS.txt
buildResults.xml [deleted file]
mDNSCore/DNSCommon.c
mDNSCore/DNSCommon.h
mDNSCore/DNSDigest.c
mDNSCore/mDNS.c
mDNSCore/mDNSDebug.h
mDNSCore/mDNSEmbeddedAPI.h
mDNSCore/uDNS.c
mDNSCore/uDNS.h
mDNSMacOS9/Mac OS Test Responder.c
mDNSMacOS9/Mac OS Test Searcher.c
mDNSMacOSX/DNSServiceDiscovery.c
mDNSMacOSX/LaunchDaemonInfo.dnsextd.plist
mDNSMacOSX/LaunchDaemonInfo.helper.plist
mDNSMacOSX/LaunchDaemonInfo.plist
mDNSMacOSX/LegacyNATTraversal.c
mDNSMacOSX/PreferencePane/ConfigurationAuthority.c
mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m
mDNSMacOSX/PreferencePane/PrivilegedOperations.c
mDNSMacOSX/PreferencePane/ddnswriteconfig.m
mDNSMacOSX/SamplemDNSClient.c
mDNSMacOSX/daemon.c
mDNSMacOSX/helper-main.c
mDNSMacOSX/helper-server.h
mDNSMacOSX/helper-stubs.c
mDNSMacOSX/helper.c
mDNSMacOSX/helper.h
mDNSMacOSX/helpermsg-types.h
mDNSMacOSX/helpermsg.defs
mDNSMacOSX/mDNSMacOSX.c
mDNSMacOSX/mDNSMacOSX.h
mDNSMacOSX/mDNSResponder.order
mDNSMacOSX/mDNSResponder.sb
mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
mDNSMacOSX/safe_vproc.c [new file with mode: 0644]
mDNSMacOSX/safe_vproc.h [new file with mode: 0644]
mDNSPosix/Client.c
mDNSPosix/Identify.c
mDNSPosix/Makefile
mDNSPosix/NetMonitor.c
mDNSPosix/PosixDaemon.c
mDNSPosix/ProxyResponder.c
mDNSPosix/Responder.c
mDNSPosix/mDNSPosix.c
mDNSPosix/mDNSUNP.c
mDNSPosix/nss_mdns.c
mDNSResponder.sln
mDNSShared/CommonServices.h
mDNSShared/Java/DNSSD.java
mDNSShared/PlatformCommon.c
mDNSShared/dns_sd.h
mDNSShared/dnsextd.c
mDNSShared/dnsextd_lexer.l
mDNSShared/dnsextd_parser.y
mDNSShared/dnssd_clientlib.c
mDNSShared/dnssd_clientstub.c
mDNSShared/dnssd_ipc.c
mDNSShared/dnssd_ipc.h
mDNSShared/mDNSDebug.c
mDNSShared/mDNSResponder.8
mDNSShared/uds_daemon.c
mDNSShared/uds_daemon.h
mDNSVxWorks/mDNSVxWorks.c
mDNSVxWorks/mDNSVxWorksIPv4Only.c
mDNSWindows/ControlPanel/ConfigPropertySheet.cpp
mDNSWindows/ControlPanel/ConfigPropertySheet.h
mDNSWindows/ControlPanel/ControlPanel.cpp
mDNSWindows/ControlPanel/ControlPanel.rc
mDNSWindows/ControlPanel/ControlPanel.vcproj
mDNSWindows/ControlPanel/ControlPanelDll.rc
mDNSWindows/ControlPanel/ControlPanelExe.rc
mDNSWindows/ControlPanel/ControlPanelExe.vcproj
mDNSWindows/ControlPanel/FirstPage.cpp
mDNSWindows/ControlPanel/FourthPage.cpp [new file with mode: 0755]
mDNSWindows/ControlPanel/FourthPage.h [new file with mode: 0755]
mDNSWindows/ControlPanel/SharedSecret.cpp
mDNSWindows/ControlPanel/SharedSecret.h
mDNSWindows/ControlPanel/res/ControlPanel.manifest [new file with mode: 0644]
mDNSWindows/ControlPanel/res/ControlPanel64.manifest [new file with mode: 0644]
mDNSWindows/ControlPanel/resource.h
mDNSWindows/DLL.NET/AssemblyInfo.cpp
mDNSWindows/DLL.NET/Stdafx.h
mDNSWindows/DLL.NET/dnssd_NET.cpp
mDNSWindows/DLL.NET/dnssd_NET.vcproj
mDNSWindows/DLL/dnssd.def
mDNSWindows/DLL/dnssd.vcproj
mDNSWindows/DLLStub/DLLStub.cpp [new file with mode: 0755]
mDNSWindows/DLLStub/DLLStub.h [new file with mode: 0755]
mDNSWindows/DLLStub/DLLStub.vcproj [new file with mode: 0755]
mDNSWindows/DLLX/DLLX.cpp [new file with mode: 0755]
mDNSWindows/DLLX/DLLX.def [new file with mode: 0755]
mDNSWindows/DLLX/DLLX.idl [new file with mode: 0755]
mDNSWindows/DLLX/DLLX.rc [new file with mode: 0755]
mDNSWindows/DLLX/DLLX.rgs [new file with mode: 0755]
mDNSWindows/DLLX/DLLX.vcproj [new file with mode: 0755]
mDNSWindows/DLLX/DNSSD.cpp [new file with mode: 0755]
mDNSWindows/DLLX/DNSSDEventManager.cpp [new file with mode: 0755]
mDNSWindows/DLLX/DNSSDEventManager.h [new file with mode: 0755]
mDNSWindows/DLLX/DNSSDEventManager.rgs [new file with mode: 0755]
mDNSWindows/DLLX/DNSSDRecord.cpp [new file with mode: 0755]
mDNSWindows/DLLX/DNSSDRecord.h [new file with mode: 0755]
mDNSWindows/DLLX/DNSSDRecord.rgs [new file with mode: 0755]
mDNSWindows/DLLX/DNSSDService.cpp [new file with mode: 0755]
mDNSWindows/DLLX/DNSSDService.h [new file with mode: 0755]
mDNSWindows/DLLX/DNSSDService.rgs [new file with mode: 0755]
mDNSWindows/DLLX/StringServices.cpp [new file with mode: 0755]
mDNSWindows/DLLX/StringServices.h [new file with mode: 0755]
mDNSWindows/DLLX/TXTRecord.cpp [new file with mode: 0755]
mDNSWindows/DLLX/TXTRecord.h [new file with mode: 0755]
mDNSWindows/DLLX/TXTRecord.rgs [new file with mode: 0755]
mDNSWindows/DLLX/_IDNSSDEvents_CP.h [new file with mode: 0755]
mDNSWindows/DLLX/dlldatax.c [new file with mode: 0755]
mDNSWindows/DLLX/dlldatax.h [new file with mode: 0755]
mDNSWindows/DLLX/resource.h [new file with mode: 0755]
mDNSWindows/DLLX/stdafx.h [new file with mode: 0755]
mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.cpp
mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.h
mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp
mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp
mDNSWindows/Java/Java.vcproj
mDNSWindows/Java/makefile
mDNSWindows/NSPTool/NSPTool.vcproj
mDNSWindows/RegNames.h
mDNSWindows/Secret.c [new file with mode: 0644]
mDNSWindows/Secret.h [new file with mode: 0644]
mDNSWindows/SystemService/Firewall.cpp
mDNSWindows/SystemService/Firewall.h
mDNSWindows/SystemService/Service.c
mDNSWindows/SystemService/Service.vcproj
mDNSWindows/SystemService/res/mDNSResponder.manifest [new file with mode: 0644]
mDNSWindows/SystemService/res/mDNSResponder64.manifest [new file with mode: 0644]
mDNSWindows/WinServices.cpp
mDNSWindows/WinServices.h
mDNSWindows/WinVersRes.h
mDNSWindows/isocode.h
mDNSWindows/mDNSWin32.c
mDNSWindows/mDNSWin32.h
mDNSWindows/mdnsNSP/mdnsNSP.c
mDNSWindows/mdnsNSP/mdnsNSP.vcproj

diff --git a/Clients/ClientCommon.c b/Clients/ClientCommon.c
new file mode 100644 (file)
index 0000000..f25fbb6
--- /dev/null
@@ -0,0 +1,86 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2008 Apple Inc. All rights reserved.
+ *
+ * Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+ * ("Apple") in consideration of your agreement to the following terms, and your
+ * use, installation, modification or redistribution of this Apple software
+ * constitutes acceptance of these terms.  If you do not agree with these terms,
+ * please do not use, install, modify or redistribute this Apple software.
+ *
+ * In consideration of your agreement to abide by the following terms, and subject
+ * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ * copyrights in this original Apple software (the "Apple Software"), to use,
+ * reproduce, modify and redistribute the Apple Software, with or without
+ * modifications, in source and/or binary forms; provided that if you redistribute
+ * the Apple Software in its entirety and without modifications, you must retain
+ * this notice and the following text and disclaimers in all such redistributions of
+ * the Apple Software.  Neither the name, trademarks, service marks or logos of
+ * Apple Computer, Inc. may be used to endorse or promote products derived from the
+ * Apple Software without specific prior written permission from Apple.  Except as
+ * expressly stated in this notice, no other rights or licenses, express or implied,
+ * are granted by Apple herein, including but not limited to any patent rights that
+ * may be infringed by your derivative works or by other works in which the Apple
+ * Software may be incorporated.
+ *
+ * The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ * COMBINATION WITH YOUR PRODUCTS.
+ *
+ * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    Change History (most recent first):
+
+$Log: ClientCommon.c,v $
+Revision 1.2  2008/05/08 00:42:03  cheshire
+Removed some unnecessary header files
+
+Revision 1.1  2008/05/08 00:25:48  cheshire
+<rdar://problem/5919272> GetNextLabel insufficiently defensive
+
+
+*/
+
+#include <ctype.h>
+#include <stdio.h>                     // For stdout, stderr
+
+#include "ClientCommon.h"
+
+const char *GetNextLabel(const char *cstr, char label[64])
+       {
+       char *ptr = label;
+       while (*cstr && *cstr != '.')                           // While we have characters in the label...
+               {
+               char c = *cstr++;
+               if (c == '\\' && *cstr)                                 // If we have a backslash, and it's not the last character of the string
+                       {
+                       c = *cstr++;
+                       if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
+                               {
+                               int v0 = cstr[-1] - '0';                                                // then interpret as three-digit decimal
+                               int v1 = cstr[ 0] - '0';
+                               int v2 = cstr[ 1] - '0';
+                               int val = v0 * 100 + v1 * 10 + v2;
+                               // If valid three-digit decimal value, use it
+                               // Note that although ascii nuls are possible in DNS labels
+                               // we're building a C string here so we have no way to represent that
+                               if (val == 0) val = '-';
+                               if (val <= 255) { c = (char)val; cstr += 2; }
+                               }
+                       }
+               *ptr++ = c;
+               if (ptr >= label+64) { label[63] = 0; return(NULL); }   // Illegal label more than 63 bytes
+               }
+       *ptr = 0;                                                                                                       // Null-terminate label text
+       if (ptr == label) return(NULL);                                                         // Illegal empty label
+       if (*cstr) cstr++;                                                                                      // Skip over the trailing dot (if present)
+       return(cstr);
+       }
diff --git a/Clients/ClientCommon.h b/Clients/ClientCommon.h
new file mode 100644 (file)
index 0000000..5c28307
--- /dev/null
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2008 Apple Inc. All rights reserved.
+ *
+ * Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+ * ("Apple") in consideration of your agreement to the following terms, and your
+ * use, installation, modification or redistribution of this Apple software
+ * constitutes acceptance of these terms.  If you do not agree with these terms,
+ * please do not use, install, modify or redistribute this Apple software.
+ *
+ * In consideration of your agreement to abide by the following terms, and subject
+ * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ * copyrights in this original Apple software (the "Apple Software"), to use,
+ * reproduce, modify and redistribute the Apple Software, with or without
+ * modifications, in source and/or binary forms; provided that if you redistribute
+ * the Apple Software in its entirety and without modifications, you must retain
+ * this notice and the following text and disclaimers in all such redistributions of
+ * the Apple Software.  Neither the name, trademarks, service marks or logos of
+ * Apple Computer, Inc. may be used to endorse or promote products derived from the
+ * Apple Software without specific prior written permission from Apple.  Except as
+ * expressly stated in this notice, no other rights or licenses, express or implied,
+ * are granted by Apple herein, including but not limited to any patent rights that
+ * may be infringed by your derivative works or by other works in which the Apple
+ * Software may be incorporated.
+ *
+ * The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ * COMBINATION WITH YOUR PRODUCTS.
+ *
+ * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    Change History (most recent first):
+
+$Log: ClientCommon.h,v $
+Revision 1.1  2008/05/08 00:25:48  cheshire
+<rdar://problem/5919272> GetNextLabel insufficiently defensive
+
+
+*/
+
+extern const char *GetNextLabel(const char *cstr, char label[64]);
diff --git a/Clients/DNS-SD.VisualStudio/DNS-SD.manifest b/Clients/DNS-SD.VisualStudio/DNS-SD.manifest
new file mode 100644 (file)
index 0000000..9e0b08a
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+       <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Apple.Bonjour.DNS-SD" type="win32"/>
+       <description>Command line utility.</description>
+       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+               <security>
+                               <requestedPrivileges>
+                               <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
+                               </requestedPrivileges>
+               </security>
+       </trustInfo>
+</assembly>
diff --git a/Clients/DNS-SD.VisualStudio/DNS-SD64.manifest b/Clients/DNS-SD.VisualStudio/DNS-SD64.manifest
new file mode 100644 (file)
index 0000000..caa49df
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
+       <assemblyIdentity version="1.0.0.0" processorArchitecture="amd64" name="Apple.Bonjour.DNS-SD" type="win32"/> 
+       <description>Command Line Utility</description> 
+       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+               <security>
+                               <requestedPrivileges>
+                               <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
+                               </requestedPrivileges>
+               </security>
+       </trustInfo>
+</assembly>
index 4c3a515f6791447125a8c3630716fe2c79fa16f8..db1a499b53fb91dd77fb0ba5bb82e37f892ba167 100755 (executable)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="dns-sd"\r
        ProjectGUID="{AA230639-E115-4A44-AA5A-44A61235BA50}"\r
-       Keyword="Win32Proj">\r
+       Keyword="Win32Proj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory="Debug"\r
-                       IntermediateDirectory="Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN"\r
-                               MinimalRebuild="TRUE"\r
+                               PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="5"\r
+                               RuntimeLibrary="1"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="3"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="4"/>\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../../mDNSWindows/DLL/Debug/dnssd.lib ws2_32.lib"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../../mDNSWindows/DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
                                OutputFile="$(OutDir)/dns-sd.exe"\r
                                LinkIncremental="2"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/dns-sd.pdb"\r
                                SubSystem="1"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="DNS-SD.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../../mDNSWindows/DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/dns-sd.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/dns-sd.pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="17"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCALinkTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="DNS-SD64.manifest"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
                                InlineFunctionExpansion="1"\r
-                               OmitFramePointers="TRUE"\r
+                               OmitFramePointers="true"\r
                                AdditionalIncludeDirectories="../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN"\r
-                               StringPooling="TRUE"\r
-                               RuntimeLibrary="4"\r
-                               EnableFunctionLevelLinking="TRUE"\r
+                               PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="true"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="3"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="3"/>\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../../mDNSWindows/DLL/Release/dnssd.lib ws2_32.lib "\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../../mDNSWindows/DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
                                OutputFile="$(OutDir)/dns-sd.exe"\r
                                LinkIncremental="1"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="1"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCALinkTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="DNS-SD.manifest"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;            mkdir &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour SDK\Samples\C&quot;               mkdir &quot;$(DSTROOT)\Program Files\Bonjour SDK\Samples\C&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                           &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(ProjectDir)..\dns-sd.c&quot;                                                            &quot;$(DSTROOT)\Program Files\Bonjour SDK\Samples\C&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               OmitFramePointers="true"\r
+                               AdditionalIncludeDirectories="../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="true"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../../mDNSWindows/DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/dns-sd.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="DNS-SD64.manifest"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;            mkdir &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour SDK\Samples\C&quot;               mkdir &quot;$(DSTROOT)\Program Files\Bonjour SDK\Samples\C&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                           &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
-                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\ClientCommon.c"\r
+                               >\r
+                       </File>\r
                        <File\r
-                               RelativePath="..\dns-sd.c">\r
+                               RelativePath="..\dns-sd.c"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
-                       Filter="h;hpp;hxx;hm;inl;inc">\r
+                       Filter="h;hpp;hxx;hm;inl;inc"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\ClientCommon.h"\r
+                               >\r
+                       </File>\r
                        <File\r
-                               RelativePath="resource.h">\r
+                               RelativePath="resource.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+                       >\r
                        <File\r
-                               RelativePath="dns-sd.rc">\r
+                               RelativePath="dns-sd.rc"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r
index 6ed5d53d285b4bcaa7b151888706db24baa3adee..f2d54f04728cff4959169da0960af590b7b8dff8 100644 (file)
@@ -27,6 +27,7 @@
                FF1B6915067114AF002304DD /* DNSServiceBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = FF1B6914067114AF002304DD /* DNSServiceBrowser.m */; };
                FF1E351C06711BCF003DD5BC /* DNSServiceReg.m in Sources */ = {isa = PBXBuildFile; fileRef = FF1E351B06711BCF003DD5BC /* DNSServiceReg.m */; };
                FF1E352606711BD6003DD5BC /* DNSServiceReg.nib in Resources */ = {isa = PBXBuildFile; fileRef = FF1E352506711BD6003DD5BC /* DNSServiceReg.nib */; };
+               FF2704F90F12A60900299571 /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF2704F80F12A60900299571 /* ClientCommon.c */; };
                FF964AA10671153B0099215A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF964AA00671153B0099215A /* Foundation.framework */; };
                FF964CAA0671155C0099215A /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF964CA90671155C0099215A /* AppKit.framework */; };
                FF964DAC067115710099215A /* DNSServiceBrowser.nib in Resources */ = {isa = PBXBuildFile; fileRef = FF964DAB067115710099215A /* DNSServiceBrowser.nib */; };
 
 /* Begin PBXFileReference section */
                08FB7796FE84155DC02AAC07 /* dns-sd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "dns-sd.c"; sourceTree = "<group>"; };
-               8DD76F7E0486A8DE00D96B5E /* dns-sd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "dns-sd"; sourceTree = BUILT_PRODUCTS_DIR; };
+               8DD76F7E0486A8DE00D96B5E /* dns-sd */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = "dns-sd"; sourceTree = BUILT_PRODUCTS_DIR; };
                FF1B691106711383002304DD /* DNS Service Browser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DNS Service Browser.app"; sourceTree = BUILT_PRODUCTS_DIR; };
                FF1B6914067114AF002304DD /* DNSServiceBrowser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNSServiceBrowser.m; sourceTree = "<group>"; };
                FF1E351306711B5C003DD5BC /* DNS Service Registration.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DNS Service Registration.app"; sourceTree = BUILT_PRODUCTS_DIR; };
                FF1E351B06711BCF003DD5BC /* DNSServiceReg.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNSServiceReg.m; sourceTree = "<group>"; };
                FF1E352506711BD6003DD5BC /* DNSServiceReg.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = DNSServiceReg.nib; sourceTree = "<group>"; };
+               FF2704F80F12A60900299571 /* ClientCommon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ClientCommon.c; sourceTree = "<group>"; };
                FF964AA00671153B0099215A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
                FF964CA90671155C0099215A /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
                FF964DAB067115710099215A /* DNSServiceBrowser.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = DNSServiceBrowser.nib; sourceTree = "<group>"; };
                        isa = PBXGroup;
                        children = (
                                08FB7796FE84155DC02AAC07 /* dns-sd.c */,
+                               FF2704F80F12A60900299571 /* ClientCommon.c */,
                                FF1B6914067114AF002304DD /* DNSServiceBrowser.m */,
                                FF1E351B06711BCF003DD5BC /* DNSServiceReg.m */,
                        );
                        buildActionMask = 2147483647;
                        files = (
                                8DD76F770486A8DE00D96B5E /* dns-sd.c in Sources */,
+                               FF2704F90F12A60900299571 /* ClientCommon.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index d43cf10661a4d0d36bf0a2f63698a5aa81d0b230..cbb7c30bddb091a325831768759887a1bb692ac2 100755 (executable)
-<VisualStudioProject>\r
-    <CSHARP\r
-        ProjectType = "Local"\r
-        ProductVersion = "7.0.9466"\r
-        SchemaVersion = "1.0"\r
-        ProjectGuid = "{DE8DB97E-37A3-43ED-9A5E-CCC5F6DE9CB4}"\r
-    >\r
-        <Build>\r
-            <Settings\r
-                ApplicationIcon = ""\r
-                AssemblyKeyContainerName = ""\r
-                AssemblyName = "DNSServiceBrowser_NET"\r
-                AssemblyOriginatorKeyFile = ""\r
-                DefaultClientScript = "JScript"\r
-                DefaultHTMLPageLayout = "Grid"\r
-                DefaultTargetSchema = "IE50"\r
-                DelaySign = "false"\r
-                OutputType = "WinExe"\r
-                RootNamespace = "DNSServiceBrowser_NET"\r
-                StartupObject = ""\r
-            >\r
-                <Config\r
-                    Name = "Debug"\r
-                    AllowUnsafeBlocks = "false"\r
-                    BaseAddress = "285212672"\r
-                    CheckForOverflowUnderflow = "false"\r
-                    ConfigurationOverrideFile = ""\r
-                    DefineConstants = "DEBUG;TRACE"\r
-                    DocumentationFile = ""\r
-                    DebugSymbols = "true"\r
-                    FileAlignment = "4096"\r
-                    IncrementalBuild = "true"\r
-                    Optimize = "false"\r
-                    OutputPath = "bin\Debug\"\r
-                    RegisterForComInterop = "false"\r
-                    RemoveIntegerChecks = "false"\r
-                    TreatWarningsAsErrors = "false"\r
-                    WarningLevel = "4"\r
-                />\r
-                <Config\r
-                    Name = "Release"\r
-                    AllowUnsafeBlocks = "false"\r
-                    BaseAddress = "285212672"\r
-                    CheckForOverflowUnderflow = "false"\r
-                    ConfigurationOverrideFile = ""\r
-                    DefineConstants = "TRACE"\r
-                    DocumentationFile = ""\r
-                    DebugSymbols = "false"\r
-                    FileAlignment = "4096"\r
-                    IncrementalBuild = "false"\r
-                    Optimize = "true"\r
-                    OutputPath = "bin\Release\"\r
-                    RegisterForComInterop = "false"\r
-                    RemoveIntegerChecks = "false"\r
-                    TreatWarningsAsErrors = "false"\r
-                    WarningLevel = "4"\r
-                />\r
-            </Settings>\r
-            <References>\r
-                <Reference\r
-                    Name = "System"\r
-                    AssemblyName = "System"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"\r
-                />\r
-                <Reference\r
-                    Name = "System.Data"\r
-                    AssemblyName = "System.Data"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"\r
-                />\r
-                <Reference\r
-                    Name = "System.Drawing"\r
-                    AssemblyName = "System.Drawing"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"\r
-                />\r
-                <Reference\r
-                    Name = "System.Windows.Forms"\r
-                    AssemblyName = "System.Windows.Forms"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"\r
-                />\r
-                <Reference\r
-                    Name = "System.XML"\r
-                    AssemblyName = "System.Xml"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"\r
-                />\r
-                <Reference\r
-                    Name = "dnssd.NET"\r
-                    AssemblyName = "dnssd.NET"\r
-                    HintPath = "..\..\mDNSWindows\DLL.NET\Release\dnssd.NET.dll"\r
-                />\r
-            </References>\r
-        </Build>\r
-        <Files>\r
-            <Include>\r
-                <File\r
-                    RelPath = "App.ico"\r
-                    BuildAction = "Content"\r
-                />\r
-                <File\r
-                    RelPath = "AssemblyInfo.cs"\r
-                    SubType = "Code"\r
-                    BuildAction = "Compile"\r
-                />\r
-                <File\r
-                    RelPath = "DNSServiceBrowser.cs"\r
-                    SubType = "Form"\r
-                    BuildAction = "Compile"\r
-                />\r
-                <File\r
-                    RelPath = "DNSServiceBrowser.resx"\r
-                    DependentUpon = "DNSServiceBrowser.cs"\r
-                    BuildAction = "EmbeddedResource"\r
-                />\r
-            </Include>\r
-        </Files>\r
-    </CSHARP>\r
-</VisualStudioProject>\r
-\r
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <ProjectType>Local</ProjectType>\r
+    <ProductVersion>8.0.50727</ProductVersion>\r
+    <SchemaVersion>2.0</SchemaVersion>\r
+    <ProjectGuid>{DE8DB97E-37A3-43ED-9A5E-CCC5F6DE9CB4}</ProjectGuid>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+    <ApplicationIcon>\r
+    </ApplicationIcon>\r
+    <AssemblyKeyContainerName>\r
+    </AssemblyKeyContainerName>\r
+    <AssemblyName>DNSServiceBrowser_NET</AssemblyName>\r
+    <AssemblyOriginatorKeyFile>\r
+    </AssemblyOriginatorKeyFile>\r
+    <DefaultClientScript>JScript</DefaultClientScript>\r
+    <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>\r
+    <DefaultTargetSchema>IE50</DefaultTargetSchema>\r
+    <DelaySign>false</DelaySign>\r
+    <OutputType>WinExe</OutputType>\r
+    <RootNamespace>DNSServiceBrowser_NET</RootNamespace>\r
+    <StartupObject>\r
+    </StartupObject>\r
+    <FileUpgradeFlags>\r
+    </FileUpgradeFlags>\r
+    <UpgradeBackupLocation>\r
+    </UpgradeBackupLocation>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>\r
+    <BaseAddress>285212672</BaseAddress>\r
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>\r
+    <ConfigurationOverrideFile>\r
+    </ConfigurationOverrideFile>\r
+    <DefineConstants>DEBUG;TRACE</DefineConstants>\r
+    <DocumentationFile>\r
+    </DocumentationFile>\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <FileAlignment>4096</FileAlignment>\r
+    <Optimize>false</Optimize>\r
+    <RegisterForComInterop>false</RegisterForComInterop>\r
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>\r
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>\r
+    <WarningLevel>4</WarningLevel>\r
+    <DebugType>full</DebugType>\r
+    <ErrorReport>prompt</ErrorReport>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>\r
+    <BaseAddress>285212672</BaseAddress>\r
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>\r
+    <ConfigurationOverrideFile>\r
+    </ConfigurationOverrideFile>\r
+    <DefineConstants>TRACE</DefineConstants>\r
+    <DocumentationFile>\r
+    </DocumentationFile>\r
+    <DebugSymbols>false</DebugSymbols>\r
+    <FileAlignment>4096</FileAlignment>\r
+    <Optimize>true</Optimize>\r
+    <RegisterForComInterop>false</RegisterForComInterop>\r
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>\r
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>\r
+    <WarningLevel>4</WarningLevel>\r
+    <DebugType>none</DebugType>\r
+    <ErrorReport>prompt</ErrorReport>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System">\r
+      <Name>System</Name>\r
+    </Reference>\r
+    <Reference Include="System.Data">\r
+      <Name>System.Data</Name>\r
+    </Reference>\r
+    <Reference Include="System.Drawing">\r
+      <Name>System.Drawing</Name>\r
+    </Reference>\r
+    <Reference Include="System.Windows.Forms">\r
+      <Name>System.Windows.Forms</Name>\r
+    </Reference>\r
+    <Reference Include="System.Xml">\r
+      <Name>System.XML</Name>\r
+    </Reference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Content Include="App.ico" />\r
+    <Compile Include="AssemblyInfo.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="DNSServiceBrowser.cs">\r
+      <SubType>Form</SubType>\r
+    </Compile>\r
+    <EmbeddedResource Include="DNSServiceBrowser.resx">\r
+      <DependentUpon>DNSServiceBrowser.cs</DependentUpon>\r
+      <SubType>Designer</SubType>\r
+    </EmbeddedResource>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <COMReference Include="Bonjour">\r
+      <Guid>{18FBED6D-F2B7-4EC8-A4A4-46282E635308}</Guid>\r
+      <VersionMajor>1</VersionMajor>\r
+      <VersionMinor>0</VersionMinor>\r
+      <Lcid>0</Lcid>\r
+      <WrapperTool>tlbimp</WrapperTool>\r
+      <Isolated>False</Isolated>\r
+    </COMReference>\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />\r
+  <PropertyGroup>\r
+    <PreBuildEvent>\r
+    </PreBuildEvent>\r
+    <PostBuildEvent>\r
+    </PostBuildEvent>\r
+  </PropertyGroup>\r
+</Project>
\ No newline at end of file
index e279d184b21131d4afd52a9454f2e1ad40bb9309..c86b45e356d335e64f46007fee3423674bc398d2 100755 (executable)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: DNSServiceBrowser.cs,v $
+Revision 1.8  2009/06/02 18:49:23  herscher
+<rdar://problem/3948252> Update the .NET code to use the new Bonjour COM component
+
 Revision 1.7  2006/08/14 23:23:58  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -50,7 +53,7 @@ using System.ComponentModel;
 using System.Windows.Forms;
 using System.Data;
 using System.Text;
-using Apple.DNSSD;
+using Bonjour;
 
 namespace DNSServiceBrowser_NET
 {
@@ -61,24 +64,15 @@ namespace DNSServiceBrowser_NET
        {
                private System.Windows.Forms.ComboBox typeBox;
                private System.Windows.Forms.ListBox browseList;
-               private ServiceRef browser = null;
-               private ServiceRef resolver = null;
+        private Bonjour.DNSSDEventManager   eventManager = null;
+        private Bonjour.DNSSDService        service = null;
+               private Bonjour.DNSSDService        browser = null;
+               private Bonjour.DNSSDService        resolver = null;
                /// <summary>
                /// Required designer variable.
                /// </summary>
                private System.ComponentModel.Container components = null;
 
-
-               //
-               // These delegates are invoked as a result of DNSService
-               // operation.
-               //
-               delegate void AddServiceCallback(BrowseData data);
-               delegate void RemoveServiceCallback(BrowseData data);
-               delegate void ResolveServiceCallback(ResolveData data);
-
-               AddServiceCallback              addServiceCallback;
-               RemoveServiceCallback   removeServiceCallback;
                private System.Windows.Forms.Label label1;
                private System.Windows.Forms.Label label2;
                private System.Windows.Forms.Label label3;
@@ -90,7 +84,6 @@ namespace DNSServiceBrowser_NET
                private System.Windows.Forms.TextBox portField;
                private System.Windows.Forms.Label label5;
                private System.Windows.Forms.ListBox serviceTextField;
-               ResolveServiceCallback  resolveServiceCallback;
 
                public Form1()
                {
@@ -99,19 +92,20 @@ namespace DNSServiceBrowser_NET
                        //
                        InitializeComponent();
 
-                       addServiceCallback              = new AddServiceCallback(OnAddService);
-                       removeServiceCallback   = new RemoveServiceCallback(OnRemoveService);
-                       resolveServiceCallback  = new ResolveServiceCallback(OnResolveService);
-
                        this.Load += new System.EventHandler(this.Form1_Load);
+
+            eventManager                    =  new DNSSDEventManager();
+            eventManager.ServiceFound       += new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
+            eventManager.ServiceLost        += new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
+            eventManager.ServiceResolved    += new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
+            eventManager.OperationFailed    += new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
+            
+            service = new DNSSDService();
                }
 
                private void Form1_Load(object sender, EventArgs e) 
-
                {
-
-                       typeBox.SelectedItem = "_spike._tcp";
-
+                       typeBox.SelectedItem = "_http._tcp";
                }
 
 
@@ -122,15 +116,30 @@ namespace DNSServiceBrowser_NET
                {
                        if( disposing )
                        {
-                               if (components != null) 
-                               {
-                                       components.Dispose();
-                               }
+                if (components != null)
+                {
+                    components.Dispose();
+                }
 
-                               if (browser != null)
-                               {
-                                       browser.Dispose();
-                               }
+                if (resolver != null)
+                {
+                    resolver.Stop();
+                }
+
+                if (browser != null)
+                {
+                    browser.Stop();
+                }
+
+                if (service != null)
+                {
+                    service.Stop();
+                }
+
+                eventManager.ServiceFound    -= new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
+                eventManager.ServiceLost     -= new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
+                eventManager.ServiceResolved -= new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
+                eventManager.OperationFailed -= new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
                        }
                        base.Dispose( disposing );
                }
@@ -467,7 +476,7 @@ namespace DNSServiceBrowser_NET
                //
                public class BrowseData
                {
-                       public int              InterfaceIndex;
+                       public uint             InterfaceIndex;
                        public String   Name;
                        public String   Type;
                        public String   Domain;
@@ -516,11 +525,11 @@ namespace DNSServiceBrowser_NET
                //
                public class ResolveData
                {
-                       public int              InterfaceIndex;
-                       public String   FullName;
-                       public String   HostName;
-                       public int              Port;
-                       public Byte[]   TxtRecord;
+                       public uint                 InterfaceIndex;
+                       public String       FullName;
+                       public String       HostName;
+                       public int                  Port;
+                       public TXTRecord        TxtRecord;
 
                        public override String
                                ToString()
@@ -545,29 +554,30 @@ namespace DNSServiceBrowser_NET
                        portField.Text  = resolveData.Port.ToString();
 
                        serviceTextField.Items.Clear();
-               
-                       if (resolveData.TxtRecord != null)
-                       {
-                               for (int idx = 0; idx < TextRecord.GetCount(resolveData.TxtRecord); idx++)
-                               {
-                                       String  key;
-                                       Byte[]  bytes;
-                               
-                                       bytes   = TextRecord.GetItemAtIndex(resolveData.TxtRecord, idx, out key);
+            
+            if (resolveData.TxtRecord != null)
+            {
+                for (uint idx = 0; idx < resolveData.TxtRecord.GetCount(); idx++)
+                {
+                    String key;
+                    Byte[] bytes;
 
-                                       if (key.Length > 0)
-                                       {
-                                               String  val = "";
+                    key = resolveData.TxtRecord.GetKeyAtIndex(idx);
+                    bytes = (Byte[])resolveData.TxtRecord.GetValueAtIndex(idx);
 
-                                               if (bytes != null)
-                                               {
-                                                       val = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
-                                               }
+                    if (key.Length > 0)
+                    {
+                        String val = "";
 
-                                               serviceTextField.Items.Add(key + "=" + val);
-                                       }
-                               }
-                       }
+                        if (bytes != null)
+                        {
+                            val = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
+                        }
+
+                        serviceTextField.Items.Add(key + "=" + val);
+                    }
+                }
+            }
                }
 
                //
@@ -579,7 +589,7 @@ namespace DNSServiceBrowser_NET
 
                        if (browser != null)
                        {
-                               browser.Dispose();
+                               browser.Stop();
                        }
 
                        nameField.Text = "";
@@ -591,7 +601,7 @@ namespace DNSServiceBrowser_NET
 
                        try
                        {
-                               browser = DNSService.Browse(0, 0, typeBox.SelectedItem.ToString(), null, new DNSService.BrowseReply(OnBrowseReply));
+                               browser = service.Browse( 0, 0, typeBox.SelectedItem.ToString(), null, eventManager );
                        }
                        catch
                        {
@@ -604,7 +614,8 @@ namespace DNSServiceBrowser_NET
                {
                        if (resolver != null)
                        {
-                               resolver.Dispose();
+                               resolver.Stop();
+                resolver = null;
                        }
 
             if (browseList.SelectedItem != null)
@@ -613,7 +624,7 @@ namespace DNSServiceBrowser_NET
                 {
                     BrowseData data = (BrowseData) browseList.SelectedItem;
 
-                    resolver = DNSService.Resolve(0, 0, data.Name, data.Type, data.Domain, new DNSService.ResolveReply(OnResolveReply));
+                    resolver = service.Resolve(0, data.InterfaceIndex, data.Name, data.Type, data.Domain, eventManager);
                 }
                 catch
                 {
@@ -624,125 +635,86 @@ namespace DNSServiceBrowser_NET
                }
 
                //
-               // OnAddService
+               // ServiceFound
                //
-               // This method is "Invoked" by OnBrowseReply.  This call
-               // executes in the context of the main thread
+               // This call is invoked by the DNSService core.  We create
+        // a BrowseData object and invoked the appropriate method
+        // in the GUI thread so we can update the UI
                //
-               private void OnAddService
-                                                               (
-                                                               BrowseData      data
-                                                               )
+               public void ServiceFound
+                                               (
+                                               DNSSDService    sref,
+                                               DNSSDFlags      flags,
+                                               uint                    ifIndex,
+                        String          serviceName,
+                        String          regType,
+                        String          domain
+                                               )
                {
-                       browseList.Items.Add(data);
-                       browseList.Invalidate();
-               }
+                       BrowseData data = new BrowseData();
 
-               //
-               // OnRemoveService
-               //
-               // This method is "Invoked" by OnBrowseReply.  This call
-               // executes in the context of the main thread
-               //
-               private void OnRemoveService
-                                                               (
-                                                               BrowseData      data
-                                                               )
-               {
-                       browseList.Items.Remove(data);
-                       browseList.Invalidate();
+                       data.InterfaceIndex = ifIndex;
+                       data.Name           = serviceName;
+                       data.Type           = regType;
+                       data.Domain         = domain;
+
+            browseList.Items.Add(data);
+            browseList.Invalidate();
                }
 
-               //
-               // OnResolveService
-               //
-               // This method is "Invoked" by OnResolveReply.  This call
-               // executes in the context of the main thread
-               //
-               private void OnResolveService
-                                                               (
-                                                               ResolveData     data
-                                                               )
+        public void ServiceLost
+                        (
+                        DNSSDService    sref,
+                        DNSSDFlags      flags,
+                        uint            ifIndex,
+                        String          serviceName,
+                        String          regType,
+                        String          domain
+                        )
+        {
+            BrowseData data = new BrowseData();
+
+                       data.InterfaceIndex = ifIndex;
+                       data.Name           = serviceName;
+                       data.Type           = regType;
+                       data.Domain         = domain;
+
+            browseList.Items.Remove(data);
+                       browseList.Invalidate();
+        }             
+
+               public void ServiceResolved
+                                               (
+                                               DNSSDService    sref,  
+                                               DNSSDFlags      flags,
+                                               uint                    ifIndex,
+                        String          fullName,
+                        String          hostName,
+                        ushort           port,
+                        TXTRecord       txtRecord
+                                               )
                {
-                       resolver.Dispose();
+                       ResolveData data = new ResolveData();
+
+                       data.InterfaceIndex = ifIndex;
+                       data.FullName           = fullName;
+                       data.HostName           = hostName;
+                       data.Port                       = port;
+                       data.TxtRecord          = txtRecord;
+
+            resolver.Stop();
                        resolver = null;
 
                        Populate((BrowseData) browseList.SelectedItem, data);
                }
 
-               //
-               // OnBrowseReply
-               //
-               // This call is invoked by the DNSService core.  It is
-               // executed in the context of a worker thread, not the
-               // main (GUI) thread.  We create a BrowseData object
-               // and invoked the appropriate method in the GUI thread
-               // so we can update the UI
-               //
-               private void OnBrowseReply
-                                                               (
-                                                               ServiceRef              sdRef,
-                                                               ServiceFlags    flags,
-                                                               int                             interfaceIndex,
-                                                               ErrorCode               errorCode,
-                                                               String                  name,
-                                                               String                  type,
-                                                               String                  domain
-                                                               )
-               {
-                       if (errorCode == ErrorCode.NoError)
-                       {
-                               BrowseData data = new BrowseData();
-
-                               data.InterfaceIndex = interfaceIndex;
-                               data.Name = name;
-                               data.Type = type;
-                               data.Domain = domain;
-       
-                               if ((flags & ServiceFlags.Add) != 0)
-                               {
-                                       Invoke(addServiceCallback, new Object[]{data});
-                                       
-                               }
-                               else if ((flags == 0) || ((flags & ServiceFlags.MoreComing) != 0))
-                               {
-                                       Invoke(removeServiceCallback, new Object[]{data});
-                               }
-                       }
-                       else
-                       {
-                               MessageBox.Show("OnBrowseReply returned an error code: " + errorCode, "Error");
-                       }
-               }
-
-               private void OnResolveReply
-                                                               (
-                                                               ServiceRef              sdRef,  
-                                                               ServiceFlags    flags,
-                                                               int                             interfaceIndex,
-                                                               ErrorCode               errorCode,
-                                                               String                  fullName,
-                                                               String                  hostName,
-                                                               int                             port,
-                                                               Byte[]                  txtRecord
-                                                               )
-               {
-                       if (errorCode == ErrorCode.NoError)
-                       {
-                               ResolveData data = new ResolveData();
-
-                               data.InterfaceIndex = interfaceIndex;
-                               data.FullName           = fullName;
-                               data.HostName           = hostName;
-                               data.Port                       = port;
-                               data.TxtRecord          = txtRecord;
-       
-                               Invoke(resolveServiceCallback, new Object[]{data});
-                       }
-                       else
-                       {
-                               MessageBox.Show("OnResolveReply returned an error code: " + errorCode, "Error");
-                       }
-               }
-       }
+        public void OperationFailed
+                        (
+                        DNSSDService sref,
+                        DNSSDError error
+                        )
+        {
+            MessageBox.Show("Operation failed: error code: " + error, "Error");
+        }
+    }
 }
diff --git a/Clients/DNSServiceBrowser.VB/DNSServiceBrowser.Designer.vb b/Clients/DNSServiceBrowser.VB/DNSServiceBrowser.Designer.vb
new file mode 100644 (file)
index 0000000..0c6280b
--- /dev/null
@@ -0,0 +1,206 @@
+<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _\r
+Partial Class DNSServiceBrowser\r
+    Inherits System.Windows.Forms.Form\r
+\r
+    'Form overrides dispose to clean up the component list.\r
+    <System.Diagnostics.DebuggerNonUserCode()> _\r
+    Protected Overrides Sub Dispose(ByVal disposing As Boolean)\r
+        Try\r
+            If disposing AndAlso components IsNot Nothing Then\r
+                components.Dispose()\r
+            End If\r
+        Finally\r
+            MyBase.Dispose(disposing)\r
+        End Try\r
+    End Sub\r
+\r
+    'Required by the Windows Form Designer\r
+    Private components As System.ComponentModel.IContainer\r
+\r
+    'NOTE: The following procedure is required by the Windows Form Designer\r
+    'It can be modified using the Windows Form Designer.  \r
+    'Do not modify it using the code editor.\r
+    <System.Diagnostics.DebuggerStepThrough()> _\r
+    Private Sub InitializeComponent()\r
+        Me.ComboBox1 = New System.Windows.Forms.ComboBox\r
+        Me.ServiceNames = New System.Windows.Forms.ListBox\r
+        Me.Label1 = New System.Windows.Forms.Label\r
+        Me.Label2 = New System.Windows.Forms.Label\r
+        Me.Label3 = New System.Windows.Forms.Label\r
+        Me.Label4 = New System.Windows.Forms.Label\r
+        Me.Label5 = New System.Windows.Forms.Label\r
+        Me.NameField = New System.Windows.Forms.TextBox\r
+        Me.PortField = New System.Windows.Forms.TextBox\r
+        Me.HostField = New System.Windows.Forms.TextBox\r
+        Me.DomainField = New System.Windows.Forms.TextBox\r
+        Me.TypeField = New System.Windows.Forms.TextBox\r
+        Me.TextRecord = New System.Windows.Forms.ListBox\r
+        Me.SuspendLayout()\r
+        '\r
+        'ComboBox1\r
+        '\r
+        Me.ComboBox1.FormattingEnabled = True\r
+        Me.ComboBox1.Items.AddRange(New Object() {"_accessone._tcp", "_accountedge._tcp", "_actionitems._tcp", "_addressbook._tcp", "_aecoretech._tcp", "_afpovertcp._tcp", "_airport._tcp", "_animobserver._tcp", "_animolmd._tcp", "_apple-sasl._tcp", "_aquamon._tcp", "_async._tcp", "_auth._tcp", "_beep._tcp", "_bfagent._tcp", "_bootps._udp", "_bousg._tcp", "_bsqdea._tcp", "_cheat._tcp", "_chess._tcp", "_clipboard._tcp", "_collection._tcp", "_contactserver._tcp", "_cvspserver._tcp", "_cytv._tcp", "_daap._tcp", "_difi._tcp", "_distcc._tcp", "_dossier._tcp", "_dpap._tcp", "_earphoria._tcp", "_ebms._tcp", "_ebreg._tcp", "_ecbyesfsgksc._tcp", "_eheap._tcp", "_embrace._tcp", "_eppc._tcp", "_eventserver._tcp", "_exec._tcp", "_facespan._tcp", "_faxstfx._tcp", "_fish._tcp", "_fjork._tcp", "_fmpro-internal._tcp", "_ftp._tcp", "_ftpcroco._tcp", "_gbs-smp._tcp", "_gbs-stp._tcp", "_grillezvous._tcp", "_h323._tcp", "_hotwayd._tcp", "_http._tcp", "_hydra._tcp", "_ica-networking._tcp", "_ichalkboard._tcp", "_ichat._tcp", "_iconquer._tcp", "_ifolder._tcp", "_ilynx._tcp", "_imap._tcp", "_imidi._tcp", "_ipbroadcaster._tcp", "_ipp._tcp", "_ishare._tcp", "_isparx._tcp", "_ispq-vc._tcp", "_isticky._tcp", "_istorm._tcp", "_iwork._tcp", "_lan2p._tcp", "_ldap._tcp", "_liaison._tcp", "_login._tcp", "_lontalk._tcp", "_lonworks._tcp", "_macfoh-remote._tcp", "_macminder._tcp", "_moneyworks._tcp", "_mp3sushi._tcp", "_mttp._tcp", "_ncbroadcast._tcp", "_ncdirect._tcp", "_ncsyncserver._tcp", "_net-assistant._tcp", "_newton-dock._tcp", "_nfs._udp", "_nssocketport._tcp", "_odabsharing._tcp", "_omni-bookmark._tcp", "_openbase._tcp", "_p2pchat._udp", "_pdl-datastream._tcp", "_poch._tcp", "_pop3._tcp", "_postgresql._tcp", "_presence._tcp", "_printer._tcp", "_ptp._tcp", "_quinn._tcp", "_raop._tcp", "_rce._tcp", "_realplayfavs._tcp", "_rfb._tcp", "_riousbprint._tcp", "_rtsp._tcp", "_safarimenu._tcp", "_sallingclicker._tcp", "_scone._tcp", "_sdsharing._tcp", "_see._tcp", "_seeCard._tcp", "_serendipd._tcp", "_servermgr._tcp", "_sge-exec._tcp", "_sge-qmaster._tcp", "_shell._tcp", "_shout._tcp", "_shoutcast._tcp", "_soap._tcp", "_spike._tcp", "_spincrisis._tcp", "_spl-itunes._tcp", "_spr-itunes._tcp", "_ssh._tcp", "_ssscreenshare._tcp", "_stickynotes._tcp", "_strateges._tcp", "_sxqdea._tcp", "_sybase-tds._tcp", "_teamlist._tcp", "_teleport._udp", "_telnet._tcp", "_tftp._udp", "_ticonnectmgr._tcp", "_tinavigator._tcp", "_tryst._tcp", "_upnp._tcp", "_utest._tcp", "_vue4rendercow._tcp", "_webdav._tcp", "_whamb._tcp", "_wired._tcp", "_workgroup._tcp", "_workstation._tcp", "_wormhole._tcp", "_ws._tcp", "_xserveraid._tcp", "_xsync._tcp", "_xtshapro._tcp"})\r
+        Me.ComboBox1.Location = New System.Drawing.Point(13, 13)\r
+        Me.ComboBox1.Name = "ComboBox1"\r
+        Me.ComboBox1.Size = New System.Drawing.Size(252, 21)\r
+        Me.ComboBox1.Sorted = True\r
+        Me.ComboBox1.TabIndex = 0\r
+        '\r
+        'ServiceNames\r
+        '\r
+        Me.ServiceNames.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _\r
+                    Or System.Windows.Forms.AnchorStyles.Left) _\r
+                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)\r
+        Me.ServiceNames.FormattingEnabled = True\r
+        Me.ServiceNames.Location = New System.Drawing.Point(13, 41)\r
+        Me.ServiceNames.Name = "ServiceNames"\r
+        Me.ServiceNames.Size = New System.Drawing.Size(662, 251)\r
+        Me.ServiceNames.Sorted = True\r
+        Me.ServiceNames.TabIndex = 1\r
+        '\r
+        'Label1\r
+        '\r
+        Me.Label1.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.Label1.AutoSize = True\r
+        Me.Label1.Location = New System.Drawing.Point(16, 311)\r
+        Me.Label1.Name = "Label1"\r
+        Me.Label1.Size = New System.Drawing.Size(38, 13)\r
+        Me.Label1.TabIndex = 2\r
+        Me.Label1.Text = "Name:"\r
+        '\r
+        'Label2\r
+        '\r
+        Me.Label2.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.Label2.AutoSize = True\r
+        Me.Label2.Location = New System.Drawing.Point(16, 439)\r
+        Me.Label2.Name = "Label2"\r
+        Me.Label2.Size = New System.Drawing.Size(29, 13)\r
+        Me.Label2.TabIndex = 3\r
+        Me.Label2.Text = "Port:"\r
+        '\r
+        'Label3\r
+        '\r
+        Me.Label3.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.Label3.AutoSize = True\r
+        Me.Label3.Location = New System.Drawing.Point(16, 407)\r
+        Me.Label3.Name = "Label3"\r
+        Me.Label3.Size = New System.Drawing.Size(32, 13)\r
+        Me.Label3.TabIndex = 4\r
+        Me.Label3.Text = "Host:"\r
+        '\r
+        'Label4\r
+        '\r
+        Me.Label4.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.Label4.AutoSize = True\r
+        Me.Label4.Location = New System.Drawing.Point(16, 374)\r
+        Me.Label4.Name = "Label4"\r
+        Me.Label4.Size = New System.Drawing.Size(46, 13)\r
+        Me.Label4.TabIndex = 5\r
+        Me.Label4.Text = "Domain:"\r
+        '\r
+        'Label5\r
+        '\r
+        Me.Label5.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.Label5.AutoSize = True\r
+        Me.Label5.Location = New System.Drawing.Point(16, 342)\r
+        Me.Label5.Name = "Label5"\r
+        Me.Label5.Size = New System.Drawing.Size(34, 13)\r
+        Me.Label5.TabIndex = 6\r
+        Me.Label5.Text = "Type:"\r
+        '\r
+        'NameField\r
+        '\r
+        Me.NameField.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.NameField.Location = New System.Drawing.Point(69, 309)\r
+        Me.NameField.Name = "NameField"\r
+        Me.NameField.ReadOnly = True\r
+        Me.NameField.Size = New System.Drawing.Size(195, 20)\r
+        Me.NameField.TabIndex = 7\r
+        '\r
+        'PortField\r
+        '\r
+        Me.PortField.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.PortField.Location = New System.Drawing.Point(69, 436)\r
+        Me.PortField.Name = "PortField"\r
+        Me.PortField.ReadOnly = True\r
+        Me.PortField.Size = New System.Drawing.Size(195, 20)\r
+        Me.PortField.TabIndex = 8\r
+        '\r
+        'HostField\r
+        '\r
+        Me.HostField.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.HostField.Location = New System.Drawing.Point(69, 403)\r
+        Me.HostField.Name = "HostField"\r
+        Me.HostField.ReadOnly = True\r
+        Me.HostField.Size = New System.Drawing.Size(195, 20)\r
+        Me.HostField.TabIndex = 9\r
+        '\r
+        'DomainField\r
+        '\r
+        Me.DomainField.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.DomainField.Location = New System.Drawing.Point(69, 371)\r
+        Me.DomainField.Name = "DomainField"\r
+        Me.DomainField.ReadOnly = True\r
+        Me.DomainField.Size = New System.Drawing.Size(195, 20)\r
+        Me.DomainField.TabIndex = 10\r
+        '\r
+        'TypeField\r
+        '\r
+        Me.TypeField.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.TypeField.Location = New System.Drawing.Point(69, 340)\r
+        Me.TypeField.Name = "TypeField"\r
+        Me.TypeField.ReadOnly = True\r
+        Me.TypeField.Size = New System.Drawing.Size(195, 20)\r
+        Me.TypeField.TabIndex = 11\r
+        '\r
+        'TextRecord\r
+        '\r
+        Me.TextRecord.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _\r
+                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)\r
+        Me.TextRecord.FormattingEnabled = True\r
+        Me.TextRecord.Location = New System.Drawing.Point(278, 309)\r
+        Me.TextRecord.Name = "TextRecord"\r
+        Me.TextRecord.SelectionMode = System.Windows.Forms.SelectionMode.None\r
+        Me.TextRecord.Size = New System.Drawing.Size(397, 147)\r
+        Me.TextRecord.TabIndex = 12\r
+        '\r
+        'Form1\r
+        '\r
+        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)\r
+        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font\r
+        Me.ClientSize = New System.Drawing.Size(690, 480)\r
+        Me.Controls.Add(Me.TextRecord)\r
+        Me.Controls.Add(Me.TypeField)\r
+        Me.Controls.Add(Me.DomainField)\r
+        Me.Controls.Add(Me.HostField)\r
+        Me.Controls.Add(Me.PortField)\r
+        Me.Controls.Add(Me.NameField)\r
+        Me.Controls.Add(Me.Label5)\r
+        Me.Controls.Add(Me.Label4)\r
+        Me.Controls.Add(Me.Label3)\r
+        Me.Controls.Add(Me.Label2)\r
+        Me.Controls.Add(Me.Label1)\r
+        Me.Controls.Add(Me.ServiceNames)\r
+        Me.Controls.Add(Me.ComboBox1)\r
+        Me.Name = "Form1"\r
+        Me.Text = "Bonjour Browser"\r
+        Me.ResumeLayout(False)\r
+        Me.PerformLayout()\r
+\r
+    End Sub\r
+    Friend WithEvents ComboBox1 As System.Windows.Forms.ComboBox\r
+    Friend WithEvents ServiceNames As System.Windows.Forms.ListBox\r
+    Friend WithEvents Label1 As System.Windows.Forms.Label\r
+    Friend WithEvents Label2 As System.Windows.Forms.Label\r
+    Friend WithEvents Label3 As System.Windows.Forms.Label\r
+    Friend WithEvents Label4 As System.Windows.Forms.Label\r
+    Friend WithEvents Label5 As System.Windows.Forms.Label\r
+    Friend WithEvents NameField As System.Windows.Forms.TextBox\r
+    Friend WithEvents PortField As System.Windows.Forms.TextBox\r
+    Friend WithEvents HostField As System.Windows.Forms.TextBox\r
+    Friend WithEvents DomainField As System.Windows.Forms.TextBox\r
+    Friend WithEvents TypeField As System.Windows.Forms.TextBox\r
+    Friend WithEvents TextRecord As System.Windows.Forms.ListBox\r
+\r
+End Class\r
diff --git a/Clients/DNSServiceBrowser.VB/DNSServiceBrowser.VB.vbproj b/Clients/DNSServiceBrowser.VB/DNSServiceBrowser.VB.vbproj
new file mode 100644 (file)
index 0000000..d4e59eb
--- /dev/null
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+    <ProductVersion>8.0.50727</ProductVersion>\r
+    <SchemaVersion>2.0</SchemaVersion>\r
+    <ProjectGuid>{FB79E297-5703-435C-A829-51AA51CD71C2}</ProjectGuid>\r
+    <OutputType>WinExe</OutputType>\r
+    <StartupObject>DNSServiceBrowser.VB.My.MyApplication</StartupObject>\r
+    <RootNamespace>DNSServiceBrowser.VB</RootNamespace>\r
+    <AssemblyName>DNSServiceBrowser.VB</AssemblyName>\r
+    <MyType>WindowsForms</MyType>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <DefineDebug>true</DefineDebug>\r
+    <DefineTrace>true</DefineTrace>\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <DocumentationFile>DNSServiceBrowser.VB.xml</DocumentationFile>\r
+    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <DebugType>pdbonly</DebugType>\r
+    <DefineDebug>false</DefineDebug>\r
+    <DefineTrace>true</DefineTrace>\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <DocumentationFile>DNSServiceBrowser.VB.xml</DocumentationFile>\r
+    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System" />\r
+    <Reference Include="System.Data" />\r
+    <Reference Include="System.Deployment" />\r
+    <Reference Include="System.Drawing" />\r
+    <Reference Include="System.Windows.Forms" />\r
+    <Reference Include="System.Xml" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Import Include="Microsoft.VisualBasic" />\r
+    <Import Include="System" />\r
+    <Import Include="System.Collections" />\r
+    <Import Include="System.Collections.Generic" />\r
+    <Import Include="System.Data" />\r
+    <Import Include="System.Drawing" />\r
+    <Import Include="System.Diagnostics" />\r
+    <Import Include="System.Windows.Forms" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="DNSServiceBrowser.vb">\r
+      <SubType>Form</SubType>\r
+    </Compile>\r
+    <Compile Include="DNSServiceBrowser.Designer.vb">\r
+      <DependentUpon>DNSServiceBrowser.vb</DependentUpon>\r
+      <SubType>Form</SubType>\r
+    </Compile>\r
+    <Compile Include="My Project\AssemblyInfo.vb" />\r
+    <Compile Include="My Project\Application.Designer.vb">\r
+      <AutoGen>True</AutoGen>\r
+      <DependentUpon>Application.myapp</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="My Project\Resources.Designer.vb">\r
+      <AutoGen>True</AutoGen>\r
+      <DesignTime>True</DesignTime>\r
+      <DependentUpon>Resources.resx</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="My Project\Settings.Designer.vb">\r
+      <AutoGen>True</AutoGen>\r
+      <DependentUpon>Settings.settings</DependentUpon>\r
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>\r
+    </Compile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <EmbeddedResource Include="DNSServiceBrowser.resx">\r
+      <SubType>Designer</SubType>\r
+      <DependentUpon>DNSServiceBrowser.vb</DependentUpon>\r
+    </EmbeddedResource>\r
+    <EmbeddedResource Include="My Project\Resources.resx">\r
+      <Generator>VbMyResourcesResXFileCodeGenerator</Generator>\r
+      <LastGenOutput>Resources.Designer.vb</LastGenOutput>\r
+      <CustomToolNamespace>My.Resources</CustomToolNamespace>\r
+      <SubType>Designer</SubType>\r
+    </EmbeddedResource>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <None Include="My Project\Application.myapp">\r
+      <Generator>MyApplicationCodeGenerator</Generator>\r
+      <LastGenOutput>Application.Designer.vb</LastGenOutput>\r
+    </None>\r
+    <None Include="My Project\Settings.settings">\r
+      <Generator>SettingsSingleFileGenerator</Generator>\r
+      <CustomToolNamespace>My</CustomToolNamespace>\r
+      <LastGenOutput>Settings.Designer.vb</LastGenOutput>\r
+    </None>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <COMReference Include="Bonjour">\r
+      <Guid>{18FBED6D-F2B7-4EC8-A4A4-46282E635308}</Guid>\r
+      <VersionMajor>1</VersionMajor>\r
+      <VersionMinor>0</VersionMinor>\r
+      <Lcid>0</Lcid>\r
+      <WrapperTool>tlbimp</WrapperTool>\r
+      <Isolated>False</Isolated>\r
+    </COMReference>\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />\r
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+       Other similar extension points exist, see Microsoft.Common.targets.\r
+  <Target Name="BeforeBuild">\r
+  </Target>\r
+  <Target Name="AfterBuild">\r
+  </Target>\r
+  -->\r
+</Project>
\ No newline at end of file
diff --git a/Clients/DNSServiceBrowser.VB/DNSServiceBrowser.resx b/Clients/DNSServiceBrowser.VB/DNSServiceBrowser.resx
new file mode 100644 (file)
index 0000000..ff31a6d
--- /dev/null
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<root>\r
+  <!-- \r
+    Microsoft ResX Schema \r
+    \r
+    Version 2.0\r
+    \r
+    The primary goals of this format is to allow a simple XML format \r
+    that is mostly human readable. The generation and parsing of the \r
+    various data types are done through the TypeConverter classes \r
+    associated with the data types.\r
+    \r
+    Example:\r
+    \r
+    ... ado.net/XML headers & schema ...\r
+    <resheader name="resmimetype">text/microsoft-resx</resheader>\r
+    <resheader name="version">2.0</resheader>\r
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\r
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\r
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>\r
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>\r
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">\r
+        <value>[base64 mime encoded serialized .NET Framework object]</value>\r
+    </data>\r
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">\r
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\r
+        <comment>This is a comment</comment>\r
+    </data>\r
+                \r
+    There are any number of "resheader" rows that contain simple \r
+    name/value pairs.\r
+    \r
+    Each data row contains a name, and value. The row also contains a \r
+    type or mimetype. Type corresponds to a .NET class that support \r
+    text/value conversion through the TypeConverter architecture. \r
+    Classes that don't support this are serialized and stored with the \r
+    mimetype set.\r
+    \r
+    The mimetype is used for serialized objects, and tells the \r
+    ResXResourceReader how to depersist the object. This is currently not \r
+    extensible. For a given mimetype the value must be set accordingly:\r
+    \r
+    Note - application/x-microsoft.net.object.binary.base64 is the format \r
+    that the ResXResourceWriter will generate, however the reader can \r
+    read any of the formats listed below.\r
+    \r
+    mimetype: application/x-microsoft.net.object.binary.base64\r
+    value   : The object must be serialized with \r
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\r
+            : and then encoded with base64 encoding.\r
+    \r
+    mimetype: application/x-microsoft.net.object.soap.base64\r
+    value   : The object must be serialized with \r
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\r
+            : and then encoded with base64 encoding.\r
+\r
+    mimetype: application/x-microsoft.net.object.bytearray.base64\r
+    value   : The object must be serialized into a byte array \r
+            : using a System.ComponentModel.TypeConverter\r
+            : and then encoded with base64 encoding.\r
+    -->\r
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />\r
+    <xsd:element name="root" msdata:IsDataSet="true">\r
+      <xsd:complexType>\r
+        <xsd:choice maxOccurs="unbounded">\r
+          <xsd:element name="metadata">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" use="required" type="xsd:string" />\r
+              <xsd:attribute name="type" type="xsd:string" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" />\r
+              <xsd:attribute ref="xml:space" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="assembly">\r
+            <xsd:complexType>\r
+              <xsd:attribute name="alias" type="xsd:string" />\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="data">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />\r
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />\r
+              <xsd:attribute ref="xml:space" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="resheader">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" use="required" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+        </xsd:choice>\r
+      </xsd:complexType>\r
+    </xsd:element>\r
+  </xsd:schema>\r
+  <resheader name="resmimetype">\r
+    <value>text/microsoft-resx</value>\r
+  </resheader>\r
+  <resheader name="version">\r
+    <value>2.0</value>\r
+  </resheader>\r
+  <resheader name="reader">\r
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+  <resheader name="writer">\r
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+</root>
\ No newline at end of file
diff --git a/Clients/DNSServiceBrowser.VB/DNSServiceBrowser.vb b/Clients/DNSServiceBrowser.VB/DNSServiceBrowser.vb
new file mode 100644 (file)
index 0000000..1e7a7ae
--- /dev/null
@@ -0,0 +1,111 @@
+Public Class DNSServiceBrowser\r
+    Public WithEvents MyEventManager As New Bonjour.DNSSDEventManager\r
+\r
+    Private m_service As New Bonjour.DNSSDService\r
+    Private m_browser As Bonjour.DNSSDService\r
+    Private m_resolver As Bonjour.DNSSDService\r
+\r
+    Public Sub New()\r
+        MyBase.New()\r
+\r
+        'This call is required by the Windows Form Designer.\r
+        InitializeComponent()\r
+\r
+        ComboBox1.SelectedIndex = 0\r
+    End Sub\r
+    Public Sub MyEventManager_ServiceFound(ByVal browser As Bonjour.DNSSDService, ByVal flags As Bonjour.DNSSDFlags, ByVal ifIndex As UInteger, ByVal serviceName As String, ByVal regtype As String, ByVal domain As String) Handles MyEventManager.ServiceFound\r
+        Dim browseData As New BrowseData\r
+        browseData.ServiceName = serviceName\r
+        browseData.RegType = regtype\r
+        browseData.Domain = domain\r
+        ServiceNames.Items.Add(browseData)\r
+    End Sub\r
+    Public Sub MyEventManager_ServiceLost(ByVal browser As Bonjour.DNSSDService, ByVal flags As Bonjour.DNSSDFlags, ByVal ifIndex As UInteger, ByVal serviceName As String, ByVal regtype As String, ByVal domain As String) Handles MyEventManager.ServiceLost\r
+        ServiceNames.Items.Remove(serviceName)\r
+    End Sub\r
+    Public Sub MyEventManager_ServiceResolved(ByVal resolver As Bonjour.DNSSDService, ByVal flags As Bonjour.DNSSDFlags, ByVal ifIndex As UInteger, ByVal fullname As String, ByVal hostname As String, ByVal port As UShort, ByVal record As Bonjour.TXTRecord) Handles MyEventManager.ServiceResolved\r
+        m_resolver.Stop()\r
+        m_resolver = Nothing\r
+        Dim browseData As BrowseData = ServiceNames.Items.Item(ServiceNames.SelectedIndex)\r
+        NameField.Text = browseData.ServiceName\r
+        TypeField.Text = browseData.RegType\r
+        DomainField.Text = browseData.Domain\r
+        HostField.Text = hostname\r
+        PortField.Text = port\r
+\r
+        If record IsNot Nothing Then\r
+            For i As UInteger = 0 To record.GetCount() - 1\r
+                Dim key As String = record.GetKeyAtIndex(i)\r
+                If key.Length() > 0 Then\r
+                    TextRecord.Items.Add(key + "=" + System.Text.Encoding.ASCII.GetString(record.GetValueAtIndex(i)))\r
+                End If\r
+            Next i\r
+        End If\r
+    End Sub\r
+    Private Sub ClearServiceInfo()\r
+        TextRecord.Items.Clear()\r
+        NameField.Text = ""\r
+        TypeField.Text = ""\r
+        DomainField.Text = ""\r
+        HostField.Text = ""\r
+        PortField.Text = ""\r
+    End Sub\r
+    Private Sub ServiceNames_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ServiceNames.SelectedIndexChanged\r
+        If m_resolver IsNot Nothing Then\r
+            m_resolver.Stop()\r
+        End If\r
+        Me.ClearServiceInfo()\r
+        Dim browseData As BrowseData = ServiceNames.Items.Item(ServiceNames.SelectedIndex)\r
+        m_resolver = m_service.Resolve(0, 0, browseData.ServiceName, browseData.RegType, browseData.Domain, MyEventManager)\r
+    End Sub\r
+    Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged\r
+        If m_browser IsNot Nothing Then\r
+            m_browser.Stop()\r
+        End If\r
+\r
+        ServiceNames.Items.Clear()\r
+        Me.ClearServiceInfo()\r
+        m_browser = m_service.Browse(0, 0, ComboBox1.Items.Item(ComboBox1.SelectedIndex), "", MyEventManager)\r
+    End Sub\r
+\r
+    Private Sub ListBox2_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextRecord.SelectedIndexChanged\r
+\r
+    End Sub\r
+End Class\r
+Public Class BrowseData\r
+    Private m_serviceName As String\r
+    Private m_regType As String\r
+    Private m_domain As String\r
+\r
+    Property ServiceName() As String\r
+        Get\r
+            Return m_serviceName\r
+        End Get\r
+        Set(ByVal Value As String)\r
+            m_serviceName = Value\r
+        End Set\r
+    End Property\r
+\r
+    Property RegType() As String\r
+        Get\r
+            Return m_regType\r
+        End Get\r
+        Set(ByVal Value As String)\r
+            m_regType = Value\r
+        End Set\r
+    End Property\r
+\r
+    Property Domain() As String\r
+        Get\r
+            Return m_domain\r
+        End Get\r
+        Set(ByVal Value As String)\r
+            m_domain = Value\r
+        End Set\r
+    End Property\r
+\r
+    Public Overrides Function ToString() As String\r
+        Return m_serviceName\r
+    End Function\r
+\r
+End Class\r
diff --git a/Clients/DNSServiceBrowser.VB/My Project/Application.Designer.vb b/Clients/DNSServiceBrowser.VB/My Project/Application.Designer.vb
new file mode 100644 (file)
index 0000000..ad73d2e
--- /dev/null
@@ -0,0 +1,38 @@
+'------------------------------------------------------------------------------\r
+' <auto-generated>\r
+'     This code was generated by a tool.\r
+'     Runtime Version:2.0.50727.4918\r
+'\r
+'     Changes to this file may cause incorrect behavior and will be lost if\r
+'     the code is regenerated.\r
+' </auto-generated>\r
+'------------------------------------------------------------------------------\r
+\r
+Option Strict On\r
+Option Explicit On\r
+\r
+\r
+Namespace My\r
+    \r
+    'NOTE: This file is auto-generated; do not modify it directly.  To make changes,\r
+    ' or if you encounter build errors in this file, go to the Project Designer\r
+    ' (go to Project Properties or double-click the My Project node in\r
+    ' Solution Explorer), and make changes on the Application tab.\r
+    '\r
+    Partial Friend Class MyApplication\r
+        \r
+        <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _\r
+        Public Sub New()\r
+            MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.AuthenticationMode.Windows)\r
+            Me.IsSingleInstance = false\r
+            Me.EnableVisualStyles = true\r
+            Me.SaveMySettingsOnExit = true\r
+            Me.ShutDownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses\r
+        End Sub\r
+        \r
+        <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _\r
+        Protected Overrides Sub OnCreateMainForm()\r
+            Me.MainForm = Global.DNSServiceBrowser.VB.DNSServiceBrowser\r
+        End Sub\r
+    End Class\r
+End Namespace\r
diff --git a/Clients/DNSServiceBrowser.VB/My Project/Application.myapp b/Clients/DNSServiceBrowser.VB/My Project/Application.myapp
new file mode 100644 (file)
index 0000000..85cb2c9
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">\r
+  <MySubMain>true</MySubMain>\r
+  <MainForm>DNSServiceBrowser</MainForm>\r
+  <SingleInstance>false</SingleInstance>\r
+  <ShutdownMode>0</ShutdownMode>\r
+  <EnableVisualStyles>true</EnableVisualStyles>\r
+  <AuthenticationMode>0</AuthenticationMode>\r
+  <SaveMySettingsOnExit>true</SaveMySettingsOnExit>\r
+</MyApplicationData>
\ No newline at end of file
diff --git a/Clients/DNSServiceBrowser.VB/My Project/AssemblyInfo.vb b/Clients/DNSServiceBrowser.VB/My Project/AssemblyInfo.vb
new file mode 100644 (file)
index 0000000..32fd3b7
--- /dev/null
@@ -0,0 +1,35 @@
+Imports System\r
+Imports System.Reflection\r
+Imports System.Runtime.InteropServices\r
+\r
+' General Information about an assembly is controlled through the following \r
+' set of attributes. Change these attribute values to modify the information\r
+' associated with an assembly.\r
+\r
+' Review the values of the assembly attributes\r
+\r
+<Assembly: AssemblyTitle("VBTester")> \r
+<Assembly: AssemblyDescription("")> \r
+<Assembly: AssemblyCompany("Porchdog Software, Inc.")> \r
+<Assembly: AssemblyProduct("VBTester")> \r
+<Assembly: AssemblyCopyright("Copyright © Porchdog Software, Inc. 2009")> \r
+<Assembly: AssemblyTrademark("")> \r
+\r
+<Assembly: ComVisible(False)>\r
+\r
+'The following GUID is for the ID of the typelib if this project is exposed to COM\r
+<Assembly: Guid("fa682747-1bdc-4ddb-962e-e3e3a9291b22")> \r
+\r
+' Version information for an assembly consists of the following four values:\r
+'\r
+'      Major Version\r
+'      Minor Version \r
+'      Build Number\r
+'      Revision\r
+'\r
+' You can specify all the values or you can default the Build and Revision Numbers \r
+' by using the '*' as shown below:\r
+' <Assembly: AssemblyVersion("1.0.*")> \r
+\r
+<Assembly: AssemblyVersion("1.0.0.0")> \r
+<Assembly: AssemblyFileVersion("1.0.0.0")> \r
diff --git a/Clients/DNSServiceBrowser.VB/My Project/Resources.Designer.vb b/Clients/DNSServiceBrowser.VB/My Project/Resources.Designer.vb
new file mode 100644 (file)
index 0000000..1f3f960
--- /dev/null
@@ -0,0 +1,62 @@
+'------------------------------------------------------------------------------\r
+' <auto-generated>\r
+'     This code was generated by a tool.\r
+'     Runtime Version:2.0.50727.3082\r
+'\r
+'     Changes to this file may cause incorrect behavior and will be lost if\r
+'     the code is regenerated.\r
+' </auto-generated>\r
+'------------------------------------------------------------------------------\r
+\r
+Option Strict On\r
+Option Explicit On\r
+\r
+\r
+Namespace My.Resources\r
+    \r
+    'This class was auto-generated by the StronglyTypedResourceBuilder\r
+    'class via a tool like ResGen or Visual Studio.\r
+    'To add or remove a member, edit your .ResX file then rerun ResGen\r
+    'with the /str option, or rebuild your VS project.\r
+    '<summary>\r
+    '  A strongly-typed resource class, for looking up localized strings, etc.\r
+    '</summary>\r
+    <Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0"),  _\r
+     Global.System.Diagnostics.DebuggerNonUserCodeAttribute(),  _\r
+     Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(),  _\r
+     Global.Microsoft.VisualBasic.HideModuleNameAttribute()>  _\r
+    Friend Module Resources\r
+        \r
+        Private resourceMan As Global.System.Resources.ResourceManager\r
+        \r
+        Private resourceCulture As Global.System.Globalization.CultureInfo\r
+        \r
+        '<summary>\r
+        '  Returns the cached ResourceManager instance used by this class.\r
+        '</summary>\r
+        <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)>  _\r
+        Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager\r
+            Get\r
+                If Object.ReferenceEquals(resourceMan, Nothing) Then\r
+                    Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("VBTester.Resources", GetType(Resources).Assembly)\r
+                    resourceMan = temp\r
+                End If\r
+                Return resourceMan\r
+            End Get\r
+        End Property\r
+        \r
+        '<summary>\r
+        '  Overrides the current thread's CurrentUICulture property for all\r
+        '  resource lookups using this strongly typed resource class.\r
+        '</summary>\r
+        <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)>  _\r
+        Friend Property Culture() As Global.System.Globalization.CultureInfo\r
+            Get\r
+                Return resourceCulture\r
+            End Get\r
+            Set(ByVal value As Global.System.Globalization.CultureInfo)\r
+                resourceCulture = value\r
+            End Set\r
+        End Property\r
+    End Module\r
+End Namespace\r
diff --git a/Clients/DNSServiceBrowser.VB/My Project/Resources.resx b/Clients/DNSServiceBrowser.VB/My Project/Resources.resx
new file mode 100644 (file)
index 0000000..ffecec8
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<root>\r
+  <!-- \r
+    Microsoft ResX Schema \r
+    \r
+    Version 2.0\r
+    \r
+    The primary goals of this format is to allow a simple XML format \r
+    that is mostly human readable. The generation and parsing of the \r
+    various data types are done through the TypeConverter classes \r
+    associated with the data types.\r
+    \r
+    Example:\r
+    \r
+    ... ado.net/XML headers & schema ...\r
+    <resheader name="resmimetype">text/microsoft-resx</resheader>\r
+    <resheader name="version">2.0</resheader>\r
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\r
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\r
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>\r
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>\r
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">\r
+        <value>[base64 mime encoded serialized .NET Framework object]</value>\r
+    </data>\r
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">\r
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\r
+        <comment>This is a comment</comment>\r
+    </data>\r
+                \r
+    There are any number of "resheader" rows that contain simple \r
+    name/value pairs.\r
+    \r
+    Each data row contains a name, and value. The row also contains a \r
+    type or mimetype. Type corresponds to a .NET class that support \r
+    text/value conversion through the TypeConverter architecture. \r
+    Classes that don't support this are serialized and stored with the \r
+    mimetype set.\r
+    \r
+    The mimetype is used for serialized objects, and tells the \r
+    ResXResourceReader how to depersist the object. This is currently not \r
+    extensible. For a given mimetype the value must be set accordingly:\r
+    \r
+    Note - application/x-microsoft.net.object.binary.base64 is the format \r
+    that the ResXResourceWriter will generate, however the reader can \r
+    read any of the formats listed below.\r
+    \r
+    mimetype: application/x-microsoft.net.object.binary.base64\r
+    value   : The object must be serialized with \r
+            : System.Serialization.Formatters.Binary.BinaryFormatter\r
+            : and then encoded with base64 encoding.\r
+    \r
+    mimetype: application/x-microsoft.net.object.soap.base64\r
+    value   : The object must be serialized with \r
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\r
+            : and then encoded with base64 encoding.\r
+\r
+    mimetype: application/x-microsoft.net.object.bytearray.base64\r
+    value   : The object must be serialized into a byte array \r
+            : using a System.ComponentModel.TypeConverter\r
+            : and then encoded with base64 encoding.\r
+    -->\r
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
+    <xsd:element name="root" msdata:IsDataSet="true">\r
+      <xsd:complexType>\r
+        <xsd:choice maxOccurs="unbounded">\r
+          <xsd:element name="metadata">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+              <xsd:attribute name="type" type="xsd:string" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="assembly">\r
+            <xsd:complexType>\r
+              <xsd:attribute name="alias" type="xsd:string" />\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="data">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />\r
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="resheader">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" use="required" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+        </xsd:choice>\r
+      </xsd:complexType>\r
+    </xsd:element>\r
+  </xsd:schema>\r
+  <resheader name="resmimetype">\r
+    <value>text/microsoft-resx</value>\r
+  </resheader>\r
+  <resheader name="version">\r
+    <value>2.0</value>\r
+  </resheader>\r
+  <resheader name="reader">\r
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+  <resheader name="writer">\r
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+</root>
\ No newline at end of file
diff --git a/Clients/DNSServiceBrowser.VB/My Project/Settings.Designer.vb b/Clients/DNSServiceBrowser.VB/My Project/Settings.Designer.vb
new file mode 100644 (file)
index 0000000..a8c1536
--- /dev/null
@@ -0,0 +1,73 @@
+'------------------------------------------------------------------------------\r
+' <auto-generated>\r
+'     This code was generated by a tool.\r
+'     Runtime Version:2.0.50727.3082\r
+'\r
+'     Changes to this file may cause incorrect behavior and will be lost if\r
+'     the code is regenerated.\r
+' </auto-generated>\r
+'------------------------------------------------------------------------------\r
+\r
+Option Strict On\r
+Option Explicit On\r
+\r
+\r
+Namespace My\r
+\r
+    <Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(),  _\r
+     Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0"),  _\r
+     Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)>  _\r
+    Partial Friend NotInheritable Class MySettings\r
+        Inherits Global.System.Configuration.ApplicationSettingsBase\r
+        \r
+        Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)\r
+        \r
+#Region "My.Settings Auto-Save Functionality"\r
+#If _MyType = "WindowsForms" Then\r
+        Private Shared addedHandler As Boolean\r
+\r
+        Private Shared addedHandlerLockObject As New Object\r
+\r
+        <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _\r
+        Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)\r
+            If My.Application.SaveMySettingsOnExit Then\r
+                My.Settings.Save()\r
+            End If\r
+        End Sub\r
+#End If\r
+#End Region\r
+        \r
+        Public Shared ReadOnly Property [Default]() As MySettings\r
+            Get\r
+                \r
+#If _MyType = "WindowsForms" Then\r
+                   If Not addedHandler Then\r
+                        SyncLock addedHandlerLockObject\r
+                            If Not addedHandler Then\r
+                                AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings\r
+                                addedHandler = True\r
+                            End If\r
+                        End SyncLock\r
+                    End If\r
+#End If\r
+                Return defaultInstance\r
+            End Get\r
+        End Property\r
+    End Class\r
+End Namespace\r
+\r
+Namespace My\r
+    \r
+    <Global.Microsoft.VisualBasic.HideModuleNameAttribute(),  _\r
+     Global.System.Diagnostics.DebuggerNonUserCodeAttribute(),  _\r
+     Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()>  _\r
+    Friend Module MySettingsProperty\r
+        \r
+        <Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _\r
+        Friend ReadOnly Property Settings() As Global.DNSServiceBrowser.VB.My.MySettings\r
+            Get\r
+                Return Global.DNSServiceBrowser.VB.My.MySettings.Default\r
+            End Get\r
+        End Property\r
+    End Module\r
+End Namespace\r
diff --git a/Clients/DNSServiceBrowser.VB/My Project/Settings.settings b/Clients/DNSServiceBrowser.VB/My Project/Settings.settings
new file mode 100644 (file)
index 0000000..377f56d
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>\r
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">\r
+  <Profiles>\r
+    <Profile Name="(Default)" />\r
+  </Profiles>\r
+  <Settings />\r
+</SettingsFile>\r
index 783a9ced70ef3744c5cd08ac1fa78fcb50f7ddd0..4a63f2c25d4888852645ad575062e226c612fdf2 100644 (file)
@@ -4,6 +4,7 @@
 #include "stdafx.h"
 #include "ExplorerPlugin.h"
 #include "About.h"
+#include "WinVersRes.h"
 #include <DebugServices.h>
 
 
@@ -48,6 +49,14 @@ CAbout::OnInitDialog()
                control->SetBitmap( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_ABOUT ) ) );
        }
 
+       control = ( CStatic* ) GetDlgItem( IDC_COMPONENT_VERSION );
+       check( control );
+
+       if ( control )
+       {
+               control->SetWindowText( TEXT( MASTER_PROD_VERS_STR2 ) );
+       }
+
        return b;
 }
 
index f09d9833492ca27bf8ff2f08e0b41a18115dbfe1..3aea9a299561b7e467fffc58277f52bfcf70de5d 100644 (file)
     Change History (most recent first):
     
 $Log: ExplorerBar.cpp,v $
+Revision 1.5  2009/03/30 18:44:53  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.4  2006/08/14 23:24:00  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -588,7 +592,7 @@ STDMETHODIMP  ExplorerBar::QueryContextMenu(HMENU hShellContextMenu, UINT iConte
 //===========================================================================================================================
 
 // Not called for explorer bars
-STDMETHODIMP ExplorerBar::GetCommandString(UINT idCmd, UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax)
+STDMETHODIMP ExplorerBar::GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax)
 {
        DEBUG_UNUSED( idCmd );
        DEBUG_UNUSED( uType );
index 5af86eb08646a2862fab43c1e1cd539170a4ef75..988f8c3977d400612949a9966baf030cfea28a33 100644 (file)
     Change History (most recent first):
     
 $Log: ExplorerBar.h,v $
+Revision 1.4  2009/03/30 18:46:13  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.3  2006/08/14 23:24:00  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -108,7 +112,7 @@ class       ExplorerBar : public IDeskBand,
                // IContextMenu methods
    
                STDMETHOD( QueryContextMenu )( HMENU hContextMenu, UINT iContextMenuFirstItem, UINT idCmdFirst, UINT idCmdLast, UINT uFlags );
-               STDMETHOD( GetCommandString )( UINT idCmd, UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax );
+               STDMETHOD( GetCommandString )( UINT_PTR idCmd, UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax );
                STDMETHOD( InvokeCommand )( LPCMINVOKECOMMANDINFO lpici );
 
                // Other
index 88f4858f86ad220c03660ec29ce065a309eef52b..7b5b2ea401070dbae06902e4c46bb727fe993747 100644 (file)
     Change History (most recent first):
     
 $Log: ExplorerBarWindow.cpp,v $
+Revision 1.23  2009/03/30 18:47:40  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.22  2006/08/14 23:24:00  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -381,7 +385,7 @@ exit:
 //     OnServiceEvent
 //===========================================================================================================================
 
-LONG
+LRESULT
 ExplorerBarWindow::OnServiceEvent(WPARAM inWParam, LPARAM inLParam)
 {
        if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
@@ -472,13 +476,13 @@ void DNSSD_API
                err = UTF8StringToStringObject( inName, service->displayName );
                check_noerr( err );
 
-               service->name = strdup( inName );
+               service->name = _strdup( inName );
                require_action( service->name, exit, err = kNoMemoryErr );
                
-               service->type = strdup( inType );
+               service->type = _strdup( inType );
                require_action( service->type, exit, err = kNoMemoryErr );
                
-               service->domain = strdup( inDomain );
+               service->domain = _strdup( inDomain );
                require_action( service->domain, exit, err = kNoMemoryErr );
                
                service->ifi            = inInterfaceIndex;
index f035872d880c63b52b7a45a53cd77113e5008004..0bbbcae1b25c2eec44e99d6bd7879348988df62a 100644 (file)
     Change History (most recent first):
     
 $Log: ExplorerBarWindow.h,v $
+Revision 1.9  2009/03/30 18:49:15  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.8  2006/08/14 23:24:00  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -242,7 +246,7 @@ class       ExplorerBarWindow : public CWnd
                afx_msg void    OnDestroy( void );
                afx_msg void    OnSize( UINT inType, int inX, int inY );
                afx_msg void    OnDoubleClick( NMHDR *inNMHDR, LRESULT *outResult );
-               afx_msg LONG    OnServiceEvent( WPARAM inWParam, LPARAM inLParam );
+               afx_msg LRESULT OnServiceEvent( WPARAM inWParam, LPARAM inLParam );
                
                // Browsing
                
index c2c661b0a849f8ec8db36c68713d8858430d5eed..b83dac843a0a3856374f3efc54c2d757aaa1ded6 100644 (file)
     Change History (most recent first):
     
 $Log: ExplorerPlugin.cpp,v $
+Revision 1.10  2009/03/30 18:51:04  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.9  2006/08/14 23:24:00  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -90,16 +94,6 @@ static char THIS_FILE[] = __FILE__;
 //     Prototypes
 //===========================================================================================================================
 
-// DLL Exports
-
-extern "C" BOOL WINAPI DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved );
-
-// MFC Support
-
-DEBUG_LOCAL OSStatus   MFCDLLProcessAttach( HINSTANCE inInstance );
-DEBUG_LOCAL void               MFCDLLProcessDetach( HINSTANCE inInstance );
-DEBUG_LOCAL void               MFCDLLThreadDetach( HINSTANCE inInstance );
-
 // Utilities
 
 DEBUG_LOCAL OSStatus   RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName );
@@ -141,9 +135,9 @@ DEFINE_GUID(CLSID_CompCatCacheDaemon,
 //     Globals
 //===========================================================================================================================
 
-HINSTANCE              gInstance               = NULL;
-int                            gDLLRefCount    = 0;
-CWinApp                        gApp;
+HINSTANCE                      gInstance               = NULL;
+int                                    gDLLRefCount    = 0;
+CExplorerPluginApp     gApp;
 
 #if 0
 #pragma mark -
@@ -151,53 +145,83 @@ CWinApp                   gApp;
 #endif
 
 //===========================================================================================================================
-//     DllMain
+//     CExplorerPluginApp::CExplorerPluginApp
 //===========================================================================================================================
 
-BOOL WINAPI    DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved )
+IMPLEMENT_DYNAMIC(CExplorerPluginApp, CWinApp);
+
+CExplorerPluginApp::CExplorerPluginApp()
 {
-       BOOL                    ok;
-       OSStatus                err;
-       
-       DEBUG_UNUSED( inReserved );
-       
-       ok = TRUE;
-       switch( inReason )
-       {
-               case DLL_PROCESS_ATTACH:
-                       gInstance = inInstance;
-                       debug_initialize( kDebugOutputTypeWindowsEventLog, "DNSServices Bar", inInstance );
-                       debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
-                       dlog( kDebugLevelTrace, "\nDllMain: process attach\n" );
-                       
-                       err = MFCDLLProcessAttach( inInstance );
-                       ok = ( err == kNoErr );
-                       require_noerr( err, exit );
-                       break;
-               
-               case DLL_PROCESS_DETACH:
-                       dlog( kDebugLevelTrace, "DllMain: process detach\n" );
-                       MFCDLLProcessDetach( inInstance );
-                       break;
-               
-               case DLL_THREAD_ATTACH:
-                       dlog( kDebugLevelTrace, "DllMain: thread attach\n" );
-                       break;
-               
-               case DLL_THREAD_DETACH:
-                       dlog( kDebugLevelTrace, "DllMain: thread detach\n" );
-                       MFCDLLThreadDetach( inInstance );
-                       break;
-               
-               default:
-                       dlog( kDebugLevelTrace, "DllMain: unknown reason code (%d)\n",inReason );
-                       break;
-       }
-       
+}
+
+
+//===========================================================================================================================
+//     CExplorerPluginApp::~CExplorerPluginApp
+//===========================================================================================================================
+
+CExplorerPluginApp::~CExplorerPluginApp()
+{
+}
+
+
+//===========================================================================================================================
+//     CExplorerPluginApp::InitInstance
+//===========================================================================================================================
+
+BOOL
+CExplorerPluginApp::InitInstance()
+{
+       wchar_t                                 resource[MAX_PATH];
+       OSStatus                                err;
+       int                                             res;
+       HINSTANCE inInstance;
+
+       inInstance = AfxGetInstanceHandle();
+       gInstance = inInstance;
+
+       debug_initialize( kDebugOutputTypeWindowsEventLog, "DNSServices Bar", inInstance );
+       debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
+       dlog( kDebugLevelTrace, "\nCCPApp::InitInstance\n" );
+
+       res = PathForResource( inInstance, L"ExplorerPluginResources.dll", resource, MAX_PATH );
+
+       err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
+       require_noerr( err, exit );
+
+       g_nonLocalizedResources = LoadLibrary( resource );
+       translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       g_nonLocalizedResourcesName = resource;
+
+       res = PathForResource( inInstance, L"ExplorerPluginLocalized.dll", resource, MAX_PATH );
+       err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
+       require_noerr( err, exit );
+
+       g_localizedResources = LoadLibrary( resource );
+       translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       AfxSetResourceHandle( g_localizedResources );
+
 exit:
-       return( ok );
+
+       return TRUE;
+}
+
+
+//===========================================================================================================================
+//     CExplorerPluginApp::ExitInstance
+//===========================================================================================================================
+
+int
+CExplorerPluginApp::ExitInstance()
+{
+       return 0;
 }
 
+
+
 //===========================================================================================================================
 //     DllCanUnloadNow
 //===========================================================================================================================
@@ -305,142 +329,6 @@ exit:
        return( err );
 }
 
-#if 0
-#pragma mark -
-#pragma mark == MFC Support ==
-#endif
-
-//===========================================================================================================================
-//     MFCDLLProcessAttach
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus   MFCDLLProcessAttach( HINSTANCE inInstance )
-{
-       wchar_t                                 resource[MAX_PATH];
-       OSStatus                                err;
-       _AFX_THREAD_STATE *             threadState;
-       AFX_MODULE_STATE *              previousModuleState;
-       BOOL                                    ok;
-       int                                             res;
-       CWinApp *                               app;
-       
-       app = NULL;
-       
-       // Simulate what is done in dllmodul.cpp.
-       
-       threadState = AfxGetThreadState();
-       check( threadState );
-       previousModuleState = threadState->m_pPrevModuleState;
-       
-       ok = AfxWinInit( inInstance, NULL, TEXT( "" ), 0 );
-       require_action( ok, exit, err = kUnknownErr );
-       
-       app = AfxGetApp();
-       require_action( ok, exit, err = kNotInitializedErr );
-       
-       // Before we load the resources, let's load the error string
-
-       // errorMessage.LoadString( IDS_REINSTALL );
-       // errorCaption.LoadString( IDS_REINSTALL_CAPTION );
-
-       // Load Resources
-
-       res = PathForResource( inInstance, L"ExplorerPluginResources.dll", resource, MAX_PATH );
-
-       err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
-       require_noerr( err, exit );
-
-       g_nonLocalizedResources = LoadLibrary( resource );
-       translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
-       require_noerr( err, exit );
-
-       g_nonLocalizedResourcesName = resource;
-
-       res = PathForResource( inInstance, L"ExplorerPluginLocalized.dll", resource, MAX_PATH );
-       err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
-       require_noerr( err, exit );
-
-       g_localizedResources = LoadLibrary( resource );
-       translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
-       require_noerr( err, exit );
-
-       AfxSetResourceHandle( g_localizedResources );
-
-       ok = app->InitInstance();
-       require_action( ok, exit, err = kUnknownErr );
-       
-       threadState->m_pPrevModuleState = previousModuleState;
-       threadState = NULL;
-       AfxInitLocalData( inInstance );
-       err = kNoErr;
-       
-exit:
-       if( err )
-       {
-               if( app )
-               {
-                       app->ExitInstance();
-               }
-               AfxWinTerm();
-       }
-       if( threadState )
-       {
-               threadState->m_pPrevModuleState = previousModuleState;
-       }
-       return( err );
-}
-
-//===========================================================================================================================
-//     MFCDLLProcessDetach
-//===========================================================================================================================
-
-DEBUG_LOCAL void       MFCDLLProcessDetach( HINSTANCE inInstance )
-{
-       CWinApp *               app;
-
-       // Simulate what is done in dllmodul.cpp.
-       
-       app = AfxGetApp();
-       if( app )
-       {
-               app->ExitInstance();
-       }
-
-#if( DEBUG )
-       if( AfxGetModuleThreadState()->m_nTempMapLock != 0 )
-       {
-               dlog( kDebugLevelWarning, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock );
-       }
-#endif
-       
-       AfxLockTempMaps();
-       AfxUnlockTempMaps( -1 );
-
-       // Terminate the library before destructors are called.
-       
-       AfxWinTerm();
-       AfxTermLocalData( inInstance, TRUE );
-}
-
-//===========================================================================================================================
-//     MFCDLLFinalize
-//===========================================================================================================================
-
-DEBUG_LOCAL void       MFCDLLThreadDetach( HINSTANCE inInstance )
-{
-       // Simulate what is done in dllmodul.cpp.
-       
-#if( DEBUG )
-       if( AfxGetModuleThreadState()->m_nTempMapLock != 0 )
-       {
-               dlog( kDebugLevelWarning, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock );
-       }
-#endif
-       
-       AfxLockTempMaps();
-       AfxUnlockTempMaps( -1 );
-       AfxTermThread( inInstance );
-}
 
 #if 0
 #pragma mark -
index d14edd3fb66fa7d06133a000c5146b64faff7c30..307c99a57999ee03a6a26ecb0d4174fca84880b8 100644 (file)
     Change History (most recent first):
     
 $Log: ExplorerPlugin.h,v $
+Revision 1.5  2009/03/30 18:52:02  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.4  2006/08/14 23:24:00  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -34,6 +38,8 @@ Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within
 
 */
 
+#pragma once
+
 //===========================================================================================================================
 //     Globals
 //===========================================================================================================================
@@ -47,3 +53,18 @@ extern int                           gDLLRefCount;
 extern HINSTANCE               GetNonLocalizedResources();
 extern HINSTANCE               GetLocalizedResources();
 
+
+class CExplorerPluginApp : public CWinApp
+{
+public:
+
+       CExplorerPluginApp();
+       virtual ~CExplorerPluginApp();
+
+protected:
+
+       virtual BOOL    InitInstance();
+       virtual int     ExitInstance();
+
+       DECLARE_DYNAMIC(CExplorerPluginApp);
+};
index 6a5c4fc17dcc37bf1aea097c9505f9909aa0c7fc..78e74436c44aab24ee9d444ec74bbfcf5cb7e555 100644 (file)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="ExplorerPlugin"\r
        ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
-       SccProjectName=""\r
-       SccLocalPath="">\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
-                       CharacterSet="1">\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                               Description=""\r
+                               CommandLine=""\r
+                               Outputs=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0501"\r
-                               StringPooling="TRUE"\r
+                               PreprocessorDefinitions="_USRDLL;WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0501;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="1"\r
-                               ForceConformanceInForLoopScope="TRUE"\r
+                               BufferSecurityCheck="true"\r
+                               ForceConformanceInForLoopScope="true"\r
                                UsePrecompiledHeader="0"\r
                                PrecompiledHeaderFile=""\r
-                               AssemblerListingLocation=".\Debug/"\r
-                               ObjectFile=".\Debug/"\r
-                               ProgramDataBaseFileName=".\Debug/"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
                                BrowseInformation="1"\r
                                WarningLevel="4"\r
-                               WarnAsError="FALSE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                                CallingConvention="2"\r
-                               CompileAs="0"/>\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"\r
-                               Description="Registering"\r
-                               CommandLine="regsvr32.exe /s /c $(OutDir)/ExplorerPlugin.dll\r
-"\r
-                               Outputs="$(OUTDIR)\Register.out"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
-                               AdditionalDependencies="../../mDNSWindows/DLL/Debug/dnssd.lib uafxcwd.lib ws2_32.lib"\r
+                               AdditionalOptions="/MACHINE:I386 /IGNORE:4089 /NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib uafxcwd.lib ws2_32.lib"\r
                                OutputFile="$(OutDir)/ExplorerPlugin.dll"\r
                                LinkIncremental="1"\r
-                               SuppressStartupBanner="TRUE"\r
+                               SuppressStartupBanner="true"\r
                                IgnoreDefaultLibraryNames="uafxcwd.lib"\r
                                ModuleDefinitionFile="./$(ProjectName).def"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
                                SubSystem="2"\r
-                               ImportLibrary="$(OutDir)/$(ProjectName).lib"/>\r
+                               ImportLibrary="$(OutDir)/$(ProjectName).lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ExplorerPlugin.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                               Description=""\r
+                               CommandLine=""\r
+                               Outputs=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
-                               MkTypLibCompatible="TRUE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               TargetEnvironment="1"\r
-                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="_USRDLL;WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0501;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               BufferSecurityCheck="true"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderFile=""\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
+                               BrowseInformation="1"\r
+                               WarningLevel="4"\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/IGNORE:4089 /NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib uafxcwd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/ExplorerPlugin.dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreDefaultLibraryNames="uafxcwd.lib"\r
+                               ModuleDefinitionFile="./$(ProjectName).def"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               ImportLibrary="$(OutDir)/$(ProjectName).lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ExplorerPlugin64.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
-                       CharacterSet="1">\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                               Description=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
-                               GlobalOptimizations="TRUE"\r
                                InlineFunctionExpansion="2"\r
                                FavorSizeOrSpeed="2"\r
-                               OmitFramePointers="TRUE"\r
+                               OmitFramePointers="true"\r
                                AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0501"\r
-                               StringPooling="TRUE"\r
+                               PreprocessorDefinitions="_USRDLL;WIN32;NDEBUG;_WINDOWS;WINVER=0x0501;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
                                RuntimeLibrary="0"\r
-                               BufferSecurityCheck="FALSE"\r
-                               EnableFunctionLevelLinking="FALSE"\r
-                               ForceConformanceInForLoopScope="TRUE"\r
+                               BufferSecurityCheck="true"\r
+                               EnableFunctionLevelLinking="false"\r
+                               ForceConformanceInForLoopScope="true"\r
                                UsePrecompiledHeader="0"\r
                                PrecompiledHeaderFile=""\r
-                               AssemblerListingLocation=".\Release/"\r
-                               ObjectFile=".\Release/"\r
-                               ProgramDataBaseFileName=".\Release/"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
                                BrowseInformation="1"\r
                                WarningLevel="4"\r
-                               WarnAsError="FALSE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               CompileAs="0"/>\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
-                               AdditionalDependencies="../../mDNSWindows/DLL/Release/dnssd.lib ws2_32.lib uafxcw.lib"\r
+                               AdditionalOptions="/MACHINE:I386 /IGNORE:4089 /NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib uafxcw.lib"\r
                                OutputFile="$(OutDir)/$(ProjectName).dll"\r
                                LinkIncremental="1"\r
-                               SuppressStartupBanner="TRUE"\r
+                               SuppressStartupBanner="true"\r
                                IgnoreDefaultLibraryNames="uafxcw.lib"\r
                                ModuleDefinitionFile="./$(ProjectName).def"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
                                SubSystem="2"\r
                                OptimizeReferences="0"\r
                                EnableCOMDATFolding="0"\r
-                               ImportLibrary="$(IntDir)/$(ProjectName).lib"/>\r
+                               ImportLibrary="$(IntDir)/$(ProjectName).lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ExplorerPlugin.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                  &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                               Description=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
-                               MkTypLibCompatible="TRUE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               TargetEnvironment="1"\r
-                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="2"\r
+                               FavorSizeOrSpeed="2"\r
+                               OmitFramePointers="true"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="_USRDLL;WIN32;NDEBUG;_WINDOWS;WINVER=0x0501;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               BufferSecurityCheck="true"\r
+                               EnableFunctionLevelLinking="false"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderFile=""\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
+                               BrowseInformation="1"\r
+                               WarningLevel="4"\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/IGNORE:4089 /NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib uafxcw.lib"\r
+                               OutputFile="$(OutDir)/$(ProjectName).dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreDefaultLibraryNames="uafxcw.lib"\r
+                               ModuleDefinitionFile="./$(ProjectName).def"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="0"\r
+                               EnableCOMDATFolding="0"\r
+                               ImportLibrary="$(IntDir)/$(ProjectName).lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ExplorerPlugin64.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                  &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
        <Files>\r
                <Filter\r
                        Name="Support"\r
-                       Filter="">\r
+                       >\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\CommonServices.h">\r
+                               RelativePath="..\..\mDNSShared\CommonServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.c">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.h">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\isocode.h">\r
+                               RelativePath="..\..\mDNSWindows\isocode.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\loclibrary.c">\r
+                               RelativePath="..\..\mDNSWindows\loclibrary.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\loclibrary.h">\r
+                               RelativePath="..\..\mDNSWindows\loclibrary.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\WinServices.cpp">\r
+                               RelativePath="..\..\mDNSWindows\WinServices.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\WinServices.h">\r
+                               RelativePath="..\..\mDNSWindows\WinServices.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Source Files"\r
-                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"\r
+                       >\r
                        <File\r
-                               RelativePath="About.cpp">\r
+                               RelativePath="About.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ClassFactory.cpp">\r
+                               RelativePath="ClassFactory.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ExplorerBar.cpp">\r
+                               RelativePath="ExplorerBar.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ExplorerBarWindow.cpp">\r
+                               RelativePath="ExplorerBarWindow.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ExplorerPlugin.cpp">\r
+                               RelativePath="ExplorerPlugin.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ExplorerPlugin.def">\r
+                               RelativePath="ExplorerPlugin.def"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="LoginDialog.cpp">\r
+                               RelativePath="LoginDialog.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="StdAfx.cpp">\r
+                               RelativePath="StdAfx.cpp"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
-                       Filter="h;hpp;hxx;hm;inl;inc">\r
+                       Filter="h;hpp;hxx;hm;inl;inc"\r
+                       >\r
                        <File\r
-                               RelativePath=".\About.h">\r
+                               RelativePath=".\About.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ClassFactory.h">\r
+                               RelativePath="ClassFactory.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ExplorerBar.h">\r
+                               RelativePath="ExplorerBar.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ExplorerBarWindow.h">\r
+                               RelativePath="ExplorerBarWindow.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ExplorerPlugin.h">\r
+                               RelativePath="ExplorerPlugin.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="LoginDialog.h">\r
+                               RelativePath="LoginDialog.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="Resource.h">\r
+                               RelativePath="Resource.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="resource_dll.h">\r
+                               RelativePath="resource_dll.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="StdAfx.h">\r
+                               RelativePath="StdAfx.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest"\r
+                       >\r
                        <File\r
-                               RelativePath="ExplorerPlugin.rc">\r
+                               RelativePath="ExplorerPlugin.rc"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r
        <Globals>\r
                <Global\r
                        Name="RESOURCE_FILE"\r
-                       Value="ExplorerPlugin.rc"/>\r
+                       Value="ExplorerPlugin.rc"\r
+               />\r
        </Globals>\r
 </VisualStudioProject>\r
index 4d741871b5f68dc728af61abbbcad417bba75354..b17cf3bfb98c5dd4a0b158bcb6ebb55f60267814 100755 (executable)
@@ -126,9 +126,11 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN\r
     CONTROL         "",IDC_ABOUT_BACKGROUND,"Static",SS_BITMAP | SS_REALSIZEIMAGE,0,0,\r
                     220,86\r
-    CONTROL         MASTER_PROD_VERS_STR3,IDC_COMPONENT,"Static",\r
+    CONTROL         "Explorer Plugin",IDC_COMPONENT,"Static",\r
                     SS_SIMPLE | WS_GROUP,92,10,122,8\r
-    LTEXT           "Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved. Apple and the Apple logo are trademarks of Apple Computer, Inc., registered in the U.S. and other countries.",\r
+    CONTROL         "",IDC_COMPONENT_VERSION,"Static",\r
+                    SS_SIMPLE | WS_GROUP,142,10,122,8\r
+    LTEXT           "Copyright (c) 2004-2007 Apple Inc. All rights reserved. Apple and the Apple logo are trademarks of Apple Inc., registered in the U.S. and other countries.",\r
                     IDC_LEGAL,92,31,123,50,0,WS_EX_RTLREADING\r
 END\r
 \r
@@ -181,7 +183,7 @@ BEGIN
     IDS_NAME                "Bonjour"\r
     IDS_WEB_SITES           "Web Sites"\r
     IDS_PRINTERS            "Printers"\r
-    IDS_MDNSRESPONDER_NOT_AVAILABLE "Bonjour Service Not Available"\r
+    IDS_MDNSRESPONDER_NOT_AVAILABLE "Bonjour Service is not available."\r
     IDS_FIREWALL            "Check firewall settings"\r
 END\r
 \r
index 71e630e01da2c4f90d699dec95da3b02417d4971..54b03923593dc9b54fff8a3a42c4971710f646b2 100755 (executable)
@@ -1,33 +1,61 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="ExplorerPluginLocRes"\r
-       ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
-       SccProjectName=""\r
-       SccLocalPath="">\r
+       ProjectGUID="{1643427B-F226-4AD6-B413-97DA64D5C6B4}"\r
+       RootNamespace="ExplorerPluginLocRes"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug\ExplorerPlugin.Resources\en.lproj"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
-                       CharacterSet="1">\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="..\..\mDNSWindows"\r
                                PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0400"\r
-                               StringPooling="TRUE"\r
+                               StringPooling="true"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="1"\r
-                               ForceConformanceInForLoopScope="TRUE"\r
+                               ForceConformanceInForLoopScope="true"\r
                                UsePrecompiledHeader="0"\r
                                PrecompiledHeaderFile=""\r
                                AssemblerListingLocation=".\Debug/"\r
                                ProgramDataBaseFileName=".\Debug/"\r
                                BrowseInformation="1"\r
                                WarningLevel="4"\r
-                               WarnAsError="FALSE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                                CallingConvention="2"\r
-                               CompileAs="0"/>\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist $(OutDir)\ExplorerPlugin.Resources mkdir $(OutDir)\ExplorerPlugin.Resources&#x0D;&#x0A;if not exist $(OutDir)\ExplorerPlugin.Resources\en.lproj mkdir $(OutDir)\ExplorerPlugin.Resources\en.lproj&#x0D;&#x0A;"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
                                AdditionalDependencies=""\r
-                               OutputFile="$(OutDir)/ExplorerPluginLocalized.dll"\r
+                               OutputFile="$(OutDir)\ExplorerPlugin.Resources\en.lproj\ExplorerPluginLocalized.dll"\r
                                LinkIncremental="1"\r
-                               SuppressStartupBanner="TRUE"\r
+                               SuppressStartupBanner="true"\r
                                IgnoreDefaultLibraryNames=""\r
                                ModuleDefinitionFile=""\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
                                SubSystem="2"\r
-                               ResourceOnlyDLL="TRUE"\r
-                               ImportLibrary="$(OutDir)/$(ProjectName).lib"/>\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(OutDir)/$(ProjectName).lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
-                               MkTypLibCompatible="TRUE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               TargetEnvironment="1"\r
-                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0400"\r
+                               StringPooling="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderFile=""\r
+                               AssemblerListingLocation=".\Debug/"\r
+                               ObjectFile=".\Debug/"\r
+                               ProgramDataBaseFileName=".\Debug/"\r
+                               BrowseInformation="1"\r
+                               WarningLevel="4"\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
-                       <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                               Description="Building Output Directories"\r
-                               CommandLine="if not exist Debug\ExplorerPlugin.Resources mkdir Debug\ExplorerPlugin.Resources\r
-if not exist Debug\ExplorerPlugin.Resources\en.lproj mkdir Debug\ExplorerPlugin.Resources\en.lproj\r
-"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist $(OutDir)\ExplorerPlugin.Resources mkdir $(OutDir)\ExplorerPlugin.Resources&#x0D;&#x0A;if not exist $(OutDir)\ExplorerPlugin.Resources\en.lproj mkdir $(OutDir)\ExplorerPlugin.Resources\en.lproj&#x0D;&#x0A;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+                               AdditionalDependencies=""\r
+                               OutputFile="$(OutDir)\ExplorerPlugin.Resources\en.lproj\ExplorerPluginLocalized.dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreDefaultLibraryNames=""\r
+                               ModuleDefinitionFile=""\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(OutDir)/$(ProjectName).lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\ExplorerPlugin.Resources\en.lproj"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
-                       CharacterSet="1">\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
-                               GlobalOptimizations="TRUE"\r
                                InlineFunctionExpansion="2"\r
                                FavorSizeOrSpeed="2"\r
-                               OmitFramePointers="TRUE"\r
+                               OmitFramePointers="true"\r
                                AdditionalIncludeDirectories="..\..\mDNSWindows"\r
                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0400"\r
-                               StringPooling="TRUE"\r
+                               StringPooling="true"\r
                                RuntimeLibrary="0"\r
-                               BufferSecurityCheck="FALSE"\r
-                               EnableFunctionLevelLinking="FALSE"\r
-                               ForceConformanceInForLoopScope="TRUE"\r
+                               BufferSecurityCheck="false"\r
+                               EnableFunctionLevelLinking="false"\r
+                               ForceConformanceInForLoopScope="true"\r
                                UsePrecompiledHeader="0"\r
                                PrecompiledHeaderFile=""\r
                                AssemblerListingLocation=".\Release/"\r
@@ -119,60 +282,178 @@ if not exist Debug\ExplorerPlugin.Resources\en.lproj mkdir Debug\ExplorerPlugin.
                                ProgramDataBaseFileName=".\Release/"\r
                                BrowseInformation="1"\r
                                WarningLevel="4"\r
-                               WarnAsError="FALSE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               CompileAs="0"/>\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist $(OutDir)\ExplorerPlugin.Resources mkdir $(OutDir)\ExplorerPlugin.Resources&#x0D;&#x0A;if not exist $(OutDir)\ExplorerPlugin.Resources\en.lproj mkdir $(OutDir)\ExplorerPlugin.Resources\en.lproj&#x0D;&#x0A;"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
                                AdditionalDependencies=""\r
-                               OutputFile="$(OutDir)/ExplorerPluginLocalized.dll"\r
+                               OutputFile="$(OutDir)\ExplorerPlugin.Resources\en.lproj\ExplorerPluginLocalized.dll"\r
                                LinkIncremental="1"\r
-                               SuppressStartupBanner="TRUE"\r
+                               SuppressStartupBanner="true"\r
                                IgnoreDefaultLibraryNames=""\r
                                ModuleDefinitionFile=""\r
                                ProgramDatabaseFile=""\r
                                SubSystem="2"\r
                                OptimizeReferences="0"\r
                                EnableCOMDATFolding="0"\r
-                               ResourceOnlyDLL="TRUE"\r
-                               ImportLibrary="$(IntDir)/$(ProjectName).lib"/>\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(IntDir)/$(ProjectName).lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                                                                          &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj&quot;&#x0D;&#x0A;:END"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
-                               MkTypLibCompatible="TRUE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               TargetEnvironment="1"\r
-                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="2"\r
+                               FavorSizeOrSpeed="2"\r
+                               OmitFramePointers="true"\r
+                               AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0400"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               BufferSecurityCheck="false"\r
+                               EnableFunctionLevelLinking="false"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderFile=""\r
+                               AssemblerListingLocation=".\Release/"\r
+                               ObjectFile=".\Release/"\r
+                               ProgramDataBaseFileName=".\Release/"\r
+                               BrowseInformation="1"\r
+                               WarningLevel="4"\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                               Description="Building Output Directories"\r
-                               CommandLine="if not exist Release mkdir Release\r
-if not exist &quot;Release\ExplorerPlugin.Resources&quot; mkdir &quot;Release\ExplorerPlugin.Resources&quot;\r
-if not exist &quot;Release\ExplorerPlugin.Resources\en.lproj&quot; mkdir &quot;Release\ExplorerPlugin.Resources\en.lproj&quot;\r
-"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist $(OutDir)\ExplorerPlugin.Resources mkdir $(OutDir)\ExplorerPlugin.Resources&#x0D;&#x0A;if not exist $(OutDir)\ExplorerPlugin.Resources\en.lproj mkdir $(OutDir)\ExplorerPlugin.Resources\en.lproj&#x0D;&#x0A;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+                               AdditionalDependencies=""\r
+                               OutputFile="$(OutDir)\ExplorerPlugin.Resources\en.lproj\ExplorerPluginLocalized.dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreDefaultLibraryNames=""\r
+                               ModuleDefinitionFile=""\r
+                               ProgramDatabaseFile=""\r
+                               SubSystem="2"\r
+                               OptimizeReferences="0"\r
+                               EnableCOMDATFolding="0"\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(IntDir)/$(ProjectName).lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                                                                          &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj&quot;&#x0D;&#x0A;:END"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
@@ -180,22 +461,27 @@ if not exist &quot;Release\ExplorerPlugin.Resources\en.lproj&quot; mkdir &quot;R
        <Files>\r
                <Filter\r
                        Name="Header Files"\r
-                       Filter="h;hpp;hxx;hm;inl;inc">\r
+                       Filter="h;hpp;hxx;hm;inl;inc"\r
+                       >\r
                        <File\r
-                               RelativePath="resource_loc_res.h">\r
+                               RelativePath="resource_loc_res.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest"\r
+                       >\r
                        <File\r
-                               RelativePath="ExplorerPluginLocRes.rc">\r
+                               RelativePath="ExplorerPluginLocRes.rc"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r
        <Globals>\r
                <Global\r
                        Name="RESOURCE_FILE"\r
-                       Value="ExplorerPluginLocRes.rc"/>\r
+                       Value="ExplorerPluginLocRes.rc"\r
+               />\r
        </Globals>\r
 </VisualStudioProject>\r
index a0b83bb1176046926e68813e9bdc12c7f29ae19c..3c73311f1636cb9b884852e61b879150a2d7f559 100755 (executable)
@@ -1,33 +1,60 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="ExplorerPluginRes"\r
-       ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
-       SccProjectName=""\r
-       SccLocalPath="">\r
+       ProjectGUID="{871B1492-B4A4-4B57-9237-FA798484D7D7}"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug\ExplorerPlugin.Resources"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
-                       CharacterSet="1">\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="..\..\mDNSWindows"\r
                                PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0400"\r
-                               StringPooling="TRUE"\r
+                               StringPooling="true"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="1"\r
-                               ForceConformanceInForLoopScope="TRUE"\r
+                               ForceConformanceInForLoopScope="true"\r
                                UsePrecompiledHeader="0"\r
                                PrecompiledHeaderFile=""\r
                                AssemblerListingLocation=".\Debug/"\r
                                ProgramDataBaseFileName=".\Debug/"\r
                                BrowseInformation="1"\r
                                WarningLevel="4"\r
-                               WarnAsError="FALSE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                                CallingConvention="2"\r
-                               CompileAs="0"/>\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist Debug\ExplorerPlugin.Resources mkdir Debug\ExplorerPlugin.Resources"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
-                               OutputFile="$(OutDir)\ExplorerPluginResources.dll"\r
+                               OutputFile="$(OutDir)\ExplorerPlugin.Resources\ExplorerPluginResources.dll"\r
                                LinkIncremental="1"\r
-                               SuppressStartupBanner="TRUE"\r
+                               SuppressStartupBanner="true"\r
                                IgnoreDefaultLibraryNames=""\r
                                ModuleDefinitionFile=""\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
                                SubSystem="2"\r
-                               ResourceOnlyDLL="TRUE"\r
-                               ImportLibrary="$(OutDir)/$(ProjectName).lib"/>\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(OutDir)/$(ProjectName).lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
-                               MkTypLibCompatible="TRUE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               TargetEnvironment="1"\r
-                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
-                       <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0400"\r
+                               StringPooling="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderFile=""\r
+                               AssemblerListingLocation=".\Debug/"\r
+                               ObjectFile=".\Debug/"\r
+                               ProgramDataBaseFileName=".\Debug/"\r
+                               BrowseInformation="1"\r
+                               WarningLevel="4"\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                               Description="Building Output Directories"\r
-                               CommandLine="if not exist Debug\ExplorerPlugin.Resources mkdir Debug\ExplorerPlugin.Resources"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist Debug\ExplorerPlugin.Resources mkdir Debug\ExplorerPlugin.Resources"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+                               OutputFile="$(OutDir)\ExplorerPlugin.Resources\ExplorerPluginResources.dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreDefaultLibraryNames=""\r
+                               ModuleDefinitionFile=""\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(OutDir)/$(ProjectName).lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\ExplorerPlugin.Resources"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
-                       CharacterSet="1">\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
-                               GlobalOptimizations="TRUE"\r
                                InlineFunctionExpansion="2"\r
                                FavorSizeOrSpeed="2"\r
-                               OmitFramePointers="TRUE"\r
+                               OmitFramePointers="true"\r
                                AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0400"\r
-                               StringPooling="TRUE"\r
+                               StringPooling="true"\r
                                RuntimeLibrary="0"\r
-                               BufferSecurityCheck="FALSE"\r
-                               EnableFunctionLevelLinking="FALSE"\r
-                               ForceConformanceInForLoopScope="TRUE"\r
+                               BufferSecurityCheck="false"\r
+                               EnableFunctionLevelLinking="false"\r
+                               ForceConformanceInForLoopScope="true"\r
                                UsePrecompiledHeader="0"\r
                                PrecompiledHeaderFile=""\r
                                AssemblerListingLocation=".\Release/"\r
                                ProgramDataBaseFileName=".\Release/"\r
                                BrowseInformation="1"\r
                                WarningLevel="4"\r
-                               WarnAsError="FALSE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               CompileAs="0"/>\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist Release mkdir Release&#x0D;&#x0A;if not exist &quot;Release\ExplorerPlugin.Resources&quot; mkdir &quot;Release\ExplorerPlugin.Resources&quot;&#x0D;&#x0A;"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
-                               OutputFile="$(OutDir)\ExplorerPluginResources.dll"\r
+                               OutputFile="$(OutDir)\ExplorerPlugin.Resources\ExplorerPluginResources.dll"\r
                                LinkIncremental="1"\r
-                               SuppressStartupBanner="TRUE"\r
+                               SuppressStartupBanner="true"\r
                                IgnoreDefaultLibraryNames=""\r
                                ModuleDefinitionFile=""\r
                                ProgramDatabaseFile=""\r
                                SubSystem="2"\r
                                OptimizeReferences="0"\r
                                EnableCOMDATFolding="0"\r
-                               ResourceOnlyDLL="TRUE"\r
-                               ImportLibrary="$(IntDir)/$(ProjectName).lib"/>\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(IntDir)/$(ProjectName).lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                                                            &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources&quot;&#x0D;&#x0A;:END"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
-                               MkTypLibCompatible="TRUE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               TargetEnvironment="1"\r
-                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="2"\r
+                               FavorSizeOrSpeed="2"\r
+                               OmitFramePointers="true"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0400"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               BufferSecurityCheck="false"\r
+                               EnableFunctionLevelLinking="false"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderFile=""\r
+                               AssemblerListingLocation=".\Release/"\r
+                               ObjectFile=".\Release/"\r
+                               ProgramDataBaseFileName=".\Release/"\r
+                               BrowseInformation="1"\r
+                               WarningLevel="4"\r
+                               WarnAsError="false"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               CompileAs="0"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                               Description="Building Output Directories"\r
-                               CommandLine="if not exist Release mkdir Release\r
-if not exist &quot;Release\ExplorerPlugin.Resources&quot; mkdir &quot;Release\ExplorerPlugin.Resources&quot;\r
-"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist Release mkdir Release&#x0D;&#x0A;if not exist &quot;Release\ExplorerPlugin.Resources&quot; mkdir &quot;Release\ExplorerPlugin.Resources&quot;&#x0D;&#x0A;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+                               OutputFile="$(OutDir)\ExplorerPlugin.Resources\ExplorerPluginResources.dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreDefaultLibraryNames=""\r
+                               ModuleDefinitionFile=""\r
+                               ProgramDatabaseFile=""\r
+                               SubSystem="2"\r
+                               OptimizeReferences="0"\r
+                               EnableCOMDATFolding="0"\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(IntDir)/$(ProjectName).lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                                                            &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources&quot;&#x0D;&#x0A;:END"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
@@ -175,49 +456,63 @@ if not exist &quot;Release\ExplorerPlugin.Resources&quot; mkdir &quot;Release\Ex
        <Files>\r
                <Filter\r
                        Name="Header Files"\r
-                       Filter="h;hpp;hxx;hm;inl;inc">\r
+                       Filter="h;hpp;hxx;hm;inl;inc"\r
+                       >\r
                        <File\r
-                               RelativePath="resource_res.h">\r
+                               RelativePath="resource_res.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest"\r
+                       >\r
                        <File\r
-                               RelativePath="res\about.bmp">\r
+                               RelativePath="res\about.bmp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\about.bmp">\r
+                               RelativePath=".\about.bmp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\button-2k.ico">\r
+                               RelativePath="res\button-2k.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\button-xp.ico">\r
+                               RelativePath="res\button-xp.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\res\cold.ico">\r
+                               RelativePath=".\res\cold.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ExplorerPluginRes.rc">\r
+                               RelativePath="ExplorerPluginRes.rc"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\hot.ico">\r
+                               RelativePath=".\hot.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\logo.bmp">\r
+                               RelativePath="res\logo.bmp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\logo.bmp">\r
+                               RelativePath=".\logo.bmp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="Web.ico">\r
+                               RelativePath="Web.ico"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r
        <Globals>\r
                <Global\r
                        Name="RESOURCE_FILE"\r
-                       Value="ExplorerPluginRes.rc"/>\r
+                       Value="ExplorerPluginRes.rc"\r
+               />\r
        </Globals>\r
 </VisualStudioProject>\r
diff --git a/Clients/ExplorerPlugin/res/ExplorerPlugin.manifest b/Clients/ExplorerPlugin/res/ExplorerPlugin.manifest
new file mode 100644 (file)
index 0000000..90a067e
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
+<assemblyIdentity 
+    version="1.0.0.0" 
+    processorArchitecture="X86" 
+    name="Microsoft.Windows.Wiz97_3"
+    type="win32" 
+/> 
+<description>Your app description here</description> 
+<dependency> 
+    <dependentAssembly> 
+        <assemblyIdentity 
+            type="win32" 
+            name="Microsoft.Windows.Common-Controls" 
+            version="6.0.0.0" 
+            processorArchitecture="X86" 
+            publicKeyToken="6595b64144ccf1df" 
+            language="*" 
+        /> 
+    </dependentAssembly> 
+</dependency> 
+</assembly>
diff --git a/Clients/ExplorerPlugin/res/ExplorerPlugin64.manifest b/Clients/ExplorerPlugin/res/ExplorerPlugin64.manifest
new file mode 100644 (file)
index 0000000..ddc54b5
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
+<assemblyIdentity 
+    version="1.0.0.0" 
+    processorArchitecture="amd64" 
+    name="Microsoft.Windows.Wiz97_3"
+    type="win32" 
+/> 
+<description>Your app description here</description> 
+<dependency> 
+    <dependentAssembly> 
+        <assemblyIdentity 
+            type="win32" 
+            name="Microsoft.Windows.Common-Controls" 
+            version="6.0.0.0" 
+            processorArchitecture="amd64" 
+            publicKeyToken="6595b64144ccf1df" 
+            language="*" 
+        /> 
+    </dependentAssembly> 
+</dependency> 
+</assembly>
index 6374ce24c59f4c191f217aa77bb192e44b620901..0fd2c902403ce9fb589dd28c5907223de5683b15 100755 (executable)
@@ -9,6 +9,7 @@
 #define IDS_FIREWALL                    111\r
 #define IDC_COMPONENT                   1001\r
 #define IDC_LEGAL                       1002\r
+#define IDC_COMPONENT_VERSION           1003\r
 #define IDC_LOGIN_USERNAME_TEXT         1182\r
 #define IDC_LOGIN_PASSWORD_TEXT         1183\r
 #define ID_Menu                         40001\r
index ea18e83437ef233db18485a36b272402781e8cb6..f2e86cdd410370934635a72b2f6a2e6871297291 100755 (executable)
@@ -15,6 +15,7 @@
 #define IDS_ABOUT_URL                   148\r
 #define IDC_COMPONENT                   1001\r
 #define IDC_LEGAL                       1002\r
+#define IDC_COMPONENT_VERSION           1003\r
 #define IDC_LOGIN_USERNAME_TEXT         1182\r
 #define IDC_LOGIN_PASSWORD_TEXT         1183\r
 #define ID_Menu                         40001\r
index c4aae0a10a7a0d598f9b94b4cc724b44fb209d40..44062be7e0c3589e055cb78ac1d2becec3781b97 100755 (executable)
@@ -13,6 +13,7 @@
 #define IDB_ABOUT                       119\r
 #define IDC_COMPONENT                   1001\r
 #define IDC_LEGAL                       1002\r
+#define IDC_COMPONENT_VERSION           1003\r
 #define IDC_LOGIN_USERNAME_TEXT         1182\r
 #define IDC_LOGIN_PASSWORD_TEXT         1183\r
 #define ID_Menu                         40001\r
index cbdd200713b7ef22808025840e82a712054eaddb..8f512151658b25e885d511bab5f967656619905a 100644 (file)
@@ -54,7 +54,7 @@ import javax.swing.event.*;
 import com.apple.dnssd.*;
 
 
-class  BrowserApp implements ListSelectionListener, ResolveListener
+class  BrowserApp implements ListSelectionListener, ResolveListener, Runnable
 {
        static BrowserApp       app;
        JFrame                          frame;
@@ -63,6 +63,8 @@ class BrowserApp implements ListSelectionListener, ResolveListener
        JList                           domainPane, servicesPane, servicePane;
        DNSSDService            servicesBrowser, serviceBrowser, domainBrowser;
        JLabel                          hostLabel, portLabel;
+       String                          hostNameForUpdate;
+       int                                     portForUpdate;
 
        public          BrowserApp()
        {
@@ -170,22 +172,43 @@ class     BrowserApp implements ListSelectionListener, ResolveListener
                                                                                serviceList.getNthServiceName( newSel), 
                                                                                serviceList.getNthRegType( newSel), 
                                                                                serviceList.getNthDomain( newSel), 
-                                                                               new SwingResolveListener( this));
+                                                                               this);
                                }
                        }
                }
                catch ( Exception ex) { terminateWithException( ex); }
        }
 
+       public void run()
+       {
+               hostLabel.setText( hostNameForUpdate);
+               portLabel.setText( String.valueOf( portForUpdate));             
+       }
+
        public void     serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName, 
                                                                String hostName, int port, TXTRecord txtRecord)
        {
-               hostLabel.setText( hostName);
-               portLabel.setText( String.valueOf( port));
+               // We want to update GUI on the AWT event dispatching thread, but we can't stop
+               // the resolve from that thread, since stop() is synchronized with this callback.
+               // So, we stop the resolve on this thread, then invokeAndWait on the AWT event thread.
+
+               resolver.stop();
+
+               hostNameForUpdate = hostName;
+               portForUpdate = port;
+
+               try {
+                       SwingUtilities.invokeAndWait(this);
+               }
+               catch ( Exception e)
+               {
+                       e.printStackTrace();
+               }
        }
 
        public void     operationFailed( DNSSDService service, int errorCode)
        {
+               service.stop();
                // handle failure here
        }
 
index fe6c13416e91530a07ab577ce6e74c83c5457204..fbb68257e4d8d42735e71adff80aa9e52b06b970 100755 (executable)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="JavaSamples"\r
        ProjectGUID="{A987A0C1-344F-475C-869C-F082EB11EEBA}"\r
-       Keyword="MakeFileProj">\r
+       Keyword="MakeFileProj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
                        OutputDirectory="Debug"\r
                        IntermediateDirectory="Debug"\r
-                       ConfigurationType="0">\r
+                       ConfigurationType="0"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       >\r
                        <Tool\r
                                Name="VCNMakeTool"\r
                                BuildCommandLine="nmake /f nmakefile DEBUG=1 DNS_SD=..\..\mDNSWindows\Java\build\debug\dns_sd.jar"\r
                                ReBuildCommandLine="nmake /f nmakefile DEBUG=1 DNS_SD=..\..\mDNSWindows\Java\build\debug\dns_sd.jar"\r
-                               CleanCommandLine="nmake /f nmakefile DEBUG=1 CLEAN"/>\r
+                               CleanCommandLine="nmake /f nmakefile DEBUG=1 CLEAN"\r
+                               Output=""\r
+                               PreprocessorDefinitions=""\r
+                               IncludeSearchPath=""\r
+                               ForcedIncludes=""\r
+                               AssemblySearchPath=""\r
+                               ForcedUsingAssemblies=""\r
+                               CompileAsManaged=""\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
                        OutputDirectory="Release"\r
                        IntermediateDirectory="Release"\r
-                       ConfigurationType="0">\r
+                       ConfigurationType="0"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       >\r
+                       <Tool\r
+                               Name="VCNMakeTool"\r
+                               BuildCommandLine="nmake /f nmakefile DNS_SD=..\..\mDNSWindows\Java\build\prod\dns_sd.jar"\r
+                               ReBuildCommandLine="nmake /f nmakefile DNS_SD=..\..\mDNSWindows\Java\build\prod\dns_sd.jar"\r
+                               CleanCommandLine="nmake /f nmakefile CLEAN"\r
+                               Output=""\r
+                               PreprocessorDefinitions=""\r
+                               IncludeSearchPath=""\r
+                               ForcedIncludes=""\r
+                               AssemblySearchPath=""\r
+                               ForcedUsingAssemblies=""\r
+                               CompileAsManaged=""\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="0"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       >\r
+                       <Tool\r
+                               Name="VCNMakeTool"\r
+                               BuildCommandLine="nmake /f nmakefile DEBUG=1 DNS_SD=..\..\mDNSWindows\Java\build\debug\dns_sd.jar"\r
+                               ReBuildCommandLine="nmake /f nmakefile DEBUG=1 DNS_SD=..\..\mDNSWindows\Java\build\debug\dns_sd.jar"\r
+                               CleanCommandLine="nmake /f nmakefile DEBUG=1 CLEAN"\r
+                               Output=""\r
+                               PreprocessorDefinitions=""\r
+                               IncludeSearchPath=""\r
+                               ForcedIncludes=""\r
+                               AssemblySearchPath=""\r
+                               ForcedUsingAssemblies=""\r
+                               CompileAsManaged=""\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="0"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       >\r
                        <Tool\r
                                Name="VCNMakeTool"\r
                                BuildCommandLine="nmake /f nmakefile DNS_SD=..\..\mDNSWindows\Java\build\prod\dns_sd.jar"\r
                                ReBuildCommandLine="nmake /f nmakefile DNS_SD=..\..\mDNSWindows\Java\build\prod\dns_sd.jar"\r
-                               CleanCommandLine="nmake /f nmakefile CLEAN"/>\r
+                               CleanCommandLine="nmake /f nmakefile CLEAN"\r
+                               Output=""\r
+                               PreprocessorDefinitions=""\r
+                               IncludeSearchPath=""\r
+                               ForcedIncludes=""\r
+                               AssemblySearchPath=""\r
+                               ForcedUsingAssemblies=""\r
+                               CompileAsManaged=""\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
diff --git a/Clients/Java/SwingResolveListener.java b/Clients/Java/SwingResolveListener.java
deleted file mode 100644 (file)
index 19c1799..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode: Java; tab-width: 4 -*-
- *
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
- * ("Apple") in consideration of your agreement to the following terms, and your
- * use, installation, modification or redistribution of this Apple software
- * constitutes acceptance of these terms.  If you do not agree with these terms,
- * please do not use, install, modify or redistribute this Apple software.
- *
- * In consideration of your agreement to abide by the following terms, and subject
- * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- * copyrights in this original Apple software (the "Apple Software"), to use,
- * reproduce, modify and redistribute the Apple Software, with or without
- * modifications, in source and/or binary forms; provided that if you redistribute
- * the Apple Software in its entirety and without modifications, you must retain
- * this notice and the following text and disclaimers in all such redistributions of
- * the Apple Software.  Neither the name, trademarks, service marks or logos of
- * Apple Computer, Inc. may be used to endorse or promote products derived from the
- * Apple Software without specific prior written permission from Apple.  Except as
- * expressly stated in this notice, no other rights or licenses, express or implied,
- * are granted by Apple herein, including but not limited to any patent rights that
- * may be infringed by your derivative works or by other works in which the Apple
- * Software may be incorporated.
- *
- * The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
- * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- * COMBINATION WITH YOUR PRODUCTS.
- *
- * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-import javax.swing.*;
-import com.apple.dnssd.*;
-
-
-/**    Use this to schedule ResolveListener callbacks via SwingUtilities.invokeAndWait(). */
-
-public class SwingResolveListener implements Runnable, ResolveListener
-{
-       /** Create a listener for DNSSD that will call your listener on the Swing/AWT event thread. */
-       public  SwingResolveListener( ResolveListener listener)
-       { fListener = listener; }
-
-       public void     operationFailed( DNSSDService service, int errorCode)
-       {
-               fResolver = service;
-               fErrorCode = errorCode;
-               this.schedule();
-       }
-
-       /** (Clients should not call this method directly.) */
-       public void     serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName, 
-                                                               String hostName, int port, TXTRecord txtRecord)
-       {
-               fResolver = resolver;
-               fFlags = flags;
-               fIndex = ifIndex;
-               fFullName = fullName;
-               fHostName = hostName;
-               fPort = port;
-               fTXTRecord = txtRecord;
-               this.schedule();
-       }
-
-       /** (Clients should not call this method directly.) */
-       public void             run()
-       {
-               if ( fErrorCode != 0)
-                       fListener.operationFailed( fResolver, fErrorCode);
-               else
-                       fListener.serviceResolved( fResolver, fFlags, fIndex, fFullName, fHostName, fPort, fTXTRecord);
-       }
-
-       protected void  schedule()
-       {
-               try {
-                       SwingUtilities.invokeAndWait( this);
-               }
-               catch ( Exception e)
-               {
-                       e.printStackTrace();
-               }
-       }
-
-       protected ResolveListener       fListener;
-
-       protected DNSSDService          fResolver;
-       protected int                           fFlags;
-       protected int                           fIndex;
-       protected int                           fErrorCode;
-       protected String                        fFullName;
-       protected String                        fHostName;
-       protected int                           fPort;
-       protected TXTRecord                     fTXTRecord;
-}
-
index 9b08ccbba0bd159dd30d0fdd08167dd52b55cba2..89168e0b1d7ff734648e9f0e2afa2dbc2404874c 100644 (file)
@@ -55,7 +55,7 @@ BAOBJ = $(OBJDIR)\BrowserApp
 
 #############################################################################
 
-all: setup Java
+all: setup Java postbuild
 
 # 'setup' sets up the build directory structure the way we want
 setup:
@@ -66,6 +66,16 @@ setup:
        @if not exist $(BAOBJ)          mkdir $(BAOBJ)
        @if not exist $(BUILDDIR)       mkdir $(BUILDDIR)
 
+postbuild:
+       @if not "%RC_XBS%"=="YES" GOTO END
+       @if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\Java" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\Java"
+       @copy "nmakefile"                       "$(DSTROOT)\Program Files\Bonjour SDK\Samples\Java"
+       @copy "BrowserApp.java"         "$(DSTROOT)\Program Files\Bonjour SDK\Samples\Java"
+       @copy "SimpleChat.java"         "$(DSTROOT)\Program Files\Bonjour SDK\Samples\Java"
+       @copy "Swing*.java"                     "$(DSTROOT)\Program Files\Bonjour SDK\Samples\Java"
+       @copy "$(BUILDDIR)\*.jar"       "$(DSTROOT)\Program Files\Bonjour SDK\Samples\Java"
+       @:END
+
 # clean removes targets and objects
 clean:
        @if exist $(OBJDIR)             $(RMDIR) $(OBJDIR)
@@ -84,8 +94,7 @@ SIMPLECHATMAN = SimpleChat.manifest
 $(BUILDDIR)\SimpleChat.jar: $(SIMPLECHATOBJ) $(SIMPLECHATMAN)
        $(JAR) -cfm $@ $(SIMPLECHATMAN) -C $(SCOBJ) .
 
-BROWSERAPPOBJ =        $(BAOBJ)\SwingResolveListener.class \
-                               $(BAOBJ)\BrowserApp.class 
+BROWSERAPPOBJ =        $(BAOBJ)\BrowserApp.class 
 BROWSERAPPMAN = BrowserApp.manifest
 
 $(BUILDDIR)\BrowserApp.jar: $(BROWSERAPPOBJ) $(BROWSERAPPMAN)
index 3fbb8df2d505e7153e92e4ff783737ecf0a7f860..9703ced3b71e50600a0d9d5588c8ed64cf20b43c 100755 (executable)
@@ -15,6 +15,9 @@
 # limitations under the License.
 #
 # $Log: Makefile,v $
+# Revision 1.12  2008/09/05 17:37:08  cheshire
+# Need to include ClientCommon.c when building dns-sd
+#
 # Revision 1.11  2007/05/29 19:57:33  cheshire
 # Use "-Wall" for stricter compiler warnings
 #
@@ -77,10 +80,10 @@ clean:
 build:
        mkdir build
 
-build/dns-sd: build dns-sd.c
+build/dns-sd: build dns-sd.c ClientCommon.c
        cc $(filter %.c %.o, $+) $(LIBS) -I../mDNSShared -Wall -o $@
 
-build/dns-sd64: build dns-sd.c
+build/dns-sd64: build dns-sd.c ClientCommon.c
        cc $(filter %.c %.o, $+) $(LIBS) -I../mDNSShared -Wall -o $@ -m64
 
 # Note, we can make a 'fat' version of dns-sd using 'lipo', as shown below, but we
diff --git a/Clients/PrinterSetupWizard/Logger.cpp b/Clients/PrinterSetupWizard/Logger.cpp
new file mode 100644 (file)
index 0000000..c5ffabf
--- /dev/null
@@ -0,0 +1,98 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 1997-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.
+
+    Change History (most recent first):
+    
+$Log: Logger.cpp,v $
+Revision 1.3  2009/06/11 23:32:12  herscher
+<rdar://problem/4458913> Follow the app data folder naming convention of Safari/iTunes on Windows
+
+Revision 1.2  2009/06/11 23:11:53  herscher
+<rdar://problem/4458913> Log to user's app data folder
+
+Revision 1.1  2009/06/11 22:27:14  herscher
+<rdar://problem/4458913> Add comprehensive logging during printer installation process.
+
+ */
+
+#include "stdafx.h"
+#include "Logger.h"
+#include "DebugServices.h"
+#include <string>
+
+
+Logger::Logger()
+{
+       std::string     tmp;
+       char            path[ MAX_PATH ];
+       HRESULT         err;
+       BOOL            ok;
+
+       err = SHGetFolderPathA( NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path );
+       require_noerr( err, exit );
+
+       tmp = path;
+
+       // Create Logs subdir
+       tmp += "\\Apple";
+       ok = CreateDirectoryA( tmp.c_str(), NULL );
+       require_action( ( ok || ( GetLastError() == ERROR_ALREADY_EXISTS ) ), exit, err = -1 );
+
+       // Create Logs subdir
+       tmp += "\\Bonjour";
+       ok = CreateDirectoryA( tmp.c_str(), NULL );
+       require_action( ( ok || ( GetLastError() == ERROR_ALREADY_EXISTS ) ), exit, err = -1 );
+
+       // Create log file
+       tmp += "\\PrinterSetupLog.txt";
+       open( tmp.c_str());
+
+       *this << currentTime() << " Log started" << std::endl;
+
+exit:
+
+       return;
+}
+
+
+Logger::~Logger()
+{
+       *this << currentTime() << " Log finished" << std::endl;
+       flush();
+}
+
+
+std::string
+Logger::currentTime()
+{
+       time_t                                  ltime;
+       struct tm                               now;
+       int                                             err;
+       std::string                             ret;
+       
+       time( &ltime );
+       err = localtime_s( &now, &ltime );
+
+       if ( !err )
+       {
+               char temp[ 64 ];
+               
+               strftime( temp, sizeof( temp ), "%m/%d/%y %I:%M:%S %p", &now );
+               ret = temp;
+       }
+
+       return ret;
+}
diff --git a/Clients/PrinterSetupWizard/Logger.h b/Clients/PrinterSetupWizard/Logger.h
new file mode 100644 (file)
index 0000000..c74c315
--- /dev/null
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 1997-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.
+
+    Change History (most recent first):
+    
+$Log: Logger.h,v $
+Revision 1.1  2009/06/11 22:27:15  herscher
+<rdar://problem/4458913> Add comprehensive logging during printer installation process.
+
+
+ */
+
+#ifndef _Logger_h
+#define _Logger_h
+
+#include <fstream>
+#include <string>
+
+
+class Logger : public std::ofstream
+{
+public:
+
+       Logger();
+       ~Logger();
+
+       std::string
+       currentTime();
+};
+
+
+#define        require_noerr_with_log( LOG, MESSAGE, ERR, LABEL )      \
+               do                                              \
+               {                                               \
+                       int_least32_t localErr;                 \
+                       localErr = (int_least32_t)( ERR );      \
+                       if( localErr != 0 )                     \
+                       {                                       \
+                               log << log.currentTime() << " [ERROR] " << MESSAGE << " returned " << ERR << std::endl;                                         \
+                               log << log.currentTime() << " [WHERE] " << "\"" << __FILE__ << "\", \"" << __FUNCTION__ << "\", line " << __LINE__ << std::endl << std::endl;   \
+                               goto LABEL;                     \
+                       }                                       \
+               } while( 0 )
+
+
+#define        require_action_with_log( LOG, X, LABEL, ACTION )        \
+               do                                              \
+               {                                               \
+                       if( !( X ) )                            \
+                       {                                       \
+                               log << log.currentTime() << " [ERROR] " << #X << std::endl;     \
+                               log << log.currentTime() << " [WHERE] " << "\"" << __FILE__ << "\", \"" << __FUNCTION__ << "\", line " << __LINE__ << std::endl << std::endl;   \
+                               { ACTION; }                     \
+                               goto LABEL;                     \
+                       }                                       \
+               } while( 0 )
+
+#endif
index 982b0f22800c6d91c83a6e7b03503e7f687a6348..d57bed5d771a82b5bec3b9cb86a4419abd641543 100644 (file)
@@ -119,13 +119,6 @@ BEGIN
 END\r
 \r
 \r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// RT_MANIFEST\r
-//\r
-\r
-IDR_MANIFEST            RT_MANIFEST             "res\\PrinterSetupWizard.manifest"\r
-\r
 /////////////////////////////////////////////////////////////////////////////\r
 //\r
 // String Table\r
index a4b41358a83b4c1c35dfb183aaad9c56001ab3ab..65f5324cd1bd88e354bebf0af197808d037e82f2 100644 (file)
 <?xml version="1.0" encoding="windows-1251"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="PrinterSetupWizard"\r
        ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
-       Keyword="MFCProj">\r
+       Keyword="MFCProj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       CharacterSet="2">\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="false"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0501;UNICODE;_UNICODE"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="TRUE"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0501;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="1"\r
-                               BufferSecurityCheck="TRUE"\r
-                               TreatWChar_tAsBuiltInType="TRUE"\r
+                               BufferSecurityCheck="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
                                CallingConvention="0"\r
-                               DisableSpecificWarnings="4702"/>\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../../mDNSWindows/DLL/Debug/dnssd.lib ws2_32.lib iphlpapi.lib winspool.lib"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib iphlpapi.lib winspool.lib setupapi.lib"\r
                                OutputFile="$(OutDir)/PrinterWizard.exe"\r
                                LinkIncremental="2"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
                                SubSystem="2"\r
                                EntryPointSymbol="wWinMainCRTStartup"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\PrinterSetupWizard.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
-                               MkTypLibCompatible="FALSE"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0501;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               BufferSecurityCheck="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="0"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib iphlpapi.lib winspool.lib setupapi.lib"\r
+                               OutputFile="$(OutDir)/PrinterWizard.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               EntryPointSymbol="wWinMainCRTStartup"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\PrinterSetupWizard64.manifest"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       CharacterSet="2">\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="false"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
                                InlineFunctionExpansion="1"\r
-                               OmitFramePointers="TRUE"\r
+                               OmitFramePointers="true"\r
                                AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0501;UNICODE;_UNICODE"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="FALSE"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0501;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="false"\r
                                RuntimeLibrary="0"\r
-                               EnableFunctionLevelLinking="TRUE"\r
-                               TreatWChar_tAsBuiltInType="TRUE"\r
+                               EnableFunctionLevelLinking="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
-                               DisableSpecificWarnings="4702"/>\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../../mDNSWindows/DLL/Release/dnssd.lib ws2_32.lib iphlpapi.lib winspool.lib"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib iphlpapi.lib winspool.lib setupapi.lib"\r
                                OutputFile="$(OutDir)/PrinterWizard.exe"\r
                                LinkIncremental="1"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
                                SubSystem="2"\r
                                OptimizeReferences="0"\r
                                EnableCOMDATFolding="0"\r
                                EntryPointSymbol="wWinMainCRTStartup"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\PrinterSetupWizard.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                  &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
-                               MkTypLibCompatible="FALSE"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               OmitFramePointers="true"\r
+                               AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0501;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="false"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib iphlpapi.lib winspool.lib setupapi.lib"\r
+                               OutputFile="$(OutDir)/PrinterWizard.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="0"\r
+                               EnableCOMDATFolding="0"\r
+                               EntryPointSymbol="wWinMainCRTStartup"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\PrinterSetupWizard64.manifest"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                  &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
-                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"\r
+                       >\r
                        <File\r
-                               RelativePath=".\About.cpp">\r
+                               RelativePath=".\About.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="FirstPage.cpp">\r
+                               RelativePath="FirstPage.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\FourthPage.cpp">\r
+                               RelativePath=".\FourthPage.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="PrinterSetupWizardApp.cpp">\r
+                               RelativePath="PrinterSetupWizardApp.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="PrinterSetupWizardSheet.cpp">\r
+                               RelativePath="PrinterSetupWizardSheet.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="SecondPage.cpp">\r
+                               RelativePath="SecondPage.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="stdafx.cpp">\r
+                               RelativePath="stdafx.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\StdioFileEx.cpp">\r
+                               RelativePath=".\StdioFileEx.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ThirdPage.cpp">\r
+                               RelativePath="ThirdPage.cpp"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
-                       Filter="h;hpp;hxx;hm;inl;inc">\r
+                       Filter="h;hpp;hxx;hm;inl;inc"\r
+                       >\r
                        <File\r
-                               RelativePath=".\About.h">\r
+                               RelativePath=".\About.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="FirstPage.h">\r
+                               RelativePath="FirstPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\FourthPage.h">\r
+                               RelativePath=".\FourthPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="PrinterSetupWizardApp.h">\r
+                               RelativePath="PrinterSetupWizardApp.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="PrinterSetupWizardSheet.h">\r
+                               RelativePath="PrinterSetupWizardSheet.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="resource.h">\r
+                               RelativePath="resource.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="resource_exe.h">\r
+                               RelativePath="resource_exe.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="SecondPage.h">\r
+                               RelativePath="SecondPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="stdafx.h">\r
+                               RelativePath="stdafx.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\StdioFileEx.h">\r
+                               RelativePath=".\StdioFileEx.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ThirdPage.h">\r
+                               RelativePath="ThirdPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\UtilTypes.h">\r
+                               RelativePath=".\UtilTypes.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest"\r
+                       >\r
                        <File\r
-                               RelativePath="res\about.bmp">\r
+                               RelativePath="res\about.bmp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\banner_icon.bmp">\r
+                               RelativePath="res\banner_icon.bmp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\Info.ico">\r
+                               RelativePath="res\Info.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\NetworkPrinter.ico">\r
+                               RelativePath="res\NetworkPrinter.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\Print.ico">\r
+                               RelativePath="res\Print.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\PrinterSetupWizard.manifest">\r
+                               RelativePath="res\PrinterSetupWizard.manifest"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       ExcludedFromBuild="true"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCustomBuildTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       ExcludedFromBuild="true"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCustomBuildTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       ExcludedFromBuild="true"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCustomBuildTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       ExcludedFromBuild="true"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCustomBuildTool"\r
+                                       />\r
+                               </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="PrinterSetupWizard.rc">\r
+                               RelativePath="PrinterSetupWizard.rc"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\watermark.bmp">\r
+                               RelativePath="res\watermark.bmp"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Support"\r
-                       Filter="">\r
+                       >\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\CommonServices.h">\r
+                               RelativePath="..\..\mDNSShared\CommonServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.c">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.h">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dns_sd.h">\r
+                               RelativePath="..\..\mDNSShared\dns_sd.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\isocode.h">\r
+                               RelativePath="..\..\mDNSWindows\isocode.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\loclibrary.c">\r
+                               RelativePath="..\..\mDNSWindows\loclibrary.c"\r
+                               >\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
-                                               DisableSpecificWarnings="4201"/>\r
+                                               DisableSpecificWarnings="4201"\r
+                                       />\r
                                </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               DisableSpecificWarnings="4201"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSWindows\loclibrary.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\Logger.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\loclibrary.h">\r
+                               RelativePath=".\Logger.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\WinServices.cpp">\r
+                               RelativePath="..\..\mDNSWindows\WinServices.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\WinServices.h">\r
+                               RelativePath="..\..\mDNSWindows\WinServices.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <File\r
-                       RelativePath="ReadMe.txt">\r
+                       RelativePath="ReadMe.txt"\r
+                       >\r
                </File>\r
        </Files>\r
        <Globals>\r
                <Global\r
                        Name="RESOURCE_FILE"\r
-                       Value="PrinterSetupWizard.rc"/>\r
+                       Value="PrinterSetupWizard.rc"\r
+               />\r
        </Globals>\r
 </VisualStudioProject>\r
index e9e255f41080145e1d3ddbde06fd6e11e32184f2..c811e7efc98df68af1e10d766c81f79e77edaa6e 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: PrinterSetupWizardApp.cpp,v $
+Revision 1.10  2009/05/26 05:38:18  herscher
+<rdar://problem/6123821> use HeapSetInformation(HeapEnableTerminationOnCorruption) in dns-sd.exe and PrinterWizard.exe
+
 Revision 1.9  2006/08/14 23:24:09  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -59,6 +62,11 @@ First checked in
 #define new DEBUG_NEW
 #endif
 
+#ifndef HeapEnableTerminationOnCorruption
+#      define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS) 1
+#endif
+
+
 // Stash away pointers to our resource DLLs
 
 static HINSTANCE g_nonLocalizedResources       = NULL;
@@ -110,6 +118,8 @@ BOOL CPrinterSetupWizardApp::InitInstance()
        int                     res;
        OSStatus        err = kNoErr;
 
+       HeapSetInformation( NULL, HeapEnableTerminationOnCorruption, NULL, 0 );
+
        //
        // initialize the debugging framework
        //
index ea189ecfd767a97cca3595cc407935f66c3bcfa3..d535344679f054dc7c8534082e3778a7c8395784 100755 (executable)
@@ -171,8 +171,8 @@ BEGIN
     LTEXT           "",IDC_PRINTER_MODEL,172,104,113,8\r
     LTEXT           "",IDC_PRINTER_PROTOCOL,172,117,113,8\r
     LTEXT           "",IDC_PRINTER_DEFAULT,172,130,113,8\r
-    LTEXT           "To complete the installation, click Finish.",IDC_STATIC,116,187,\r
-                    171,8\r
+    LTEXT           "To complete the installation, click Finish.",IDC_STATIC,116,180,171,8\r
+    LTEXT           "To change these settings, click Back.",IDC_STATIC,116,190,171,8\r
 END\r
 \r
 IDD_DIALOG1 DIALOGEX 0, 0, 265, 130\r
@@ -256,6 +256,8 @@ BEGIN
     IDS_INSTALL_ERROR_CAPTION "Error"\r
     IDS_INSTALL_ERROR_MESSAGE \r
                             "You do not have sufficient access to your computer to connect to the selected printer."\r
+       IDS_BAD_INF_FILE                "The specified location does not contain information about your printer"\r
+       IDS_BAD_INF_FILE_CAPTION "Select Device"\r
     IDS_MANUFACTURER_HEADING "Manufacturer"\r
     IDS_MODEL_HEADING       "Model"\r
     IDS_NO_PRINTERS         "No Bonjour Printers are available"\r
index b961304920550b72f10cb724e272c087fad65018..062778630d2ded13875e56747b4d9f43859ac646 100755 (executable)
 <?xml version="1.0" encoding="windows-1251"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="PrinterSetupWizardLocRes"\r
-       ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
-       Keyword="MFCProj">\r
+       ProjectGUID="{967F5375-0176-43D3-ADA3-22EE25551C37}"\r
+       Keyword="MFCProj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug\PrinterWizard.Resources\en.lproj"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       CharacterSet="2">\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="false"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="..\..\mDNSWindows"\r
                                PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0400;UNICODE;_UNICODE"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="TRUE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="1"\r
-                               BufferSecurityCheck="TRUE"\r
-                               TreatWChar_tAsBuiltInType="TRUE"\r
+                               BufferSecurityCheck="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="4"\r
                                CallingConvention="0"\r
-                               DisableSpecificWarnings="4702"/>\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist $(OutDir)\PrinterWizard.Resources mkdir $(OutDir)\PrinterWizard.Resources&#x0D;&#x0A;if not exist $(OutDir)\PrinterWizard.Resources\en.lproj mkdir $(OutDir)\PrinterWizard.Resources\en.lproj&#x0D;&#x0A;"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="$(OutDir)/PrinterWizardLocalized.dll"\r
+                               OutputFile="$(OutDir)\PrinterWizard.Resources\en.lproj\PrinterWizardLocalized.dll"\r
                                LinkIncremental="2"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="2"\r
                                EntryPointSymbol=""\r
-                               ResourceOnlyDLL="TRUE"\r
+                               ResourceOnlyDLL="true"\r
                                ImportLibrary="$(OutDir)/Localized.lib"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
-                               MkTypLibCompatible="FALSE"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0400;UNICODE;_UNICODE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               BufferSecurityCheck="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="0"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                               Description="Building Output Directories"\r
-                               CommandLine="if not exist Debug\PrinterWizard.Resources mkdir Debug\PrinterWizard.Resources\r
-if not exist Debug\PrinterWizard.Resources\en.lproj mkdir Debug\PrinterWizard.Resources\en.lproj\r
-"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist $(OutDir)\PrinterWizard.Resources mkdir $(OutDir)\PrinterWizard.Resources&#x0D;&#x0A;if not exist $(OutDir)\PrinterWizard.Resources\en.lproj mkdir $(OutDir)\PrinterWizard.Resources\en.lproj&#x0D;&#x0A;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)\PrinterWizard.Resources\en.lproj\PrinterWizardLocalized.dll"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="2"\r
+                               EntryPointSymbol=""\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(OutDir)/Localized.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\PrinterWizard.Resources\en.lproj"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       CharacterSet="2">\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="false"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
                                InlineFunctionExpansion="1"\r
-                               OmitFramePointers="TRUE"\r
+                               OmitFramePointers="true"\r
                                AdditionalIncludeDirectories="..\..\mDNSWindows"\r
                                PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0400;UNICODE;_UNICODE"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="FALSE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="false"\r
                                RuntimeLibrary="0"\r
-                               EnableFunctionLevelLinking="TRUE"\r
-                               TreatWChar_tAsBuiltInType="TRUE"\r
+                               EnableFunctionLevelLinking="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
-                               DisableSpecificWarnings="4702"/>\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist $(OutDir)\PrinterWizard.Resources mkdir $(OutDir)\PrinterWizard.Resources&#x0D;&#x0A;if not exist $(OutDir)\PrinterWizard.Resources\en.lproj mkdir $(OutDir)\PrinterWizard.Resources\en.lproj&#x0D;&#x0A;"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="$(OutDir)/PrinterWizardLocalized.dll"\r
+                               OutputFile="$(OutDir)\PrinterWizard.Resources\en.lproj\PrinterWizardLocalized.dll"\r
                                LinkIncremental="1"\r
-                               GenerateDebugInformation="FALSE"\r
+                               GenerateDebugInformation="false"\r
                                SubSystem="2"\r
                                OptimizeReferences="0"\r
                                EnableCOMDATFolding="0"\r
                                EntryPointSymbol=""\r
-                               ResourceOnlyDLL="TRUE"\r
+                               ResourceOnlyDLL="true"\r
                                ImportLibrary="$(IntDir)/$(TargetName).lib"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                                                                         &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj&quot;&#x0D;&#x0A;:END"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
-                               MkTypLibCompatible="FALSE"/>\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
-                       <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               OmitFramePointers="true"\r
+                               AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0400;UNICODE;_UNICODE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="false"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                               Description="Building Output Directories"\r
-                               CommandLine="if not exist Release mkdir Release\r
-if not exist &quot;Release\PrinterWizard.Resources&quot; mkdir &quot;Release\PrinterWizard.Resources&quot;\r
-if not exist &quot;Release\PrinterWizard.Resources\en.lproj&quot; mkdir &quot;Release\PrinterWizard.Resources\en.lproj&quot;\r
-"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist $(OutDir)\PrinterWizard.Resources mkdir $(OutDir)\PrinterWizard.Resources&#x0D;&#x0A;if not exist $(OutDir)\PrinterWizard.Resources\en.lproj mkdir $(OutDir)\PrinterWizard.Resources\en.lproj&#x0D;&#x0A;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)\PrinterWizard.Resources\en.lproj\PrinterWizardLocalized.dll"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="false"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="0"\r
+                               EnableCOMDATFolding="0"\r
+                               EntryPointSymbol=""\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(IntDir)/$(TargetName).lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                                                                         &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj&quot;&#x0D;&#x0A;:END"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
@@ -151,28 +407,35 @@ if not exist &quot;Release\PrinterWizard.Resources\en.lproj&quot; mkdir &quot;Re
        <Files>\r
                <Filter\r
                        Name="Header Files"\r
-                       Filter="h;hpp;hxx;hm;inl;inc">\r
+                       Filter="h;hpp;hxx;hm;inl;inc"\r
+                       >\r
                        <File\r
-                               RelativePath="resource_loc_dll.h">\r
+                               RelativePath="resource_loc_dll.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest"\r
+                       >\r
                        <File\r
-                               RelativePath="PrinterSetupWizardLocRes.rc">\r
+                               RelativePath="PrinterSetupWizardLocRes.rc"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\PrinterSetupWizardLocRes.rc2">\r
+                               RelativePath="res\PrinterSetupWizardLocRes.rc2"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <File\r
-                       RelativePath="ReadMe.txt">\r
+                       RelativePath="ReadMe.txt"\r
+                       >\r
                </File>\r
        </Files>\r
        <Globals>\r
                <Global\r
                        Name="RESOURCE_FILE"\r
-                       Value="PrinterSetupWizardLocRes.rc"/>\r
+                       Value="PrinterSetupWizardLocRes.rc"\r
+               />\r
        </Globals>\r
 </VisualStudioProject>\r
index e23103d97809d9b258c8801022edf29ff3ba8f0e..31c30c61677481eeb093cc566912dc23faa28493 100755 (executable)
 <?xml version="1.0" encoding="windows-1251"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="PrinterSetupWizardRes"\r
-       ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
-       Keyword="MFCProj">\r
+       ProjectGUID="{CFCCB176-6CAA-472B-B0A2-90511C8E2E52}"\r
+       Keyword="MFCProj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug\PrinterWizard.Resources"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       CharacterSet="2">\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="false"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="..\..\mDNSWindows"\r
                                PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0400;UNICODE;_UNICODE"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="TRUE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="1"\r
-                               BufferSecurityCheck="TRUE"\r
-                               TreatWChar_tAsBuiltInType="TRUE"\r
+                               BufferSecurityCheck="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="4"\r
                                CallingConvention="0"\r
-                               DisableSpecificWarnings="4702"/>\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist Debug\PrinterWizard.Resources mkdir Debug\PrinterWizard.Resources"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="$(OutDir)/PrinterWizardResources.dll"\r
+                               OutputFile="$(OutDir)\PrinterWizard.Resources\PrinterWizardResources.dll"\r
                                LinkIncremental="2"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                SubSystem="2"\r
                                EntryPointSymbol=""\r
-                               ResourceOnlyDLL="TRUE"\r
+                               ResourceOnlyDLL="true"\r
                                ImportLibrary="$(OutDir)/Localized.lib"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
-                               MkTypLibCompatible="FALSE"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0400;UNICODE;_UNICODE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               BufferSecurityCheck="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="0"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                               Description="Building Output Directories"\r
-                               CommandLine="if not exist Debug\PrinterWizard.Resources mkdir Debug\PrinterWizard.Resources"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist Debug\PrinterWizard.Resources mkdir Debug\PrinterWizard.Resources"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)\PrinterWizard.Resources\PrinterWizardResources.dll"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="2"\r
+                               EntryPointSymbol=""\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(OutDir)/Localized.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\PrinterWizard.Resources"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       CharacterSet="2">\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="false"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
                                InlineFunctionExpansion="1"\r
-                               OmitFramePointers="TRUE"\r
+                               OmitFramePointers="true"\r
                                AdditionalIncludeDirectories="..\..\mDNSWindows"\r
                                PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0400;UNICODE;_UNICODE"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="FALSE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="false"\r
                                RuntimeLibrary="0"\r
-                               EnableFunctionLevelLinking="TRUE"\r
-                               TreatWChar_tAsBuiltInType="TRUE"\r
+                               EnableFunctionLevelLinking="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
-                               DisableSpecificWarnings="4702"/>\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist Release mkdir Release&#x0D;&#x0A;if not exist &quot;Release\PrinterWizard.Resources&quot; mkdir &quot;Release\PrinterWizard.Resources&quot;&#x0D;&#x0A;"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="$(OutDir)/PrinterWizardResources.dll"\r
+                               OutputFile="$(OutDir)\PrinterWizard.Resources\PrinterWizardResources.dll"\r
                                LinkIncremental="1"\r
-                               GenerateDebugInformation="FALSE"\r
+                               GenerateDebugInformation="false"\r
                                SubSystem="2"\r
                                OptimizeReferences="0"\r
                                EnableCOMDATFolding="0"\r
                                EntryPointSymbol=""\r
-                               ResourceOnlyDLL="TRUE"\r
+                               ResourceOnlyDLL="true"\r
                                ImportLibrary="$(IntDir)/$(TargetName).lib"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                                                           &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources&quot;&#x0D;&#x0A;:END"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
-                               MkTypLibCompatible="FALSE"/>\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
-                       <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               OmitFramePointers="true"\r
+                               AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0400;UNICODE;_UNICODE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="false"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                               Description="Building Output Directories"\r
-                               CommandLine="if not exist Release mkdir Release\r
-if not exist &quot;Release\PrinterWizard.Resources&quot; mkdir &quot;Release\PrinterWizard.Resources&quot;\r
-"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+                               AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               Description="Building Output Directories"\r
+                               CommandLine="if not exist Release mkdir Release&#x0D;&#x0A;if not exist &quot;Release\PrinterWizard.Resources&quot; mkdir &quot;Release\PrinterWizard.Resources&quot;&#x0D;&#x0A;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)\PrinterWizard.Resources\PrinterWizardResources.dll"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="false"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="0"\r
+                               EnableCOMDATFolding="0"\r
+                               EntryPointSymbol=""\r
+                               ResourceOnlyDLL="true"\r
+                               ImportLibrary="$(IntDir)/$(TargetName).lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                                                           &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources&quot;&#x0D;&#x0A;:END"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
@@ -148,58 +407,75 @@ if not exist &quot;Release\PrinterWizard.Resources&quot; mkdir &quot;Release\Pri
        <Files>\r
                <Filter\r
                        Name="Header Files"\r
-                       Filter="h;hpp;hxx;hm;inl;inc">\r
+                       Filter="h;hpp;hxx;hm;inl;inc"\r
+                       >\r
                        <File\r
-                               RelativePath="resource_dll.h">\r
+                               RelativePath="resource_dll.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest"\r
+                       >\r
                        <File\r
-                               RelativePath=".\res\about.bmp">\r
+                               RelativePath=".\res\about.bmp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\banner_icon.bmp">\r
+                               RelativePath="res\banner_icon.bmp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\res\Info.ico">\r
+                               RelativePath=".\res\Info.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\res\NetworkPrinter.ico">\r
+                               RelativePath=".\res\NetworkPrinter.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\res\Print.ico">\r
+                               RelativePath=".\res\Print.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\res\Printer.bmp">\r
+                               RelativePath=".\res\Printer.bmp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\res\Printer.ico">\r
+                               RelativePath=".\res\Printer.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\res\Printer2.ico">\r
+                               RelativePath=".\res\Printer2.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\PrinterSetupWizard.ico">\r
+                               RelativePath="res\PrinterSetupWizard.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="PrinterSetupWizardRes.rc">\r
+                               RelativePath="PrinterSetupWizardRes.rc"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\PrinterSetupWizardRes.rc2">\r
+                               RelativePath="res\PrinterSetupWizardRes.rc2"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\watermark.bmp">\r
+                               RelativePath="res\watermark.bmp"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <File\r
-                       RelativePath="ReadMe.txt">\r
+                       RelativePath="ReadMe.txt"\r
+                       >\r
                </File>\r
        </Files>\r
        <Globals>\r
                <Global\r
                        Name="RESOURCE_FILE"\r
-                       Value="PrinterSetupWizardRes.rc"/>\r
+                       Value="PrinterSetupWizardRes.rc"\r
+               />\r
        </Globals>\r
 </VisualStudioProject>\r
index e912716b3a2e0284a0f2976ac8c7ec086c415e3b..565c6ea6789d14f03e0a1053ae5cb2c6b3deed22 100644 (file)
     Change History (most recent first):
     
 $Log: PrinterSetupWizardSheet.cpp,v $
+Revision 1.40  2009/06/18 18:05:50  herscher
+<rdar://problem/4694554> Eliminate the first screen of Printer Wizard and maybe combine others ("I'm Feeling Lucky")
+
+Revision 1.39  2009/06/11 22:27:16  herscher
+<rdar://problem/4458913> Add comprehensive logging during printer installation process.
+
+Revision 1.38  2009/05/27 04:49:02  herscher
+<rdar://problem/4417884> Consider setting DoubleSpool for LPR queues to improve compatibility
+
+Revision 1.37  2009/03/30 19:17:37  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/6141389> Printer Wizard crashes on launch when Bonjour Service isn't running
+<rdar://problem/5258789> Buffer overflow in PrinterWizard when printer dns hostname is too long
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
+Revision 1.36  2008/10/23 22:33:23  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
 Revision 1.35  2006/08/14 23:24:09  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -279,7 +297,7 @@ exit:
 //
 // Installs a printer with Windows.
 //
-// NOTE: this works one of two ways, depending on whether
+// Note: this works one of two ways, depending on whether
 // there are drivers already installed for this printer.
 // If there are, then we can just create a port with XcvData,
 // and then call AddPrinter.  If not, we use the printui.dll
@@ -292,9 +310,10 @@ exit:
 OSStatus
 CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
 {
+       Logger          log;
        Service *       service;
        BOOL            ok;
-       OSStatus        err;
+       OSStatus        err = 0;
 
        service = printer->services.front();
        check( service );
@@ -316,7 +335,7 @@ CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
                //
                hThread = (HANDLE) _beginthreadex_compat( NULL, 0, InstallDriverThread, printer, 0, &threadID );
                err = translate_errno( hThread, (OSStatus) GetLastError(), kUnknownErr );
-               require_noerr( err, exit );
+               require_noerr_with_log( log, "_beginthreadex_compat()", err, exit );
                        
                //
                // go modal
@@ -329,18 +348,18 @@ CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                }
-       
+
                //
                // Wait until child process exits.
                //
                dwResult = WaitForSingleObject( hThread, INFINITE );
                err = translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr );
-               require_noerr( err, exit );
+               require_noerr_with_log( log, "WaitForSingleObject()", err, exit );
 
                //
                // check the return value of thread
                //
-               require_noerr( m_driverThreadExitCode, exit );
+               require_noerr_with_log( log, "thread exit code", m_driverThreadExitCode, exit );
 
                //
                // now we know that the driver was successfully installed
@@ -350,23 +369,22 @@ CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
 
        if ( service->type == kPDLServiceType )
        {
-               err = InstallPrinterPDLAndLPR( printer, service, PROTOCOL_RAWTCP_TYPE );
-               require_noerr( err, exit );
+               err = InstallPrinterPDLAndLPR( printer, service, PROTOCOL_RAWTCP_TYPE, log );
+               require_noerr_with_log( log, "InstallPrinterPDLAndLPR()", err, exit );
        }
        else if ( service->type == kLPRServiceType )
        {
-               err = InstallPrinterPDLAndLPR( printer, service, PROTOCOL_LPR_TYPE );
-               require_noerr( err, exit );
+               err = InstallPrinterPDLAndLPR( printer, service, PROTOCOL_LPR_TYPE, log );
+               require_noerr_with_log( log, "InstallPrinterPDLAndLPR()", err, exit );
        }
        else if ( service->type == kIPPServiceType )
        {
-               err = InstallPrinterIPP( printer, service );
-               require_noerr( err, exit );
+               err = InstallPrinterIPP( printer, service, log );
+               require_noerr_with_log( log, "InstallPrinterIPP()", err, exit );
        }
        else
        {
-               err = kUnknownErr;
-               require_noerr( err, exit );
+               require_action_with_log( log, ( service->type == kPDLServiceType ) || ( service->type == kLPRServiceType ) || ( service->type == kIPPServiceType ), exit, err = kUnknownErr );
        }
 
        printer->installed = true;
@@ -378,7 +396,7 @@ CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
        {
                ok = SetDefaultPrinter( printer->actualName );
                err = translate_errno( ok, errno_compat(), err = kUnknownErr );
-               require_noerr( err, exit );
+               require_noerr_with_log( log, "SetDefaultPrinter()", err, exit );
        }
 
 exit:
@@ -388,7 +406,7 @@ exit:
 
 
 OSStatus
-CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * service, DWORD protocol )
+CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * service, DWORD protocol, Logger & log )
 {
        PRINTER_DEFAULTS        printerDefaults =       { NULL,  NULL, SERVER_ACCESS_ADMINISTER };
        DWORD                           dwStatus;
@@ -411,7 +429,7 @@ CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * s
 
        ok = OpenPrinter(L",XcvMonitor Standard TCP/IP Port", &hXcv, &printerDefaults);
        err = translate_errno( ok, errno_compat(), kUnknownErr );
-       require_noerr( err, exit );
+       require_noerr_with_log( log, "OpenPrinter()", err, exit );
 
        //
        // BUGBUG: MSDN said this is not required, but my experience shows it is required
@@ -425,28 +443,33 @@ CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * s
                pOutputData = NULL;
        }
 
-       require_action( pOutputData, exit, err = kNoMemoryErr );
+       require_action_with_log( log, pOutputData, exit, err = kNoMemoryErr );
        
        //
        // setup the port
        //
        ZeroMemory(&portData, sizeof(PORT_DATA_1));
-       wcscpy(portData.sztPortName, printer->portName);
+
+       require_action_with_log( log, wcslen(printer->portName) < sizeof_array(portData.sztPortName), exit, err = kSizeErr );
+       wcscpy_s(portData.sztPortName, printer->portName);
        
        portData.dwPortNumber   =       service->portNumber;
        portData.dwVersion              =       1;
+       portData.dwDoubleSpool  =       1;
        
        portData.dwProtocol     = protocol;
        portData.cbSize         = sizeof PORT_DATA_1;
        portData.dwReserved     = 0L;
        
-       wcscpy(portData.sztQueue, q->name);
-       wcscpy(portData.sztIPAddress, service->hostname); 
-       wcscpy(portData.sztHostAddress, service->hostname);
+       require_action_with_log( log, wcslen(q->name) < sizeof_array(portData.sztQueue), exit, err = kSizeErr );
+       wcscpy_s(portData.sztQueue, q->name);
+
+       require_action_with_log( log, wcslen( service->hostname ) < sizeof_array(portData.sztHostAddress), exit, err = kSizeErr );
+       wcscpy_s( portData.sztHostAddress, service->hostname );
 
        ok = XcvData(hXcv, L"AddPort", (PBYTE) &portData, sizeof(PORT_DATA_1), pOutputData, cbInputData,  &cbOutputNeeded, &dwStatus);
        err = translate_errno( ok, errno_compat(), kUnknownErr );
-       require_noerr( err, exit );
+       require_noerr_with_log( log, "XcvData()", err, exit );
 
        //
        // add the printer
@@ -475,7 +498,7 @@ CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * s
 
        hPrinter = AddPrinter(NULL, 2, (LPBYTE) &pInfo);
        err = translate_errno( hPrinter, errno_compat(), kUnknownErr );
-       require_noerr( err, exit );
+       require_noerr_with_log( log, "AddPrinter()", err, exit );
 
 exit:
 
@@ -499,7 +522,7 @@ exit:
 
 
 OSStatus
-CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service)
+CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service, Logger & log)
 {
        DEBUG_UNUSED( service );
 
@@ -525,7 +548,7 @@ CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service
        
        hPrinter = AddPrinter(NULL, 2, (LPBYTE)&pInfo);
        err = translate_errno( hPrinter, errno_compat(), kUnknownErr );
-       require_noerr( err, exit );
+       require_noerr_with_log( log, "AddPrinter()", err, exit );
 
 exit:
 
@@ -596,12 +619,14 @@ exit:
                }
                else
                {
-                       CPrinterSetupWizardSheet::WizardException exc;
-                       
-                       exc.text.LoadString( IDS_NO_MDNSRESPONDER_SERVICE_TEXT );
-                       exc.caption.LoadString( IDS_ERROR_CAPTION );
-                       
-                       throw(exc);
+                       CString text, caption;
+
+                       text.LoadString( IDS_NO_MDNSRESPONDER_SERVICE_TEXT );
+                       caption.LoadString( IDS_ERROR_CAPTION );
+
+                       MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
+
+                       _exit( 0 );
                }
        }
 
@@ -676,7 +701,6 @@ CPrinterSetupWizardSheet::OnOK()
 
 void CPrinterSetupWizardSheet::Init(void)
 {
-       AddPage(&m_pgFirst);
        AddPage(&m_pgSecond);
        AddPage(&m_pgThird);
        AddPage(&m_pgFourth);
@@ -693,7 +717,7 @@ void CPrinterSetupWizardSheet::Init(void)
 }
 
 
-LONG
+LRESULT
 CPrinterSetupWizardSheet::OnSocketEvent(WPARAM inWParam, LPARAM inLParam)
 {
        if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
@@ -726,7 +750,7 @@ CPrinterSetupWizardSheet::OnSocketEvent(WPARAM inWParam, LPARAM inLParam)
 }
 
 
-LONG
+LRESULT
 CPrinterSetupWizardSheet::OnProcessEvent(WPARAM inWParam, LPARAM inLParam)
 {
        DEBUG_UNUSED(inLParam);
index b9cc5ff1e3c5f1eadf803a9b0dcc2b4af9e63f28..5e2306b0534fd5a89f791e8bfa9d4b333a3fe1fc 100644 (file)
     Change History (most recent first):
     
 $Log: PrinterSetupWizardSheet.h,v $
+Revision 1.14  2009/06/11 22:27:16  herscher
+<rdar://problem/4458913> Add comprehensive logging during printer installation process.
+
+Revision 1.13  2009/03/30 19:18:49  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.12  2006/08/14 23:24:09  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -67,6 +74,7 @@ First checked in
 #include "thirdpage.h"
 #include "fourthpage.h"
 #include "UtilTypes.h"
+#include "Logger.h"
 #include "dns_sd.h"
 #include <stdexcept>
 #include <map>
@@ -113,10 +121,10 @@ public:
        //
        // handles end of process event
        //
-       virtual LONG
+       virtual LRESULT
        OnProcessEvent(WPARAM inWParam, LPARAM inLParam);
        
-       virtual LONG
+       virtual LRESULT
        OnSocketEvent(WPARAM inWParam, LPARAM inLParam);
 
        virtual BOOL
@@ -265,10 +273,10 @@ private:
        InstallPrinter(Printer * printer);
 
        OSStatus
-       InstallPrinterPDLAndLPR(Printer * printer, Service * service, DWORD protocol);
+       InstallPrinterPDLAndLPR(Printer * printer, Service * service, DWORD protocol, Logger & log);
 
        OSStatus
-       InstallPrinterIPP(Printer * printer, Service * service);
+       InstallPrinterIPP(Printer * printer, Service * service, Logger & log);
 
        static unsigned WINAPI
        InstallDriverThread( LPVOID inParam );
index 83e6685b8a7ece996fd15ecb98aa382dc39f4f53..4bed3f713f7612de3e761e1b5b10ae01f014670f 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: SecondPage.cpp,v $
+Revision 1.20  2009/06/18 18:05:50  herscher
+<rdar://problem/4694554> Eliminate the first screen of Printer Wizard and maybe combine others ("I'm Feeling Lucky")
+
 Revision 1.19  2006/08/14 23:24:09  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -225,12 +228,20 @@ CSecondPage::OnSetActive()
                OnAddPrinter( *it, false );
        }
 
-       // And if we hit 'Back' from page 3, then re-select printer
-
-       if ( ( psheet->GetLastPage() == psheet->GetPage( 2 ) ) && printer )
+       if ( ( !printer && ( psheet->m_printers.size() > 0 ) ) || ( printer != psheet->GetSelectedPrinter() ) )
        {
+               if ( !printer )
+               {
+                       printer = psheet->m_printers.front();
+               }
+
                psheet->SetSelectedPrinter( printer );
-               m_browseList.Select( printer->item, TVGN_FIRSTVISIBLE );
+       }
+       
+       if ( printer )
+       {
+               m_browseList.SelectItem( printer->item );
+               ::SetFocus( m_browseList );
        }
 
 exit:
@@ -270,6 +281,7 @@ CSecondPage::OnAddPrinter(
                                        bool            moreComing )
 {
        CPrinterSetupWizardSheet        *       psheet;
+       Printer                                         *       selectedPrinter;
        OSStatus                                                err = kNoErr;
 
        check( IsWindow( m_hWnd ) );
@@ -278,6 +290,8 @@ CSecondPage::OnAddPrinter(
 
        psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
        require_quiet( psheet, exit );
+       
+       selectedPrinter = psheet->GetSelectedPrinter();
 
        printer->item = m_browseList.InsertItem(printer->displayName);
 
@@ -301,6 +315,13 @@ CSecondPage::OnAddPrinter(
                m_browseList.EnableWindow(TRUE);
        }
 
+       if ( !selectedPrinter )
+       {
+               psheet->SetSelectedPrinter( printer );
+               m_browseList.SelectItem( printer->item );
+               ::SetFocus( m_browseList );
+       }
+
 exit:
 
        if (!moreComing)
index 4c156fd98d32cc0da1bacc359fec8a5b9676aa54..f3d0432739c23edba76ff039d98e89e4da0c0b18 100644 (file)
     Change History (most recent first):
     
 $Log: ThirdPage.cpp,v $
+Revision 1.41  2009/06/18 18:05:50  herscher
+<rdar://problem/4694554> Eliminate the first screen of Printer Wizard and maybe combine others ("I'm Feeling Lucky")
+
+Revision 1.40  2009/05/29 20:43:36  herscher
+<rdar://problem/6928136> Printer Wizard doesn't work correctly in Windows 7 64 bit
+
+Revision 1.39  2009/05/27 06:25:49  herscher
+<rdar://problem/4176334> Need error dialog when selecting bad INF file
+
+Revision 1.38  2009/05/27 04:59:57  herscher
+<rdar://problem/4517393> COMPATIBILITY WITH HP CLJ4700
+<rdar://problem/6142138> Compatibility with Samsung print driver files
+
 Revision 1.37  2007/06/08 06:30:26  herscher
 <rdar://problem/5257700> Fix uninitialized pointers when detecting generic PCL and PS drivers
 
@@ -150,6 +163,7 @@ First checked in
 #include <dns_sd.h>
 #include <tcpxcv.h>
 #include <winspool.h>
+#include <setupapi.h>
 
 // local variable is initialize but not referenced
 #pragma warning(disable:4189)
@@ -179,16 +193,6 @@ First checked in
 #define kGenericPCLColorDriver         L"HP Color LaserJet 4550 PCL"
 #define kGenericPCLDriver                      L"HP LaserJet 4050 Series PCL"
 
-//
-// states for parsing ntprint.inf
-//
-enum PrinterParsingState
-{
-       Looking,
-       ParsingManufacturers,
-       ParsingModels,
-       ParsingStrings
-};
 
 // CThirdPage dialog
 
@@ -478,24 +482,6 @@ CThirdPage::AutoScroll( CListCtrl & list, int nIndex )
 // ------------------------------------------------------
 // LoadPrintDriverDefsFromFile
 //
-// This function does all the heavy lifting in parsing inf
-// files.  It is called to parse both ntprint.inf, and driver
-// files that might be shipped on a printer's installation
-// disk
-//
-// The inf file is not totally parsed.  I only want to determine
-// the manufacturer and models that are involved. I leave it
-// to printui.dll to actually copy the driver files to the
-// right places.
-//
-// I was aiming to parse as little as I could so as not to
-// duplicate the parsing code that is contained in Windows.  There
-// are no public APIs for parsing inf files.
-//
-// That part of the inf file that we're interested in has a fairly
-// easy format.  Tags are strings that are enclosed in brackets.
-// We are only interested in [MANUFACTURERS] and models.
-//
 // The only potentially opaque thing about this function is the
 // checkForDuplicateModels flag.  The problem here is that ntprint.inf
 // doesn't contain duplicate models, and it has hundreds of models
@@ -508,345 +494,193 @@ CThirdPage::AutoScroll( CListCtrl & list, int nIndex )
 OSStatus
 CThirdPage::LoadPrintDriverDefsFromFile(Manufacturers & manufacturers, const CString & filename, bool checkForDuplicateModels )
 {
-       PrinterParsingState             state           = Looking;
-       Manufacturers::iterator iter            = manufacturers.end();
-       CStdioFileEx                    file;
-       CFileException                  feError;
-       CString                                 s;
-       OSStatus                                err;
-       BOOL                                    ok;
-
-       typedef std::map<CString, CString> StringMap;
+       HINF                    handle  = INVALID_HANDLE_VALUE;
+       const TCHAR *   section = TEXT( "Manufacturer" );
+       LONG                    sectionCount;
+       TCHAR                   line[ 1000 ];
+       CString                 klass;
+       INFCONTEXT              manufacturerContext;
+       BOOL                    ok;
+       OSStatus                err             = 0;
+       
+       // Make sure we can open the file
+       handle = SetupOpenInfFile( filename, NULL, INF_STYLE_WIN4, NULL );
+       translate_errno( handle != INVALID_HANDLE_VALUE, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
 
-       StringMap                               strings;
-       ok = file.Open( filename,  CFile::modeRead|CFile::typeText, &feError);
-       err = translate_errno( ok, errno_compat(), kUnknownErr );
+       // Make sure it's a printer file
+       ok = SetupGetLineText( NULL, handle, TEXT( "Version" ), TEXT( "Class" ), line, sizeof( line ), NULL );
+       translate_errno( ok, GetLastError(), kUnknownErr );
        require_noerr( err, exit );
+       klass = line;
+       require_action( klass == TEXT( "Printer" ), exit, err = kUnknownErr );
 
-       check ( state == Looking );
-       check ( iter == manufacturers.end() );
+       sectionCount = SetupGetLineCount( handle, section );
+       translate_errno( sectionCount != -1, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
 
-       //
-       // first, parse the file looking for string sections
-       //
-       while (file.ReadString(s))
+       memset( &manufacturerContext, 0, sizeof( manufacturerContext ) );
+                       
+       for ( LONG i = 0; i < sectionCount; i++ )
        {
-               //
-               // check for comment
-               //
-               if (s.Find(';') == 0)
+               Manufacturers::iterator iter;
+               Manufacturer    *       manufacturer;
+               CString                         manufacturerName;
+               CString                         temp;
+               CStringList                     modelSectionNameDecl;
+               CString                         modelSectionName;
+               CString                         baseModelName;
+               CString                         model;
+               INFCONTEXT                      modelContext;
+               LONG                            modelCount;
+               POSITION                        p;
+
+               if ( i == 0 )
                {
-                       continue;
-               }
-
-               //
-               // check for tag
-               //
-               else if (s.Find('[') == 0)
-               {
-                       //
-                       // handle any capitalization issues here
-                       //
-                       CString tag = s;
-
-                       tag.MakeLower();
-
-                       if (tag == L"[strings]")
-                       {
-                               state = ParsingStrings;
-                       }
-                       else
-                       {
-                               state = Looking;
-                       }
+                       ok = SetupFindFirstLine( handle, section, NULL, &manufacturerContext );
+                       err = translate_errno( ok, GetLastError(), kUnknownErr );
+                       require_noerr( err, exit );
                }
                else
                {
-                       switch (state)
-                       {
-                               case ParsingStrings:
-                               {
-                                       int     curPos = 0;
-
-                                       if (s.GetLength() > 0)
-                                       {
-                                               CString key = s.Tokenize(L"=",curPos);
-                                               CString val = s.Tokenize(L"=",curPos);
-
-                                               //
-                                               // get rid of all delimiters
-                                               //
-                                               key.Trim();
-                                               val.Remove('"');
-       
-                                               //
-                                               // and store it
-                                               //
-                                               strings[key] = val;
-                                       }
-                               }
-                               break;
-                       }
+                       ok = SetupFindNextLine( &manufacturerContext, &manufacturerContext );
+                       err = translate_errno( ok, GetLastError(), kUnknownErr );
+                       require_noerr( err, exit );
                }
-       }
-
-       file.Close();
 
-       ok = file.Open( filename,  CFile::modeRead|CFile::typeText, &feError);
-       err = translate_errno( ok, errno_compat(), kUnknownErr );
-       require_noerr( err, exit );
-
-       state = Looking;
+               ok = SetupGetStringField( &manufacturerContext, 0, line, sizeof( line ), NULL );
+               err = translate_errno( ok, GetLastError(), kUnknownErr );
+               require_noerr( err, exit );
+               manufacturerName = line;
 
-       check ( iter == manufacturers.end() );
+               ok = SetupGetLineText( &manufacturerContext, handle, NULL, NULL, line, sizeof( line ), NULL );
+               err = translate_errno( ok, GetLastError(), kUnknownErr );
+               require_noerr( err, exit );
 
-       while (file.ReadString(s))
-       {
+               // Try to find some model section name that has entries. Explanation of int file structure
+               // can be found at:
                //
-               // check for comment
-               //
-               if (s.Find(';') == 0)
+               // <http://msdn.microsoft.com/en-us/library/ms794359.aspx>
+               Split( line, ',', modelSectionNameDecl );
+
+               p                                       = modelSectionNameDecl.GetHeadPosition();
+               modelSectionName        = modelSectionNameDecl.GetNext( p );
+               modelCount                      = SetupGetLineCount( handle, modelSectionName );
+               baseModelName           = modelSectionName;
+               
+               while ( modelCount <= 0 && p )
                {
-                       continue;
+                       CString targetOSVersion;
+
+                       targetOSVersion         = modelSectionNameDecl.GetNext( p );
+                       modelSectionName        = baseModelName + TEXT( "." ) + targetOSVersion;
+                       modelCount                      = SetupGetLineCount( handle, modelSectionName );
                }
 
-               //
-               // check for tag
-               //
-               else if (s.Find('[') == 0)
+               if ( modelCount > 0 )
                {
-                       //
-                       // handle any capitalization issues here
-                       //
-                       CString tag = s;
+                       manufacturerName = NormalizeManufacturerName( manufacturerName );
 
-                       tag.MakeLower();
+                       iter = manufacturers.find( manufacturerName );
 
-                       if (tag == L"[manufacturer]")
+                       if ( iter != manufacturers.end() )
                        {
-                               state = ParsingManufacturers;
+                               manufacturer = iter->second;
+                               require_action( manufacturer, exit, err = kUnknownErr );
                        }
                        else
                        {
-                               CString name;
-                               int             curPos;
-
-                               //
-                               // remove the leading and trailing delimiters
-                               //
-                               s.Remove('[');
-                               s.Remove(']');
-
-                               //
-                               // <rdar://problem/4826126>
-                               //
-                               // Ignore decorations in model declarations
-                               //
-                               curPos  = 0;
-                               name    = s.Tokenize( L".", curPos );
-
-                               //
-                               // check to see if this is a printer entry
-                               //
-                               iter = manufacturers.find( name );
-
-                               if (iter != manufacturers.end())
+                               try
                                {
-                                       state = ParsingModels;
+                                       manufacturer = new Manufacturer;
                                }
-                               else
+                               catch (...)
                                {
-                                       state = Looking;
+                                       manufacturer = NULL;
                                }
-                       }
-               }
-               //
-               // only look at this if the line isn't empty, or
-               // if it isn't a comment
-               //
-               else if ((s.GetLength() > 0) && (s.Find(';') != 0))
-               {
-                       switch (state)
-                       {
-                               //
-                               // if we're parsing manufacturers, then we will parse
-                               // an entry of the form key=val, where key is a delimited
-                               // string specifying a manufacturer name, and val is
-                               // a tag that is used later in the file.  the key is
-                               // delimited by either '"' (quotes) or '%' (percent sign).
-                               //
-                               // the tag is used further down the file when models are
-                               // declared.  this allows multiple manufacturers to exist
-                               // in a single inf file.
-                               //
-                               case ParsingManufacturers:
-                               {
-                                       Manufacturer    *       manufacturer;
-                                       int                                     curPos = 0;
-
-                                       CString key = s.Tokenize(L"=",curPos);
-                                       CString val = s.Tokenize(L"=",curPos);
-
-                                       try
-                                       {
-                                               manufacturer = new Manufacturer;
-                                       }
-                                       catch (...)
-                                       {
-                                               manufacturer = NULL;
-                                       }
-
-                                       require_action( manufacturer, exit, err = kNoMemoryErr );
-
-                                       //
-                                       // if it's a variable, look it up
-                                       //
-                                       if (key.Find('%') == 0)
-                                       {
-                                               StringMap::iterator it;
 
-                                               key.Remove('%');
-
-                                               it = strings.find(key);
-
-                                               if (it != strings.end())
-                                               {
-                                                       key = it->second;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               key.Remove('"');
-                                       }
-
-                                       val.TrimLeft();
-                                       val.TrimRight();
-
-                                       //
-                                       // why is there no consistency in inf files?
-                                       //
-                                       if (val.GetLength() == 0)
-                                       {
-                                               val = key;
-                                       }
+                               require_action( manufacturer, exit, err = kNoMemoryErr );
 
-                                       //
-                                       // fix the manufacturer name if necessary
-                                       //
-                                       curPos  =       0;
-                                       val             =       val.Tokenize(L",", curPos);
+                               manufacturer->name                                      = manufacturerName;
+                               manufacturers[ manufacturerName ]       = manufacturer;
+                       }
 
-                                       for ( ;; )
-                                       {
-                                               CString decoration;
-
-                                               decoration = val.Tokenize( L",", curPos );
-
-                                               if ( decoration.GetLength() > 0 )
-                                               {
-                                                       manufacturer->decorations.push_back( decoration );
-                                               }
-                                               else
-                                               {
-                                                       break;
-                                               }
-                                       }
+                       memset( &modelContext, 0, sizeof( modelContext ) );
 
-                                       manufacturer->name = NormalizeManufacturerName( key );
-                                       manufacturer->tag  = val;
+                       for ( LONG j = 0; j < modelCount; j++ )
+                       {
+                               CString modelName;
+                               Model * model;
 
-                                       manufacturers[val] = manufacturer;
+                               if ( j == 0 )
+                               {
+                                       ok = SetupFindFirstLine( handle, modelSectionName, NULL, &modelContext );
+                                       err = translate_errno( ok, GetLastError(), kUnknownErr );
+                                       require_noerr( err, exit );
                                }
-                               break;
-
-                               case ParsingModels:
+                               else
                                {
-                                       check( iter != manufacturers.end() );
-
-                                       Model   *       model;
-                                       int                     curPos = 0;
-
-                                       CString name            = s.Tokenize(L"=",curPos);
-                                       CString description = s.Tokenize(L"=",curPos);
-                                       
-                                       if (name.Find('%') == 0)
-                                       {
-                                               StringMap::iterator it;
-
-                                               name.Remove('%');
+                                       SetupFindNextLine( &modelContext, &modelContext );
+                                       err = translate_errno( ok, GetLastError(), kUnknownErr );
+                                       require_noerr( err, exit );
+                               }
 
-                                               it = strings.find(name);
+                               ok = SetupGetStringField( &modelContext, 0, line, sizeof( line ), NULL );
+                               err = translate_errno( ok, GetLastError(), kUnknownErr );
+                               require_noerr( err, exit );
 
-                                               if (it != strings.end())
-                                               {
-                                                       name = it->second;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               name.Remove('"');
-                                       }
+                               modelName = line;
 
-                                       name.Trim();
-                                       description.Trim();
-                                       
-                                       //
-                                       // If true, see if we've seen this guy before
-                                       //
-                                       if (checkForDuplicateModels == true)
-                                       {
-                                               if ( MatchModel( iter->second, ConvertToModelName( name ) ) != NULL )
-                                               {
-                                                       continue;
-                                               }
-                                       }
-
-                                       //
-                                       // Stock Vista printer inf files embed guids in the model
-                                       // declarations for Epson printers. Let's ignore those.
-                                       //
-                                       if ( name.Find( L"{", 0 ) != -1 )
+                               if (checkForDuplicateModels == true)
+                               {
+                                       if ( MatchModel( manufacturer, ConvertToModelName( modelName ) ) != NULL )
                                        {
                                                continue;
                                        }
+                               }
 
-                                       try
-                                       {
-                                               model = new Model;
-                                       }
-                                       catch (...)
-                                       {
-                                               model = NULL;
-                                       }
-
-                                       require_action( model, exit, err = kNoMemoryErr );
-
-                                       model->infFileName              =       filename;
-                                       model->displayName              =       name;
-                                       model->name                             =       name;
-                                       model->driverInstalled  =       false;
-
-                                       iter->second->models.push_back(model);
+                               //
+                               // Stock Vista printer inf files embed guids in the model
+                               // declarations for Epson printers. Let's ignore those.
+                               //
+                               if ( modelName.Find( TEXT( "{" ), 0 ) != -1 )
+                               {
+                                       continue;
                                }
-                               break;
 
-                               default:
+                               try
+                               {
+                                       model = new Model;
+                               }
+                               catch (...)
                                {
-                                       // pay no attention if we are in any other state
+                                       model = NULL;
                                }
-                               break;
+
+                               require_action( model, exit, err = kNoMemoryErr );
+
+                               model->infFileName              =       filename;
+                               model->displayName              =       modelName;
+                               model->name                             =       modelName;
+                               model->driverInstalled  =       false;
+
+                               manufacturer->models.push_back(model);
                        }
                }
        }
 
 exit:
 
-       file.Close();
+       if ( handle != INVALID_HANDLE_VALUE )
+       {
+               SetupCloseInfFile( handle );
+               handle = NULL;
+       }
 
-       return (err);
+       return err;
 }
 
+
 // -------------------------------------------------------
 // LoadPrintDriverDefs
 //
@@ -1622,9 +1456,14 @@ CThirdPage::OnSetActive()
        // and try and match the printer
        //
 
-       if ( psheet->GetLastPage() == psheet->GetPage(1) )
+       if ( psheet->GetLastPage() == psheet->GetPage(0) )
        {
                MatchPrinter( m_manufacturers, printer, service, true );
+
+               if ( ( m_manufacturerSelected != NULL ) && ( m_modelSelected != NULL  ) )
+               {
+                       GetParent()->PostMessage(PSM_SETCURSEL, 2 );
+               }
        }
        else
        {
@@ -1816,6 +1655,16 @@ void CThirdPage::OnBnClickedHaveDisk()
 
                                break;
                        }
+                       else
+                       {
+                               CString errorMessage;
+                               CString errorCaption;
+
+                               errorMessage.LoadString( IDS_BAD_INF_FILE );
+                               errorCaption.LoadString( IDS_BAD_INF_FILE_CAPTION );
+
+                               MessageBox( errorMessage, errorCaption, MB_OK );
+                       }
                }
                else
                {
@@ -1827,3 +1676,21 @@ exit:
 
        return;
 }
+
+
+void
+CThirdPage::Split( const CString & string, TCHAR ch, CStringList & components )
+{
+       CString temp;
+       int             n;
+
+       temp = string;
+       
+       while ( ( n = temp.Find( ch ) ) != -1 )
+       {
+               components.AddTail( temp.Left( n ) );
+               temp = temp.Right( temp.GetLength() - ( n + 1 ) );
+       }
+
+       components.AddTail( temp );
+}
index 2ab62b1514e1b26e1e290240f63ed3257dfdcc76..cb929d43274f15798eb753cc228d1e091bc32474 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: ThirdPage.h,v $
+Revision 1.10  2009/05/29 20:43:37  herscher
+<rdar://problem/6928136> Printer Wizard doesn't work correctly in Windows 7 64 bit
+
 Revision 1.9  2007/04/13 23:42:20  herscher
 <rdar://problem/4580061> mDNS: Printers added using Bonjour should be set as the default printer.
 
@@ -179,7 +182,12 @@ public:
        afx_msg void OnLvnItemchangedPrinterModel(NMHDR *pNMHDR, LRESULT *pResult);
        afx_msg void OnBnClickedDefaultPrinter();
 private:
+
+       void
+       Split( const CString & string, TCHAR ch, CStringList & components );
+
        CButton m_defaultPrinterCtrl;
+
 public:
        CStatic m_printerSelectionText;
        CStatic *       m_printerImage;
index c467f3d2c3893223d0c6605f8a335bb2f666f2d1..41a3251c3c54b2f575ca6b9073ca178c4a58f757 100644 (file)
     Change History (most recent first):
     
 $Log: UtilTypes.h,v $
+Revision 1.18  2009/05/29 20:43:37  herscher
+<rdar://problem/6928136> Printer Wizard doesn't work correctly in Windows 7 64 bit
+
+Revision 1.17  2009/05/27 04:59:57  herscher
+<rdar://problem/4517393> COMPATIBILITY WITH HP CLJ4700
+<rdar://problem/6142138> Compatibility with Samsung print driver files
+
 Revision 1.16  2007/04/20 22:58:10  herscher
 <rdar://problem/4826126> mDNS: Printer Wizard doesn't offer generic HP printers or generic PS support on Vista RC2
 
@@ -97,7 +104,6 @@ namespace PrinterSetupWizard
        typedef std::list<Printer*>     Printers;
        typedef std::list<Service*>     Services;
        typedef std::list<Model*>       Models;
-       typedef std::list<CString>      Decorations;
 
        struct Printer
        {
@@ -218,9 +224,7 @@ namespace PrinterSetupWizard
        struct Manufacturer
        {
                CString         name;
-               CString         tag;
                Models          models;
-               Decorations     decorations;
 
                Model*
                find( const CString & name );
index 90a067ee210914594fba9dfb2bdededd699cd1d9..a72bccadab458e50ec7c41b8796ab7652fedff2d 100644 (file)
@@ -1,22 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
-<assemblyIdentity 
-    version="1.0.0.0" 
-    processorArchitecture="X86" 
-    name="Microsoft.Windows.Wiz97_3"
-    type="win32" 
-/> 
-<description>Your app description here</description> 
-<dependency> 
-    <dependentAssembly> 
-        <assemblyIdentity 
-            type="win32" 
-            name="Microsoft.Windows.Common-Controls" 
-            version="6.0.0.0" 
-            processorArchitecture="X86" 
-            publicKeyToken="6595b64144ccf1df" 
-            language="*" 
-        /> 
-    </dependentAssembly> 
-</dependency> 
+       <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Apple.Bonjour.PrinterSetupWizard" type="win32"/> 
+       <description>Printer Setup Wizard</description> 
+       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+               <security>
+                       <requestedPrivileges>
+                               <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
+                       </requestedPrivileges>
+               </security>
+       </trustInfo>
+       <dependency> 
+       <dependentAssembly> 
+               <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*"/> 
+       </dependentAssembly> 
+       </dependency> 
 </assembly>
diff --git a/Clients/PrinterSetupWizard/res/PrinterSetupWizard64.manifest b/Clients/PrinterSetupWizard/res/PrinterSetupWizard64.manifest
new file mode 100644 (file)
index 0000000..f535d80
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
+       <assemblyIdentity version="1.0.0.0" processorArchitecture="amd64" name="Apple.Bonjour.PrinterSetupWizard" type="win32"/> 
+       <description>Printer Setup Wizard</description> 
+       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+               <security>
+                       <requestedPrivileges>
+                               <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
+                       </requestedPrivileges>
+               </security>
+       </trustInfo>
+       <dependency> 
+       <dependentAssembly> 
+               <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*"/> 
+       </dependentAssembly> 
+       </dependency> 
+</assembly>
index 46cd451d94ed0af43bfc84cc05cf12d8e10d1cd7..4a4f98077a9159a352ed5da65201ba9518846f95 100755 (executable)
@@ -2,7 +2,6 @@
 // Microsoft Visual C++ generated include file.\r
 // Used by PrinterSetupWizard.rc\r
 //\r
-#define IDR_MANIFEST                    1\r
 #define IDM_ABOUTBOX                    0x0010\r
 #define IDD_ABOUTBOX                    100\r
 #define IDS_ABOUTBOX                    101\r
 #define IDI_PRINTER                     141\r
 #define IDS_REINSTALL                                  142\r
 #define IDS_REINSTALL_CAPTION                  143\r
+#define IDC_INFO                                               144\r
+#define IDS_PRINTER_UNAVAILABLE         145\r
+#define IDS_BAD_INF_FILE                               150\r
+#define IDS_BAD_INF_FILE_CAPTION               151\r
 #define IDC_BUTTON1                     1000\r
 #define IDC_LIST1                       1000\r
 #define IDC_BROWSE_LIST                 1000\r
index b5a3bf99b7571290513da9d31290df57110cf32b..951c54d027e5cea53110c993a20e79708ba53234 100755 (executable)
@@ -2,7 +2,6 @@
 // Microsoft Visual C++ generated include file.\r
 // Used by PrinterSetupWizardLocRes.rc\r
 //\r
-#define IDR_MANIFEST                    1\r
 #define IDM_ABOUTBOX                    0x0010\r
 #define IDD_ABOUTBOX                    100\r
 #define IDS_ABOUTBOX                    101\r
@@ -51,6 +50,8 @@
 #define IDS_REINSTALL_CAPTION           143\r
 #define IDC_INFO                                                                144\r
 #define IDS_PRINTER_UNAVAILABLE         145\r
+#define IDS_BAD_INF_FILE                               150\r
+#define IDS_BAD_INF_FILE_CAPTION               151\r
 #define IDC_BUTTON1                     1000\r
 #define IDC_LIST1                       1000\r
 #define IDC_BROWSE_LIST                 1000\r
index 46cd451d94ed0af43bfc84cc05cf12d8e10d1cd7..4a4f98077a9159a352ed5da65201ba9518846f95 100755 (executable)
@@ -2,7 +2,6 @@
 // Microsoft Visual C++ generated include file.\r
 // Used by PrinterSetupWizard.rc\r
 //\r
-#define IDR_MANIFEST                    1\r
 #define IDM_ABOUTBOX                    0x0010\r
 #define IDD_ABOUTBOX                    100\r
 #define IDS_ABOUTBOX                    101\r
 #define IDI_PRINTER                     141\r
 #define IDS_REINSTALL                                  142\r
 #define IDS_REINSTALL_CAPTION                  143\r
+#define IDC_INFO                                               144\r
+#define IDS_PRINTER_UNAVAILABLE         145\r
+#define IDS_BAD_INF_FILE                               150\r
+#define IDS_BAD_INF_FILE_CAPTION               151\r
 #define IDC_BUTTON1                     1000\r
 #define IDC_LIST1                       1000\r
 #define IDC_BROWSE_LIST                 1000\r
index 2165beb5e2d224912bb327ef3da638fd18793a44..a80011a4aec35a3a2af676b1d5b9fee6992e102a 100755 (executable)
-<VisualStudioProject>\r
-    <CSHARP\r
-        ProjectType = "Local"\r
-        ProductVersion = "7.0.9466"\r
-        SchemaVersion = "1.0"\r
-        ProjectGuid = "{726DED99-34D0-45F3-9F4D-C7068DF4BCDA}"\r
-    >\r
-        <Build>\r
-            <Settings\r
-                ApplicationIcon = "App.ico"\r
-                AssemblyKeyContainerName = ""\r
-                AssemblyName = "SimpleChat.NET"\r
-                AssemblyOriginatorKeyFile = ""\r
-                DefaultClientScript = "JScript"\r
-                DefaultHTMLPageLayout = "Grid"\r
-                DefaultTargetSchema = "IE50"\r
-                DelaySign = "false"\r
-                OutputType = "WinExe"\r
-                RootNamespace = "SimpleChat.NET"\r
-                StartupObject = ""\r
-            >\r
-                <Config\r
-                    Name = "Debug"\r
-                    AllowUnsafeBlocks = "false"\r
-                    BaseAddress = "285212672"\r
-                    CheckForOverflowUnderflow = "false"\r
-                    ConfigurationOverrideFile = ""\r
-                    DefineConstants = "DEBUG;TRACE"\r
-                    DocumentationFile = ""\r
-                    DebugSymbols = "true"\r
-                    FileAlignment = "4096"\r
-                    IncrementalBuild = "true"\r
-                    Optimize = "false"\r
-                    OutputPath = "bin\Debug\"\r
-                    RegisterForComInterop = "false"\r
-                    RemoveIntegerChecks = "false"\r
-                    TreatWarningsAsErrors = "false"\r
-                    WarningLevel = "4"\r
-                />\r
-                <Config\r
-                    Name = "Release"\r
-                    AllowUnsafeBlocks = "false"\r
-                    BaseAddress = "285212672"\r
-                    CheckForOverflowUnderflow = "false"\r
-                    ConfigurationOverrideFile = ""\r
-                    DefineConstants = "TRACE"\r
-                    DocumentationFile = ""\r
-                    DebugSymbols = "false"\r
-                    FileAlignment = "4096"\r
-                    IncrementalBuild = "false"\r
-                    Optimize = "true"\r
-                    OutputPath = "bin\Release\"\r
-                    RegisterForComInterop = "false"\r
-                    RemoveIntegerChecks = "false"\r
-                    TreatWarningsAsErrors = "false"\r
-                    WarningLevel = "4"\r
-                />\r
-            </Settings>\r
-            <References>\r
-                <Reference\r
-                    Name = "System"\r
-                    AssemblyName = "System"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"\r
-                />\r
-                <Reference\r
-                    Name = "System.Data"\r
-                    AssemblyName = "System.Data"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"\r
-                />\r
-                <Reference\r
-                    Name = "System.Drawing"\r
-                    AssemblyName = "System.Drawing"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"\r
-                />\r
-                <Reference\r
-                    Name = "System.Windows.Forms"\r
-                    AssemblyName = "System.Windows.Forms"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"\r
-                />\r
-                <Reference\r
-                    Name = "System.XML"\r
-                    AssemblyName = "System.XML"\r
-                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"\r
-                />\r
-                <Reference\r
-                    Name = "dnssd.NET"\r
-                    AssemblyName = "dnssd.NET"\r
-                    HintPath = "..\..\mDNSWindows\DLL.NET\Release\dnssd.NET.dll"\r
-                />\r
-            </References>\r
-        </Build>\r
-        <Files>\r
-            <Include>\r
-                <File\r
-                    RelPath = "App.ico"\r
-                    BuildAction = "Content"\r
-                />\r
-                <File\r
-                    RelPath = "AssemblyInfo.cs"\r
-                    BuildAction = "Compile"\r
-                />\r
-                <File\r
-                    RelPath = "SimpleChat.cs"\r
-                    SubType = "Form"\r
-                    BuildAction = "Compile"\r
-                />\r
-                <File\r
-                    RelPath = "SimpleChat.resx"\r
-                    DependentUpon = "SimpleChat.cs"\r
-                    BuildAction = "EmbeddedResource"\r
-                />\r
-            </Include>\r
-        </Files>\r
-    </CSHARP>\r
-</VisualStudioProject>\r
-\r
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <ProjectType>Local</ProjectType>\r
+    <ProductVersion>8.0.50727</ProductVersion>\r
+    <SchemaVersion>2.0</SchemaVersion>\r
+    <ProjectGuid>{726DED99-34D0-45F3-9F4D-C7068DF4BCDA}</ProjectGuid>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+    <ApplicationIcon>App.ico</ApplicationIcon>\r
+    <AssemblyKeyContainerName>\r
+    </AssemblyKeyContainerName>\r
+    <AssemblyName>SimpleChat.NET</AssemblyName>\r
+    <AssemblyOriginatorKeyFile>\r
+    </AssemblyOriginatorKeyFile>\r
+    <DefaultClientScript>JScript</DefaultClientScript>\r
+    <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>\r
+    <DefaultTargetSchema>IE50</DefaultTargetSchema>\r
+    <DelaySign>false</DelaySign>\r
+    <OutputType>WinExe</OutputType>\r
+    <RootNamespace>SimpleChat.NET</RootNamespace>\r
+    <StartupObject>\r
+    </StartupObject>\r
+    <FileUpgradeFlags>\r
+    </FileUpgradeFlags>\r
+    <UpgradeBackupLocation>\r
+    </UpgradeBackupLocation>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>\r
+    <BaseAddress>285212672</BaseAddress>\r
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>\r
+    <ConfigurationOverrideFile>\r
+    </ConfigurationOverrideFile>\r
+    <DefineConstants>DEBUG;TRACE</DefineConstants>\r
+    <DocumentationFile>\r
+    </DocumentationFile>\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <FileAlignment>4096</FileAlignment>\r
+    <Optimize>false</Optimize>\r
+    <RegisterForComInterop>false</RegisterForComInterop>\r
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>\r
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>\r
+    <WarningLevel>4</WarningLevel>\r
+    <DebugType>full</DebugType>\r
+    <ErrorReport>prompt</ErrorReport>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>\r
+    <BaseAddress>285212672</BaseAddress>\r
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>\r
+    <ConfigurationOverrideFile>\r
+    </ConfigurationOverrideFile>\r
+    <DefineConstants>TRACE</DefineConstants>\r
+    <DocumentationFile>\r
+    </DocumentationFile>\r
+    <DebugSymbols>false</DebugSymbols>\r
+    <FileAlignment>4096</FileAlignment>\r
+    <Optimize>true</Optimize>\r
+    <RegisterForComInterop>false</RegisterForComInterop>\r
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>\r
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>\r
+    <WarningLevel>4</WarningLevel>\r
+    <DebugType>none</DebugType>\r
+    <ErrorReport>prompt</ErrorReport>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System">\r
+      <Name>System</Name>\r
+    </Reference>\r
+    <Reference Include="System.Data">\r
+      <Name>System.Data</Name>\r
+    </Reference>\r
+    <Reference Include="System.Drawing">\r
+      <Name>System.Drawing</Name>\r
+    </Reference>\r
+    <Reference Include="System.Windows.Forms">\r
+      <Name>System.Windows.Forms</Name>\r
+    </Reference>\r
+    <Reference Include="System.XML">\r
+      <Name>System.XML</Name>\r
+    </Reference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Content Include="App.ico" />\r
+    <Compile Include="AssemblyInfo.cs" />\r
+    <Compile Include="SimpleChat.cs">\r
+      <SubType>Form</SubType>\r
+    </Compile>\r
+    <EmbeddedResource Include="SimpleChat.resx">\r
+      <DependentUpon>SimpleChat.cs</DependentUpon>\r
+      <SubType>Designer</SubType>\r
+    </EmbeddedResource>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <COMReference Include="Bonjour">\r
+      <Guid>{18FBED6D-F2B7-4EC8-A4A4-46282E635308}</Guid>\r
+      <VersionMajor>1</VersionMajor>\r
+      <VersionMinor>0</VersionMinor>\r
+      <Lcid>0</Lcid>\r
+      <WrapperTool>tlbimp</WrapperTool>\r
+      <Isolated>False</Isolated>\r
+    </COMReference>\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />\r
+  <PropertyGroup>\r
+    <PreBuildEvent>\r
+    </PreBuildEvent>\r
+    <PostBuildEvent>\r
+    </PostBuildEvent>\r
+  </PropertyGroup>\r
+</Project>
\ No newline at end of file
index e7f3b1e2f639db311c7d9023d6c8b1aa51463eff..cdfdad3ca54b2ce339e0e9098981896bc6f5519c 100755 (executable)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: SimpleChat.cs,v $
+Revision 1.7  2009/06/04 20:21:19  herscher
+<rdar://problem/3948252> Update code to work with DNSSD COM component
+
 Revision 1.6  2006/08/14 23:24:21  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -48,7 +51,7 @@ using System.Net;
 using System.Net.Sockets;
 using System.Data;
 using System.Text;
-using Apple.DNSSD;
+using Bonjour;
 
 namespace SimpleChat.NET
 {
@@ -57,426 +60,226 @@ namespace SimpleChat.NET
        /// </summary>
        /// 
 
-       //
-       // PeerData
-       //
-       // Holds onto the information associated with a peer on the network
-       //
-       public class PeerData
-       {
-               public int                      InterfaceIndex;
-               public String           Name;
-               public String           Type;
-               public String           Domain;
-               public IPAddress        Address;
-               public int                      Port;
-
-               public override String
-               ToString()
-               {
-                       return Name;
-               }
-
-               public override bool
-               Equals(object other)
-               {
-                       bool result = false;
-
-                       if (other != null)
-                       {
-                               if ((object) this == other)
-                               {
-                                       result = true;
-                               }
-                               else if (other is PeerData)
-                               {
-                                       PeerData otherPeerData = (PeerData) other;
-
-                                       result = (this.Name == otherPeerData.Name);
-                               }
-                       }
-
-                       return result;
-               }
-       
-               public override int
-               GetHashCode()
-               {
-                       return Name.GetHashCode();
-               }
-       };
-
-       //
-       // ResolveData
-       //
-       // Holds onto the information associated with the resolution
-       // of a DNSService
-       //
-       public class ResolveData
-       {
-               public int              InterfaceIndex;
-               public String   FullName;
-               public String   HostName;
-               public int              Port;
-               public Byte[]   TxtRecord;
-
-               public override String
-               ToString()
-               {
-                       return FullName;
-               }
-       };
-
-
-       //
-       // SocketStateObject
-       //
-       // Holds onto the data associated with an asynchronous
-       // socket operation
-       //
-       class SocketStateObject
+       public class SimpleChat : System.Windows.Forms.Form
        {
-               public const int                BUFFER_SIZE = 1024;
-               private Socket                  m_socket;
-               public byte[]                   m_buffer;
-               public bool                             m_complete;
-               public StringBuilder    m_sb = new StringBuilder();
-
-               public SocketStateObject(Socket socket)
-               {
-                       m_buffer        = new byte[BUFFER_SIZE];
-                       m_complete      = false;
-                       m_socket        = socket;
-               }
-
-               public Socket
-               WorkSocket
-               {
-                       get
-                       {
-                               return m_socket;
-                       }
-               }
-       }
-       public class Form1 : System.Windows.Forms.Form
-       {
-               private System.Windows.Forms.ComboBox comboBox1;
-               private System.Windows.Forms.TextBox textBox2;
-               private System.Windows.Forms.Button button1;
-               private System.Windows.Forms.Label label1;
-               private ServiceRef registrar = null;
-               private ServiceRef browser = null;
-               private ServiceRef resolver = null;
-               private String                                  myName;
+               private System.Windows.Forms.ComboBox   comboBox1;
+               private System.Windows.Forms.TextBox    textBox2;
+               private System.Windows.Forms.Button     button1;
+               private System.Windows.Forms.Label      label1;\r
+        private Bonjour.DNSSDEventManager       m_eventManager = null;\r
+        private Bonjour.DNSSDService            m_service = null;\r
+        private Bonjour.DNSSDService            m_registrar = null;\r
+        private Bonjour.DNSSDService            m_browser = null;\r
+        private Bonjour.DNSSDService            m_resolver = null;
+               private String                                          m_name;\r
+        private Socket                          m_socket = null;\r
+        private const int                       BUFFER_SIZE = 1024;\r
+        public byte[]                           m_buffer = new byte[BUFFER_SIZE];\r
+        public bool                             m_complete = false;\r
+        public StringBuilder                    m_sb = new StringBuilder();\r
+        delegate void                           ReadMessageCallback(String data);\r
+        ReadMessageCallback                     m_readMessageCallback;
                /// <summary>
                /// Required designer variable.
                /// </summary>
                private System.ComponentModel.Container components = null;
-               
-               //
-               // These all of our callbacks.  These are invoked in the context
-               // of the main (GUI) thread.  The DNSService callbacks Invoke()
-               // them
-               delegate void RegisterServiceCallback(String name);
-               delegate void AddPeerCallback(PeerData data);
-               delegate void RemovePeerCallback(PeerData data);
-               delegate void ResolveServiceCallback(ResolveData data);
-               delegate void ResolveAddressCallback(System.Net.IPAddress address);
-               delegate void ReadMessageCallback(String data);
-
-               RegisterServiceCallback registerServiceCallback;
-               AddPeerCallback                 addPeerCallback;
-               RemovePeerCallback              removePeerCallback;
-               ResolveServiceCallback  resolveServiceCallback;
-               ResolveAddressCallback  resolveAddressCallback;
-               ReadMessageCallback             readMessageCallback;
                private System.Windows.Forms.RichTextBox richTextBox1;
 
+               // ServiceRegistered
                //
-               // The socket that we will be reading data from
-               //
-               Socket socket = null;
-
-               //
-               // OnRegisterService
-               //
-               // The name that we are passed might be different than the
-               // name we called Register with.  So we hold onto this name
-               // rather than the name we Register with.
-               //
-               // This is called (indirectly) from OnRegisterReply().
-               //
-               private void
-               OnRegisterService
-                               (
-                               String name
-                               )
-               {
-                       myName = name;
-               }
-
-               //
-               // OnAddPeer
-               //
-               // Called when DNSServices detects a new P2P Chat peer has
-               // joined.
-               //
-               // This is called (indirectly) from OnBrowseReply()
-               //
-               private void
-               OnAddPeer
-                               (
-                               PeerData  peer
-                               )
-               {
-                       comboBox1.Items.Add(peer);
-
-                       if (comboBox1.Items.Count == 1)
-                       {
-                               comboBox1.SelectedIndex = 0;
-                       }
-               }
-
-               //
-               // OnRemovePeer
-               //
-               // Called when DNSServices detects a P2P peer has left
-               // the network
-               //
-               // This is called (indirectly) from OnBrowseReply()
-               //
-               private void
-               OnRemovePeer
-                               (
-                               PeerData  peer
-                               )
-               {
-                       comboBox1.Items.Remove(peer);
-               }
-
-               //
-               // OnResolveService
-               //
-               // Called when DNSServices has resolved a service.
-               //
-               // This is called (indirectly) from OnResolveService()
-               //
-               private void
-               OnResolveService
-                               (
-                               ResolveData data
-                               )
-               {
-                       resolver.Dispose();
-
-                       PeerData peer = (PeerData) comboBox1.SelectedItem;
-
-                       peer.Port = data.Port;
-
-                       try
-                       {
-                               resolver = DNSService.QueryRecord(0, 0, data.HostName, /* ns_t_a */ 1, /* ns_t_c */ 1, new DNSService.QueryRecordReply(OnQueryRecordReply));
-                       }
-                       catch
-                       {
-                               MessageBox.Show("QueryRecord Failed", "Error");
-                               Application.Exit();
-                       }
-               }
-
-               //
-               // OnResolveAddress
-               //
-               // Called when DNSServices has finished a query operation
-               //
-               // This is called (indirectly) from OnQueryRecordReply()
-               //
-               private void
-               OnResolveAddress
-                               (
-                               System.Net.IPAddress address
-                               )
-               {
-                       resolver.Dispose();
-
-                       PeerData peer = (PeerData) comboBox1.SelectedItem;
-
-                       peer.Address = address;
-               }
-
-               //
-               // OnReadMessage
-               //
-               // Called when there is data to be read on a socket
-               //
-               // This is called (indirectly) from OnReadSocket()
-               //
-               private void
-               OnReadMessage
-                               (
-                               String msg
-                               )
-               {
-                       int rgb = 0;
-
-                       for (int i = 0; i < msg.Length && msg[i] != ':'; i++)
-                       {
-                               rgb = rgb ^ ((int) msg[i] << (i % 3 + 2) * 8);
-                       }
-
-                       Color color = Color.FromArgb(rgb & 0x007F7FFF);
-
-                       richTextBox1.SelectionColor = color;
-                       
-                       richTextBox1.AppendText(msg + "\n");
-               }
-
-               //
-               // OnRegisterReply
-               //
-               // Called by DNSServices core as a result of DNSService.Register()
+               // Called by DNSServices core as a result of Register()
                // call
-               //
-               // This is called from a worker thread by DNSService core.
-               //
-               private void
-               OnRegisterReply
-                                       (
-                                       ServiceRef              sdRef,
-                                       ServiceFlags    flags,
-                                       ErrorCode               errorCode,
-                                       String                  name,
-                                       String                  regtype,
-                                       String                  domain)
-               {
-                       if (errorCode == ErrorCode.NoError)
-                       {
-                               Invoke(registerServiceCallback, new Object[]{name});
-                       }
-                       else
-                       {
-                               MessageBox.Show("OnRegisterReply returned an error code " + errorCode, "Error");
-                       }
-               }
-
-
-               //
-               // OnBrowseReply
-               //
-               // Called by DNSServices core as a result of DNSService.Browse()
-               // call
-               //
-               // This is called from a worker thread by DNSService core.
-               //
-               private void
-               OnBrowseReply
-                                       (
-                                       ServiceRef              sdRef,
-                                       ServiceFlags    flags,
-                                       int                             interfaceIndex,
-                                       ErrorCode               errorCode,
-                                       String                  name,
-                                       String                  type,
-                                       String                  domain)
-               {
-                       if (errorCode == ErrorCode.NoError)
-                       {
-                               PeerData peer = new PeerData();
-
-                               peer.InterfaceIndex = interfaceIndex;
-                               peer.Name = name;
-                               peer.Type = type;
-                               peer.Domain = domain;
-                               peer.Address = null;
-
-                               if ((flags & ServiceFlags.Add) != 0)
-                               {
-                                       Invoke(addPeerCallback, new Object[]{peer});
-                               }
-                               else if ((flags == 0) || ((flags & ServiceFlags.MoreComing) != 0))
-                               {
-                                       Invoke(removePeerCallback, new Object[]{peer});
-                               }
-                       }
-                       else
-                       {
-                               MessageBox.Show("OnBrowseReply returned an error code " + errorCode, "Error");
-                       }
-               }
-
-               //
-               // OnResolveReply
+               //\r
+\r
+        public void\r
+        ServiceRegistered\r
+                    (\r
+                    DNSSDService service,\r
+                    DNSSDFlags flags,\r
+                    String name,\r
+                    String regType,\r
+                    String domain\r
+                    )\r
+        {\r
+            m_name = name;\r
+\r
+            try\r
+            {\r
+                m_browser = m_service.Browse(0, 0, "_p2pchat._udp", null, m_eventManager);\r
+            }\r
+            catch\r
+            {\r
+                MessageBox.Show("Browse Failed", "Error");\r
+                Application.Exit();\r
+            }\r
+        }
+
+               //
+               // ServiceFound
+               //
+               // Called by DNSServices core as a result of a Browse call
+               //
+
+               public void
+        ServiceFound
+                                   (
+                                   DNSSDService    sref,
+                                   DNSSDFlags          flags,
+                                   uint                        ifIndex,
+                    String          serviceName,
+                    String          regType,
+                    String          domain
+                                   )
+               {\r
+            if (serviceName != m_name)\r
+            {\r
+                PeerData peer = new PeerData();\r
+\r
+                peer.InterfaceIndex = ifIndex;\r
+                peer.Name = serviceName;\r
+                peer.Type = regType;\r
+                peer.Domain = domain;\r
+                peer.Address = null;\r
+\r
+                comboBox1.Items.Add(peer);\r
+\r
+                if (comboBox1.Items.Count == 1)\r
+                {\r
+                    comboBox1.SelectedIndex = 0;\r
+                }\r
+            }
+               }\r
+\r
+        //\r
+        // ServiceLost\r
+        //\r
+        // Called by DNSServices core as a result of a Browse call\r
+        //\r
+\r
+        public void\r
+        ServiceLost\r
+                    (\r
+                    DNSSDService sref,\r
+                    DNSSDFlags flags,\r
+                    uint ifIndex,\r
+                    String serviceName,\r
+                    String regType,\r
+                    String domain\r
+                    )\r
+        {\r
+            PeerData peer = new PeerData();\r
+\r
+            peer.InterfaceIndex = ifIndex;\r
+            peer.Name = serviceName;\r
+            peer.Type = regType;\r
+            peer.Domain = domain;\r
+            peer.Address = null;\r
+\r
+            comboBox1.Items.Remove(peer);\r
+        }
+
+               //
+               // ServiceResolved
                //
                // Called by DNSServices core as a result of DNSService.Resolve()
                // call
                //
-               // This is called from a worker thread by DNSService core.
-               //
-               private void
-               OnResolveReply
-                       (
-                       ServiceRef              sdRef,
-                       ServiceFlags    flags,
-                       int                             interfaceIndex,
-                       ErrorCode               errorCode,
-                       String                  fullName,
-                       String                  hostName,
-                       int                             port,
-                       Byte[]                  txtRecord
-                       )
-               {
-                       if (errorCode == ErrorCode.NoError)
-                       {
-                               ResolveData data = new ResolveData();
-
-                               data.InterfaceIndex = interfaceIndex;
-                               data.FullName           = fullName;
-                               data.HostName           = hostName;
-                               data.Port                       = port;
-                               data.TxtRecord          = txtRecord;
-
-                               Invoke(resolveServiceCallback, new Object[]{data});
-                       }
-                       else
-                       {
-                               MessageBox.Show("OnResolveReply returned an error code: " + errorCode, "Error");
-                       }
+\r
+        public void\r
+        ServiceResolved\r
+                    (\r
+                    DNSSDService sref,\r
+                    DNSSDFlags flags,\r
+                    uint ifIndex,\r
+                    String fullName,\r
+                    String hostName,\r
+                    ushort port,\r
+                    TXTRecord txtRecord\r
+                    )
+               {\r
+            m_resolver.Stop();\r
+            m_resolver = null;\r
+\r
+            PeerData peer = (PeerData)comboBox1.SelectedItem;\r
+\r
+            peer.Port = port;\r
+\r
+            try\r
+            {\r
+                m_resolver = m_service.QueryRecord(0, ifIndex, hostName, DNSSDRRType.kDNSSDType_A, DNSSDRRClass.kDNSSDClass_IN, m_eventManager );\r
+            }\r
+            catch\r
+            {\r
+                MessageBox.Show("QueryRecord Failed", "Error");\r
+                Application.Exit();\r
+            }
                }
 
                //
-               // OnQueryRecordReply
+               // QueryAnswered
                //
                // Called by DNSServices core as a result of DNSService.QueryRecord()
                // call
                //
-               // This is called from a worker thread by DNSService core.
-               //
-               private void
-               OnQueryRecordReply
+
+               public void
+               QueryAnswered
                        (
-                       ServiceRef              sdRef,
-                       ServiceFlags    flags,
-                       int                             interfaceIndex,
-                       ErrorCode               errorCode,      
-                       String                  fullName,
-                       int                             rrtype,
-                       int                             rrclass,
-                       Byte[]                  rdata,
-                       int                             ttl
-                       )
-               {
-                       if (errorCode == ErrorCode.NoError)
-                       {
-                               uint bits                                       = BitConverter.ToUInt32(rdata, 0);
-                               System.Net.IPAddress data       = new System.Net.IPAddress(bits);
-               
-                               Invoke(resolveAddressCallback, new Object[]{data});
-                       }
-                       else
-                       {
-                               MessageBox.Show("OnQueryRecordReply returned an error code: " + errorCode, "Error");
-                       }
-               }
+            DNSSDService    service, 
+            DNSSDFlags      flags,
+            uint            ifIndex,
+            String          fullName,
+            DNSSDRRType     rrtype,
+            DNSSDRRClass    rrclass,
+            Object          rdata,
+            uint            ttl
+            )
+        {\r
+            m_resolver.Stop();\r
+            m_resolver = null;\r
+\r
+            PeerData peer = (PeerData) comboBox1.SelectedItem;\r
+
+                       uint bits = BitConverter.ToUInt32( (Byte[])rdata, 0);
+                       System.Net.IPAddress address = new System.Net.IPAddress(bits);
+
+            peer.Address = address;
+               }\r
+\r
+        public void\r
+        OperationFailed\r
+                    (\r
+                    DNSSDService service,\r
+                    DNSSDError error\r
+                    )\r
+        {\r
+            MessageBox.Show("Operation returned an error code " + error, "Error");\r
+        }\r
+\r
+        //\r
+        // OnReadMessage\r
+        //\r
+        // Called when there is data to be read on a socket\r
+        //\r
+        // This is called (indirectly) from OnReadSocket()\r
+        //\r
+        private void\r
+        OnReadMessage\r
+                (\r
+                String msg\r
+                )\r
+        {\r
+            int rgb = 0;\r
+\r
+            for (int i = 0; i < msg.Length && msg[i] != ':'; i++)\r
+            {\r
+                rgb = rgb ^ ((int)msg[i] << (i % 3 + 2) * 8);\r
+            }\r
+\r
+            Color color = Color.FromArgb(rgb & 0x007F7FFF);\r
+            richTextBox1.SelectionColor = color;\r
+            richTextBox1.AppendText(msg + Environment.NewLine);\r
+        }
 
                //
                // OnReadSocket
@@ -491,26 +294,17 @@ namespace SimpleChat.NET
                                IAsyncResult ar
                                )
                {
-                       SocketStateObject so = (SocketStateObject) ar.AsyncState;
-                       Socket s = so.WorkSocket;
-
                        try
                        {
-                               if (s == null)
-                               {
-                                       return;
-                               }
-
-                               int read = s.EndReceive(ar);
+                               int read = m_socket.EndReceive(ar);
 
                                if (read > 0)
                                {
-                                       String msg = Encoding.UTF8.GetString(so.m_buffer, 0, read);
-                                       
-                                       Invoke(readMessageCallback, new Object[]{msg});
+                                       String msg = Encoding.UTF8.GetString(m_buffer, 0, read);
+                                       Invoke(m_readMessageCallback, new Object[]{msg});
                                }
 
-                               s.BeginReceive(so.m_buffer, 0, SocketStateObject.BUFFER_SIZE, 0, new AsyncCallback(OnReadSocket), so);
+                               m_socket.BeginReceive(m_buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(OnReadSocket), this);
                        }
                        catch
                        {
@@ -518,19 +312,32 @@ namespace SimpleChat.NET
                }
 
 
-               public Form1()
+               public SimpleChat()
                {
                        //
                        // Required for Windows Form Designer support
                        //
-                       InitializeComponent();
-
-                       registerServiceCallback = new RegisterServiceCallback(OnRegisterService);
-                       addPeerCallback                 = new AddPeerCallback(OnAddPeer);
-                       removePeerCallback              = new RemovePeerCallback(OnRemovePeer);
-                       resolveServiceCallback  = new ResolveServiceCallback(OnResolveService);
-                       resolveAddressCallback  = new ResolveAddressCallback(OnResolveAddress);
-                       readMessageCallback             = new ReadMessageCallback(OnReadMessage);
+                       InitializeComponent();\r
+\r
+            try\r
+            {\r
+                m_service = new DNSSDService();\r
+            }\r
+            catch\r
+            {\r
+                MessageBox.Show("Bonjour Service is not available", "Error");\r
+                Application.Exit();\r
+            }\r
+\r
+            m_eventManager = new DNSSDEventManager();\r
+            m_eventManager.ServiceRegistered += new _IDNSSDEvents_ServiceRegisteredEventHandler(this.ServiceRegistered);\r
+            m_eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);\r
+            m_eventManager.ServiceLost += new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);\r
+            m_eventManager.ServiceResolved += new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);\r
+            m_eventManager.QueryRecordAnswered += new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);\r
+            m_eventManager.OperationFailed += new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
+
+                       m_readMessageCallback = new ReadMessageCallback(OnReadMessage);
 
                        this.Load += new System.EventHandler(this.Form1_Load);
 
@@ -550,15 +357,26 @@ namespace SimpleChat.NET
                                        components.Dispose();
                                }
 
-                               if (registrar != null)
+                               if (m_registrar != null)
                                {
-                                       registrar.Dispose();
+                                       m_registrar.Stop();
                                }
 
-                               if (browser != null)
+                               if (m_browser != null)
                                {
-                                       browser.Dispose();
-                               }
+                                       m_browser.Stop();
+                               }\r
+\r
+                if (m_resolver != null)\r
+                {\r
+                    m_resolver.Stop();\r
+                }\r
+\r
+                m_eventManager.ServiceFound -= new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);\r
+                m_eventManager.ServiceLost -= new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);\r
+                m_eventManager.ServiceResolved -= new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);\r
+                m_eventManager.QueryRecordAnswered -= new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);\r
+                m_eventManager.OperationFailed -= new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
                        }
                        base.Dispose( disposing );
                }
@@ -656,27 +474,25 @@ namespace SimpleChat.NET
                        //
                        // create the socket and bind to INADDR_ANY
                        //
-                       socket  = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
-                       socket.Bind(localEP);
-                       localEP = (IPEndPoint) socket.LocalEndPoint;
+                       m_socket        = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+                       m_socket.Bind(localEP);
+                       localEP = (IPEndPoint) m_socket.LocalEndPoint;
 
                        //
                        // start asynchronous read
                        //
-                       SocketStateObject so = new SocketStateObject(socket);
-                       socket.BeginReceive(so.m_buffer, 0, SocketStateObject.BUFFER_SIZE, 0, new AsyncCallback(this.OnReadSocket), so);   
+                       m_socket.BeginReceive(m_buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(this.OnReadSocket), this);   
 
                        try
                        {
                                //
                                // start the register and browse operations
                                //
-                               registrar       =       DNSService.Register(0, 0, System.Environment.UserName, "_p2pchat._udp", null, null, localEP.Port, null, new DNSService.RegisterReply(OnRegisterReply));
-                               browser         =       DNSService.Browse(0, 0, "_p2pchat._udp", null, new DNSService.BrowseReply(OnBrowseReply));                      
+                               m_registrar     =       m_service.Register( 0, 0, System.Environment.UserName, "_p2pchat._udp", null, null, ( ushort ) localEP.Port, null, m_eventManager );    
                        }
                        catch
                        {
-                               MessageBox.Show("DNSServices Not Available", "Error");
+                               MessageBox.Show("Bonjour service is not available", "Error");
                                Application.Exit();
                        }
                }
@@ -687,7 +503,7 @@ namespace SimpleChat.NET
                [STAThread]
                static void Main() 
                {
-                       Application.Run(new Form1());
+                       Application.Run(new SimpleChat());
                }
 
                //
@@ -697,13 +513,13 @@ namespace SimpleChat.NET
                {
                        PeerData peer = (PeerData) comboBox1.SelectedItem;
 
-                       String message = myName + ": " + textBox2.Text;
+                       String message = m_name + ": " + textBox2.Text;
 
                        Byte[] bytes = Encoding.UTF8.GetBytes(message);
-                       
-                       UdpClient udpSocket = new UdpClient(peer.Address.ToString(), peer.Port);
 
-                       udpSocket.Send(bytes, bytes.Length);
+            IPEndPoint endPoint = new IPEndPoint( peer.Address, peer.Port );\r
+\r
+            m_socket.SendTo(bytes, endPoint);
 
                        richTextBox1.SelectionColor = Color.Black;
 
@@ -718,15 +534,7 @@ namespace SimpleChat.NET
                private void textBox2_TextChanged(object sender, System.EventArgs e)
                {
                        PeerData peer = (PeerData) comboBox1.SelectedItem;
-
-                       if ((peer.Address != null) && (textBox2.Text.Length > 0))
-                       {
-                               button1.Enabled = true;
-                       }
-                       else
-                       {
-                               button1.Enabled = false;
-                       }
+            button1.Enabled = ((peer.Address != null) && (textBox2.Text.Length > 0));
                }
 
                //
@@ -742,7 +550,7 @@ namespace SimpleChat.NET
 
                        try
                        {
-                               resolver = DNSService.Resolve(0, 0, peer.Name, peer.Type, peer.Domain, new DNSService.ResolveReply(OnResolveReply));
+                               m_resolver = m_service.Resolve(0, peer.InterfaceIndex, peer.Name, peer.Type, peer.Domain, m_eventManager);
                        }
                        catch
                        {
@@ -750,5 +558,54 @@ namespace SimpleChat.NET
                                Application.Exit();
                        }
                }
-       }
+       }\r
+\r
+    //\r
+    // PeerData\r
+    //\r
+    // Holds onto the information associated with a peer on the network\r
+    //\r
+    public class PeerData\r
+    {\r
+        public uint InterfaceIndex;\r
+        public String Name;\r
+        public String Type;\r
+        public String Domain;\r
+        public IPAddress Address;\r
+        public int Port;\r
+\r
+        public override String\r
+        ToString()\r
+        {\r
+            return Name;\r
+        }\r
+\r
+        public override bool\r
+        Equals(object other)\r
+        {\r
+            bool result = false;\r
+\r
+            if (other != null)\r
+            {\r
+                if ((object)this == other)\r
+                {\r
+                    result = true;\r
+                }\r
+                else if (other is PeerData)\r
+                {\r
+                    PeerData otherPeerData = (PeerData)other;\r
+\r
+                    result = (this.Name == otherPeerData.Name);\r
+                }\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public override int\r
+        GetHashCode()\r
+        {\r
+            return Name.GetHashCode();\r
+        }\r
+    };
 }
index e5b5a111fb18af6607b0be3404ce3fcc0b293a45..567181813946c89f01a119b7e6d4d56284828691 100755 (executable)
@@ -97,6 +97,6 @@
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
   </resheader>\r
   <data name="$this.Name">\r
-    <value>Form1</value>\r
+    <value>SimpleChat.NET</value>\r
   </data>\r
 </root>
\ No newline at end of file
diff --git a/Clients/SimpleChat.VB/My Project/Application.Designer.vb b/Clients/SimpleChat.VB/My Project/Application.Designer.vb
new file mode 100644 (file)
index 0000000..8ec3666
--- /dev/null
@@ -0,0 +1,38 @@
+'------------------------------------------------------------------------------\r
+' <auto-generated>\r
+'     This code was generated by a tool.\r
+'     Runtime Version:2.0.50727.4918\r
+'\r
+'     Changes to this file may cause incorrect behavior and will be lost if\r
+'     the code is regenerated.\r
+' </auto-generated>\r
+'------------------------------------------------------------------------------\r
+\r
+Option Strict On\r
+Option Explicit On\r
+\r
+\r
+Namespace My\r
+    \r
+    'NOTE: This file is auto-generated; do not modify it directly.  To make changes,\r
+    ' or if you encounter build errors in this file, go to the Project Designer\r
+    ' (go to Project Properties or double-click the My Project node in\r
+    ' Solution Explorer), and make changes on the Application tab.\r
+    '\r
+    Partial Friend Class MyApplication\r
+        \r
+        <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _\r
+        Public Sub New()\r
+            MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.AuthenticationMode.Windows)\r
+            Me.IsSingleInstance = false\r
+            Me.EnableVisualStyles = true\r
+            Me.SaveMySettingsOnExit = true\r
+            Me.ShutDownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses\r
+        End Sub\r
+        \r
+        <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _\r
+        Protected Overrides Sub OnCreateMainForm()\r
+            Me.MainForm = Global.SimpleChat.VB.SimpleChat\r
+        End Sub\r
+    End Class\r
+End Namespace\r
diff --git a/Clients/SimpleChat.VB/My Project/Application.myapp b/Clients/SimpleChat.VB/My Project/Application.myapp
new file mode 100644 (file)
index 0000000..890288c
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-16"?>\r
+<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">\r
+  <MySubMain>true</MySubMain>\r
+  <MainForm>SimpleChat</MainForm>\r
+  <SingleInstance>false</SingleInstance>\r
+  <ShutdownMode>0</ShutdownMode>\r
+  <EnableVisualStyles>true</EnableVisualStyles>\r
+  <AuthenticationMode>0</AuthenticationMode>\r
+  <SaveMySettingsOnExit>true</SaveMySettingsOnExit>\r
+</MyApplicationData>
\ No newline at end of file
diff --git a/Clients/SimpleChat.VB/My Project/AssemblyInfo.vb b/Clients/SimpleChat.VB/My Project/AssemblyInfo.vb
new file mode 100644 (file)
index 0000000..869313a
--- /dev/null
@@ -0,0 +1,35 @@
+Imports System\r
+Imports System.Reflection\r
+Imports System.Runtime.InteropServices\r
+\r
+' General Information about an assembly is controlled through the following \r
+' set of attributes. Change these attribute values to modify the information\r
+' associated with an assembly.\r
+\r
+' Review the values of the assembly attributes\r
+\r
+<Assembly: AssemblyTitle("SimpleChat.VB")> \r
+<Assembly: AssemblyDescription("")> \r
+<Assembly: AssemblyCompany("Microsoft")> \r
+<Assembly: AssemblyProduct("SimpleChat.VB")> \r
+<Assembly: AssemblyCopyright("Copyright © Microsoft 2009")> \r
+<Assembly: AssemblyTrademark("")> \r
+\r
+<Assembly: ComVisible(False)>\r
+\r
+'The following GUID is for the ID of the typelib if this project is exposed to COM\r
+<Assembly: Guid("a07d7322-054b-4fda-a670-d75f589804c8")> \r
+\r
+' Version information for an assembly consists of the following four values:\r
+'\r
+'      Major Version\r
+'      Minor Version \r
+'      Build Number\r
+'      Revision\r
+'\r
+' You can specify all the values or you can default the Build and Revision Numbers \r
+' by using the '*' as shown below:\r
+' <Assembly: AssemblyVersion("1.0.*")> \r
+\r
+<Assembly: AssemblyVersion("1.0.0.0")> \r
+<Assembly: AssemblyFileVersion("1.0.0.0")> \r
diff --git a/Clients/SimpleChat.VB/My Project/Resources.Designer.vb b/Clients/SimpleChat.VB/My Project/Resources.Designer.vb
new file mode 100644 (file)
index 0000000..babd06f
--- /dev/null
@@ -0,0 +1,62 @@
+'------------------------------------------------------------------------------\r
+' <auto-generated>\r
+'     This code was generated by a tool.\r
+'     Runtime Version:2.0.50727.4918\r
+'\r
+'     Changes to this file may cause incorrect behavior and will be lost if\r
+'     the code is regenerated.\r
+' </auto-generated>\r
+'------------------------------------------------------------------------------\r
+\r
+Option Strict On\r
+Option Explicit On\r
+\r
+\r
+Namespace My.Resources\r
+    \r
+    'This class was auto-generated by the StronglyTypedResourceBuilder\r
+    'class via a tool like ResGen or Visual Studio.\r
+    'To add or remove a member, edit your .ResX file then rerun ResGen\r
+    'with the /str option, or rebuild your VS project.\r
+    '<summary>\r
+    '  A strongly-typed resource class, for looking up localized strings, etc.\r
+    '</summary>\r
+    <Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0"),  _\r
+     Global.System.Diagnostics.DebuggerNonUserCodeAttribute(),  _\r
+     Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(),  _\r
+     Global.Microsoft.VisualBasic.HideModuleNameAttribute()>  _\r
+    Friend Module Resources\r
+        \r
+        Private resourceMan As Global.System.Resources.ResourceManager\r
+        \r
+        Private resourceCulture As Global.System.Globalization.CultureInfo\r
+        \r
+        '<summary>\r
+        '  Returns the cached ResourceManager instance used by this class.\r
+        '</summary>\r
+        <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)>  _\r
+        Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager\r
+            Get\r
+                If Object.ReferenceEquals(resourceMan, Nothing) Then\r
+                    Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("SimpleChat.VB.Resources", GetType(Resources).Assembly)\r
+                    resourceMan = temp\r
+                End If\r
+                Return resourceMan\r
+            End Get\r
+        End Property\r
+        \r
+        '<summary>\r
+        '  Overrides the current thread's CurrentUICulture property for all\r
+        '  resource lookups using this strongly typed resource class.\r
+        '</summary>\r
+        <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)>  _\r
+        Friend Property Culture() As Global.System.Globalization.CultureInfo\r
+            Get\r
+                Return resourceCulture\r
+            End Get\r
+            Set(ByVal value As Global.System.Globalization.CultureInfo)\r
+                resourceCulture = value\r
+            End Set\r
+        End Property\r
+    End Module\r
+End Namespace\r
diff --git a/Clients/SimpleChat.VB/My Project/Resources.resx b/Clients/SimpleChat.VB/My Project/Resources.resx
new file mode 100644 (file)
index 0000000..ffecec8
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<root>\r
+  <!-- \r
+    Microsoft ResX Schema \r
+    \r
+    Version 2.0\r
+    \r
+    The primary goals of this format is to allow a simple XML format \r
+    that is mostly human readable. The generation and parsing of the \r
+    various data types are done through the TypeConverter classes \r
+    associated with the data types.\r
+    \r
+    Example:\r
+    \r
+    ... ado.net/XML headers & schema ...\r
+    <resheader name="resmimetype">text/microsoft-resx</resheader>\r
+    <resheader name="version">2.0</resheader>\r
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\r
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\r
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>\r
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>\r
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">\r
+        <value>[base64 mime encoded serialized .NET Framework object]</value>\r
+    </data>\r
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">\r
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\r
+        <comment>This is a comment</comment>\r
+    </data>\r
+                \r
+    There are any number of "resheader" rows that contain simple \r
+    name/value pairs.\r
+    \r
+    Each data row contains a name, and value. The row also contains a \r
+    type or mimetype. Type corresponds to a .NET class that support \r
+    text/value conversion through the TypeConverter architecture. \r
+    Classes that don't support this are serialized and stored with the \r
+    mimetype set.\r
+    \r
+    The mimetype is used for serialized objects, and tells the \r
+    ResXResourceReader how to depersist the object. This is currently not \r
+    extensible. For a given mimetype the value must be set accordingly:\r
+    \r
+    Note - application/x-microsoft.net.object.binary.base64 is the format \r
+    that the ResXResourceWriter will generate, however the reader can \r
+    read any of the formats listed below.\r
+    \r
+    mimetype: application/x-microsoft.net.object.binary.base64\r
+    value   : The object must be serialized with \r
+            : System.Serialization.Formatters.Binary.BinaryFormatter\r
+            : and then encoded with base64 encoding.\r
+    \r
+    mimetype: application/x-microsoft.net.object.soap.base64\r
+    value   : The object must be serialized with \r
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\r
+            : and then encoded with base64 encoding.\r
+\r
+    mimetype: application/x-microsoft.net.object.bytearray.base64\r
+    value   : The object must be serialized into a byte array \r
+            : using a System.ComponentModel.TypeConverter\r
+            : and then encoded with base64 encoding.\r
+    -->\r
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
+    <xsd:element name="root" msdata:IsDataSet="true">\r
+      <xsd:complexType>\r
+        <xsd:choice maxOccurs="unbounded">\r
+          <xsd:element name="metadata">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+              <xsd:attribute name="type" type="xsd:string" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="assembly">\r
+            <xsd:complexType>\r
+              <xsd:attribute name="alias" type="xsd:string" />\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="data">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />\r
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="resheader">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" use="required" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+        </xsd:choice>\r
+      </xsd:complexType>\r
+    </xsd:element>\r
+  </xsd:schema>\r
+  <resheader name="resmimetype">\r
+    <value>text/microsoft-resx</value>\r
+  </resheader>\r
+  <resheader name="version">\r
+    <value>2.0</value>\r
+  </resheader>\r
+  <resheader name="reader">\r
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+  <resheader name="writer">\r
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+</root>
\ No newline at end of file
diff --git a/Clients/SimpleChat.VB/My Project/Settings.Designer.vb b/Clients/SimpleChat.VB/My Project/Settings.Designer.vb
new file mode 100644 (file)
index 0000000..259ca35
--- /dev/null
@@ -0,0 +1,73 @@
+'------------------------------------------------------------------------------\r
+' <auto-generated>\r
+'     This code was generated by a tool.\r
+'     Runtime Version:2.0.50727.4918\r
+'\r
+'     Changes to this file may cause incorrect behavior and will be lost if\r
+'     the code is regenerated.\r
+' </auto-generated>\r
+'------------------------------------------------------------------------------\r
+\r
+Option Strict On\r
+Option Explicit On\r
+\r
+\r
+Namespace My\r
+\r
+    <Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(),  _\r
+     Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0"),  _\r
+     Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)>  _\r
+    Partial Friend NotInheritable Class MySettings\r
+        Inherits Global.System.Configuration.ApplicationSettingsBase\r
+        \r
+        Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)\r
+        \r
+#Region "My.Settings Auto-Save Functionality"\r
+#If _MyType = "WindowsForms" Then\r
+        Private Shared addedHandler As Boolean\r
+\r
+        Private Shared addedHandlerLockObject As New Object\r
+\r
+        <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _\r
+        Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)\r
+            If My.Application.SaveMySettingsOnExit Then\r
+                My.Settings.Save()\r
+            End If\r
+        End Sub\r
+#End If\r
+#End Region\r
+        \r
+        Public Shared ReadOnly Property [Default]() As MySettings\r
+            Get\r
+                \r
+#If _MyType = "WindowsForms" Then\r
+                   If Not addedHandler Then\r
+                        SyncLock addedHandlerLockObject\r
+                            If Not addedHandler Then\r
+                                AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings\r
+                                addedHandler = True\r
+                            End If\r
+                        End SyncLock\r
+                    End If\r
+#End If\r
+                Return defaultInstance\r
+            End Get\r
+        End Property\r
+    End Class\r
+End Namespace\r
+\r
+Namespace My\r
+    \r
+    <Global.Microsoft.VisualBasic.HideModuleNameAttribute(),  _\r
+     Global.System.Diagnostics.DebuggerNonUserCodeAttribute(),  _\r
+     Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()>  _\r
+    Friend Module MySettingsProperty\r
+        \r
+        <Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")>  _\r
+        Friend ReadOnly Property Settings() As Global.SimpleChat.VB.My.MySettings\r
+            Get\r
+                Return Global.SimpleChat.VB.My.MySettings.Default\r
+            End Get\r
+        End Property\r
+    End Module\r
+End Namespace\r
diff --git a/Clients/SimpleChat.VB/My Project/Settings.settings b/Clients/SimpleChat.VB/My Project/Settings.settings
new file mode 100644 (file)
index 0000000..377f56d
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>\r
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">\r
+  <Profiles>\r
+    <Profile Name="(Default)" />\r
+  </Profiles>\r
+  <Settings />\r
+</SettingsFile>\r
diff --git a/Clients/SimpleChat.VB/SimpleChat.Designer.vb b/Clients/SimpleChat.VB/SimpleChat.Designer.vb
new file mode 100644 (file)
index 0000000..4cdc2aa
--- /dev/null
@@ -0,0 +1,102 @@
+<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _\r
+Partial Class SimpleChat\r
+    Inherits System.Windows.Forms.Form\r
+\r
+    'Form overrides dispose to clean up the component list.\r
+    <System.Diagnostics.DebuggerNonUserCode()> _\r
+    Protected Overrides Sub Dispose(ByVal disposing As Boolean)\r
+        Try\r
+            If disposing AndAlso components IsNot Nothing Then\r
+                components.Dispose()\r
+            End If\r
+        Finally\r
+            MyBase.Dispose(disposing)\r
+        End Try\r
+    End Sub\r
+\r
+    'Required by the Windows Form Designer\r
+    Private components As System.ComponentModel.IContainer\r
+\r
+    'NOTE: The following procedure is required by the Windows Form Designer\r
+    'It can be modified using the Windows Form Designer.  \r
+    'Do not modify it using the code editor.\r
+    <System.Diagnostics.DebuggerStepThrough()> _\r
+    Private Sub InitializeComponent()\r
+        Me.TextBox1 = New System.Windows.Forms.TextBox\r
+        Me.TextBox2 = New System.Windows.Forms.TextBox\r
+        Me.TalkTo = New System.Windows.Forms.Label\r
+        Me.ComboBox1 = New System.Windows.Forms.ComboBox\r
+        Me.Button1 = New System.Windows.Forms.Button\r
+        Me.SuspendLayout()\r
+        '\r
+        'TextBox1\r
+        '\r
+        Me.TextBox1.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)\r
+        Me.TextBox1.Location = New System.Drawing.Point(12, 12)\r
+        Me.TextBox1.Multiline = True\r
+        Me.TextBox1.Name = "TextBox1"\r
+        Me.TextBox1.ReadOnly = True\r
+        Me.TextBox1.Size = New System.Drawing.Size(459, 362)\r
+        Me.TextBox1.TabIndex = 0\r
+        '\r
+        'TextBox2\r
+        '\r
+        Me.TextBox2.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _\r
+                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)\r
+        Me.TextBox2.Location = New System.Drawing.Point(13, 431)\r
+        Me.TextBox2.Name = "TextBox2"\r
+        Me.TextBox2.Size = New System.Drawing.Size(374, 20)\r
+        Me.TextBox2.TabIndex = 1\r
+        '\r
+        'TalkTo\r
+        '\r
+        Me.TalkTo.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.TalkTo.AutoSize = True\r
+        Me.TalkTo.Location = New System.Drawing.Point(13, 395)\r
+        Me.TalkTo.Name = "TalkTo"\r
+        Me.TalkTo.Size = New System.Drawing.Size(43, 13)\r
+        Me.TalkTo.TabIndex = 2\r
+        Me.TalkTo.Text = "Talk to:"\r
+        '\r
+        'ComboBox1\r
+        '\r
+        Me.ComboBox1.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)\r
+        Me.ComboBox1.FormattingEnabled = True\r
+        Me.ComboBox1.Location = New System.Drawing.Point(63, 392)\r
+        Me.ComboBox1.Name = "ComboBox1"\r
+        Me.ComboBox1.Size = New System.Drawing.Size(324, 21)\r
+        Me.ComboBox1.TabIndex = 3\r
+        '\r
+        'Button1\r
+        '\r
+        Me.Button1.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)\r
+        Me.Button1.Location = New System.Drawing.Point(409, 430)\r
+        Me.Button1.Name = "Button1"\r
+        Me.Button1.Size = New System.Drawing.Size(59, 23)\r
+        Me.Button1.TabIndex = 4\r
+        Me.Button1.Text = "Send"\r
+        Me.Button1.UseVisualStyleBackColor = True\r
+        '\r
+        'SimpleChat\r
+        '\r
+        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)\r
+        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font\r
+        Me.ClientSize = New System.Drawing.Size(483, 462)\r
+        Me.Controls.Add(Me.Button1)\r
+        Me.Controls.Add(Me.ComboBox1)\r
+        Me.Controls.Add(Me.TalkTo)\r
+        Me.Controls.Add(Me.TextBox2)\r
+        Me.Controls.Add(Me.TextBox1)\r
+        Me.Name = "SimpleChat"\r
+        Me.Text = "SimpleChat.VB"\r
+        Me.ResumeLayout(False)\r
+        Me.PerformLayout()\r
+\r
+    End Sub\r
+    Friend WithEvents TextBox1 As System.Windows.Forms.TextBox\r
+    Friend WithEvents TextBox2 As System.Windows.Forms.TextBox\r
+    Friend WithEvents TalkTo As System.Windows.Forms.Label\r
+    Friend WithEvents ComboBox1 As System.Windows.Forms.ComboBox\r
+    Friend WithEvents Button1 As System.Windows.Forms.Button\r
+\r
+End Class\r
diff --git a/Clients/SimpleChat.VB/SimpleChat.VB.vbproj b/Clients/SimpleChat.VB/SimpleChat.VB.vbproj
new file mode 100644 (file)
index 0000000..1c1643d
--- /dev/null
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+    <ProductVersion>8.0.50727</ProductVersion>\r
+    <SchemaVersion>2.0</SchemaVersion>\r
+    <ProjectGuid>{5ACED234-EB98-415E-9974-B54A70789821}</ProjectGuid>\r
+    <OutputType>WinExe</OutputType>\r
+    <StartupObject>SimpleChat.VB.My.MyApplication</StartupObject>\r
+    <RootNamespace>SimpleChat.VB</RootNamespace>\r
+    <AssemblyName>SimpleChat.VB</AssemblyName>\r
+    <MyType>WindowsForms</MyType>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <DefineDebug>true</DefineDebug>\r
+    <DefineTrace>true</DefineTrace>\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <DocumentationFile>SimpleChat.VB.xml</DocumentationFile>\r
+    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <DebugType>pdbonly</DebugType>\r
+    <DefineDebug>false</DefineDebug>\r
+    <DefineTrace>true</DefineTrace>\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <DocumentationFile>SimpleChat.VB.xml</DocumentationFile>\r
+    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System" />\r
+    <Reference Include="System.Data" />\r
+    <Reference Include="System.Deployment" />\r
+    <Reference Include="System.Drawing" />\r
+    <Reference Include="System.Windows.Forms" />\r
+    <Reference Include="System.Xml" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Import Include="Microsoft.VisualBasic" />\r
+    <Import Include="System" />\r
+    <Import Include="System.Collections" />\r
+    <Import Include="System.Collections.Generic" />\r
+    <Import Include="System.Data" />\r
+    <Import Include="System.Drawing" />\r
+    <Import Include="System.Diagnostics" />\r
+    <Import Include="System.Windows.Forms" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="SimpleChat.vb">\r
+      <SubType>Form</SubType>\r
+    </Compile>\r
+    <Compile Include="SimpleChat.Designer.vb">\r
+      <DependentUpon>SimpleChat.vb</DependentUpon>\r
+      <SubType>Form</SubType>\r
+    </Compile>\r
+    <Compile Include="My Project\AssemblyInfo.vb" />\r
+    <Compile Include="My Project\Application.Designer.vb">\r
+      <AutoGen>True</AutoGen>\r
+      <DependentUpon>Application.myapp</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="My Project\Resources.Designer.vb">\r
+      <AutoGen>True</AutoGen>\r
+      <DesignTime>True</DesignTime>\r
+      <DependentUpon>Resources.resx</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="My Project\Settings.Designer.vb">\r
+      <AutoGen>True</AutoGen>\r
+      <DependentUpon>Settings.settings</DependentUpon>\r
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>\r
+    </Compile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <EmbeddedResource Include="SimpleChat.resx">\r
+      <SubType>Designer</SubType>\r
+      <DependentUpon>SimpleChat.vb</DependentUpon>\r
+    </EmbeddedResource>\r
+    <EmbeddedResource Include="My Project\Resources.resx">\r
+      <Generator>VbMyResourcesResXFileCodeGenerator</Generator>\r
+      <LastGenOutput>Resources.Designer.vb</LastGenOutput>\r
+      <CustomToolNamespace>My.Resources</CustomToolNamespace>\r
+      <SubType>Designer</SubType>\r
+    </EmbeddedResource>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <None Include="My Project\Application.myapp">\r
+      <Generator>MyApplicationCodeGenerator</Generator>\r
+      <LastGenOutput>Application.Designer.vb</LastGenOutput>\r
+    </None>\r
+    <None Include="My Project\Settings.settings">\r
+      <Generator>SettingsSingleFileGenerator</Generator>\r
+      <CustomToolNamespace>My</CustomToolNamespace>\r
+      <LastGenOutput>Settings.Designer.vb</LastGenOutput>\r
+    </None>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <COMReference Include="Bonjour">\r
+      <Guid>{18FBED6D-F2B7-4EC8-A4A4-46282E635308}</Guid>\r
+      <VersionMajor>1</VersionMajor>\r
+      <VersionMinor>0</VersionMinor>\r
+      <Lcid>0</Lcid>\r
+      <WrapperTool>tlbimp</WrapperTool>\r
+      <Isolated>False</Isolated>\r
+    </COMReference>\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />\r
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+       Other similar extension points exist, see Microsoft.Common.targets.\r
+  <Target Name="BeforeBuild">\r
+  </Target>\r
+  <Target Name="AfterBuild">\r
+  </Target>\r
+  -->\r
+</Project>
\ No newline at end of file
diff --git a/Clients/SimpleChat.VB/SimpleChat.resx b/Clients/SimpleChat.VB/SimpleChat.resx
new file mode 100644 (file)
index 0000000..ff31a6d
--- /dev/null
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<root>\r
+  <!-- \r
+    Microsoft ResX Schema \r
+    \r
+    Version 2.0\r
+    \r
+    The primary goals of this format is to allow a simple XML format \r
+    that is mostly human readable. The generation and parsing of the \r
+    various data types are done through the TypeConverter classes \r
+    associated with the data types.\r
+    \r
+    Example:\r
+    \r
+    ... ado.net/XML headers & schema ...\r
+    <resheader name="resmimetype">text/microsoft-resx</resheader>\r
+    <resheader name="version">2.0</resheader>\r
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\r
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\r
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>\r
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>\r
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">\r
+        <value>[base64 mime encoded serialized .NET Framework object]</value>\r
+    </data>\r
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">\r
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\r
+        <comment>This is a comment</comment>\r
+    </data>\r
+                \r
+    There are any number of "resheader" rows that contain simple \r
+    name/value pairs.\r
+    \r
+    Each data row contains a name, and value. The row also contains a \r
+    type or mimetype. Type corresponds to a .NET class that support \r
+    text/value conversion through the TypeConverter architecture. \r
+    Classes that don't support this are serialized and stored with the \r
+    mimetype set.\r
+    \r
+    The mimetype is used for serialized objects, and tells the \r
+    ResXResourceReader how to depersist the object. This is currently not \r
+    extensible. For a given mimetype the value must be set accordingly:\r
+    \r
+    Note - application/x-microsoft.net.object.binary.base64 is the format \r
+    that the ResXResourceWriter will generate, however the reader can \r
+    read any of the formats listed below.\r
+    \r
+    mimetype: application/x-microsoft.net.object.binary.base64\r
+    value   : The object must be serialized with \r
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\r
+            : and then encoded with base64 encoding.\r
+    \r
+    mimetype: application/x-microsoft.net.object.soap.base64\r
+    value   : The object must be serialized with \r
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\r
+            : and then encoded with base64 encoding.\r
+\r
+    mimetype: application/x-microsoft.net.object.bytearray.base64\r
+    value   : The object must be serialized into a byte array \r
+            : using a System.ComponentModel.TypeConverter\r
+            : and then encoded with base64 encoding.\r
+    -->\r
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />\r
+    <xsd:element name="root" msdata:IsDataSet="true">\r
+      <xsd:complexType>\r
+        <xsd:choice maxOccurs="unbounded">\r
+          <xsd:element name="metadata">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" use="required" type="xsd:string" />\r
+              <xsd:attribute name="type" type="xsd:string" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" />\r
+              <xsd:attribute ref="xml:space" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="assembly">\r
+            <xsd:complexType>\r
+              <xsd:attribute name="alias" type="xsd:string" />\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="data">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />\r
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />\r
+              <xsd:attribute ref="xml:space" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="resheader">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" use="required" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+        </xsd:choice>\r
+      </xsd:complexType>\r
+    </xsd:element>\r
+  </xsd:schema>\r
+  <resheader name="resmimetype">\r
+    <value>text/microsoft-resx</value>\r
+  </resheader>\r
+  <resheader name="version">\r
+    <value>2.0</value>\r
+  </resheader>\r
+  <resheader name="reader">\r
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+  <resheader name="writer">\r
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+</root>
\ No newline at end of file
diff --git a/Clients/SimpleChat.VB/SimpleChat.vb b/Clients/SimpleChat.VB/SimpleChat.vb
new file mode 100644 (file)
index 0000000..bcf5ef0
--- /dev/null
@@ -0,0 +1,121 @@
+\r
+Imports System.Net\r
+Imports System.Net.Sockets\r
+Imports System.Data\r
+Imports System.Text\r
+\r
+Public Class SimpleChat\r
+    Public WithEvents MyEventManager As New Bonjour.DNSSDEventManager\r
+    Private m_service As New Bonjour.DNSSDService\r
+    Private m_registrar As Bonjour.DNSSDService\r
+    Private m_browser As Bonjour.DNSSDService\r
+    Private m_resolver As Bonjour.DNSSDService\r
+    Private m_socket As New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)\r
+    Private m_port As Integer\r
+    Private m_buffer(1024 * 32) As Byte\r
+    Private m_async As IAsyncResult\r
+    Public Delegate Sub SocketDelegate(ByVal msg As String)\r
+    Private m_socketDelegate As SocketDelegate\r
+    Private m_name As String\r
+\r
+    Public Sub New()\r
+        MyBase.New()\r
+\r
+        'This call is required by the Windows Form Designer.\r
+        InitializeComponent()\r
+\r
+        Button1.Enabled = False\r
+\r
+        m_socketDelegate = New SocketDelegate(AddressOf MessageReceived)\r
+\r
+        Dim endPoint As New IPEndPoint(IPAddress.Any, 0)\r
+        m_socket.Bind(endPoint)\r
+        endPoint = m_socket.LocalEndPoint\r
+        m_port = endPoint.Port\r
+\r
+        Dim txtRecord As Bonjour.TXTRecord\r
+        m_async = m_socket.BeginReceive(m_buffer, 0, m_buffer.Length, SocketFlags.Partial, New AsyncCallback(AddressOf OnReceive), Me)\r
+        m_registrar = m_service.Register(0, 0, Environment.UserName, "_p2pchat._udp", vbNullString, vbNullString, m_port, txtRecord, MyEventManager)\r
+    End Sub\r
+    Public Sub MyEventManager_ServiceRegistered(ByVal registrar As Bonjour.DNSSDService, ByVal flags As Bonjour.DNSSDFlags, ByVal name As String, ByVal regType As String, ByVal domain As String) Handles MyEventManager.ServiceRegistered\r
+        m_name = name\r
+        m_browser = m_service.Browse(0, 0, regType, vbNullString, MyEventManager)\r
+    End Sub\r
+    Public Sub MyEventManager_ServiceFound(ByVal browser As Bonjour.DNSSDService, ByVal flags As Bonjour.DNSSDFlags, ByVal ifIndex As UInteger, ByVal serviceName As String, ByVal regtype As String, ByVal domain As String) Handles MyEventManager.ServiceFound\r
+        If (serviceName <> m_name) Then\r
+            Dim peer As PeerData = New PeerData\r
+            peer.InterfaceIndex = ifIndex\r
+            peer.Name = serviceName\r
+            peer.Type = regtype\r
+            peer.Domain = domain\r
+            ComboBox1.Items.Add(peer)\r
+            ComboBox1.SelectedIndex = 0\r
+        End If\r
+    End Sub\r
+    Public Sub MyEventManager_ServiceLost(ByVal browser As Bonjour.DNSSDService, ByVal flags As Bonjour.DNSSDFlags, ByVal ifIndex As UInteger, ByVal serviceName As String, ByVal regtype As String, ByVal domain As String) Handles MyEventManager.ServiceLost\r
+        ComboBox1.Items.Remove(serviceName)\r
+    End Sub\r
+    Public Sub MyEventManager_ServiceResolved(ByVal resolver As Bonjour.DNSSDService, ByVal flags As Bonjour.DNSSDFlags, ByVal ifIndex As UInteger, ByVal fullname As String, ByVal hostname As String, ByVal port As UShort, ByVal record As Bonjour.TXTRecord) Handles MyEventManager.ServiceResolved\r
+        m_resolver.Stop()\r
+        Dim peer As PeerData = ComboBox1.SelectedItem\r
+        peer.Port = port\r
+        m_resolver = m_service.QueryRecord(0, ifIndex, hostname, Bonjour.DNSSDRRType.kDNSSDType_A, Bonjour.DNSSDRRClass.kDNSSDClass_IN, MyEventManager)\r
+    End Sub\r
+    Public Sub MyEventManager_QueryAnswered(ByVal resolver As Bonjour.DNSSDService, ByVal flags As Bonjour.DNSSDFlags, ByVal ifIndex As UInteger, ByVal fullName As String, ByVal rrtype As Bonjour.DNSSDRRType, ByVal rrclass As Bonjour.DNSSDRRClass, ByVal rdata As Object, ByVal ttl As UInteger) Handles MyEventManager.QueryRecordAnswered\r
+        m_resolver.Stop()\r
+        Dim peer As PeerData = ComboBox1.SelectedItem
+        Dim bits As UInteger = BitConverter.ToUInt32(rdata, 0)
+        Dim address As IPAddress = New System.Net.IPAddress(bits)
+        peer.Address = address\r
+    End Sub\r
+    Public Sub MyEventManager_OperationFailed(ByVal registrar As Bonjour.DNSSDService, ByVal errorCode As Bonjour.DNSSDError) Handles MyEventManager.OperationFailed\r
+        MessageBox.Show("Operation failed error code: " + errorCode)\r
+    End Sub\r
+\r
+    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click\r
+        Dim peer As PeerData = ComboBox1.SelectedItem
+        Dim message As String = m_name + ": " + TextBox2.Text
+        Dim bytes As Byte() = Encoding.UTF8.GetBytes(message)
+        Dim endPoint As IPEndPoint = New IPEndPoint(peer.Address, peer.Port)
+        m_socket.SendTo(bytes, 0, bytes.Length, 0, endPoint)
+        TextBox1.AppendText(TextBox2.Text + Environment.NewLine)
+        TextBox2.Text = ""\r
+    End Sub\r
+\r
+    Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged\r
+        Dim peer As PeerData = ComboBox1.SelectedItem\r
+        m_resolver = m_service.Resolve(0, peer.InterfaceIndex, peer.Name, peer.Type, peer.Domain, MyEventManager)\r
+    End Sub\r
+    Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged\r
+        Dim peer As PeerData = ComboBox1.SelectedItem\r
+        If ((peer.Address IsNot Nothing) And TextBox2.Text.Length > 0) Then\r
+            Button1.Enabled = True\r
+        Else\r
+            Button1.Enabled = False\r
+        End If\r
+    End Sub\r
+    Public Sub MessageReceived(ByVal msg As System.String)\r
+        TextBox1.AppendText(msg)\r
+    End Sub\r
+    Private Sub OnReceive(ByVal ar As IAsyncResult)\r
+        Dim bytesReceived As Integer = m_socket.EndReceive(ar)\r
+        If (bytesReceived > 0) Then\r
+            Dim msg As String = Encoding.UTF8.GetString(m_buffer, 0, bytesReceived)\r
+            Me.Invoke(m_socketDelegate, msg)\r
+        End If\r
+        m_async = m_socket.BeginReceive(m_buffer, 0, m_buffer.Length, SocketFlags.Partial, New AsyncCallback(AddressOf OnReceive), Me)\r
+    End Sub\r
+End Class\r
+\r
+Public Class PeerData\r
+    Public InterfaceIndex As UInteger\r
+    Public Name As String\r
+    Public Type As String\r
+    Public Domain As String\r
+    Public Address As IPAddress\r
+    Public Port As UShort\r
+\r
+    Overrides Function ToString() As String\r
+        Return Name\r
+    End Function\r
+End Class\r
index 497c5dc269cb964ea53421b73b22b53805b854b0..993632d713e8030120af0a8cb2524daa9d5d53c2 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 4 -*-
  *
- * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Apple Inc. All rights reserved.
  *
  * Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
  * ("Apple") in consideration of your agreement to the following terms, and your
@@ -73,7 +73,7 @@ cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT ws2_32.lib ..\mDNSWindows\DLL\Rele
 #include <ctype.h>
 #include <stdio.h>                     // For stdout, stderr
 #include <stdlib.h>                    // For exit()
-#include <string.h>                    // For strlen(), strcpy(), bzero()
+#include <string.h>                    // For strlen(), strcpy()
 #include <errno.h>                     // For errno, EINTR
 #include <time.h>
 #include <sys/types.h>         // For u_char
@@ -81,12 +81,69 @@ cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT ws2_32.lib ..\mDNSWindows\DLL\Rele
 #ifdef _WIN32
        #include <winsock2.h>
        #include <ws2tcpip.h>
+       #include <Iphlpapi.h>
        #include <process.h>
        typedef int        pid_t;
        #define getpid     _getpid
        #define strcasecmp _stricmp
        #define snprintf   _snprintf
        static const char kFilePathSep = '\\';
+       #ifndef HeapEnableTerminationOnCorruption
+       #     define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS)1
+       #endif
+       #if !defined(IFNAMSIZ)
+        #define IFNAMSIZ 16
+    #endif
+       #define if_nametoindex if_nametoindex_win
+       #define if_indextoname if_indextoname_win
+
+       typedef PCHAR (WINAPI * if_indextoname_funcptr_t)(ULONG index, PCHAR name);
+       typedef ULONG (WINAPI * if_nametoindex_funcptr_t)(PCSTR name);
+
+       unsigned if_nametoindex_win(const char *ifname)
+               {
+               HMODULE library;
+               unsigned index = 0;
+
+               // Try and load the IP helper library dll
+               if ((library = LoadLibrary(TEXT("Iphlpapi")) ) != NULL )
+                       {
+                       if_nametoindex_funcptr_t if_nametoindex_funcptr;
+
+                       // On Vista and above there is a Posix like implementation of if_nametoindex
+                       if ((if_nametoindex_funcptr = (if_nametoindex_funcptr_t) GetProcAddress(library, "if_nametoindex")) != NULL )
+                               {
+                               index = if_nametoindex_funcptr(ifname);
+                               }
+
+                       FreeLibrary(library);
+                       }
+
+               return index;
+               }
+
+       char * if_indextoname_win( unsigned ifindex, char *ifname)
+               {
+               HMODULE library;
+               char * name = NULL;
+
+               // Try and load the IP helper library dll
+               if ((library = LoadLibrary(TEXT("Iphlpapi")) ) != NULL )
+                       {
+                       if_indextoname_funcptr_t if_indextoname_funcptr;
+
+                       // On Vista and above there is a Posix like implementation of if_indextoname
+                       if ((if_indextoname_funcptr = (if_indextoname_funcptr_t) GetProcAddress(library, "if_indextoname")) != NULL )
+                               {
+                               name = if_indextoname_funcptr(ifindex, ifname);
+                               }
+
+                       FreeLibrary(library);
+                       }
+
+               return name;
+               }
+
 #else
        #include <unistd.h>                     // For getopt() and optind
        #include <netdb.h>                      // For getaddrinfo()
@@ -104,6 +161,8 @@ cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT ws2_32.lib ..\mDNSWindows\DLL\Rele
 
 #include "dns_sd.h"
 
+#include "ClientCommon.h"
+
 #if TEST_NEW_CLIENTSTUB
 #include "../mDNSShared/dnssd_ipc.c"
 #include "../mDNSShared/dnssd_clientlib.c"
@@ -135,7 +194,7 @@ static DNSRecordRef record = NULL;
 static char myhinfoW[14] = "\002PC\012Windows XP";
 static char myhinfoX[ 9] = "\003Mac\004OS X";
 static char updatetest[3] = "\002AA";
-static char bigNULL[8200];
+static char bigNULL[8192];     // 8K is maximum rdata we support
 
 // Note: the select() implementation on Windows (Winsock2) fails with any timeout much larger than this
 #define LONG_TIME 100000000
@@ -239,31 +298,7 @@ static void printtimestamp(void)
 #define DomainMsg(X) (((X) & kDNSServiceFlagsDefault) ? "(Default)" : \
                       ((X) & kDNSServiceFlagsAdd)     ? "Added"     : "Removed")
 
-static const char *GetNextLabel(const char *cstr, char label[64])
-       {
-       char *ptr = label;
-       while (*cstr && *cstr != '.')                                                           // While we have characters in the label...
-               {
-               char c = *cstr++;
-               if (c == '\\')
-                       {
-                       c = *cstr++;
-                       if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
-                               {
-                               int v0 = cstr[-1] - '0';                                                // then interpret as three-digit decimal
-                               int v1 = cstr[ 0] - '0';
-                               int v2 = cstr[ 1] - '0';
-                               int val = v0 * 100 + v1 * 10 + v2;
-                               if (val <= 255) { c = (char)val; cstr += 2; }   // If valid three-digit decimal value, use it
-                               }
-                       }
-               *ptr++ = c;
-               if (ptr >= label+64) return(NULL);
-               }
-       if (*cstr) cstr++;                                                                                      // Skip over the trailing dot (if present)
-       *ptr++ = 0;
-       return(cstr);
-       }
+#define MAX_LABELS 128
 
 static void DNSSD_API enum_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex,
        DNSServiceErrorType errorCode, const char *replyDomain, void *context)
@@ -271,7 +306,7 @@ static void DNSSD_API enum_reply(DNSServiceRef sdref, const DNSServiceFlags flag
        DNSServiceFlags partialflags = flags & ~(kDNSServiceFlagsMoreComing | kDNSServiceFlagsAdd | kDNSServiceFlagsDefault);
        int labels = 0, depth = 0, i, initial = 0;
        char text[64];
-       const char *label[128];
+       const char *label[MAX_LABELS];
        
        (void)sdref;        // Unused
        (void)ifIndex;      // Unused
@@ -292,7 +327,7 @@ static void DNSSD_API enum_reply(DNSServiceRef sdref, const DNSServiceFlags flag
                else printf("             ");
                
                // 2. Count the labels
-               while (*replyDomain)
+               while (replyDomain && *replyDomain && labels < MAX_LABELS)
                        {
                        label[labels++] = replyDomain;
                        replyDomain = GetNextLabel(replyDomain, text);
@@ -326,6 +361,97 @@ static void DNSSD_API enum_reply(DNSServiceRef sdref, const DNSServiceFlags flag
        if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
        }
 
+static int CopyLabels(char *dst, const char *lim, const char **srcp, int labels)
+       {
+       const char *src = *srcp;
+       while (*src != '.' || --labels > 0)
+               {
+               if (*src == '\\') *dst++ = *src++;      // Make sure "\." doesn't confuse us
+               if (!*src || dst >= lim) return -1;
+               *dst++ = *src++;
+               if (!*src || dst >= lim) return -1;
+               }
+       *dst++ = 0;
+       *srcp = src + 1;        // skip over final dot
+       return 0;
+       }
+
+static void DNSSD_API zonedata_resolve(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
+       const char *fullname, const char *hosttarget, uint16_t opaqueport, uint16_t txtLen, const unsigned char *txt, void *context)
+       {
+       union { uint16_t s; u_char b[2]; } port = { opaqueport };
+       uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1];
+
+       const char *p = fullname;
+       char n[kDNSServiceMaxDomainName];
+       char t[kDNSServiceMaxDomainName];
+
+       const unsigned char *max = txt + txtLen;
+
+       (void)sdref;        // Unused
+       (void)ifIndex;      // Unused
+       (void)context;      // Unused
+
+       //if (!(flags & kDNSServiceFlagsAdd)) return;
+       if (errorCode) { printf("Error code %d\n", errorCode); return; }
+
+       if (CopyLabels(n, n + kDNSServiceMaxDomainName, &p, 3)) return;         // Fetch name+type
+       p = fullname;
+       if (CopyLabels(t, t + kDNSServiceMaxDomainName, &p, 1)) return;         // Skip first label
+       if (CopyLabels(t, t + kDNSServiceMaxDomainName, &p, 2)) return;         // Fetch next two labels (service type)
+
+       if (num_printed++ == 0)
+               {
+               printf("\n");
+               printf("; To direct clients to browse a different domain, substitute that domain in place of '@'\n");
+               printf("%-47s PTR     %s\n", "lb._dns-sd._udp", "@");
+               printf("\n");
+               printf("; In the list of services below, the SRV records will typically reference dot-local Multicast DNS names.\n");
+               printf("; When transferring this zone file data to your unicast DNS server, you'll need to replace those dot-local\n");
+               printf("; names with the correct fully-qualified (unicast) domain name of the target host offering the service.\n");
+               }
+
+       printf("\n");
+       printf("%-47s PTR     %s\n", t, n);
+       printf("%-47s SRV     0 0 %d %s ; Replace with unicast FQDN of target host\n", n, PortAsNumber, hosttarget);
+       printf("%-47s TXT    ", n);
+
+       while (txt < max)
+               {
+               const unsigned char *const end = txt + 1 + txt[0];
+               txt++;          // Skip over length byte
+               printf(" \"");
+               while (txt<end)
+                       {
+                       if (*txt == '\\' || *txt == '\"') printf("\\");
+                       printf("%c", *txt++);
+                       }
+               printf("\"");
+               }
+       printf("\n");
+
+       DNSServiceRefDeallocate(sdref);
+       free(context);
+
+       if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
+       }
+
+static void DNSSD_API zonedata_browse(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
+       const char *replyName, const char *replyType, const char *replyDomain, void *context)
+       {
+       DNSServiceRef *newref;
+
+       (void)sdref;        // Unused
+       (void)context;      // Unused
+
+       if (!(flags & kDNSServiceFlagsAdd)) return;
+       if (errorCode) { printf("Error code %d\n", errorCode); return; }
+
+       newref = malloc(sizeof(*newref));
+       *newref = client;
+       DNSServiceResolve(newref, kDNSServiceFlagsShareConnection, ifIndex, replyName, replyType, replyDomain, zonedata_resolve, newref);
+       }
+
 static void DNSSD_API browse_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
        const char *replyName, const char *replyType, const char *replyDomain, void *context)
        {
@@ -391,7 +517,7 @@ static void DNSSD_API resolve_reply(DNSServiceRef sdref, const DNSServiceFlags f
        if (errorCode) printf("Error code %d\n", errorCode);
        else
                {
-               printf("%s can be reached at %s:%u", fullname, hosttarget, PortAsNumber);
+               printf("%s can be reached at %s:%u (interface %d)", fullname, hosttarget, PortAsNumber, ifIndex);
                if (flags) printf(" Flags: %X", flags);
                // Don't show degenerate TXT records containing nothing but a single empty string
                if (txtLen > 1) { printf("\n"); ShowTXTRecord(txtLen, txtRecord); }
@@ -824,7 +950,14 @@ int main(int argc, char **argv)
        const char *a0 = strrchr(argv[0], kFilePathSep) + 1;
        if (a0 == (const char *)1) a0 = argv[0];
 
+#if defined(_WIN32)
+       HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
+#endif
+
+#if TEST_NEW_CLIENTSTUB
+       printf("Using embedded copy of dnssd_clientstub instead of system library\n");
        if (sizeof(argv) == 8) printf("Running in 64-bit mode\n");
+#endif
 
        // Test code for TXTRecord functions
        //TXTRecordRef txtRecord;
@@ -850,7 +983,7 @@ int main(int argc, char **argv)
                }
 
        if (argc < 2) goto Fail;        // Minimum command line is the command name and one argument
-       operation = getfirstoption(argc, argv, "EFBLRPQCAUNTMISV"
+       operation = getfirstoption(argc, argv, "EFBZLRPQCAUNTMISV"
                                                                #if HAS_NAT_PMP_API
                                                                        "X"
                                                                #endif
@@ -884,13 +1017,23 @@ int main(int argc, char **argv)
                                        err = DNSServiceBrowse(&client, 0, opinterface, typ, dom, browse_reply, NULL);
                                        break;
 
+               case 'Z':       typ = (argc < opi+1) ? "" : argv[opi+0];
+                                       dom = (argc < opi+2) ? "" : argv[opi+1];  // Missing domain argument is the same as empty string i.e. use system default(s)
+                                       typ = gettype(buffer, typ);
+                                       if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;   // We allow '.' on the command line as a synonym for empty string
+                                       printf("Browsing for %s%s%s\n", typ, dom[0] ? "." : "", dom);
+                                       err = DNSServiceCreateConnection(&client);
+                                       sc1 = client;
+                                       err = DNSServiceBrowse(&sc1, kDNSServiceFlagsShareConnection, opinterface, typ, dom, zonedata_browse, NULL);
+                                       break;
+
                case 'L':       if (argc < opi+2) goto Fail;
                                        typ = (argc < opi+2) ? ""      : argv[opi+1];
                                        dom = (argc < opi+3) ? "local" : argv[opi+2];
                                        typ = gettype(buffer, typ);
                                        if (dom[0] == '.' && dom[1] == 0) dom = "local";   // We allow '.' on the command line as a synonym for "local"
                                        printf("Lookup %s.%s.%s\n", argv[opi+0], typ, dom);
-                                       err = DNSServiceResolve(&client, 0, opinterface, argv[opi+0], typ, dom, (DNSServiceResolveReply)resolve_reply, NULL);
+                                       err = DNSServiceResolve(&client, 0, opinterface, argv[opi+0], typ, dom, resolve_reply, NULL);
                                        break;
 
                case 'R':       if (argc < opi+4) goto Fail;
@@ -907,7 +1050,7 @@ int main(int argc, char **argv)
                                        err = RegisterProxyAddressRecord(client_pa, argv[opi+4], argv[opi+5]);
                                        //err = RegisterProxyAddressRecord(client_pa, "two", argv[opi+5]);
                                        if (err) break;
-                                       err = RegisterService(&client, argv[opi+0], argv[opi+1], argv[opi+2], argv[opi+4], argv[opi+3], argc-(opi+6), argv+(opi+6));
+                                       err = RegisterService(&client, argv[opi+0], gettype(buffer, argv[opi+1]), argv[opi+2], argv[opi+4], argv[opi+3], argc-(opi+6), argv+(opi+6));
                                        //DNSServiceRemoveRecord(client_pa, record, 0);
                                        //DNSServiceRemoveRecord(client_pa, record, 0);
                                        break;
@@ -995,6 +1138,10 @@ int main(int argc, char **argv)
 
                case 'S':       {
                                        Opaque16 registerPort = { { 0x23, 0x45 } };
+                                       unsigned char txtrec[16] = "\xF" "/path=test.html";
+                                       DNSRecordRef rec;
+                                       unsigned char nulrec[4] = "1234";
+
                                        err = DNSServiceCreateConnection(&client);
                                        if (err) { fprintf(stderr, "DNSServiceCreateConnection failed %ld\n", (long int)err); return (-1); }
 
@@ -1011,6 +1158,15 @@ int main(int argc, char **argv)
                                                "_http._tcp", "local", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
                                        if (err) { fprintf(stderr, "SharedConnection DNSServiceRegister failed %ld\n", (long int)err); return (-1); }
 
+                                       err = DNSServiceUpdateRecord(sc3, NULL, 0, sizeof(txtrec), txtrec, 0);
+                                       if (err) { fprintf(stderr, "SharedConnection DNSServiceUpdateRecord failed %ld\n", (long int)err); return (-1); }
+
+                                       err = DNSServiceAddRecord(sc3, &rec, 0, kDNSServiceType_NULL, sizeof(nulrec), nulrec, 0);
+                                       if (err) { fprintf(stderr, "SharedConnection DNSServiceAddRecord failed %ld\n", (long int)err); return (-1); }
+
+                                       err = DNSServiceRemoveRecord(sc3, rec, 0);
+                                       if (err) { fprintf(stderr, "SharedConnection DNSServiceRemoveRecord failed %ld\n", (long int)err); return (-1); }
+
                                        break;
                                        }
 
@@ -1041,6 +1197,7 @@ Fail:
        fprintf(stderr, "%s -L <Name> <Type> <Domain>           (Look up a service instance)\n", a0);
        fprintf(stderr, "%s -R <Name> <Type> <Domain> <Port> [<TXT>...] (Register a service)\n", a0);
        fprintf(stderr, "%s -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...]  (Proxy)\n", a0);
+       fprintf(stderr, "%s -Z        <Type> <Domain>   (Output results in Zone File format)\n", a0);
        fprintf(stderr, "%s -Q <FQDN> <rrtype> <rrclass> (Generic query for any record type)\n", a0);
        fprintf(stderr, "%s -C <FQDN> <rrtype> <rrclass>   (Query; reconfirming each result)\n", a0);
 #if HAS_NAT_PMP_API
@@ -1049,6 +1206,8 @@ Fail:
 #if HAS_ADDRINFO_API
        fprintf(stderr, "%s -G v4/v6/v4v6 <Hostname>  (Get address information for hostname)\n", a0);
 #endif
+       fprintf(stderr, "%s -V    (Get version of currently running daemon / system service)\n", a0);
+
        fprintf(stderr, "%s -A                      (Test Adding/Updating/Deleting a record)\n", a0);
        fprintf(stderr, "%s -U                                  (Test updating a TXT record)\n", a0);
        fprintf(stderr, "%s -N                             (Test adding a large NULL record)\n", a0);
@@ -1056,7 +1215,6 @@ Fail:
        fprintf(stderr, "%s -M      (Test creating a registration with multiple TXT records)\n", a0);
        fprintf(stderr, "%s -I   (Test registering and then immediately updating TXT record)\n", a0);
        fprintf(stderr, "%s -S                 (Test multiple operations on a shared socket)\n", a0);
-       fprintf(stderr, "%s -V    (Get version of currently running daemon / system service)\n", a0);
        return 0;
        }
 
@@ -1070,6 +1228,8 @@ Fail:
 // The "@(#) " pattern is a special prefix the "what" command looks for
 const char VersionString_SCCS[] = "@(#) dns-sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
 
+#if _BUILDING_XCODE_PROJECT_
 // If the process crashes, then this string will be magically included in the automatically-generated crash log
 const char *__crashreporter_info__ = VersionString_SCCS + 5;
 asm(".desc ___crashreporter_info__, 0x10");
+#endif
index 73dd03ea9aa1b62fe69c6d6f5f486909a2d4c83f..1f62270c8a78495d6c53845b34aacf876eb83b0b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 
 include /Developer/Makefiles/pb_makefiles/platform.make
 
-MVERS = "mDNSResponder-176.3"
+MVERS = "mDNSResponder-212.1"
 
 DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
 
index 8d629073d84b0fa1cdaea9e98c8239db93d0d47a..e66bec80e0288526763429130a4ede2a1f6574c5 100644 (file)
@@ -76,7 +76,7 @@ would fix this.
 All private LLQ operations are TSIG-enabled and sent over a secure
 encrypted TLS channel. To accommodate service providers who don't want
 to have to keep open a large number of TLS connections to a large number
-of client machines, the server has the option of dropping the TSL
+of client machines, the server has the option of dropping the TLS
 connection after initial LLQ setup and sending subsequent events and
 refreshes using unencrypted UDP packets. This results in less load on
 the server, at the cost of slightly lower security (LLQs can only be set
diff --git a/buildResults.xml b/buildResults.xml
deleted file mode 100644 (file)
index b45ac9a..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-<buildResults>\r\r
-       <dest dir="ExplorerPluginModule_msm">\r\r
-               <dest dir="Program Files/Bonjour">\r\r
-                       <src file="Clients/ExplorerPlugin/Release/*.dll"/>\r\r
-               </dest>\r\r
-       </dest>\r\r
-       <dest dir="JavaModule_msm">\r\r
-               <dest dir="Program Files/Bonjour">\r\r
-                       <src file="mDNSWindows/Java/build/prod/dns_sd.jar"/>\r\r
-               </dest>\r\r
-               <dest dir="System32">\r\r
-                       <src file="mDNSWindows/Java/build/prod/jdns_sd.dll"/>\r\r
-               </dest>\r\r
-       </dest>\r\r
-       <dest dir="mDNSResponder_msm">\r\r
-               <dest dir="Program Files/Bonjour">\r\r
-                       <src file="mDNSWindows/SystemService/Release/mDNSResponder.exe"/>\r\r
-                       <src file="mDNSWindows/mdnsNSP/Release/mdnsNSP.dll"/>\r\r
-               </dest>\r\r
-               <dest dir="System32">\r\r
-                       <src file="mDNSWindows/DLL/Release/dnssd.dll"/>\r\r
-                       <src file="Clients/DNS-SD.VisualStudio/Release/dns-sd.exe"/>\r\r
-               </dest>\r\r
-       </dest>\r\r
-       <dest dir="PrinterSetupModule_msm">\r\r
-               <dest dir="Program Files/Bonjour">\r\r
-                       <src file="Clients/PrinterSetupWizard/Release/*.exe"/>\r\r
-                       <src file="Clients/PrinterSetupWizard/Release/*.dll"/>\r\r
-               </dest>\r\r
-       </dest>\r\r
-       <dest dir="sdk_root/Program Files/Bonjour SDK">\r
-               <dest dir="include">\r\r
-                       <src file="mDNSShared/dns_sd.h"/>\r
-               </dest>\r\r
-               <dest dir="lib">\r\r
-                       <src file="mDNSWindows/DLL/Release/dnssd.lib"/>\r
-               </dest>\r\r
-               <dest dir="samples/C">\r\r
-                       <src file="Clients/dns-sd.c"/>\r
-                       <src file="Clients/DNS-SD.VisualStudio/Release/dns-sd.exe"/>\r\r
-               </dest>\r\r
-               <dest dir="samples/Java">\r\r
-                       <src file="Clients/Java/nmakefile"/>\r
-                       <src file="Clients/Java/BrowserApp.java"/>\r
-                       <src file="Clients/Java/SimpleChat.java"/>\r
-                       <src file="Clients/Java/Swing*.java"/>\r
-                       <src file="Clients/Java/build/prod/*.jar"/>\r
-               </dest>\r\r
-       </dest>\r\r
-</buildResults>\r\r
index deda1b90b8e33922eacfc17e43e52e4fc51eb5f0..b001a7057adc0b79cd16f766cc11b8ef3777b127 100644 (file)
     Change History (most recent first):
 
 $Log: DNSCommon.c,v $
-Revision 1.199.2.1  2008/07/25 07:25:08  mcguire
-merge of <rdar://3988320&6041178> to SUSB for <rdar://problem/5662487&6090114>
+Revision 1.252  2009/06/27 00:27:03  cheshire
+<rdar://problem/6959273> mDNSResponder taking up 13% CPU with 400 KBps incoming bonjour requests
+Removed overly-complicate and ineffective multi-packet known-answer snooping code
+(Bracketed it with "#if ENABLE_MULTI_PACKET_QUERY_SNOOPING" for now; will delete actual code later)
+
+Revision 1.251  2009/05/19 23:40:37  cheshire
+<rdar://problem/6903507> Sleep Proxy: Retransmission logic not working reliably on quiet networks
+Added m->NextScheduledSPRetry timer for scheduling Sleep Proxy registration retries
+
+Revision 1.250  2009/05/01 21:28:33  cheshire
+<rdar://problem/6721680> AppleConnectAgent's reachability checks delay sleep by 30 seconds
+No longer suspend network operations after we've acknowledged that the machine is going to sleep,
+because other software may not have yet acknowledged the sleep event, and may be still trying
+to do unicast DNS queries or other Bonjour operations.
+
+Revision 1.249  2009/04/24 00:29:20  cheshire
+<rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
+Added support for generating/parsing/displaying NSEC records
+
+Revision 1.248  2009/04/23 22:11:16  cheshire
+Minor cleanup in debugging checks in GetLargeResourceRecord
+
+Revision 1.247  2009/04/21 23:36:25  cheshire
+<rdar://problem/6814427> Remove unused kDNSType_MAC
+
+Revision 1.246  2009/04/21 01:00:19  cheshire
+Fixed typo in previous checkin
+
+Revision 1.245  2009/04/21 00:57:23  cheshire
+<rdar://problem/6810410> Off-by-one error in putDomainNameAsLabels()
+If just writing one-byte root label, make sure we have space for that
+
+Revision 1.244  2009/04/11 00:19:30  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.243  2009/04/01 17:50:10  mcguire
+cleanup mDNSRandom
+
+Revision 1.242  2009/03/26 04:01:55  jessic2
+<rdar://problem/6613786> MessageTracer: Log service types longer than 14 characters and service types with underscores
+
+Revision 1.241  2009/03/18 20:50:08  cheshire
+<rdar://problem/6650064> uDNS: Reverse lookup of own IP address takes way too long, sometimes forever
+
+Revision 1.240  2009/03/18 20:41:04  cheshire
+Added definition of the all-ones mDNSOpaque16 ID
+
+Revision 1.239  2009/03/06 23:51:50  mcguire
+Fix broken build by defining DiscardPort
+
+Revision 1.238  2009/03/04 00:40:13  cheshire
+Updated DNS server error codes to be more consistent with definitions at
+<http://www.iana.org/assignments/dns-parameters>
+
+Revision 1.237  2009/03/03 23:04:43  cheshire
+For clarity, renamed "MAC" field to "HMAC" (Host MAC, as opposed to Interface MAC)
+
+Revision 1.236  2009/03/03 22:51:53  cheshire
+<rdar://problem/6504236> Sleep Proxy: Waking on same network but different interface will cause conflicts
+
+Revision 1.235  2009/02/07 05:55:44  cheshire
+Only pay attention to m->DelaySleep when it's nonzero
+
+Revision 1.234  2009/02/07 02:52:52  cheshire
+<rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
+Pay attention to m->DelaySleep when computing next task time
+
+Revision 1.233  2009/01/30 23:50:31  cheshire
+Added LastLabel() routine to get the last label of a domainname
+
+Revision 1.232  2009/01/15 00:22:48  mcguire
+<rdar://problem/6437092> NAT-PMP: mDNSResponder needs to listen on 224.0.0.1:5350/UDP with REUSEPORT
+
+Revision 1.231  2008/12/12 01:24:06  cheshire
+Updated GetNextScheduledEvent() to pay attention to m->SPSProxyListChanged
+
+Revision 1.230  2008/12/10 01:55:54  cheshire
+Renamed "Max" macro to avoid conflict with another "Max" macro on ARMv5
+
+Revision 1.229  2008/11/27 01:28:45  cheshire
+For display purposes, show sleep sequence number as unsigned
+
+Revision 1.228  2008/11/26 20:57:37  cheshire
+For consistency with other similar macros, renamed mdnsIsDigit/mdnsIsLetter/mdnsValidHostChar
+to mDNSIsDigit/mDNSIsLetter/mDNSValidHostChar
+
+Revision 1.227  2008/11/26 20:28:05  cheshire
+Added new SSHPort constant
+
+Revision 1.226  2008/11/16 16:55:51  cheshire
+Updated debugging messages
+
+Revision 1.225  2008/11/14 21:56:31  cheshire
+Moved debugging routine ShowTaskSchedulingError() from daemon.c into DNSCommon.c
+
+Revision 1.224  2008/11/14 02:20:03  cheshire
+Include m->NextScheduledSPS in task scheduling calculations
+
+Revision 1.223  2008/11/14 01:19:03  cheshire
+Initialize TimeRcvd and TimeExpire fields in AuthRecord_struct
+
+Revision 1.222  2008/11/14 00:00:53  cheshire
+After client machine wakes up, Sleep Proxy machine need to remove any records
+it was temporarily holding as proxy for that client
+
+Revision 1.221  2008/11/13 19:06:02  cheshire
+Added code to put, get, and display rdataOPT properly
+
+Revision 1.220  2008/11/06 01:08:11  mcguire
+Fix compiler warning about discarding const
+
+Revision 1.219  2008/11/04 23:06:50  cheshire
+Split RDataBody union definition into RDataBody and RDataBody2, and removed
+SOA from the normal RDataBody union definition, saving 270 bytes per AuthRecord
+
+Revision 1.218  2008/11/04 22:21:44  cheshire
+Changed zone field of AuthRecord_struct from domainname to pointer, saving 252 bytes per AuthRecord
+
+Revision 1.217  2008/11/04 22:13:43  cheshire
+Made RDataBody parameter to GetRRDisplayString_rdb "const"
+
+Revision 1.216  2008/11/04 20:06:19  cheshire
+<rdar://problem/6186231> Change MAX_DOMAIN_NAME to 256
+
+Revision 1.215  2008/10/23 23:54:35  cheshire
+Added missing "const" in declaration
+
+Revision 1.214  2008/10/23 22:25:55  cheshire
+Renamed field "id" to more descriptive "updateid"
+
+Revision 1.213  2008/10/22 01:01:52  cheshire
+Added onesEthAddr constant, used for sending ARP broadcasts
+
+Revision 1.212  2008/10/14 21:52:18  cheshire
+Added support for putting/getting/printing kDNSType_MAC
+
+Revision 1.211  2008/10/09 22:36:08  cheshire
+Now that we have Sleep Proxy Server, can't suppress normal scheduling logic while going to sleep
+
+Revision 1.210  2008/10/08 01:03:52  cheshire
+Change GetFirstActiveInterface() so the NetworkInterfaceInfo it returns is not "const"
+Added mDNS_SetupQuestion() convenience function
+
+Revision 1.209  2008/09/23 04:13:30  cheshire
+<rdar://problem/6238774> Remove "local" from the end of _services._dns-sd._udp PTR records
+Removed old special-case Bonjour Browser hack that is no longer needed
+
+Revision 1.208  2008/09/23 02:33:56  cheshire
+<rdar://problem/4738033> uDNS: Should not compress SRV rdata in uDNS packets
+
+Revision 1.207  2008/09/23 02:30:07  cheshire
+Get rid of PutResourceRecordCappedTTL()
+
+Revision 1.206  2008/09/23 02:26:09  cheshire
+Don't need to export putEmptyResourceRecord (it's only used from DNSCommon.c)
+
+Revision 1.205  2008/09/23 02:21:00  cheshire
+Don't need to force setting of rrclass in PutResourceRecordTTLWithLimit() now that putLLQ() sets it correctly
+
+Revision 1.204  2008/08/29 19:03:05  cheshire
+<rdar://problem/6185645> Off-by-one error in putDomainNameAsLabels()
+
+Revision 1.203  2008/08/13 00:47:53  mcguire
+Handle failures when packet logging
+
+Revision 1.202  2008/08/13 00:32:48  mcguire
+refactor to use SwapDNSHeaderBytes instead of swapping manually
+
+Revision 1.201  2008/07/24 20:23:03  cheshire
+<rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+
+Revision 1.200  2008/07/18 00:07:50  cheshire
+<rdar://problem/5904999> Log a message for applications that register service types longer than 14 characters
 
 Revision 1.199  2008/03/14 19:58:38  mcguire
 <rdar://problem/5500969> BTMM: Need ability to identify version of mDNSResponder client
@@ -416,6 +587,9 @@ mDNSexport const mDNSEthAddr     zeroEthAddr       = { { 0 } };
 mDNSexport const mDNSv4Addr      onesIPv4Addr      = { { 255, 255, 255, 255 } };
 mDNSexport const mDNSv6Addr      onesIPv6Addr      = { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } };
 mDNSexport const mDNSAddr        zeroAddr          = { mDNSAddrType_None, {{{ 0 }}} };
+mDNSexport const mDNSEthAddr     onesEthAddr       = { { 255, 255, 255, 255, 255, 255 } };
+
+mDNSexport const OwnerOptData    zeroOwner         = { 0, 0, { { 0 } }, { { 0 } }, { { 0 } } };
 
 mDNSexport const mDNSInterfaceID mDNSInterface_Any       = 0;
 mDNSexport const mDNSInterfaceID mDNSInterface_LocalOnly = (mDNSInterfaceID)1;
@@ -428,38 +602,40 @@ mDNSexport const mDNSInterfaceID mDNSInterface_Unicast   = (mDNSInterfaceID)2;
 // Uncomment the appropriate lines below to build a special Multicast DNS responder for testing interoperability
 // with Microsoft's LLMNR client code.
 
+#define   DiscardPortAsNumber               9
+#define   SSHPortAsNumber                  22
+#define   UnicastDNSPortAsNumber           53
 #define   SSDPPortAsNumber               1900
-
-#define   UnicastDNSPortAsNumber         53
+#define   NSIPCPortAsNumber              5030          // Port used for dnsextd to talk to local nameserver bound to loopback
 #define   NATPMPAnnouncementPortAsNumber 5350
 #define   NATPMPPortAsNumber             5351
 #define   DNSEXTPortAsNumber             5352          // Port used for end-to-end DNS operations like LLQ, Updates with Leases, etc.
 #define   MulticastDNSPortAsNumber       5353
 #define   LoopbackIPCPortAsNumber        5354
 //#define MulticastDNSPortAsNumber       5355          // LLMNR
-
-#define   NSIPCPortAsNumber              5030     // Port used for dnsextd to talk to local nameserver bound to loopback
 #define   PrivateDNSPortAsNumber         5533
 
-mDNSexport const mDNSIPPort SSDPPort               = { { SSDPPortAsNumber               >> 8, SSDPPortAsNumber               & 0xFF } };
-
+mDNSexport const mDNSIPPort DiscardPort            = { { DiscardPortAsNumber            >> 8, DiscardPortAsNumber            & 0xFF } };
+mDNSexport const mDNSIPPort SSHPort                = { { SSHPortAsNumber                >> 8, SSHPortAsNumber                & 0xFF } };
 mDNSexport const mDNSIPPort UnicastDNSPort         = { { UnicastDNSPortAsNumber         >> 8, UnicastDNSPortAsNumber         & 0xFF } };
+mDNSexport const mDNSIPPort SSDPPort               = { { SSDPPortAsNumber               >> 8, SSDPPortAsNumber               & 0xFF } };
+mDNSexport const mDNSIPPort NSIPCPort              = { { NSIPCPortAsNumber              >> 8, NSIPCPortAsNumber              & 0xFF } };
 mDNSexport const mDNSIPPort NATPMPAnnouncementPort = { { NATPMPAnnouncementPortAsNumber >> 8, NATPMPAnnouncementPortAsNumber & 0xFF } };
 mDNSexport const mDNSIPPort NATPMPPort             = { { NATPMPPortAsNumber             >> 8, NATPMPPortAsNumber             & 0xFF } };
 mDNSexport const mDNSIPPort DNSEXTPort             = { { DNSEXTPortAsNumber             >> 8, DNSEXTPortAsNumber             & 0xFF } };
 mDNSexport const mDNSIPPort MulticastDNSPort       = { { MulticastDNSPortAsNumber       >> 8, MulticastDNSPortAsNumber       & 0xFF } };
 mDNSexport const mDNSIPPort LoopbackIPCPort        = { { LoopbackIPCPortAsNumber        >> 8, LoopbackIPCPortAsNumber        & 0xFF } };
-
-mDNSexport const mDNSIPPort NSIPCPort              = { { NSIPCPortAsNumber              >> 8, NSIPCPortAsNumber              & 0xFF } };
 mDNSexport const mDNSIPPort PrivateDNSPort         = { { PrivateDNSPortAsNumber         >> 8, PrivateDNSPortAsNumber         & 0xFF } };
 
 mDNSexport const mDNSv4Addr AllDNSAdminGroup   = { { 239, 255, 255, 251 } };
+mDNSexport const mDNSv4Addr AllSystemsMcast    = { { 224,   0,   0,   1 } }; // For NAT-PMP Annoucements
 mDNSexport const mDNSAddr   AllDNSLinkGroup_v4 = { mDNSAddrType_IPv4, { { { 224,   0,   0, 251 } } } };
 //mDNSexport const mDNSAddr AllDNSLinkGroup_v4 = { mDNSAddrType_IPv4, { { { 224,   0,   0, 252 } } } }; // LLMNR
 mDNSexport const mDNSAddr   AllDNSLinkGroup_v6 = { mDNSAddrType_IPv6, { { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB } } } };
 //mDNSexport const mDNSAddr AllDNSLinkGroup_v6 = { mDNSAddrType_IPv6, { { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x01,0x00,0x03 } } } }; // LLMNR
 
 mDNSexport const mDNSOpaque16 zeroID          = { { 0, 0 } };
+mDNSexport const mDNSOpaque16 onesID          = { { 255, 255 } };
 mDNSexport const mDNSOpaque16 QueryFlags      = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery,                0 } };
 mDNSexport const mDNSOpaque16 uQueryFlags     = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery | kDNSFlag0_RD, 0 } };
 mDNSexport const mDNSOpaque16 ResponseFlags   = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery | kDNSFlag0_AA, 0 } };
@@ -482,7 +658,7 @@ mDNSexport mDNSBool mDNSv4AddrIsRFC1918(mDNSv4Addr *addr)
                        (addr->b[0] == 192 && addr->b[1] == 168));            // 192.168/16
        }
 
-mDNSexport const NetworkInterfaceInfo *GetFirstActiveInterface(const NetworkInterfaceInfo *intf)
+mDNSexport NetworkInterfaceInfo *GetFirstActiveInterface(NetworkInterfaceInfo *intf)
        {
        while (intf && !intf->InterfaceActive) intf = intf->next;
        return(intf);
@@ -498,7 +674,7 @@ mDNSexport mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterf
        {
        mDNSu32 slot, used = 0;
        CacheGroup *cg;
-       CacheRecord *rr;
+       const CacheRecord *rr;
        FORALL_CACHERECORDS(slot, cg, rr)
                if (rr->resrec.InterfaceID == id) used++;
        return(used);
@@ -519,6 +695,7 @@ mDNSexport char *DNSTypeName(mDNSu16 rrtype)
                case kDNSType_AAAA: return("AAAA");
                case kDNSType_SRV:  return("SRV");
                case kDNSType_OPT:  return("OPT");
+               case kDNSType_NSEC: return("NSEC");
                case kDNSType_TSIG: return("TSIG");
                case kDNSQType_ANY: return("ANY");
                default:                        {
@@ -532,56 +709,88 @@ mDNSexport char *DNSTypeName(mDNSu16 rrtype)
 // Note slight bug: this code uses the rdlength from the ResourceRecord object, to display
 // the rdata from the RDataBody object. Sometimes this could be the wrong length -- but as
 // long as this routine is only used for debugging messages, it probably isn't a big problem.
-mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *rr, RDataBody *rd, char *buffer)
+mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RDataBody *const rd1, char *const buffer)
        {
-       #define Max (MaxMsg-1)
+       const RDataBody2 *const rd = (RDataBody2 *)rd1;
+       #define RemSpc (MaxMsg-1-length)
        char *ptr = buffer;
-       mDNSu32 length = mDNS_snprintf(buffer, Max, "%4d %##s %s ", rr->rdlength, rr->name->c, DNSTypeName(rr->rrtype));
+       mDNSu32 length = mDNS_snprintf(buffer, MaxMsg-1, "%4d %##s %s ", rr->rdlength, rr->name->c, DNSTypeName(rr->rrtype));
        if (rr->RecordType == kDNSRecordTypePacketNegative) return(buffer);
-       if (!rr->rdlength) { mDNS_snprintf(buffer+length, Max-length, "<< ZERO RDATA LENGTH >>"); return(buffer); }
+       if (!rr->rdlength) { mDNS_snprintf(buffer+length, RemSpc, "<< ZERO RDATA LENGTH >>"); return(buffer); }
        
        switch (rr->rrtype)
                {
-               case kDNSType_A:        mDNS_snprintf(buffer+length, Max-length, "%.4a", &rd->ipv4);          break;
+               case kDNSType_A:        mDNS_snprintf(buffer+length, RemSpc, "%.4a", &rd->ipv4);          break;
 
                case kDNSType_NS:       // Same as PTR
                case kDNSType_CNAME:// Same as PTR
-               case kDNSType_PTR:      mDNS_snprintf(buffer+length, Max-length, "%##s", rd->name.c);       break;
+               case kDNSType_PTR:      mDNS_snprintf(buffer+length, RemSpc, "%##s", rd->name.c);       break;
 
-               case kDNSType_SOA:  mDNS_snprintf(buffer+length, Max-length, "%##s %##s %d %d %d %d %d",
+               case kDNSType_SOA:  mDNS_snprintf(buffer+length, RemSpc, "%##s %##s %d %d %d %d %d",
                                                                rd->soa.mname.c, rd->soa.rname.c,
                                                                rd->soa.serial, rd->soa.refresh, rd->soa.retry, rd->soa.expire, rd->soa.min);
                                                        break;
 
                case kDNSType_HINFO:// Display this the same as TXT (show all constituent strings)
                case kDNSType_TXT:  {
-                                                       mDNSu8 *t = rd->txt.c;
+                                                       const mDNSu8 *t = rd->txt.c;
                                                        while (t < rd->txt.c + rr->rdlength)
                                                                {
-                                                               length += mDNS_snprintf(buffer+length, Max-length, "%s%#s", t > rd->txt.c ? "¦" : "", t);
+                                                               length += mDNS_snprintf(buffer+length, RemSpc, "%s%#s", t > rd->txt.c ? "¦" : "", t);
                                                                t += 1 + t[0];
                                                                }
                                                        } break;
 
-               case kDNSType_AAAA:     mDNS_snprintf(buffer+length, Max-length, "%.16a", &rd->ipv6);       break;
-               case kDNSType_SRV:      mDNS_snprintf(buffer+length, Max-length, "%u %u %u %##s",
+               case kDNSType_AAAA:     mDNS_snprintf(buffer+length, RemSpc, "%.16a", &rd->ipv6);       break;
+               case kDNSType_SRV:      mDNS_snprintf(buffer+length, RemSpc, "%u %u %u %##s",
                                                                rd->srv.priority, rd->srv.weight, mDNSVal16(rd->srv.port), rd->srv.target.c); break;
-               case kDNSType_OPT:  length += mDNS_snprintf(buffer+length, Max-length, "%d Len %d ", rd->opt.opt, rd->opt.optlen);
-                                                       length += mDNS_snprintf(buffer+length, Max-length, "Max UDP %d ", rr->rrclass);
-                                                       if (rd->opt.opt == kDNSOpt_LLQ)
+
+               case kDNSType_OPT:  {
+                                                       const rdataOPT *opt;
+                                                       const rdataOPT *const end = (const rdataOPT *)&rd->data[rr->rdlength];
+                                                       length += mDNS_snprintf(buffer+length, RemSpc, "Max %d", rr->rrclass);
+                                                       for (opt = &rd->opt[0]; opt < end; opt++)
                                                                {
-                                                               length += mDNS_snprintf(buffer+length, Max-length, "Vers %d ",     rd->opt.OptData.llq.vers);
-                                                               length += mDNS_snprintf(buffer+length, Max-length, "Op %d ",       rd->opt.OptData.llq.llqOp);
-                                                               length += mDNS_snprintf(buffer+length, Max-length, "Err/Port %d ", rd->opt.OptData.llq.err);
-                                                               length += mDNS_snprintf(buffer+length, Max-length, "ID %08X%08X ", rd->opt.OptData.llq.id.l[0], rd->opt.OptData.llq.id.l[1]);
-                                                               length += mDNS_snprintf(buffer+length, Max-length, "Lease %d",     rd->opt.OptData.llq.llqlease);
+                                                               switch(opt->opt)
+                                                                       {
+                                                                       case kDNSOpt_LLQ:
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " Vers %d",     opt->u.llq.vers);
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " Op %d",       opt->u.llq.llqOp);
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " Err/Port %d", opt->u.llq.err);
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " ID %08X%08X", opt->u.llq.id.l[0], opt->u.llq.id.l[1]);
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " Lease %d",    opt->u.llq.llqlease);
+                                                                               break;
+                                                                       case kDNSOpt_Lease:
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " Lease %d",    opt->u.updatelease);
+                                                                               break;
+                                                                       case kDNSOpt_Owner:
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " Vers %d",     opt->u.owner.vers);
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " Seq %3d", (mDNSu8)opt->u.owner.seq);   // Display as unsigned
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " MAC %.6a",    opt->u.owner.HMAC.b);
+                                                                               if (opt->optlen >= DNSOpt_OwnerData_ID_Wake_Space-4)
+                                                                                       {
+                                                                                       length += mDNS_snprintf(buffer+length, RemSpc, " I-MAC %.6a", opt->u.owner.IMAC.b);
+                                                                                       if (opt->optlen > DNSOpt_OwnerData_ID_Wake_Space-4)
+                                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " Password %.6a", opt->u.owner.password.b);
+                                                                                       }
+                                                                               break;
+                                                                       default:
+                                                                               length += mDNS_snprintf(buffer+length, RemSpc, " Unknown %d",  opt->opt);
+                                                                               break;
+                                                                       }
                                                                }
-                                                       else if (rd->opt.opt == kDNSOpt_Lease)
-                                                               length += mDNS_snprintf(buffer+length, Max-length, "kDNSOpt_Lease Lease %d", rd->opt.OptData.updatelease);
-                                                       else
-                                                               length += mDNS_snprintf(buffer+length, Max-length, "Unknown opt %d", rd->opt.opt);
+                                                       }
                                                        break;
-               default:                        mDNS_snprintf(buffer+length, Max-length, "RDLen %d: %s", rr->rdlength, rd->data);
+
+               case kDNSType_NSEC: {
+                                                       int i;
+                                                       for (i=0; i<255; i++)
+                                                               if (rd->nsec.bitmap[i>>3] & (128 >> (i&7)))
+                                                                       length += mDNS_snprintf(buffer+length, RemSpc, "%s ", DNSTypeName(i));
+                                                       }
+                                                       break;
+
+               default:                        mDNS_snprintf(buffer+length, RemSpc, "RDLen %d: %s", rr->rdlength, rd->data);
                                                        // Really should scan buffer to check if text is valid UTF-8 and only replace with dots if not
                                                        for (ptr = buffer; *ptr; ptr++) if (*ptr < ' ') *ptr = '.';
                                                        break;
@@ -589,46 +798,44 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *rr, RDataBody *rd,
        return(buffer);
        }
 
-// Long-term we need to make this cross-platform, either by using our own embedded RC4 code
-// to generate the pseudo-random sequence, or by adding another mDNSPlatformXXX() call.
-// The former would be preferable because it makes our code self-contained, so it will run anywhere.
-// The latter is less desirable because it increases the burden on people writing platform support layers
-// to now implement one more function (and an important one at that, that needs to be cryptographically strong).
-// For now, as a temporary fix, if we're building mDNSResponder for OS X we just use arc4random() directly here.
+// See comments in mDNSEmbeddedAPI.h
+#if _PLATFORM_HAS_STRONG_PRNG_
+#define mDNSRandomNumber mDNSPlatformRandomNumber
+#else
+mDNSlocal mDNSu32 mDNSRandomFromSeed(mDNSu32 seed)
+       {
+       return seed * 21 + 1;
+       }
 
-#if _BUILDING_XCODE_PROJECT_
-#include <stdlib.h>
-#endif
+mDNSlocal mDNSu32 mDNSMixRandomSeed(mDNSu32 seed, mDNSu8 iteration)
+       {
+       return iteration ? mDNSMixRandomSeed(mDNSRandomFromSeed(seed), --iteration) : seed;
+       }
 
-mDNSexport mDNSu32 mDNSRandom(mDNSu32 max)             // Returns pseudo-random result from zero to max inclusive
+mDNSlocal mDNSu32 mDNSRandomNumber()
        {
+       static mDNSBool seeded = mDNSfalse;
        static mDNSu32 seed = 0;
-       mDNSu32 mask = 1;
-
-       if (!seed)
+       if (!seeded)
                {
-               int i;
-               seed = mDNSPlatformRandomSeed();                                // Pick an initial seed
-               for (i=0; i<100; i++) seed = seed * 21 + 1;             // And mix it up a bit
+               seed = mDNSMixRandomSeed(mDNSPlatformRandomSeed(), 100);
+               seeded = mDNStrue;
                }
-       while (mask < max) mask = (mask << 1) | 1;
-
-#if _BUILDING_XCODE_PROJECT_
-       do seed = arc4random();
-#else
-       do seed = seed * 21 + 1;
-#endif
-       while ((seed & mask) > max);
-
-       return (seed & mask);
+       return (seed = mDNSRandomFromSeed(seed));
        }
-
-mDNSexport mDNSu32 mDNSRandomFromFixedSeed(mDNSu32 seed, mDNSu32 max)
+#endif // ! _PLATFORM_HAS_STRONG_PRNG_
+       
+mDNSexport mDNSu32 mDNSRandom(mDNSu32 max)             // Returns pseudo-random result from zero to max inclusive
        {
+       mDNSu32 ret = 0;
        mDNSu32 mask = 1;
+
        while (mask < max) mask = (mask << 1) | 1;
-       do seed = seed * 21 + 1; while ((seed & mask) > max);
-       return (seed & mask);
+
+       do ret = mDNSRandomNumber() & mask;
+       while (ret > max);
+
+       return ret;
        }
 
 mDNSexport mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2)
@@ -690,7 +897,7 @@ mDNSexport mDNSBool SameDomainName(const domainname *const d1, const domainname
        while (*a || *b)
                {
                if (a + 1 + *a >= max)
-                       { debugf("Malformed domain name (more than 255 characters)"); return(mDNSfalse); }
+                       { debugf("Malformed domain name (more than 256 characters)"); return(mDNSfalse); }
                if (!SameDomainLabel(a, b)) return(mDNSfalse);
                a += 1 + *a;
                b += 1 + *b;
@@ -734,11 +941,22 @@ mDNSexport mDNSBool IsLocalDomain(const domainname *d)
        return(mDNSfalse);
        }
 
+mDNSexport const mDNSu8 *LastLabel(const domainname *d)
+       {
+       const mDNSu8 *p = d->c;
+       while (d->c[0])
+               {
+               p = d->c;
+               d = (const domainname*)(d->c + 1 + d->c[0]);
+               }
+       return(p);
+       }
+
 // Returns length of a domain name INCLUDING the byte for the final null label
 // e.g. for the root label "." it returns one
 // For the FQDN "com." it returns 5 (length byte, three data bytes, final zero)
-// Legal results are 1 (just root label) to 255 (MAX_DOMAIN_NAME)
-// If the given domainname is invalid, result is 256 (MAX_DOMAIN_NAME+1)
+// Legal results are 1 (just root label) to 256 (MAX_DOMAIN_NAME)
+// If the given domainname is invalid, result is 257 (MAX_DOMAIN_NAME+1)
 mDNSexport mDNSu16 DomainNameLengthLimit(const domainname *const name, const mDNSu8 *limit)
        {
        const mDNSu8 *src = name->c;
@@ -796,7 +1014,7 @@ mDNSexport const domainname *SkipLeadingLabels(const domainname *d, int skip)
 // Any dots in the name are literal dots, not label separators
 // If successful, AppendLiteralLabelString returns a pointer to the next unused byte
 // in the domainname bufer (i.e. the next byte after the terminating zero).
-// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 255 bytes)
+// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 256 bytes)
 // AppendLiteralLabelString returns mDNSNULL.
 mDNSexport mDNSu8 *AppendLiteralLabelString(domainname *const name, const char *cstr)
        {
@@ -818,7 +1036,7 @@ mDNSexport mDNSu8 *AppendLiteralLabelString(domainname *const name, const char *
 // Textual labels, escaped as necessary using the usual DNS '\' notation, separated by dots.
 // If successful, AppendDNSNameString returns a pointer to the next unused byte
 // in the domainname bufer (i.e. the next byte after the terminating zero).
-// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 255 bytes)
+// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 256 bytes)
 // AppendDNSNameString returns mDNSNULL.
 mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstring)
        {
@@ -835,7 +1053,7 @@ mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstri
                        if (c == '\\')                                                                                  // If escape character, check next character
                                {
                                c = (mDNSu8)*cstr++;                                                            // Assume we'll just take the next character
-                               if (mdnsIsDigit(cstr[-1]) && mdnsIsDigit(cstr[0]) && mdnsIsDigit(cstr[1]))
+                               if (mDNSIsDigit(cstr[-1]) && mDNSIsDigit(cstr[0]) && mDNSIsDigit(cstr[1]))
                                        {                                                                                               // If three decimal digits,
                                        int v0 = cstr[-1] - '0';                                                // then interpret as three-digit decimal
                                        int v1 = cstr[ 0] - '0';
@@ -860,7 +1078,7 @@ mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstri
 // AppendDomainLabel appends a single label to a name.
 // If successful, AppendDomainLabel returns a pointer to the next unused byte
 // in the domainname bufer (i.e. the next byte after the terminating zero).
-// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 255 bytes)
+// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 256 bytes)
 // AppendDomainLabel returns mDNSNULL.
 mDNSexport mDNSu8 *AppendDomainLabel(domainname *const name, const domainlabel *const label)
        {
@@ -914,7 +1132,7 @@ mDNSexport mDNSBool MakeDomainLabelFromLiteralString(domainlabel *const label, c
 // Textual labels, escaped as necessary using the usual DNS '\' notation, separated by dots.
 // If successful, MakeDomainNameFromDNSNameString returns a pointer to the next unused byte
 // in the domainname bufer (i.e. the next byte after the terminating zero).
-// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 255 bytes)
+// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 256 bytes)
 // MakeDomainNameFromDNSNameString returns mDNSNULL.
 mDNSexport mDNSu8 *MakeDomainNameFromDNSNameString(domainname *const name, const char *cstr)
        {
@@ -949,10 +1167,10 @@ mDNSexport char *ConvertDomainLabelToCString_withescape(const domainlabel *const
        return(ptr);                                                                                            // and return
        }
 
-// Note: To guarantee that there will be no possible overrun, cstr must be at least MAX_ESCAPED_DOMAIN_NAME (1005 bytes)
+// Note: To guarantee that there will be no possible overrun, cstr must be at least MAX_ESCAPED_DOMAIN_NAME (1009 bytes)
 mDNSexport char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc)
        {
-       const mDNSu8 *src         = name->c;                                                            // Domain name we're reading
+       const mDNSu8 *src         = name->c;                                                    // Domain name we're reading
        const mDNSu8 *const max   = name->c + MAX_DOMAIN_NAME;                  // Maximum that's valid
 
        if (*src == 0) *ptr++ = '.';                                                                    // Special case: For root, just write a dot
@@ -989,7 +1207,7 @@ mDNSexport void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], do
                        { src += 3; continue; } // Unicode curly apostrophe
                if (ptr < lim)
                        {
-                       if (mdnsValidHostChar(*src, (ptr > &hostlabel->c[1]), (src < end-1))) *ptr++ = *src;
+                       if (mDNSValidHostChar(*src, (ptr > &hostlabel->c[1]), (src < end-1))) *ptr++ = *src;
                        else if (ptr > &hostlabel->c[1] && ptr[-1] != '-') *ptr++ = '-';
                        }
                src++;
@@ -1009,6 +1227,10 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn,
        mDNSu8 *dst = fqdn->c;
        const mDNSu8 *src;
        const char *errormsg;
+#if APPLE_OSX_mDNSResponder
+       mDNSBool        loggedUnderscore = mDNSfalse;
+       static char typeBuf[MAX_ESCAPED_DOMAIN_NAME];
+#endif
 
        // In the case where there is no name (and ONLY in that case),
        // a single-label subtype is allowed as the first label of a three-part "type"
@@ -1052,21 +1274,44 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn,
 
        src = type->c;                                                                          // Put the service type into the domain name
        len = *src;
-       if (len < 2 || len >= 0x40 || (len > 15 && !SameDomainName(domain, &localdomain)))
+       if (len < 2 || len > 15)
                {
-               errormsg = "Application protocol name must be underscore plus 1-14 characters. See <http://www.dns-sd.org/ServiceTypes.html>";
-               goto fail;
+               LogMsg("Bad service type in %#s.%##s%##s Application protocol name must be underscore plus 1-14 characters. "
+                       "See <http://www.dns-sd.org/ServiceTypes.html>", name->c, type->c, domain->c);
+#if APPLE_OSX_mDNSResponder
+               ConvertDomainNameToCString(type, typeBuf);
+               mDNSASLLog(mDNSNULL, "serviceType.nameTooLong", "noop", typeBuf, "");
+#endif
                }
+       if (len < 2 || len >= 0x40 || (len > 15 && !SameDomainName(domain, &localdomain))) return(mDNSNULL);
        if (src[1] != '_') { errormsg = "Application protocol name must begin with underscore"; goto fail; }
        for (i=2; i<=len; i++)
                {
                // Letters and digits are allowed anywhere
-               if (mdnsIsLetter(src[i]) || mdnsIsDigit(src[i])) continue;
+               if (mDNSIsLetter(src[i]) || mDNSIsDigit(src[i])) continue;
                // Hyphens are only allowed as interior characters
                // Underscores are not supposed to be allowed at all, but for backwards compatibility with some old products we do allow them,
                // with the same rule as hyphens
-               if ((src[i] == '-' || src[i] == '_') && i > 2 && i < len) continue;
-               errormsg = "Application protocol name must contain only letters, digits, and hyphens"; goto fail;
+               if ((src[i] == '-' || src[i] == '_') && i > 2 && i < len) 
+                       {
+#if APPLE_OSX_mDNSResponder
+                       if (src[i] == '_' && loggedUnderscore == mDNSfalse)
+                               {
+                               ConvertDomainNameToCString(type, typeBuf);
+                               mDNSASLLog(mDNSNULL, "serviceType.nameWithUnderscore", "noop", typeBuf, "");
+                               loggedUnderscore = mDNStrue;
+                               }
+#endif
+                       continue;
+                       }
+               errormsg = "Application protocol name must contain only letters, digits, and hyphens";
+#if APPLE_OSX_mDNSResponder
+               {
+               ConvertDomainNameToCString(type, typeBuf);
+               mDNSASLLog(mDNSNULL, "serviceType.nameWithIllegalCharacters", "noop", typeBuf, "");
+               }
+#endif
+                goto fail;
                }
        for (i=0; i<=len; i++) *dst++ = *src++;
 
@@ -1117,9 +1362,8 @@ mDNSexport mDNSBool DeconstructServiceName(const domainname *const fqdn,
 
        len = *src;
        if (!len)         { debugf("DeconstructServiceName: FQDN contains only two labels!");          return(mDNSfalse); }
-       // Can't do this check right now, until Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
-       //if (!ValidTransportProtocol(src))
-       //                  { debugf("DeconstructServiceName: Transport protocol must be _udp or _tcp"); return(mDNSfalse); }
+       if (!ValidTransportProtocol(src))
+                         { debugf("DeconstructServiceName: Transport protocol must be _udp or _tcp"); return(mDNSfalse); }
        for (i=0; i<=len; i++) *dst++ = *src++;
        *dst++ = 0;                                                                                     // Put terminator on the end of service type
 
@@ -1187,17 +1431,17 @@ mDNSexport mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDN
                {
                if (l < 4) return mDNSfalse;                                                    // Need at least " (2)"
                if (name->c[l--] != ')') return mDNSfalse;                              // Last char must be ')'
-               if (!mdnsIsDigit(name->c[l])) return mDNSfalse;                 // Preceeded by a digit
+               if (!mDNSIsDigit(name->c[l])) return mDNSfalse;                 // Preceeded by a digit
                l--;
-               while (l > 2 && mdnsIsDigit(name->c[l])) l--;                   // Strip off digits
+               while (l > 2 && mDNSIsDigit(name->c[l])) l--;                   // Strip off digits
                return (name->c[l] == '(' && name->c[l - 1] == ' ');
                }
        else
                {
                if (l < 2) return mDNSfalse;                                                    // Need at least "-2"
-               if (!mdnsIsDigit(name->c[l])) return mDNSfalse;                 // Last char must be a digit
+               if (!mDNSIsDigit(name->c[l])) return mDNSfalse;                 // Last char must be a digit
                l--;
-               while (l > 2 && mdnsIsDigit(name->c[l])) l--;                   // Strip off digits
+               while (l > 2 && mDNSIsDigit(name->c[l])) l--;                   // Strip off digits
                return (name->c[l] == '-');
                }
        }
@@ -1213,7 +1457,7 @@ mDNSexport mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText)
        if (RichText && name->c[0] >= 1 && name->c[name->c[0]] == ')') name->c[0]--;
 
        // Get any existing numerical suffix off the name
-       while (mdnsIsDigit(name->c[name->c[0]]))
+       while (mDNSIsDigit(name->c[name->c[0]]))
                { val += (name->c[name->c[0]] - '0') * multiplier; multiplier *= 10; name->c[0]--; }
 
        // Chop opening parentheses or dash from suffix
@@ -1322,6 +1566,11 @@ mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mD
        rr->AllowRemoteQuery  = mDNSfalse;
        rr->ForceMCast        = mDNSfalse;
 
+       rr->WakeUp            = zeroOwner;
+       rr->AddressProxy      = zeroAddr;
+       rr->TimeRcvd          = 0;
+       rr->TimeExpire        = 0;
+
        // Field Group 3: Transient state for Authoritative Records (set in mDNS_Register_internal)
        // Field Group 4: Transient uDNS state for Authoritative Records (set in mDNS_Register_internal)
 
@@ -1332,8 +1581,8 @@ mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mD
        rr->uselease          = 0;
        rr->expire            = 0;
        rr->Private           = 0;
-       rr->id                = zeroID;
-       rr->zone.c[0]         = 0;
+       rr->updateid          = zeroID;
+       rr->zone              = rr->resrec.name;
        rr->UpdateServer      = zeroAddr;
        rr->UpdatePort        = zeroIPPort;
        rr->nta               = mDNSNULL;
@@ -1348,48 +1597,68 @@ mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mD
        rr->namestorage.c[0]  = 0;              // MUST be set by client before calling mDNS_Register()
        }
 
+mDNSexport void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID InterfaceID, const domainname *const name,
+               const mDNSu16 qtype, mDNSQuestionCallback *const callback, void *const context)
+       {
+       q->InterfaceID         = InterfaceID;
+       q->Target              = zeroAddr;
+       AssignDomainName(&q->qname, name);
+       q->qtype               = qtype;
+       q->qclass              = kDNSClass_IN;
+       q->LongLived           = (qtype == kDNSType_PTR);
+       q->ExpectUnique        = (qtype != kDNSType_PTR);
+       q->ForceMCast          = mDNSfalse;
+       q->ReturnIntermed      = mDNSfalse;
+       q->QuestionCallback    = callback;
+       q->QuestionContext     = context;
+       }
+
 mDNSexport mDNSu32 RDataHashValue(const ResourceRecord *const rr)
        {
+       int len = rr->rdlength;
+       const RDataBody2 *const rdb = (RDataBody2 *)rr->rdata->u.data;
        switch(rr->rrtype)
                {
                case kDNSType_NS:
                case kDNSType_CNAME:
                case kDNSType_PTR:
-               case kDNSType_DNAME: return DomainNameHashValue(&rr->rdata->u.name);
+               case kDNSType_DNAME: return DomainNameHashValue(&rdb->name);
 
-               case kDNSType_SOA:   return rr->rdata->u.soa.serial  +
-                                                                       rr->rdata->u.soa.refresh +
-                                                                       rr->rdata->u.soa.retry   +
-                                                                       rr->rdata->u.soa.expire  +
-                                                                       rr->rdata->u.soa.min     +
-                                                                       DomainNameHashValue(&rr->rdata->u.soa.mname) +
-                                                                       DomainNameHashValue(&rr->rdata->u.soa.rname);
+               case kDNSType_SOA:   return rdb->soa.serial  +
+                                                                       rdb->soa.refresh +
+                                                                       rdb->soa.retry   +
+                                                                       rdb->soa.expire  +
+                                                                       rdb->soa.min     +
+                                                                       DomainNameHashValue(&rdb->soa.mname) +
+                                                                       DomainNameHashValue(&rdb->soa.rname);
 
                case kDNSType_MX:
                case kDNSType_AFSDB:
                case kDNSType_RT:
-               case kDNSType_KX:        return DomainNameHashValue(&rr->rdata->u.mx.exchange);
+               case kDNSType_KX:        return DomainNameHashValue(&rdb->mx.exchange);
+
+               case kDNSType_RP:        return DomainNameHashValue(&rdb->rp.mbox)   + DomainNameHashValue(&rdb->rp.txt);
 
-               case kDNSType_RP:        return DomainNameHashValue(&rr->rdata->u.rp.mbox)   + DomainNameHashValue(&rr->rdata->u.rp.txt);
+               case kDNSType_PX:        return DomainNameHashValue(&rdb->px.map822) + DomainNameHashValue(&rdb->px.mapx400);
 
-               case kDNSType_PX:        return DomainNameHashValue(&rr->rdata->u.px.map822) + DomainNameHashValue(&rr->rdata->u.px.mapx400);
+               case kDNSType_SRV:       return DomainNameHashValue(&rdb->srv.target);
 
-               case kDNSType_SRV:       return DomainNameHashValue(&rr->rdata->u.srv.target);
+               case kDNSType_OPT:       return 0;      // OPT is a pseudo-RR container structure; makes no sense to compare
 
-               case kDNSType_OPT:      // Okay to use blind memory sum because there are no 'holes' in the in-memory representation
+               case kDNSType_NSEC:      len = sizeof(rdataNSEC);       // Use in-memory length of 32, and fall through default checksum computation below
 
                default:
                        {
                        mDNSu32 sum = 0;
                        int i;
-                       for (i=0; i+1 < rr->rdlength; i+=2)
+                       for (i=0; i+1 < len; i+=2)
                                {
-                               sum += (((mDNSu32)(rr->rdata->u.data[i])) << 8) | rr->rdata->u.data[i+1];
+                               sum += (((mDNSu32)(rdb->data[i])) << 8) | rdb->data[i+1];
                                sum = (sum<<3) | (sum>>29);
                                }
-                       if (i < rr->rdlength)
+                       if (i < len)
                                {
-                               sum += ((mDNSu32)(rr->rdata->u.data[i])) << 8;
+                               sum += ((mDNSu32)(rdb->data[i])) << 8;
                                }
                        return(sum);
                        }
@@ -1400,42 +1669,46 @@ mDNSexport mDNSu32 RDataHashValue(const ResourceRecord *const rr)
 // r2 is just a bare RDataBody, which MUST be the same rrtype and rdlength as r1
 mDNSexport mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2)
        {
+       const RDataBody2 *const b1 = (RDataBody2 *)r1->rdata->u.data;
+       const RDataBody2 *const b2 = (RDataBody2 *)r2;
        switch(r1->rrtype)
                {
                case kDNSType_NS:
                case kDNSType_CNAME:
                case kDNSType_PTR:
-               case kDNSType_DNAME:return(SameDomainName(&r1->rdata->u.name, &r2->name));
+               case kDNSType_DNAME:return(SameDomainName(&b1->name, &b2->name));
 
-               case kDNSType_SOA:      return(mDNSBool)(       r1->rdata->u.soa.serial   == r2->soa.serial             &&
-                                                                                               r1->rdata->u.soa.refresh  == r2->soa.refresh            &&
-                                                                                               r1->rdata->u.soa.retry    == r2->soa.retry              &&
-                                                                                               r1->rdata->u.soa.expire   == r2->soa.expire             &&
-                                                                                               r1->rdata->u.soa.min      == r2->soa.min                &&
-                                                                                               SameDomainName(&r1->rdata->u.soa.mname, &r2->soa.mname) &&
-                                                                                               SameDomainName(&r1->rdata->u.soa.rname, &r2->soa.rname));
+               case kDNSType_SOA:      return(mDNSBool)(       b1->soa.serial   == b2->soa.serial             &&
+                                                                                               b1->soa.refresh  == b2->soa.refresh            &&
+                                                                                               b1->soa.retry    == b2->soa.retry              &&
+                                                                                               b1->soa.expire   == b2->soa.expire             &&
+                                                                                               b1->soa.min      == b2->soa.min                &&
+                                                                                               SameDomainName(&b1->soa.mname, &b2->soa.mname) &&
+                                                                                               SameDomainName(&b1->soa.rname, &b2->soa.rname));
 
                case kDNSType_MX:
                case kDNSType_AFSDB:
                case kDNSType_RT:
-               case kDNSType_KX:       return(mDNSBool)(       r1->rdata->u.mx.preference == r2->mx.preference &&
-                                                                                               SameDomainName(&r1->rdata->u.mx.exchange, &r2->mx.exchange));
+               case kDNSType_KX:       return(mDNSBool)(       b1->mx.preference == b2->mx.preference &&
+                                                                                               SameDomainName(&b1->mx.exchange, &b2->mx.exchange));
 
-               case kDNSType_RP:       return(mDNSBool)(       SameDomainName(&r1->rdata->u.rp.mbox, &r2->rp.mbox) &&
-                                                                                               SameDomainName(&r1->rdata->u.rp.txt,  &r2->rp.txt));
+               case kDNSType_RP:       return(mDNSBool)(       SameDomainName(&b1->rp.mbox, &b2->rp.mbox) &&
+                                                                                               SameDomainName(&b1->rp.txt,  &b2->rp.txt));
 
-               case kDNSType_PX:       return(mDNSBool)(       r1->rdata->u.px.preference == r2->px.preference          &&
-                                                                                               SameDomainName(&r1->rdata->u.px.map822,  &r2->px.map822) &&
-                                                                                               SameDomainName(&r1->rdata->u.px.mapx400, &r2->px.mapx400));
+               case kDNSType_PX:       return(mDNSBool)(       b1->px.preference == b2->px.preference          &&
+                                                                                               SameDomainName(&b1->px.map822,  &b2->px.map822) &&
+                                                                                               SameDomainName(&b1->px.mapx400, &b2->px.mapx400));
 
-               case kDNSType_SRV:      return(mDNSBool)(       r1->rdata->u.srv.priority == r2->srv.priority       &&
-                                                                                               r1->rdata->u.srv.weight   == r2->srv.weight         &&
-                                                                                               mDNSSameIPPort(r1->rdata->u.srv.port, r2->srv.port) &&
-                                                                                               SameDomainName(&r1->rdata->u.srv.target, &r2->srv.target));
+               case kDNSType_SRV:      return(mDNSBool)(       b1->srv.priority == b2->srv.priority       &&
+                                                                                               b1->srv.weight   == b2->srv.weight         &&
+                                                                                               mDNSSameIPPort(b1->srv.port, b2->srv.port) &&
+                                                                                               SameDomainName(&b1->srv.target, &b2->srv.target));
 
-               case kDNSType_OPT:      // Okay to use blind memory compare because there are no 'holes' in the in-memory representation
+               case kDNSType_OPT:      return mDNSfalse;       // OPT is a pseudo-RR container structure; makes no sense to compare
 
-               default:                        return(mDNSPlatformMemSame(r1->rdata->u.data, r2->data, r1->rdlength));
+               case kDNSType_NSEC: return(mDNSPlatformMemSame(b1->data, b2->data, sizeof(rdataNSEC)));
+
+               default:                        return(mDNSPlatformMemSame(b1->data, b2->data, r1->rdlength));
                }
        }
 
@@ -1456,8 +1729,8 @@ mDNSexport mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr
        if (rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
 
        // RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
-       if (rr->rrtype != kDNSType_CNAME && rr->rrtype  != q->qtype  && q->qtype  != kDNSQType_ANY ) return(mDNSfalse);
-       if (                                rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
+       if (!RRTypeAnswersQuestionType(rr,q->qtype)) return(mDNSfalse);
+       if (rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
 
        return(mDNStrue);
        }
@@ -1472,14 +1745,29 @@ mDNSexport mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr
        if (rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
 
        // RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
-       if (rr->rrtype != kDNSType_CNAME && rr->rrtype  != q->qtype  && q->qtype  != kDNSQType_ANY ) return(mDNSfalse);
-       if (                                rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
+       if (!RRTypeAnswersQuestionType(rr,q->qtype)) return(mDNSfalse);
+       if (rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
+
+       return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
+       }
+
+mDNSexport mDNSBool AnyTypeRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
+       {
+       if (rr->InterfaceID &&
+               q ->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly &&
+               rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
+
+       // If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question
+       if (rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
+
+       if (rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
+
        return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
        }
 
 mDNSexport mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate)
        {
-       const RDataBody *rd = &rr->rdata->u;
+       const RDataBody2 *const rd = (RDataBody2 *)rr->rdata->u.data;
        const domainname *const name = estimate ? rr->name : mDNSNULL;
        if (rr->rrclass == kDNSQClass_ANY) return(rr->rdlength);        // Used in update packets to mean "Delete An RRset" (RFC 2136)
        else switch (rr->rrtype)
@@ -1522,11 +1810,24 @@ mDNSexport mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate
 
                case kDNSType_OPT:  return(rr->rdlength);
 
+               case kDNSType_NSEC: {
+                                                       int i;
+                                                       for (i=sizeof(rdataNSEC); i>0; i--) if (rd->nsec.bitmap[i-1]) break;
+                                                       // For our simplified use of NSEC synthetic records:
+                                                       // nextname is always the record's own name,
+                                                       // the block number is always 0,
+                                                       // the count byte is a value in the range 1-32,
+                                                       // followed by the 1-32 data bytes
+                                                       return((estimate ? 1 : DomainNameLength(rr->name)) + 2 + i);
+                                                       }
+
                default:                        debugf("Warning! Don't know how to get length of resource type %d", rr->rrtype);
                                                        return(rr->rdlength);
                }
        }
 
+// When a local client registers (or updates) a record, we use this routine to do some simple validation checks
+// to help reduce the risk of bogus malformed data on the network
 mDNSexport mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd)
        {
        mDNSu16 len;
@@ -1570,6 +1871,8 @@ mDNSexport mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength,
                                                        len = DomainNameLengthLimit(&rd->u.srv.target, rd->u.data + rdlength);
                                                        return(len <= MAX_DOMAIN_NAME && rdlength == 6+len);
 
+               //case kDNSType_NSEC not checked
+
                default:                        return(mDNStrue);       // Allow all other types without checking
                }
        }
@@ -1648,50 +1951,53 @@ mDNSexport mDNSu8 *putDomainNameAsLabels(const DNSMessage *const msg,
        const mDNSu8 *      pointer     = mDNSNULL;
        const mDNSu8 *const searchlimit = ptr;
 
-       if (!ptr) { LogMsg("putDomainNameAsLabels ptr is null"); return(mDNSNULL); }
+       if (!ptr) { LogMsg("putDomainNameAsLabels %##s ptr is null", name->c); return(mDNSNULL); }
 
-       while (*np && ptr < limit-1)            // While we've got characters in the name, and space to write them in the message...
+       if (!*np)               // If just writing one-byte root label, make sure we have space for that
                {
-               if (*np > MAX_DOMAIN_LABEL)
-                       { LogMsg("Malformed domain name %##s (label more than 63 bytes)", name->c); return(mDNSNULL); }
-
-               // This check correctly allows for the final trailing root label:
-               // e.g.
-               // Suppose our domain name is exactly 255 bytes long, including the final trailing root label.
-               // Suppose np is now at name->c[248], and we're about to write our last non-null label ("local").
-               // We know that max will be at name->c[255]
-               // That means that np + 1 + 5 == max - 1, so we (just) pass the "if" test below, write our
-               // six bytes, then exit the loop, write the final terminating root label, and the domain
-               // name we've written is exactly 255 bytes long, exactly at the correct legal limit.
-               // If the name is one byte longer, then we fail the "if" test below, and correctly bail out.
-               if (np + 1 + *np >= max)
-                       { LogMsg("Malformed domain name %##s (more than 255 bytes)", name->c); return(mDNSNULL); }
-
-               if (base) pointer = FindCompressionPointer(base, searchlimit, np);
-               if (pointer)                                    // Use a compression pointer if we can
-                       {
-                       mDNSu16 offset = (mDNSu16)(pointer - base);
-                       *ptr++ = (mDNSu8)(0xC0 | (offset >> 8));
-                       *ptr++ = (mDNSu8)(        offset &  0xFF);
-                       return(ptr);
-                       }
-               else                                                    // Else copy one label and try again
-                       {
-                       int i;
-                       mDNSu8 len = *np++;
-                       if (ptr + 1 + len >= limit) return(mDNSNULL);
-                       *ptr++ = len;
-                       for (i=0; i<len; i++) *ptr++ = *np++;
-                       }
+               if (ptr >= limit) return(mDNSNULL);
                }
-
-       if (ptr < limit)                                                                                                // If we didn't run out of space
+       else                    // else, loop through writing labels and/or a compression offset
                {
-               *ptr++ = 0;                                                                                                     // Put the final root label
-               return(ptr);                                                                                            // and return
+               do      {
+                       if (*np > MAX_DOMAIN_LABEL)
+                               { LogMsg("Malformed domain name %##s (label more than 63 bytes)", name->c); return(mDNSNULL); }
+       
+                       // This check correctly allows for the final trailing root label:
+                       // e.g.
+                       // Suppose our domain name is exactly 256 bytes long, including the final trailing root label.
+                       // Suppose np is now at name->c[249], and we're about to write our last non-null label ("local").
+                       // We know that max will be at name->c[256]
+                       // That means that np + 1 + 5 == max - 1, so we (just) pass the "if" test below, write our
+                       // six bytes, then exit the loop, write the final terminating root label, and the domain
+                       // name we've written is exactly 256 bytes long, exactly at the correct legal limit.
+                       // If the name is one byte longer, then we fail the "if" test below, and correctly bail out.
+                       if (np + 1 + *np >= max)
+                               { LogMsg("Malformed domain name %##s (more than 256 bytes)", name->c); return(mDNSNULL); }
+       
+                       if (base) pointer = FindCompressionPointer(base, searchlimit, np);
+                       if (pointer)                                    // Use a compression pointer if we can
+                               {
+                               const mDNSu16 offset = (mDNSu16)(pointer - base);
+                               if (ptr+2 > limit) return(mDNSNULL);    // If we don't have two bytes of space left, give up
+                               *ptr++ = (mDNSu8)(0xC0 | (offset >> 8));
+                               *ptr++ = (mDNSu8)(        offset &  0xFF);
+                               return(ptr);
+                               }
+                       else                                                    // Else copy one label and try again
+                               {
+                               int i;
+                               mDNSu8 len = *np++;
+                               // If we don't at least have enough space for this label *plus* a terminating zero on the end, give up
+                               if (ptr + 1 + len >= limit) return(mDNSNULL);
+                               *ptr++ = len;
+                               for (i=0; i<len; i++) *ptr++ = *np++;
+                               }
+                       } while (*np);                                  // While we've got characters remaining in the name, continue
                }
 
-       return(mDNSNULL);
+       *ptr++ = 0;             // Put the final root label
+       return(ptr);
        }
 
 mDNSlocal mDNSu8 *putVal16(mDNSu8 *ptr, mDNSu16 val)
@@ -1710,133 +2016,35 @@ mDNSlocal mDNSu8 *putVal32(mDNSu8 *ptr, mDNSu32 val)
        return ptr + sizeof(mDNSu32);
        }
 
-mDNSlocal mDNSu8 *putOptRData(mDNSu8 *ptr, const mDNSu8 *limit, const ResourceRecord *const rr)
-       {
-       int nput = 0;
-       rdataOPT *opt;
-       
-       while (nput < rr->rdlength)
-               {
-               // check if space for opt/optlen
-               if (ptr + (2 * sizeof(mDNSu16)) > limit) goto space_err;
-               opt = (rdataOPT *)(rr->rdata->u.data + nput);
-               ptr = putVal16(ptr, opt->opt);
-               ptr = putVal16(ptr, opt->optlen);
-               nput += 2 * sizeof(mDNSu16);
-               if (opt->opt == kDNSOpt_LLQ)
-                       {
-                       if (ptr + LLQ_OPTLEN > limit) goto space_err;
-                       ptr = putVal16(ptr, opt->OptData.llq.vers);
-                       ptr = putVal16(ptr, opt->OptData.llq.llqOp);
-                       ptr = putVal16(ptr, opt->OptData.llq.err);
-                       mDNSPlatformMemCopy(ptr, opt->OptData.llq.id.b, 8);  // 8-byte id
-                       ptr += 8;
-                       ptr = putVal32(ptr, opt->OptData.llq.llqlease);
-                       nput += LLQ_OPTLEN;
-                       }
-               else if (opt->opt == kDNSOpt_Lease)
-                       {
-                       if (ptr + sizeof(mDNSs32) > limit) goto space_err;
-                       ptr = putVal32(ptr, opt->OptData.updatelease);
-                       nput += sizeof(mDNSs32);
-                       }
-               else { LogMsg("putOptRData - unknown option %d", opt->opt); return mDNSNULL; }
-               }
-       
-       return ptr;
-
-       space_err:
-       LogMsg("ERROR: putOptRData - out of space");
-       return mDNSNULL;
-       }
-
-mDNSlocal mDNSu16 getVal16(const mDNSu8 **ptr)
-       {
-       mDNSu16 val = (mDNSu16)(((mDNSu16)(*ptr)[0]) << 8 | (*ptr)[1]);
-       *ptr += sizeof(mDNSOpaque16);
-       return val;
-       }
-
-mDNSlocal const mDNSu8 *getOptRdata(const mDNSu8 *ptr, const mDNSu8 *const limit, LargeCacheRecord *const cr, mDNSu16 pktRDLen)
-       {
-       int nread = 0;
-       ResourceRecord *const rr = &cr->r.resrec;
-       rdataOPT *opt = (rdataOPT *)rr->rdata->u.data;
-
-       while (nread < pktRDLen && (mDNSu8 *)opt < rr->rdata->u.data + MaximumRDSize - sizeof(rdataOPT))
-               {
-               // space for opt + optlen
-               if (nread + (2 * sizeof(mDNSu16)) > rr->rdata->MaxRDLength) goto space_err;
-               opt->opt = getVal16(&ptr);
-               opt->optlen = getVal16(&ptr);
-               nread += 2 * sizeof(mDNSu16);
-               if (opt->opt == kDNSOpt_LLQ)
-                       {
-                       if ((unsigned)(limit - ptr) < LLQ_OPTLEN) goto space_err;
-                       opt->OptData.llq.vers = getVal16(&ptr);
-                       opt->OptData.llq.llqOp = getVal16(&ptr);
-                       opt->OptData.llq.err = getVal16(&ptr);
-                       mDNSPlatformMemCopy(opt->OptData.llq.id.b, ptr, 8);
-                       ptr += 8;
-                       opt->OptData.llq.llqlease = (mDNSu32) ((mDNSu32)ptr[0] << 24 | (mDNSu32)ptr[1] << 16 | (mDNSu32)ptr[2] << 8 | ptr[3]);
-                       if (opt->OptData.llq.llqlease > 0x70000000UL / mDNSPlatformOneSecond)
-                               opt->OptData.llq.llqlease = 0x70000000UL / mDNSPlatformOneSecond;
-                       ptr += sizeof(mDNSOpaque32);
-                       nread += LLQ_OPTLEN;
-                       }
-               else if (opt->opt == kDNSOpt_Lease)
-                       {
-                       if ((unsigned)(limit - ptr) < sizeof(mDNSs32)) goto space_err;
-
-                       opt->OptData.updatelease = (mDNSu32) ((mDNSu32)ptr[0] << 24 | (mDNSu32)ptr[1] << 16 | (mDNSu32)ptr[2] << 8 | ptr[3]);
-                       if (opt->OptData.updatelease > 0x70000000UL / mDNSPlatformOneSecond)
-                               opt->OptData.updatelease = 0x70000000UL / mDNSPlatformOneSecond;
-                       ptr += sizeof(mDNSs32);
-                       nread += sizeof(mDNSs32);
-                       }
-               else { LogMsg("ERROR: getOptRdata - unknown opt %d", opt->opt); return mDNSNULL; }
-               opt++;  // increment pointer into rdatabody
-               }
-       
-       rr->rdlength = pktRDLen;
-       return ptr;
-
-       space_err:
-       LogMsg("ERROR: getLLQRdata - out of space");
-       return mDNSNULL;
-       }
-
 // msg points to the message we're building (pass mDNSNULL if we don't want to use compression pointers)
 mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const ResourceRecord *const rr)
        {
+       const RDataBody2 *const rdb = (RDataBody2 *)rr->rdata->u.data;
        switch (rr->rrtype)
                {
                case kDNSType_A:        if (rr->rdlength != 4)
-                                                               {
-                                                               debugf("putRData: Illegal length %d for kDNSType_A", rr->rdlength);
-                                                               return(mDNSNULL);
-                                                               }
+                                                               { debugf("putRData: Illegal length %d for kDNSType_A", rr->rdlength); return(mDNSNULL); }
                                                        if (ptr + 4 > limit) return(mDNSNULL);
-                                                       *ptr++ = rr->rdata->u.ipv4.b[0];
-                                                       *ptr++ = rr->rdata->u.ipv4.b[1];
-                                                       *ptr++ = rr->rdata->u.ipv4.b[2];
-                                                       *ptr++ = rr->rdata->u.ipv4.b[3];
+                                                       *ptr++ = rdb->ipv4.b[0];
+                                                       *ptr++ = rdb->ipv4.b[1];
+                                                       *ptr++ = rdb->ipv4.b[2];
+                                                       *ptr++ = rdb->ipv4.b[3];
                                                        return(ptr);
 
                case kDNSType_NS:
                case kDNSType_CNAME:
                case kDNSType_PTR:
-               case kDNSType_DNAME:return(putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.name));
+               case kDNSType_DNAME:return(putDomainNameAsLabels(msg, ptr, limit, &rdb->name));
 
-               case kDNSType_SOA:  ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.soa.mname);
+               case kDNSType_SOA:  ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->soa.mname);
                                                        if (!ptr) return(mDNSNULL);
-                                                       ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.soa.rname);
+                                                       ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->soa.rname);
                                                        if (!ptr || ptr + 20 > limit) return(mDNSNULL);
-                                                       ptr = putVal32(ptr, rr->rdata->u.soa.serial);
-                                                       ptr = putVal32(ptr, rr->rdata->u.soa.refresh);
-                                                       ptr = putVal32(ptr, rr->rdata->u.soa.retry);
-                                                       ptr = putVal32(ptr, rr->rdata->u.soa.expire);
-                                                       ptr = putVal32(ptr, rr->rdata->u.soa.min);
+                                                       ptr = putVal32(ptr, rdb->soa.serial);
+                                                       ptr = putVal32(ptr, rdb->soa.refresh);
+                                                       ptr = putVal32(ptr, rdb->soa.retry);
+                                                       ptr = putVal32(ptr, rdb->soa.expire);
+                                                       ptr = putVal32(ptr, rdb->soa.min);
                                        return(ptr);
 
                case kDNSType_NULL:
@@ -1847,60 +2055,121 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS
                case kDNSType_ISDN:
                case kDNSType_LOC:
                case kDNSType_DHCID:if (ptr + rr->rdlength > limit) return(mDNSNULL);
-                                                       mDNSPlatformMemCopy(ptr, rr->rdata->u.data, rr->rdlength);
+                                                       mDNSPlatformMemCopy(ptr, rdb->data, rr->rdlength);
                                                        return(ptr + rr->rdlength);
 
                case kDNSType_MX:
                case kDNSType_AFSDB:
                case kDNSType_RT:
                case kDNSType_KX:       if (ptr + 3 > limit) return(mDNSNULL);
-                                                       ptr = putVal16(ptr, rr->rdata->u.mx.preference);
-                                                       return(putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.mx.exchange));
+                                                       ptr = putVal16(ptr, rdb->mx.preference);
+                                                       return(putDomainNameAsLabels(msg, ptr, limit, &rdb->mx.exchange));
 
-               case kDNSType_RP:       ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.rp.mbox);
+               case kDNSType_RP:       ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->rp.mbox);
                                                        if (!ptr) return(mDNSNULL);
-                                                       ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.rp.txt);
+                                                       ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->rp.txt);
                                        return(ptr);
 
                case kDNSType_PX:       if (ptr + 5 > limit) return(mDNSNULL);
-                                                       ptr = putVal16(ptr, rr->rdata->u.px.preference);
-                                                       ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.px.map822);
+                                                       ptr = putVal16(ptr, rdb->px.preference);
+                                                       ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->px.map822);
                                                        if (!ptr) return(mDNSNULL);
-                                                       ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.px.mapx400);
+                                                       ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->px.mapx400);
                                        return(ptr);
 
-               case kDNSType_AAAA:     if (rr->rdlength != sizeof(rr->rdata->u.ipv6))
+               case kDNSType_AAAA:     if (rr->rdlength != sizeof(rdb->ipv6))
+                                                               { debugf("putRData: Illegal length %d for kDNSType_AAAA", rr->rdlength); return(mDNSNULL); }
+                                                       if (ptr + sizeof(rdb->ipv6) > limit) return(mDNSNULL);
+                                                       mDNSPlatformMemCopy(ptr, &rdb->ipv6, sizeof(rdb->ipv6));
+                                                       return(ptr + sizeof(rdb->ipv6));
+
+               case kDNSType_SRV:      if (ptr + 7 > limit) return(mDNSNULL);
+                                                       *ptr++ = (mDNSu8)(rdb->srv.priority >> 8);
+                                                       *ptr++ = (mDNSu8)(rdb->srv.priority &  0xFF);
+                                                       *ptr++ = (mDNSu8)(rdb->srv.weight   >> 8);
+                                                       *ptr++ = (mDNSu8)(rdb->srv.weight   &  0xFF);
+                                                       *ptr++ = rdb->srv.port.b[0];
+                                                       *ptr++ = rdb->srv.port.b[1];
+                                                       return(putDomainNameAsLabels(msg, ptr, limit, &rdb->srv.target));
+
+               case kDNSType_OPT:      {
+                                                       int len = 0;
+                                                       const rdataOPT *opt;
+                                                       const rdataOPT *const end = (const rdataOPT *)&rr->rdata->u.data[rr->rdlength];
+                                                       for (opt = &rr->rdata->u.opt[0]; opt < end; opt++) len += DNSOpt_Data_Space(opt);
+                                                       if (ptr + len > limit) { LogMsg("ERROR: putOptRData - out of space"); return mDNSNULL; }
+                                               
+                                                       for (opt = &rr->rdata->u.opt[0]; opt < end; opt++)
                                                                {
-                                                               debugf("putRData: Illegal length %d for kDNSType_AAAA", rr->rdlength);
-                                                               return(mDNSNULL);
+                                                               const int space = DNSOpt_Data_Space(opt);
+                                                               ptr = putVal16(ptr, opt->opt);
+                                                               ptr = putVal16(ptr, space - 4);
+                                                               switch (opt->opt)
+                                                                       {
+                                                                       case kDNSOpt_LLQ:
+                                                                               ptr = putVal16(ptr, opt->u.llq.vers);
+                                                                               ptr = putVal16(ptr, opt->u.llq.llqOp);
+                                                                               ptr = putVal16(ptr, opt->u.llq.err);
+                                                                               mDNSPlatformMemCopy(ptr, opt->u.llq.id.b, 8);  // 8-byte id
+                                                                               ptr += 8;
+                                                                               ptr = putVal32(ptr, opt->u.llq.llqlease);
+                                                                               break;
+                                                                       case kDNSOpt_Lease:
+                                                                               ptr = putVal32(ptr, opt->u.updatelease);
+                                                                               break;
+                                                                       case kDNSOpt_Owner:
+                                                                               *ptr++ = opt->u.owner.vers;
+                                                                               *ptr++ = opt->u.owner.seq;
+                                                                               mDNSPlatformMemCopy(ptr, opt->u.owner.HMAC.b, 6);  // 6-byte Host identifier
+                                                                               ptr += 6;
+                                                                               if (space >= DNSOpt_OwnerData_ID_Wake_Space)
+                                                                                       {
+                                                                                       mDNSPlatformMemCopy(ptr, opt->u.owner.IMAC.b, 6);       // 6-byte interface MAC
+                                                                                       ptr += 6;
+                                                                                       if (space > DNSOpt_OwnerData_ID_Wake_Space)
+                                                                                               {
+                                                                                               mDNSPlatformMemCopy(ptr, opt->u.owner.password.b, space - DNSOpt_OwnerData_ID_Wake_Space);
+                                                                                               ptr += space - DNSOpt_OwnerData_ID_Wake_Space;
+                                                                                               }
+                                                                                       }
+                                                                               break;
+                                                                       }
                                                                }
-                                                       if (ptr + sizeof(rr->rdata->u.ipv6) > limit) return(mDNSNULL);
-                                                       mDNSPlatformMemCopy(ptr, &rr->rdata->u.ipv6, sizeof(rr->rdata->u.ipv6));
-                                                       return(ptr + sizeof(rr->rdata->u.ipv6));
+                                                       return ptr;
+                                                       }
+
+               case kDNSType_NSEC: {
+                                                       // For our simplified use of NSEC synthetic records:
+                                                       // nextname is always the record's own name,
+                                                       // the block number is always 0,
+                                                       // the count byte is a value in the range 1-32,
+                                                       // followed by the 1-32 data bytes
+                                                       int i, j;
+                                                       for (i=sizeof(rdataNSEC); i>0; i--) if (rdb->nsec.bitmap[i-1]) break;
+                                                       ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name);
+                                                       if (!ptr) return(mDNSNULL);
+                                                       if (ptr + 2 + i > limit) return(mDNSNULL);
+                                                       *ptr++ = 0;
+                                                       *ptr++ = i;
+                                                       for (j=0; j<i; j++) *ptr++ = rdb->nsec.bitmap[j];
+                                                       return ptr;
+                                                       }
 
-               case kDNSType_SRV:      if (ptr + 7 > limit) return(mDNSNULL);
-                                                       *ptr++ = (mDNSu8)(rr->rdata->u.srv.priority >> 8);
-                                                       *ptr++ = (mDNSu8)(rr->rdata->u.srv.priority &  0xFF);
-                                                       *ptr++ = (mDNSu8)(rr->rdata->u.srv.weight   >> 8);
-                                                       *ptr++ = (mDNSu8)(rr->rdata->u.srv.weight   &  0xFF);
-                                                       *ptr++ = rr->rdata->u.srv.port.b[0];
-                                                       *ptr++ = rr->rdata->u.srv.port.b[1];
-                                                       return(putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.srv.target));
-
-               case kDNSType_OPT:      return putOptRData(ptr, limit, rr);
-                                                       
                default:                        debugf("putRData: Warning! Writing unknown resource type %d as raw data", rr->rrtype);
                                                        if (ptr + rr->rdlength > limit) return(mDNSNULL);
-                                                       mDNSPlatformMemCopy(ptr, rr->rdata->u.data, rr->rdlength);
+                                                       mDNSPlatformMemCopy(ptr, rdb->data, rr->rdlength);
                                                        return(ptr + rr->rdlength);
                }
        }
 
+#define IsUnicastUpdate(X) (!mDNSOpaque16IsZero((X)->h.id) && ((X)->h.flags.b[0] & kDNSFlag0_OP_Mask) == kDNSFlag0_OP_Update)
+
 mDNSexport mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 ttl, const mDNSu8 *limit)
        {
-       mDNSu16 rrclass = (rr->rrtype == kDNSType_OPT) ? NormalMaxDNSMessageData : rr->rrclass;
        mDNSu8 *endofrdata;
        mDNSu16 actualLength;
+       // When sending SRV to conventional DNS server (i.e. in DNS update requests) we should not do name compression on the rdata (RFC 2782)
+       const DNSMessage *const rdatacompressionbase = (IsUnicastUpdate(msg) && rr->rrtype == kDNSType_SRV) ? mDNSNULL : msg;
 
        if (rr->RecordType == kDNSRecordTypeUnregistered)
                {
@@ -1914,13 +2183,13 @@ mDNSexport mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *
        if (!ptr || ptr + 10 >= limit) return(mDNSNULL);        // If we're out-of-space, return mDNSNULL
        ptr[0] = (mDNSu8)(rr->rrtype  >> 8);
        ptr[1] = (mDNSu8)(rr->rrtype  &  0xFF);
-       ptr[2] = (mDNSu8)(rrclass     >> 8);
-       ptr[3] = (mDNSu8)(rrclass     &  0xFF);
+       ptr[2] = (mDNSu8)(rr->rrclass >> 8);
+       ptr[3] = (mDNSu8)(rr->rrclass &  0xFF);
        ptr[4] = (mDNSu8)((ttl >> 24) &  0xFF);
        ptr[5] = (mDNSu8)((ttl >> 16) &  0xFF);
        ptr[6] = (mDNSu8)((ttl >>  8) &  0xFF);
        ptr[7] = (mDNSu8)( ttl        &  0xFF);
-       endofrdata = putRData(msg, ptr+10, limit, rr);
+       endofrdata = putRData(rdatacompressionbase, ptr+10, limit, rr);
        if (!endofrdata) { verbosedebugf("Ran out of space in PutResourceRecord for %##s (%s)", rr->name->c, DNSTypeName(rr->rrtype)); return(mDNSNULL); }
 
        // Go back and fill in the actual number of data bytes we wrote
@@ -1934,15 +2203,7 @@ mDNSexport mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *
        return(endofrdata);
        }
 
-mDNSexport mDNSu8 *PutResourceRecordCappedTTL(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32
-                                                                                          maxttl)
-       {
-       if (maxttl > rr->rroriginalttl) maxttl = rr->rroriginalttl;
-       return(PutResourceRecordTTL(msg, ptr, count, rr, maxttl));
-       }
-
-mDNSexport mDNSu8 *putEmptyResourceRecord(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit,
-       mDNSu16 *count, const AuthRecord *rr)
+mDNSlocal mDNSu8 *putEmptyResourceRecord(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, mDNSu16 *count, const AuthRecord *rr)
        {
        ptr = putDomainNameAsLabels(msg, ptr, limit, rr->resrec.name);
        if (!ptr || ptr + 10 > limit) return(mDNSNULL);         // If we're out-of-space, return mDNSNULL
@@ -2030,10 +2291,10 @@ mDNSexport mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domain
        
        ptr = putDomainNameAsLabels(msg, ptr, limit, name);
        if (!ptr || ptr + 10 >= limit) return mDNSNULL; // If we're out-of-space, return mDNSNULL
-       ptr[0] = (mDNSu8)(rrtype  >> 8);
-       ptr[1] = (mDNSu8)(rrtype  &  0xFF);
-       ptr[2] = (mDNSu8)(class >> 8);
-       ptr[3] = (mDNSu8)(class &  0xFF);
+       ptr[0] = (mDNSu8)(rrtype >> 8);
+       ptr[1] = (mDNSu8)(rrtype &  0xFF);
+       ptr[2] = (mDNSu8)(class  >> 8);
+       ptr[3] = (mDNSu8)(class  &  0xFF);
        ptr[4] = ptr[5] = ptr[6] = ptr[7] = 0; // zero ttl
        ptr[8] = ptr[9] = 0; // zero rdlength/rdata
 
@@ -2047,11 +2308,10 @@ mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease)
        AuthRecord rr;
        mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
        rr.resrec.rrclass    = NormalMaxDNSMessageData;
-       rr.resrec.rdlength   = LEASE_OPT_RDLEN;
-       rr.resrec.rdestimate = LEASE_OPT_RDLEN;
-       rr.resrec.rdata->u.opt.opt           = kDNSOpt_Lease;
-       rr.resrec.rdata->u.opt.optlen        = sizeof(mDNSs32);
-       rr.resrec.rdata->u.opt.OptData.updatelease = lease;
+       rr.resrec.rdlength   = sizeof(rdataOPT);        // One option in this OPT record
+       rr.resrec.rdestimate = sizeof(rdataOPT);
+       rr.resrec.rdata->u.opt[0].opt           = kDNSOpt_Lease;
+       rr.resrec.rdata->u.opt[0].u.updatelease = lease;
        end = PutResourceRecordTTLJumbo(msg, end, &msg->h.numAdditionals, &rr.resrec, 0);
        if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTL"); return mDNSNULL; }
        return end;
@@ -2133,7 +2393,7 @@ mDNSexport const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu
                        case 0x00:      if (ptr + len >= end)                                   // Remember: expect at least one more byte for the root label
                                                        { debugf("skipDomainName: Malformed domain name (overruns packet end)"); return(mDNSNULL); }
                                                if (total + 1 + len >= MAX_DOMAIN_NAME) // Remember: expect at least one more byte for the root label
-                                                       { debugf("skipDomainName: Malformed domain name (more than 255 characters)"); return(mDNSNULL); }
+                                                       { debugf("skipDomainName: Malformed domain name (more than 256 characters)"); return(mDNSNULL); }
                                                ptr += len;
                                                total += 1 + len;
                                                break;
@@ -2170,7 +2430,7 @@ mDNSexport const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8
                        case 0x00:      if (ptr + len >= end)           // Remember: expect at least one more byte for the root label
                                                        { debugf("getDomainName: Malformed domain name (overruns packet end)"); return(mDNSNULL); }
                                                if (np + 1 + len >= limit)      // Remember: expect at least one more byte for the root label
-                                                       { debugf("getDomainName: Malformed domain name (more than 255 characters)"); return(mDNSNULL); }
+                                                       { debugf("getDomainName: Malformed domain name (more than 256 characters)"); return(mDNSNULL); }
                                                *np++ = len;
                                                for (i=0; i<len; i++) *np++ = *ptr++;
                                                *np = 0;        // Tentatively place the root label here (may be overwritten if we have more labels)
@@ -2211,14 +2471,27 @@ mDNSexport const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8
        return(ptr + pktrdlength);
        }
 
+mDNSlocal mDNSu16 getVal16(const mDNSu8 **ptr)
+       {
+       mDNSu16 val = (mDNSu16)(((mDNSu16)(*ptr)[0]) << 8 | (*ptr)[1]);
+       *ptr += sizeof(mDNSOpaque16);
+       return val;
+       }
+
 mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *ptr,
-    const mDNSu8 *end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *largecr)
+    const mDNSu8 *end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *const largecr)
        {
-       CacheRecord *rr = &largecr->r;
+       CacheRecord *const rr = &largecr->r;
+       RDataBody2 *const rdb = (RDataBody2 *)rr->smallrdatastorage.data;
        mDNSu16 pktrdlength;
        
-       if (largecr == &m->rec && largecr->r.resrec.RecordType)
-               LogMsg("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &largecr->r));
+       if (largecr == &m->rec && m->rec.r.resrec.RecordType)
+               {
+               LogMsg("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r));
+#if ForceAlerts
+               *(long*)0 = 0;
+#endif
+               }
 
        rr->next              = mDNSNULL;
        rr->resrec.name       = &largecr->namestorage;
@@ -2231,10 +2504,12 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
        rr->CRActiveQuestion  = mDNSNULL;
        rr->UnansweredQueries = 0;
        rr->LastUnansweredTime= 0;
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
        rr->MPUnansweredQ     = 0;
        rr->MPLastUnansweredQT= 0;
        rr->MPUnansweredKA    = 0;
        rr->MPExpectingKA     = mDNSfalse;
+#endif
        rr->NextInCFList      = mDNSNULL;
 
        rr->resrec.InterfaceID       = InterfaceID;
@@ -2261,7 +2536,7 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
        if (ptr + pktrdlength > end) { debugf("GetLargeResourceRecord: RDATA exceeds end of packet"); return(mDNSNULL); }
        end = ptr + pktrdlength;                // Adjust end to indicate the end of the rdata for this resource record
 
-       rr->resrec.rdata = (RData*)&rr->rdatastorage;
+       rr->resrec.rdata = (RData*)&rr->smallrdatastorage;
        rr->resrec.rdata->MaxRDLength = MaximumRDSize;
 
        if (!RecordType) LogMsg("GetLargeResourceRecord: No RecordType for %##s", rr->resrec.name->c);
@@ -2276,30 +2551,30 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
        else switch (rr->resrec.rrtype)
                {
                case kDNSType_A:        if (pktrdlength != sizeof(mDNSv4Addr)) return(mDNSNULL);
-                                                       rr->resrec.rdata->u.ipv4.b[0] = ptr[0];
-                                                       rr->resrec.rdata->u.ipv4.b[1] = ptr[1];
-                                                       rr->resrec.rdata->u.ipv4.b[2] = ptr[2];
-                                                       rr->resrec.rdata->u.ipv4.b[3] = ptr[3];
+                                                       rdb->ipv4.b[0] = ptr[0];
+                                                       rdb->ipv4.b[1] = ptr[1];
+                                                       rdb->ipv4.b[2] = ptr[2];
+                                                       rdb->ipv4.b[3] = ptr[3];
                                                        break;
 
                case kDNSType_NS:
                case kDNSType_CNAME:
                case kDNSType_PTR:
-               case kDNSType_DNAME:ptr = getDomainName(msg, ptr, end, &rr->resrec.rdata->u.name);
+               case kDNSType_DNAME:ptr = getDomainName(msg, ptr, end, &rdb->name);
                                                        if (ptr != end) { debugf("GetLargeResourceRecord: Malformed CNAME/PTR RDATA name"); return(mDNSNULL); }
-                                                       //debugf("%##s PTR %##s rdlen %d", rr->resrec.name.c, rr->resrec.rdata->u.name.c, pktrdlength);
+                                                       //debugf("%##s PTR %##s rdlen %d", rr->resrec.name.c, rdb->name.c, pktrdlength);
                                                        break;
 
-               case kDNSType_SOA:  ptr = getDomainName(msg, ptr, end, &rr->resrec.rdata->u.soa.mname);
+               case kDNSType_SOA:  ptr = getDomainName(msg, ptr, end, &rdb->soa.mname);
                                                        if (!ptr)              { debugf("GetLargeResourceRecord: Malformed SOA RDATA mname"); return mDNSNULL; }
-                                                       ptr = getDomainName(msg, ptr, end, &rr->resrec.rdata->u.soa.rname);
+                                                       ptr = getDomainName(msg, ptr, end, &rdb->soa.rname);
                                                        if (!ptr)              { debugf("GetLargeResourceRecord: Malformed SOA RDATA rname"); return mDNSNULL; }
                                        if (ptr + 0x14 != end) { debugf("GetLargeResourceRecord: Malformed SOA RDATA");       return mDNSNULL; }
-                                       rr->resrec.rdata->u.soa.serial  = (mDNSs32) ((mDNSs32)ptr[0x00] << 24 | (mDNSs32)ptr[0x01] << 16 | (mDNSs32)ptr[0x02] << 8 | ptr[0x03]);
-                                       rr->resrec.rdata->u.soa.refresh = (mDNSu32) ((mDNSu32)ptr[0x04] << 24 | (mDNSu32)ptr[0x05] << 16 | (mDNSu32)ptr[0x06] << 8 | ptr[0x07]);
-                                       rr->resrec.rdata->u.soa.retry   = (mDNSu32) ((mDNSu32)ptr[0x08] << 24 | (mDNSu32)ptr[0x09] << 16 | (mDNSu32)ptr[0x0A] << 8 | ptr[0x0B]);
-                                       rr->resrec.rdata->u.soa.expire  = (mDNSu32) ((mDNSu32)ptr[0x0C] << 24 | (mDNSu32)ptr[0x0D] << 16 | (mDNSu32)ptr[0x0E] << 8 | ptr[0x0F]);
-                                       rr->resrec.rdata->u.soa.min     = (mDNSu32) ((mDNSu32)ptr[0x10] << 24 | (mDNSu32)ptr[0x11] << 16 | (mDNSu32)ptr[0x12] << 8 | ptr[0x13]);
+                                       rdb->soa.serial  = (mDNSs32) ((mDNSs32)ptr[0x00] << 24 | (mDNSs32)ptr[0x01] << 16 | (mDNSs32)ptr[0x02] << 8 | ptr[0x03]);
+                                       rdb->soa.refresh = (mDNSu32) ((mDNSu32)ptr[0x04] << 24 | (mDNSu32)ptr[0x05] << 16 | (mDNSu32)ptr[0x06] << 8 | ptr[0x07]);
+                                       rdb->soa.retry   = (mDNSu32) ((mDNSu32)ptr[0x08] << 24 | (mDNSu32)ptr[0x09] << 16 | (mDNSu32)ptr[0x0A] << 8 | ptr[0x0B]);
+                                       rdb->soa.expire  = (mDNSu32) ((mDNSu32)ptr[0x0C] << 24 | (mDNSu32)ptr[0x0D] << 16 | (mDNSu32)ptr[0x0E] << 8 | ptr[0x0F]);
+                                       rdb->soa.min     = (mDNSu32) ((mDNSu32)ptr[0x10] << 24 | (mDNSu32)ptr[0x11] << 16 | (mDNSu32)ptr[0x12] << 8 | ptr[0x13]);
                                        break;
 
                case kDNSType_NULL:
@@ -2316,49 +2591,111 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
                                                                return(mDNSNULL);
                                                                }
                                                        rr->resrec.rdlength = pktrdlength;
-                                                       mDNSPlatformMemCopy(rr->resrec.rdata->u.data, ptr, pktrdlength);
+                                                       mDNSPlatformMemCopy(rdb->data, ptr, pktrdlength);
                                                        break;
 
                case kDNSType_MX:
                case kDNSType_AFSDB:
                case kDNSType_RT:
                case kDNSType_KX:       if (pktrdlength < 3) return(mDNSNULL);  // Preference + domainname
-                                                       rr->resrec.rdata->u.mx.preference = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-                                                       ptr = getDomainName(msg, ptr+2, end, &rr->resrec.rdata->u.mx.exchange);
+                                                       rdb->mx.preference = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
+                                                       ptr = getDomainName(msg, ptr+2, end, &rdb->mx.exchange);
                                                        if (ptr != end) { debugf("GetLargeResourceRecord: Malformed MX name"); return(mDNSNULL); }
-                                                       //debugf("%##s SRV %##s rdlen %d", rr->resrec.name.c, rr->resrec.rdata->u.srv.target.c, pktrdlength);
+                                                       //debugf("%##s SRV %##s rdlen %d", rr->resrec.name.c, rdb->srv.target.c, pktrdlength);
                                                        break;
 
-               case kDNSType_RP:       ptr = getDomainName(msg, ptr, end, &rr->resrec.rdata->u.rp.mbox);       // Domainname + domainname
+               case kDNSType_RP:       ptr = getDomainName(msg, ptr, end, &rdb->rp.mbox);      // Domainname + domainname
                                                        if (!ptr)       { debugf("GetLargeResourceRecord: Malformed RP mbox"); return mDNSNULL; }
-                                                       ptr = getDomainName(msg, ptr, end, &rr->resrec.rdata->u.rp.txt);
+                                                       ptr = getDomainName(msg, ptr, end, &rdb->rp.txt);
                                                        if (ptr != end) { debugf("GetLargeResourceRecord: Malformed RP txt"); return mDNSNULL; }
                                                        break;
 
                case kDNSType_PX:       if (pktrdlength < 4) return(mDNSNULL);  // Preference + domainname + domainname
-                                                       rr->resrec.rdata->u.px.preference = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-                                                       ptr = getDomainName(msg, ptr, end, &rr->resrec.rdata->u.px.map822);
+                                                       rdb->px.preference = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
+                                                       ptr = getDomainName(msg, ptr, end, &rdb->px.map822);
                                                        if (!ptr)       { debugf("GetLargeResourceRecord: Malformed PX map822"); return mDNSNULL; }
-                                                       ptr = getDomainName(msg, ptr, end, &rr->resrec.rdata->u.px.mapx400);
+                                                       ptr = getDomainName(msg, ptr, end, &rdb->px.mapx400);
                                                        if (ptr != end) { debugf("GetLargeResourceRecord: Malformed PX mapx400"); return mDNSNULL; }
                                                        break;
 
                case kDNSType_AAAA:     if (pktrdlength != sizeof(mDNSv6Addr)) return(mDNSNULL);
-                                                       mDNSPlatformMemCopy(&rr->resrec.rdata->u.ipv6, ptr, sizeof(rr->resrec.rdata->u.ipv6));
+                                                       mDNSPlatformMemCopy(&rdb->ipv6, ptr, sizeof(rdb->ipv6));
                                                        break;
 
                case kDNSType_SRV:      if (pktrdlength < 7) return(mDNSNULL);  // Priority + weight + port + domainname
-                                                       rr->resrec.rdata->u.srv.priority = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-                                                       rr->resrec.rdata->u.srv.weight   = (mDNSu16)((mDNSu16)ptr[2] <<  8 | ptr[3]);
-                                                       rr->resrec.rdata->u.srv.port.b[0] = ptr[4];
-                                                       rr->resrec.rdata->u.srv.port.b[1] = ptr[5];
-                                                       ptr = getDomainName(msg, ptr+6, end, &rr->resrec.rdata->u.srv.target);
+                                                       rdb->srv.priority = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
+                                                       rdb->srv.weight   = (mDNSu16)((mDNSu16)ptr[2] <<  8 | ptr[3]);
+                                                       rdb->srv.port.b[0] = ptr[4];
+                                                       rdb->srv.port.b[1] = ptr[5];
+                                                       ptr = getDomainName(msg, ptr+6, end, &rdb->srv.target);
                                                        if (ptr != end) { debugf("GetLargeResourceRecord: Malformed SRV RDATA name"); return(mDNSNULL); }
-                                                       //debugf("%##s SRV %##s rdlen %d", rr->resrec.name.c, rr->resrec.rdata->u.srv.target.c, pktrdlength);
+                                                       //debugf("%##s SRV %##s rdlen %d", rr->resrec.name.c, rdb->srv.target.c, pktrdlength);
                                                        break;
 
-               case kDNSType_OPT:  ptr = getOptRdata(ptr, end, largecr, pktrdlength); break;
+               case kDNSType_OPT:      {
+                                                       rdataOPT *opt = rr->resrec.rdata->u.opt;
+                                                       rr->resrec.rdlength = 0;
+                                                       while (ptr < end && (mDNSu8 *)(opt+1) < &rr->resrec.rdata->u.data[MaximumRDSize])
+                                                               {
+                                                               if (ptr + 4 > end) { LogMsg("GetLargeResourceRecord: OPT RDATA ptr + 4 > end"); return(mDNSNULL); }
+                                                               opt->opt    = getVal16(&ptr);
+                                                               opt->optlen = getVal16(&ptr);
+                                                               if (!ValidDNSOpt(opt)) { LogMsg("GetLargeResourceRecord: opt %d optlen %d wrong", opt->opt, opt->optlen); return(mDNSNULL); }
+                                                               if (ptr + opt->optlen > end) { LogMsg("GetLargeResourceRecord: ptr + opt->optlen > end"); return(mDNSNULL); }
+                                                               switch(opt->opt)
+                                                                       {
+                                                                       case kDNSOpt_LLQ:
+                                                                               opt->u.llq.vers  = getVal16(&ptr);
+                                                                               opt->u.llq.llqOp = getVal16(&ptr);
+                                                                               opt->u.llq.err   = getVal16(&ptr);
+                                                                               mDNSPlatformMemCopy(opt->u.llq.id.b, ptr, 8);
+                                                                               ptr += 8;
+                                                                               opt->u.llq.llqlease = (mDNSu32) ((mDNSu32)ptr[0] << 24 | (mDNSu32)ptr[1] << 16 | (mDNSu32)ptr[2] << 8 | ptr[3]);
+                                                                               if (opt->u.llq.llqlease > 0x70000000UL / mDNSPlatformOneSecond)
+                                                                                       opt->u.llq.llqlease = 0x70000000UL / mDNSPlatformOneSecond;
+                                                                               ptr += sizeof(mDNSOpaque32);
+                                                                               break;
+                                                                       case kDNSOpt_Lease:
+                                                                               opt->u.updatelease = (mDNSu32) ((mDNSu32)ptr[0] << 24 | (mDNSu32)ptr[1] << 16 | (mDNSu32)ptr[2] << 8 | ptr[3]);
+                                                                               if (opt->u.updatelease > 0x70000000UL / mDNSPlatformOneSecond)
+                                                                                       opt->u.updatelease = 0x70000000UL / mDNSPlatformOneSecond;
+                                                                               ptr += sizeof(mDNSs32);
+                                                                               break;
+                                                                       case kDNSOpt_Owner:
+                                                                               opt->u.owner.vers = ptr[0];
+                                                                               opt->u.owner.seq  = ptr[1];
+                                                                               mDNSPlatformMemCopy(opt->u.owner.HMAC.b, ptr+2, 6);             // 6-byte MAC address
+                                                                               mDNSPlatformMemCopy(opt->u.owner.IMAC.b, ptr+2, 6);             // 6-byte MAC address
+                                                                               opt->u.owner.password = zeroEthAddr;
+                                                                               if (opt->optlen >= DNSOpt_OwnerData_ID_Wake_Space-4)
+                                                                                       {
+                                                                                       mDNSPlatformMemCopy(opt->u.owner.IMAC.b, ptr+8, 6);     // 6-byte MAC address
+                                                                                       if (opt->optlen > DNSOpt_OwnerData_ID_Wake_Space-4)
+                                                                                               mDNSPlatformMemCopy(opt->u.owner.password.b, ptr+14, opt->optlen - (DNSOpt_OwnerData_ID_Wake_Space-4));
+                                                                                       }
+                                                                               ptr += opt->optlen;
+                                                                               break;
+                                                                       }
+                                                               opt++;  // increment pointer into rdatabody
+                                                               }
+                                                       rr->resrec.rdlength = (mDNSu8*)opt - rr->resrec.rdata->u.data;
                                                        if (ptr != end) { LogMsg("GetLargeResourceRecord: Malformed OptRdata"); return(mDNSNULL); }
+                                                       break;
+                                                       }
+
+               case kDNSType_NSEC: {
+                                                       unsigned int i, j;
+                                                       domainname d;
+                                                       ptr = getDomainName(msg, ptr, end, &d);         // Ignored for our simplified use of NSEC synthetic records
+                                                       if (!ptr) { debugf("GetLargeResourceRecord: Malformed NSEC nextname"); return mDNSNULL; }
+                                                       if (*ptr++ != 0) { debugf("GetLargeResourceRecord: We only handle block zero NSECs"); return mDNSNULL; }
+                                                       i = *ptr++;
+                                                       if (i < 1 || i > sizeof(rdataNSEC)) { debugf("GetLargeResourceRecord: invalid block length %d", i); return mDNSNULL; }
+                                                       mDNSPlatformMemZero(rdb->nsec.bitmap, sizeof(rdb->nsec.bitmap));
+                                                       for (j=0; j<i; j++) rdb->nsec.bitmap[j] = *ptr++;
+                                                       if (ptr != end) { LogMsg("GetLargeResourceRecord: Malformed NSEC"); return(mDNSNULL); }
+                                                       break;
+                                                       }
 
                default:                        if (pktrdlength > rr->resrec.rdata->MaxRDLength)
                                                                {
@@ -2374,7 +2711,7 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
                                                        // We also grab a binary copy of the rdata anyway, since the caller
                                                        // might know how to interpret it even if we don't.
                                                        rr->resrec.rdlength = pktrdlength;
-                                                       mDNSPlatformMemCopy(rr->resrec.rdata->u.data, ptr, pktrdlength);
+                                                       mDNSPlatformMemCopy(rdb->data, ptr, pktrdlength);
                                                        break;
                }
 
@@ -2399,6 +2736,7 @@ mDNSexport const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, c
        {
        mDNSPlatformMemZero(question, sizeof(*question));
        question->InterfaceID = InterfaceID;
+       if (!InterfaceID) question->TargetQID = onesID; // In DNSQuestions we use TargetQID as the indicator of whether it's unicast or multicast
        ptr = getDomainName(msg, ptr, end, &question->qname);
        if (!ptr) { debugf("Malformed domain name in DNS question section"); return(mDNSNULL); }
        if (ptr+4 > end) { debugf("Malformed DNS question section -- no query type and class!"); return(mDNSNULL); }
@@ -2433,7 +2771,7 @@ mDNSexport const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mD
        return (ptr);
        }
 
-mDNSexport const mDNSu8 *LocateLLQOptData(const DNSMessage *const msg, const mDNSu8 *const end)
+mDNSexport const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize)
        {
        int i;
        const mDNSu8 *ptr = LocateAdditionals(msg, end);
@@ -2444,11 +2782,11 @@ mDNSexport const mDNSu8 *LocateLLQOptData(const DNSMessage *const msg, const mDN
        // but not necessarily the *last* entry in the Additional Section.
        for (i = 0; ptr && i < msg->h.numAdditionals; i++)
                {
-               if (ptr + 10 + LLQ_OPT_RDLEN <= end   &&                // Make sure we have 10+22 bytes of data
-                       ptr[0] == 0                       &&            // Name must be root label
-                       ptr[1] == (kDNSType_OPT >> 8  )   &&            // rrtype OPT
-                       ptr[2] == (kDNSType_OPT & 0xFF)   &&
-                       ((mDNSu16)ptr[9] << 8 | (mDNSu16)ptr[10]) >= (mDNSu16)LLQ_OPT_RDLEN)
+               if (ptr + DNSOpt_Header_Space + minsize <= end &&       // Make sure we have 11+minsize bytes of data
+                       ptr[0] == 0                                &&   // Name must be root label
+                       ptr[1] == (kDNSType_OPT >> 8  )            &&   // rrtype OPT
+                       ptr[2] == (kDNSType_OPT & 0xFF)            &&
+                       ((mDNSu16)ptr[9] << 8 | (mDNSu16)ptr[10]) >= (mDNSu16)minsize)
                        return(ptr);
                else
                        ptr = skipResourceRecord(msg, ptr, end);
@@ -2457,39 +2795,16 @@ mDNSexport const mDNSu8 *LocateLLQOptData(const DNSMessage *const msg, const mDN
        }
 
 // On success, GetLLQOptData returns pointer to storage within shared "m->rec";
-// it is callers responsibilty to clear m->rec.r.resrec.RecordType after use
+// it is caller's responsibilty to clear m->rec.r.resrec.RecordType after use
 // Note: An OPT RDataBody actually contains one or more variable-length rdataOPT objects packed together
 // The code that currently calls this assumes there's only one, instead of iterating through the set
 mDNSexport const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end)
        {
-       const mDNSu8 *ptr = LocateLLQOptData(msg, end);
+       const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LLQData_Space);
        if (ptr)
                {
                ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
-               if (ptr) return(&m->rec.r.resrec.rdata->u.opt);
-               }
-       return(mDNSNULL);
-       }
-
-mDNSexport const mDNSu8 *LocateLeaseOptData(const DNSMessage *const msg, const mDNSu8 *const end)
-       {
-       int i;
-       const mDNSu8 *ptr = LocateAdditionals(msg, end);
-
-       // Locate the OPT record.
-       // According to RFC 2671, "One OPT pseudo-RR can be added to the additional data section of either a request or a response."
-       // This implies that there may be *at most* one OPT record per DNS message, in the Additional Section,
-       // but not necessarily the *last* entry in the Additional Section.
-       for (i = 0; ptr && i < msg->h.numAdditionals; i++)
-               {
-               if (ptr + 10 + LEASE_OPT_RDLEN <= end &&                // Make sure we have 10+8 bytes of data
-                       ptr[0] == 0                       &&            // Name must be root label
-                       ptr[1] == (kDNSType_OPT >> 8  )   &&            // rrtype OPT
-                       ptr[2] == (kDNSType_OPT & 0xFF)   &&
-                       ((mDNSu16)ptr[9] << 8 | (mDNSu16)ptr[10]) >= (mDNSu16)LEASE_OPT_RDLEN)
-                       return(ptr);
-               else
-                       ptr = skipResourceRecord(msg, ptr, end);
+               if (ptr) return(&m->rec.r.resrec.rdata->u.opt[0]);
                }
        return(mDNSNULL);
        }
@@ -2499,10 +2814,10 @@ mDNSexport const mDNSu8 *LocateLeaseOptData(const DNSMessage *const msg, const m
 mDNSexport mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end)
        {
        mDNSu32 result = 0;
-       const mDNSu8 *ptr = LocateLeaseOptData(msg, end);
+       const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space);
        if (ptr) ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
-       if (ptr && m->rec.r.resrec.rdlength >= LEASE_OPT_RDLEN && m->rec.r.resrec.rdata->u.opt.opt == kDNSOpt_Lease)
-               result = m->rec.r.resrec.rdata->u.opt.OptData.updatelease;
+       if (ptr && m->rec.r.resrec.rdlength >= DNSOpt_LeaseData_Space && m->rec.r.resrec.rdata->u.opt[0].opt == kDNSOpt_Lease)
+               result = m->rec.r.resrec.rdata->u.opt[0].u.updatelease;
        m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
        return(result);
        }
@@ -2534,8 +2849,8 @@ mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg,
 
 #define DNS_RC_Name(X) (                             \
        (X) == kDNSFlag1_RC_NoErr    ? "NoErr"    :      \
-       (X) == kDNSFlag1_RC_FmtErr   ? "FmtErr"   :      \
-       (X) == kDNSFlag1_RC_SrvErr   ? "SrvErr"   :      \
+       (X) == kDNSFlag1_RC_FormErr  ? "FormErr"  :      \
+       (X) == kDNSFlag1_RC_ServFail ? "ServFail" :      \
        (X) == kDNSFlag1_RC_NXDomain ? "NXDomain" :      \
        (X) == kDNSFlag1_RC_NotImpl  ? "NotImpl"  :      \
        (X) == kDNSFlag1_RC_Refused  ? "Refused"  :      \
@@ -2546,7 +2861,7 @@ mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg,
        (X) == kDNSFlag1_RC_NotZone  ? "NotZone"  : "??" )
 
 // Note: DumpPacket expects the packet header fields in host byte order, not network byte order
-mDNSexport void DumpPacket(mDNS *const m, mDNSBool sent, char *transport,
+mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *transport,
        const mDNSAddr *srcaddr, mDNSIPPort srcport,
        const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end)
        {
@@ -2554,14 +2869,16 @@ mDNSexport void DumpPacket(mDNS *const m, mDNSBool sent, char *transport,
        const mDNSu8 *ptr = msg->data;
        int i;
        DNSQuestion q;
-       char sbuffer[64], dbuffer[64] = "";
+       char tbuffer[64], sbuffer[64], dbuffer[64] = "";
+       if (!status) tbuffer[mDNS_snprintf(tbuffer, sizeof(tbuffer), sent ? "Sent" : "Received"                        )] = 0;
+       else         tbuffer[mDNS_snprintf(tbuffer, sizeof(tbuffer), "ERROR %d %sing", status, sent ? "Send" : "Receiv")] = 0;
        if (sent) sbuffer[mDNS_snprintf(sbuffer, sizeof(sbuffer), "port "        )] = 0;
        else      sbuffer[mDNS_snprintf(sbuffer, sizeof(sbuffer), "%#a:", srcaddr)] = 0;
        if (dstaddr || !mDNSIPPortIsZero(dstport))
                dbuffer[mDNS_snprintf(dbuffer, sizeof(dbuffer), " to %#a:%d", dstaddr, mDNSVal16(dstport))] = 0;
 
        LogMsg("-- %s %s DNS %s%s (flags %02X%02X) RCODE: %s (%d) %s%s%s%s%s%sID: %d %d bytes from %s%d%s%s --",
-               sent ? "Sent" : "Received", transport,
+               tbuffer, transport,
                DNS_OP_Name(msg->h.flags.b[0] & kDNSFlag0_OP_Mask),
                msg->h.flags.b[0] & kDNSFlag0_QR_Response ? "Response" : "Query",
                msg->h.flags.b[0], msg->h.flags.b[1],
@@ -2611,71 +2928,52 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS
     mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo)
        {
        mStatus status = mStatus_NoError;
-       const mDNSu16 numQuestions   = msg->h.numQuestions;
-       const mDNSu16 numAnswers     = msg->h.numAnswers;
-       const mDNSu16 numAuthorities = msg->h.numAuthorities;
        const mDNSu16 numAdditionals = msg->h.numAdditionals;
-       mDNSu16 tmpNumAdditionals = numAdditionals;
-       mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions;
+       mDNSu8 *newend;
 
-       if (end <= msg->data || end - msg->data > AbsoluteMaxDNSMessageData)
+       // Zero-length message data is okay (e.g. for a DNS Update ack, where all we need is an ID and an error code
+       if (end < msg->data || end - msg->data > AbsoluteMaxDNSMessageData)
                {
                LogMsg("mDNSSendDNSMessage: invalid message %p %p %d", msg->data, end, end - msg->data);
                return mStatus_BadParamErr;
                }
 
-       end = putHINFO(m, msg, end, authInfo);
-       if (!end) { LogMsg("mDNSSendDNSMessage: putHINFO failed"); status = mStatus_NoMemoryErr; }
-       else
-               {
-               tmpNumAdditionals = msg->h.numAdditionals;
+       newend = putHINFO(m, msg, end, authInfo);
+       if (!newend) LogMsg("mDNSSendDNSMessage: putHINFO failed"); // Not fatal
+       else end = newend;
        
-               // Put all the integer values in IETF byte-order (MSB first, LSB second)
-               *ptr++ = (mDNSu8)(numQuestions   >> 8);
-               *ptr++ = (mDNSu8)(numQuestions   &  0xFF);
-               *ptr++ = (mDNSu8)(numAnswers     >> 8);
-               *ptr++ = (mDNSu8)(numAnswers     &  0xFF);
-               *ptr++ = (mDNSu8)(numAuthorities >> 8);
-               *ptr++ = (mDNSu8)(numAuthorities &  0xFF);
-               *ptr++ = (mDNSu8)(tmpNumAdditionals >> 8);
-               *ptr++ = (mDNSu8)(tmpNumAdditionals &  0xFF);
+       // Put all the integer values in IETF byte-order (MSB first, LSB second)
+       SwapDNSHeaderBytes(msg);
        
-               if (authInfo) DNSDigest_SignMessage(msg, &end, authInfo, 0);    // DNSDigest_SignMessage operates on message in network byte order
-               if (!end) { LogMsg("mDNSSendDNSMessage: DNSDigest_SignMessage failed"); status = mStatus_NoMemoryErr; }
+       if (authInfo) DNSDigest_SignMessage(msg, &end, authInfo, 0);    // DNSDigest_SignMessage operates on message in network byte order
+       if (!end) { LogMsg("mDNSSendDNSMessage: DNSDigest_SignMessage failed"); status = mStatus_NoMemoryErr; }
+       else
+               {
+               // Send the packet on the wire
+               if (!sock)
+                       status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, src, dst, dstport);
                else
                        {
-                       // Send the packet on the wire
-                       if (!sock)
-                               status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, src, dst, dstport);
+                       mDNSu16 msglen = (mDNSu16)(end - (mDNSu8 *)msg);
+                       mDNSu8 lenbuf[2] = { (mDNSu8)(msglen >> 8), (mDNSu8)(msglen & 0xFF) };
+                       long nsent = mDNSPlatformWriteTCP(sock, (char*)lenbuf, 2);              // Should do scatter/gather here -- this is probably going out as two packets
+                       if (nsent != 2) { LogMsg("mDNSSendDNSMessage: write msg length failed %d/%d", nsent, 2); status = mStatus_ConnFailed; }
                        else
                                {
-                               mDNSu16 msglen = (mDNSu16)(end - (mDNSu8 *)msg);
-                               mDNSu8 lenbuf[2] = { (mDNSu8)(msglen >> 8), (mDNSu8)(msglen & 0xFF) };
-                               long nsent = mDNSPlatformWriteTCP(sock, (char*)lenbuf, 2);              // Should do scatter/gather here -- this is probably going out as two packets
-                               if (nsent != 2) { LogMsg("mDNSSendDNSMessage: write msg length failed %d/%d", nsent, 2); status = mStatus_ConnFailed; }
-                               else
-                                       {
-                                       nsent = mDNSPlatformWriteTCP(sock, (char *)msg, msglen);
-                                       if (nsent != msglen) { LogMsg("mDNSSendDNSMessage: write msg body failed %d/%d", nsent, msglen); status = mStatus_ConnFailed; }
-                                       }
+                               nsent = mDNSPlatformWriteTCP(sock, (char *)msg, msglen);
+                               if (nsent != msglen) { LogMsg("mDNSSendDNSMessage: write msg body failed %d/%d", nsent, msglen); status = mStatus_ConnFailed; }
                                }
                        }
                }
 
-       // Put all the integer values back the way they were before we return
-       msg->h.numQuestions   = numQuestions;
-       msg->h.numAnswers     = numAnswers;
-       msg->h.numAuthorities = numAuthorities;
+       // Swap the integer values back the way they were (remember that numAdditionals may have been changed by putHINFO and/or SignMessage)
+       SwapDNSHeaderBytes(msg);
 
        // Dump the packet with the HINFO and TSIG
-       if (mDNS_LogLevel >= MDNS_LOG_VERBOSE_DEBUG && !mDNSOpaque16IsZero(msg->h.id))
-               {
-               ptr = (mDNSu8 *)&msg->h.numAdditionals;
-               msg->h.numAdditionals = (mDNSu16)ptr[0] << 8 | (mDNSu16)ptr[1];
-               DumpPacket(m, mDNStrue, sock && (sock->flags & kTCPSocketFlags_UseTLS) ? "TLS" : sock ? "TCP" : "UDP", mDNSNULL, src ? src->port : MulticastDNSPort, dst, dstport, msg, end);
-               }
+       if (mDNS_PacketLoggingEnabled && !mDNSOpaque16IsZero(msg->h.id))
+               DumpPacket(m, status, mDNStrue, sock && (sock->flags & kTCPSocketFlags_UseTLS) ? "TLS" : sock ? "TCP" : "UDP", mDNSNULL, src ? src->port : MulticastDNSPort, dst, dstport, msg, end);
 
-       // put the final integer value back the way it was
+       // put the number of additionals back the way it was
        msg->h.numAdditionals = numAdditionals;
 
        return(status);
@@ -2743,28 +3041,77 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
                }
        if (m->NewLocalOnlyQuestions)                                   return(m->timenow);
        if (m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords)) return(m->timenow);
+       if (m->SPSProxyListChanged)                                     return(m->timenow);
 #ifndef UNICAST_DISABLED
        if (e - m->NextuDNSEvent         > 0) e = m->NextuDNSEvent;
        if (e - m->NextScheduledNATOp    > 0) e = m->NextScheduledNATOp;
 #endif
        if (e - m->NextCacheCheck        > 0) e = m->NextCacheCheck;
+       if (e - m->NextScheduledSPS      > 0) e = m->NextScheduledSPS;
+       if (m->SleepLimit && e - m->NextScheduledSPRetry > 0) e = m->NextScheduledSPRetry;
+       if (m->DelaySleep && e - m->DelaySleep           > 0) e = m->DelaySleep;
 
-       if (!m->SleepState)
+       if (m->SuppressSending)
                {
-               if (m->SuppressSending)
-                       {
-                       if (e - m->SuppressSending       > 0) e = m->SuppressSending;
-                       }
-               else
-                       {
-                       if (e - m->NextScheduledQuery    > 0) e = m->NextScheduledQuery;
-                       if (e - m->NextScheduledProbe    > 0) e = m->NextScheduledProbe;
-                       if (e - m->NextScheduledResponse > 0) e = m->NextScheduledResponse;
-                       }
+               if (e - m->SuppressSending       > 0) e = m->SuppressSending;
                }
+       else
+               {
+               if (e - m->NextScheduledQuery    > 0) e = m->NextScheduledQuery;
+               if (e - m->NextScheduledProbe    > 0) e = m->NextScheduledProbe;
+               if (e - m->NextScheduledResponse > 0) e = m->NextScheduledResponse;
+               }
+
        return(e);
        }
 
+mDNSexport void ShowTaskSchedulingError(mDNS *const m)
+       {
+       mDNS_Lock(m);
+
+       LogMsg("Task Scheduling Error: Continuously busy for more than a second");
+       
+       // Note: To accurately diagnose *why* we're busy, the debugging code here needs to mirror the logic in GetNextScheduledEvent above
+
+       if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0))
+               LogMsg("Task Scheduling Error: NewQuestion %##s (%s)",
+                       m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
+
+       if (m->NewLocalOnlyQuestions)
+               LogMsg("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)",
+                       m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
+
+       if (m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords))
+               LogMsg("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, m->NewLocalRecords));
+
+       if (m->timenow - m->NextScheduledEvent    >= 0)
+               LogMsg("Task Scheduling Error: m->NextScheduledEvent %d",    m->timenow - m->NextScheduledEvent);
+       if (m->SuppressSending && m->timenow - m->SuppressSending >= 0)
+               LogMsg("Task Scheduling Error: m->SuppressSending %d",       m->timenow - m->SuppressSending);
+       if (m->timenow - m->NextCacheCheck        >= 0)
+               LogMsg("Task Scheduling Error: m->NextCacheCheck %d",        m->timenow - m->NextCacheCheck);
+       if (m->timenow - m->NextScheduledQuery    >= 0)
+               LogMsg("Task Scheduling Error: m->NextScheduledQuery %d",    m->timenow - m->NextScheduledQuery);
+       if (m->timenow - m->NextScheduledProbe    >= 0)
+               LogMsg("Task Scheduling Error: m->NextScheduledProbe %d",    m->timenow - m->NextScheduledProbe);
+       if (m->timenow - m->NextScheduledResponse >= 0)
+               LogMsg("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse);
+       if (m->timenow - m->NextScheduledNATOp    >= 0)
+               LogMsg("Task Scheduling Error: m->NextScheduledNATOp %d",    m->timenow - m->NextScheduledNATOp);
+       if (m->timenow - m->NextScheduledSPS      >= 0)
+               LogMsg("Task Scheduling Error: m->NextScheduledSPS %d",      m->timenow - m->NextScheduledSPS);
+       if (m->SleepLimit && m->timenow - m->NextScheduledSPRetry >= 0)
+               LogMsg("Task Scheduling Error: m->NextScheduledSPRetry %d",  m->timenow - m->NextScheduledSPRetry);
+       if (m->DelaySleep && m->timenow - m->DelaySleep >= 0)
+               LogMsg("Task Scheduling Error: m->DelaySleep %d",            m->timenow - m->DelaySleep);
+#ifndef UNICAST_DISABLED
+       if (m->timenow - m->NextuDNSEvent         >= 0)
+               LogMsg("Task Scheduling Error: NextuDNSEvent %d",            m->timenow - m->NextuDNSEvent);
+#endif
+
+       mDNS_Unlock(m);
+       }
+
 mDNSexport void mDNS_Unlock_(mDNS *const m)
        {
        // Decrement mDNS_busy
index 52169dea4f8c82d3c14a85b91e993c3b2cbb70c9..95d4e3026ad5274fb69bd4c70ed51162890c1761 100644 (file)
     Change History (most recent first):
 
 $Log: DNSCommon.h,v $
+Revision 1.73  2009/04/24 00:28:05  cheshire
+<rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
+Added definitions for RRTypeAnswersQuestionType/RRAssertsNonexistence/AnyTypeRecordAnswersQuestion
+
+Revision 1.72  2009/04/01 21:12:56  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+
+Revision 1.71  2009/04/01 17:50:10  mcguire
+cleanup mDNSRandom
+
+Revision 1.70  2009/03/04 00:40:12  cheshire
+Updated DNS server error codes to be more consistent with definitions at
+<http://www.iana.org/assignments/dns-parameters>
+
+Revision 1.69  2008/11/26 20:57:37  cheshire
+For consistency with other similar macros, renamed mdnsIsDigit/mdnsIsLetter/mdnsValidHostChar
+to mDNSIsDigit/mDNSIsLetter/mDNSValidHostChar
+
+Revision 1.68  2008/11/14 21:56:31  cheshire
+Moved debugging routine ShowTaskSchedulingError() from daemon.c into DNSCommon.c
+
+Revision 1.67  2008/11/13 19:05:09  cheshire
+Added definition of LocateOptRR()
+
+Revision 1.66  2008/10/22 19:56:54  cheshire
+Removed unused SameRData() macro -- it duplicates the functionality of IdenticalSameNameRecord()
+
+Revision 1.65  2008/10/20 15:39:20  cheshire
+Group "#define PutResourceRecord ..." with related definitions
+
+Revision 1.64  2008/10/08 01:03:33  cheshire
+Change GetFirstActiveInterface() so the NetworkInterfaceInfo it returns is not "const"
+
+Revision 1.63  2008/09/23 02:30:07  cheshire
+Get rid of PutResourceRecordCappedTTL()
+
+Revision 1.62  2008/09/23 02:26:09  cheshire
+Don't need to export putEmptyResourceRecord (it's only used from DNSCommon.c)
+
+Revision 1.61  2008/08/13 00:47:53  mcguire
+Handle failures when packet logging
+
 Revision 1.60  2008/07/24 20:23:03  cheshire
 <rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
 
@@ -162,8 +204,8 @@ typedef enum
 
        kDNSFlag1_RC_Mask     = 0x0F,           // Response code
        kDNSFlag1_RC_NoErr    = 0x00,
-       kDNSFlag1_RC_FmtErr   = 0x01,
-       kDNSFlag1_RC_SrvErr   = 0x02,
+       kDNSFlag1_RC_FormErr  = 0x01,
+       kDNSFlag1_RC_ServFail = 0x02,
        kDNSFlag1_RC_NXDomain = 0x03,
        kDNSFlag1_RC_NotImpl  = 0x04,
        kDNSFlag1_RC_Refused  = 0x05,
@@ -187,11 +229,10 @@ typedef enum
 #pragma mark - General Utility Functions
 #endif
 
-extern const NetworkInterfaceInfo *GetFirstActiveInterface(const NetworkInterfaceInfo *intf);
+extern NetworkInterfaceInfo *GetFirstActiveInterface(NetworkInterfaceInfo *intf);
 extern mDNSInterfaceID GetNextActiveInterfaceID(const NetworkInterfaceInfo *intf);
 
 extern mDNSu32 mDNSRandom(mDNSu32 max);                // Returns pseudo-random result from zero to max inclusive
-extern mDNSu32 mDNSRandomFromFixedSeed(mDNSu32 seed, mDNSu32 max);
 
 // ***************************************************************************
 #if COMPILER_LIKES_PRAGMA_MARK
@@ -199,12 +240,12 @@ extern mDNSu32 mDNSRandomFromFixedSeed(mDNSu32 seed, mDNSu32 max);
 #pragma mark - Domain Name Utility Functions
 #endif
 
-#define mdnsIsDigit(X)     ((X) >= '0' && (X) <= '9')
+#define mDNSIsDigit(X)     ((X) >= '0' && (X) <= '9')
 #define mDNSIsUpperCase(X) ((X) >= 'A' && (X) <= 'Z')
 #define mDNSIsLowerCase(X) ((X) >= 'a' && (X) <= 'z')
-#define mdnsIsLetter(X)    (mDNSIsUpperCase(X) || mDNSIsLowerCase(X))
+#define mDNSIsLetter(X)    (mDNSIsUpperCase(X) || mDNSIsLowerCase(X))
 
-#define mdnsValidHostChar(X, notfirst, notlast) (mdnsIsLetter(X) || mdnsIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') )
+#define mDNSValidHostChar(X, notfirst, notlast) (mDNSIsLetter(X) || mDNSIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') )
 
 extern mDNSu16 CompressedDomainNameLength(const domainname *const name, const domainname *parent);
 extern int CountLabels(const domainname *d);
@@ -252,11 +293,16 @@ extern void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichText)
        (r1)->rdatahash == (r2)->rdatahash   && \
        SameRDataBody((r1), &(r2)->rdata->u))
 
+// A given RRType answers a QuestionType if RRType is CNAME, or types match, or QuestionType is ANY,
+// or the RRType is NSEC and positively asserts the nonexistence of the type being requested
+#define RRTypeAnswersQuestionType(R,T) ((R)->rrtype == kDNSType_CNAME || (R)->rrtype == (T) || (T) == kDNSQType_ANY || RRAssertsNonexistence((R),(T)))
+#define RRAssertsNonexistence(R,T) ((R)->rrtype == kDNSType_NSEC && (T) < kDNSQType_ANY && !((R)->rdata->u.nsec.bitmap[(T)>>3] & (128 >> ((T)&7))))
+
 extern mDNSu32 RDataHashValue(const ResourceRecord *const rr);
 extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2);
-#define SameRData(r1,r2) ((r1)->rrtype == (r2)->rrtype && (r1)->rdlength == (r2)->rdlength && (r1)->rdatahash == (r2)->rdatahash && SameRDataBody((r1), &(r2)->rdata->u))
-extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
 extern mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
+extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
+extern mDNSBool AnyTypeRecordAnswersQuestion (const ResourceRecord *const rr, const DNSQuestion *const q);
 extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate);
 extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
 
@@ -281,12 +327,13 @@ extern mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *
 // If we have a single large record to put in the packet, then we allow the packet to be up to 9K bytes,
 // but in the normal case we try to keep the packets below 1500 to avoid IP fragmentation on standard Ethernet
 extern mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 ttl, const mDNSu8 *limit);
-#define PutResourceRecordTTL(msg, ptr, count, rr, ttl) PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), \
+
+#define PutResourceRecordTTL(msg, ptr, count, rr, ttl) \
+       PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), \
        ((msg)->h.numAnswers || (msg)->h.numAuthorities || (msg)->h.numAdditionals) ? (msg)->data + NormalMaxDNSMessageData : (msg)->data + AbsoluteMaxDNSMessageData)
-#define PutResourceRecordTTLJumbo(msg, ptr, count, rr, ttl) PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), \
-       (msg)->data + AbsoluteMaxDNSMessageData)
-extern mDNSu8 *PutResourceRecordCappedTTL(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 maxttl);
-extern mDNSu8 *putEmptyResourceRecord(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, mDNSu16 *count, const AuthRecord *rr);
+#define PutResourceRecordTTLJumbo(msg, ptr, count, rr, ttl) \
+       PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), (msg)->data + AbsoluteMaxDNSMessageData)
+#define PutResourceRecord(MSG, P, C, RR) PutResourceRecordTTL((MSG), (P), (C), (RR), (RR)->rroriginalttl)
 
 extern mDNSu8 *putQuestion(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name, mDNSu16 rrtype, mDNSu16 rrclass);
 extern mDNSu8 *putZone(DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit, const domainname *zone, mDNSOpaque16 zoneClass);
@@ -295,7 +342,6 @@ extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *r
 extern  mDNSu8 *putDeleteRRSet(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype);
 extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name);
 extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease);
-#define PutResourceRecord(MSG, P, C, RR) PutResourceRecordTTL((MSG), (P), (C), (RR), (RR)->rroriginalttl)
 
 extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *end, DomainAuthInfo *authInfo);
 
@@ -320,11 +366,10 @@ extern const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const
 extern const mDNSu8 *LocateAnswers(const DNSMessage *const msg, const mDNSu8 *const end);
 extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 *const end);
 extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end);
-extern const mDNSu8 *LocateLLQOptData(const DNSMessage *const msg, const mDNSu8 *const end);
+extern const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize);
 extern const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end);
-extern const mDNSu8 *LocateLeaseOptData(const DNSMessage *const msg, const mDNSu8 *const end);
 extern mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end);
-extern void DumpPacket(mDNS *const m, mDNSBool sent, char *transport,
+extern void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *transport,
        const mDNSAddr *srcaddr, mDNSIPPort srcport,
        const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end);
 
@@ -343,9 +388,14 @@ extern mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *
 #pragma mark - RR List Management & Task Management
 #endif
 
+extern void ShowTaskSchedulingError(mDNS *const m);
 extern void mDNS_Lock_(mDNS *const m);
 extern void mDNS_Unlock_(mDNS *const m);
 
+#if defined(_WIN32)
+ #define __func__ __FUNCTION__
+#endif
+
 #define mDNS_Lock(X) do { \
        if ((X)->mDNS_busy != (X)->mDNS_reentrancy) LogMsg("%s: mDNS_Lock locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy); \
        mDNS_Lock_(X); } while (0)
index 09ff7c7f7c077a9d3817b4793f15bcb9053bc1a2..d83e6355d648a98953f204b28618b5d15207ca41 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: DNSDigest.c,v $
+Revision 1.26  2008/10/10 23:21:51  mcguire
+fixed typo in original MD5 source reference
+
 Revision 1.25  2007/12/17 23:48:29  cheshire
 DNSDigest_SignMessage doesn't need to return a result -- it already updates the 'end' parameter
 
@@ -153,7 +156,7 @@ mDNSlocal mDNSu32 NToH32(mDNSu8 * bytes)
  * Note: machine archetecure specific conditionals from the original sources are turned off, but are left in the code
  * to aid in platform-specific optimizations and debugging.
  * Sources originally distributed under the following license headers:
- * CommonDigest.c - APSL
+ * CommonDigest.h - APSL
  * 
  * md32_Common.h
  * ====================================================================
index 25789112012b2c728a1434117f84864973ded85f..c26789615539f402e9795c1a7c754a8dac207878 100755 (executable)
     Change History (most recent first):
 
 $Log: mDNS.c,v $
-Revision 1.777.4.5  2008/09/30 18:03:01  mcguire
+Revision 1.969.2.1  2009/07/23 23:41:25  cheshire
+<rdar://problem/7086623> Sleep Proxy: Ten-second maintenance wake not long enough to reliably get network connectivity
+
+Revision 1.969  2009/06/30 21:18:19  cheshire
+<rdar://problem/7020041> Plugging and unplugging the power cable shouldn't cause a network change event
+Additional fixes:
+1. Made mDNS_ActivateNetWake_internal and mDNS_DeactivateNetWake_internal more defensive against bad parameters
+2. mDNS_DeactivateNetWake_internal also needs to stop any outstanding Sleep Proxy resolve operations
+
+Revision 1.968  2009/06/29 23:51:09  cheshire
+<rdar://problem/6690034> Can't bind to Active Directory
+
+Revision 1.967  2009/06/27 00:25:27  cheshire
+<rdar://problem/6959273> mDNSResponder taking up 13% CPU with 400 KBps incoming bonjour requests
+Removed overly-complicate and ineffective multi-packet known-answer snooping code
+(Bracketed it with "#if ENABLE_MULTI_PACKET_QUERY_SNOOPING" for now; will delete actual code later)
+
+Revision 1.966  2009/06/26 01:55:55  cheshire
+<rdar://problem/6890712> mDNS: iChat's Buddy photo always appears as the "shadow person" over Bonjour
+Additional refinements -- except for the case of explicit queries for record types we don't have (for names we own),
+add additional NSEC records only when there's space to do that without having to generate an additional packet
+
+Revision 1.965  2009/06/24 22:14:21  cheshire
+<rdar://problem/6911445> Plugging and unplugging the power cable shouldn't cause a network change event
+
+Revision 1.964  2009/06/03 23:07:13  cheshire
+<rdar://problem/6890712> mDNS: iChat's Buddy photo always appears as the "shadow person" over Bonjour
+Large records were not being added in cases where an NSEC record was also required
+
+Revision 1.963  2009/05/28 00:39:19  cheshire
+<rdar://problem/6926465> Sleep is delayed by 10 seconds if BTMM is on
+After receiving confirmation of wide-area record deletion, need to schedule another evaluation of whether we're ready to sleep yet
+
+Revision 1.962  2009/05/19 23:40:37  cheshire
+<rdar://problem/6903507> Sleep Proxy: Retransmission logic not working reliably on quiet networks
+Added m->NextScheduledSPRetry timer for scheduling Sleep Proxy registration retries
+
+Revision 1.961  2009/05/19 23:00:43  cheshire
+Improved comments and debugging messages
+
+Revision 1.960  2009/05/13 17:25:33  mkrochma
+<rdar://problem/6879926> Should not schedule maintenance wake when machine has no advertised services
+Sleep proxy client should only look for services being advertised via Multicast
+
+Revision 1.959  2009/05/12 23:10:31  cheshire
+<rdar://problem/6879926> Should not schedule maintenance wake when machine has no advertised services
+Make new routine mDNSCoreHaveAdvertisedServices so daemon.c can tell whether it needs to schedule a maintenance wake
+
+Revision 1.958  2009/05/12 19:19:20  cheshire
+<rdar://problem/6879925> Sleep Proxy delays sleep by ten seconds when logged in to VPN
+
+Revision 1.957  2009/05/07 23:56:25  cheshire
+<rdar://problem/6601427> Retransmit and retry Sleep Proxy Server requests
+To get negative answers for our AAAA query we need to set the ReturnIntermed flag on the NetWakeResolve question
+
+Revision 1.956  2009/05/07 23:46:27  cheshire
+<rdar://problem/6601427> Retransmit and retry Sleep Proxy Server requests
+
+Revision 1.955  2009/05/07 23:40:54  cheshire
+Minor code rearrangement in preparation for upcoming changes
+
+Revision 1.954  2009/05/01 21:28:34  cheshire
+<rdar://problem/6721680> AppleConnectAgent's reachability checks delay sleep by 30 seconds
+No longer suspend network operations after we've acknowledged that the machine is going to sleep,
+because other software may not have yet acknowledged the sleep event, and may be still trying
+to do unicast DNS queries or other Bonjour operations.
+
+Revision 1.953  2009/05/01 19:17:35  cheshire
+<rdar://problem/6501561> Sleep Proxy: Reduce the frequency of maintenance wakes: ODD, fans, power
+
+Revision 1.952  2009/05/01 19:16:45  mcguire
+<rdar://problem/6846322> Crash: mDNS_vsnprintf + 1844
+
+Revision 1.951  2009/04/28 23:48:19  jessic2
+<rdar://problem/6830541> regservice_callback: instance->request is NULL 0
+
+Revision 1.950  2009/04/25 01:17:10  mcguire
+Fix spurious TCP connect failures uncovered by <rdar://problem/6729406> PPP doesn't automatically reconnect on wake from sleep
+
+Revision 1.949  2009/04/25 01:11:02  mcguire
+Refactor: create separate function: RestartRecordGetZoneData
+
+Revision 1.948  2009/04/24 21:25:16  cheshire
+<rdar://problem/6601002> Special case Net Assistant port so Apple Remote Desktop doesn't wake up every machine on the network
+
+Revision 1.947  2009/04/24 19:41:12  mcguire
+<rdar://problem/6791775> 4 second delay in DNS response
+
+Revision 1.946  2009/04/24 19:28:39  mcguire
+<rdar://problem/6791775> 4 second delay in DNS response
+
+Revision 1.945  2009/04/24 00:30:30  cheshire
+<rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
+Added code to generate and process NSEC records
+
+Revision 1.944  2009/04/23 22:06:29  cheshire
+Added CacheRecord and InterfaceID parameters to MakeNegativeCacheRecord, in preparation for:
+<rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
+
+Revision 1.943  2009/04/22 01:19:56  jessic2
+<rdar://problem/6814585> Daemon: mDNSResponder is logging garbage for error codes because it's using %ld for int 32
+
+Revision 1.942  2009/04/21 02:13:29  cheshire
+<rdar://problem/5270176> Local hostname changed even though there really isn't a name conflict
+Made code less susceptible to being tricked by stale packets echoed back from the network.
+
+Revision 1.941  2009/04/15 22:22:23  mcguire
+<rdar://problem/6768947> uDNS: Treat RCODE 5 (Refused) responses as failures
+Additional fix: protect against deref of NULL
+
+Revision 1.940  2009/04/15 20:42:51  mcguire
+<rdar://problem/6768947> uDNS: Treat RCODE 5 (Refused) responses as failures
+
+Revision 1.939  2009/04/11 00:19:32  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.938  2009/04/06 23:44:57  cheshire
+<rdar://problem/6757838> mDNSResponder thrashing kernel lock in the UDP close path, hurting SPECweb performance
+
+Revision 1.937  2009/04/04 00:14:49  mcguire
+fix logging in BeginSleepProcessing
+
+Revision 1.936  2009/04/04 00:10:59  mcguire
+don't ignore m->SystemWakeOnLANEnabled when going to sleep
+
+Revision 1.935  2009/04/01 17:50:11  mcguire
+cleanup mDNSRandom
+
+Revision 1.934  2009/03/27 17:17:58  cheshire
+Improved "Ignoring suspect uDNS response" debugging message
+
+Revision 1.933  2009/03/21 02:40:21  cheshire
+<rdar://problem/6704514> uDNS: Need to create negative cache entries for "local" SOA
+
+Revision 1.932  2009/03/20 23:53:03  jessic2
+<rdar://problem/6646228> SIGHUP should restart all in-progress queries
+
+Revision 1.931  2009/03/18 19:08:15  cheshire
+Show old/new sleep sequence numbers in logical order
+
+Revision 1.930  2009/03/17 23:40:45  cheshire
+For now only try the highest-ranked Sleep Proxy; fixed come compiler warnings
+
+Revision 1.929  2009/03/17 21:55:56  cheshire
+Fixed mistake in logic for decided when we're ready to go to sleep
+
+Revision 1.928  2009/03/17 19:48:12  cheshire
+<rdar://problem/6688927> Don't cache negative unicast answers for Multicast DNS names
+
+Revision 1.927  2009/03/17 01:22:56  cheshire
+<rdar://problem/6601427> Sleep Proxy: Retransmit and retry Sleep Proxy Server requests
+Initial support for resolving up to three Sleep Proxies in parallel
+
+Revision 1.926  2009/03/17 01:05:07  mcguire
+<rdar://problem/6657640> Reachability fixes on DNS config change
+
+Revision 1.925  2009/03/13 01:35:36  mcguire
+<rdar://problem/6657640> Reachability fixes on DNS config change
+
+Revision 1.924  2009/03/10 23:45:20  cheshire
+Added comments explaining usage of SetSPSProxyListChanged()
+
+Revision 1.923  2009/03/09 21:53:02  cheshire
+<rdar://problem/6650479> Sleep Proxy: Need to stop proxying when it sees an ARP probe from the client
+
+Revision 1.922  2009/03/09 21:30:17  cheshire
+Improved some LogSPS messages; made RestartProbing() subroutine
+
+Revision 1.921  2009/03/06 22:53:31  cheshire
+Don't bother registering with Sleep Proxy if we have no advertised services
+
+Revision 1.920  2009/03/06 20:08:55  cheshire
+<rdar://problem/6601429> Sleep Proxy: Return error responses to clients
+
+Revision 1.919  2009/03/05 21:54:43  cheshire
+Improved "Sleep Proxy Server started / stopped" message
+
+Revision 1.918  2009/03/04 01:37:14  cheshire
+<rdar://problem/6601428> Limit maximum number of records that a Sleep Proxy Server will accept
+
+Revision 1.917  2009/03/03 23:14:25  cheshire
+Got rid of code duplication by making subroutine "SetupOwnerOpt"
+
+Revision 1.916  2009/03/03 23:04:43  cheshire
+For clarity, renamed "MAC" field to "HMAC" (Host MAC, as opposed to Interface MAC)
+
+Revision 1.915  2009/03/03 22:51:53  cheshire
+<rdar://problem/6504236> Sleep Proxy: Waking on same network but different interface will cause conflicts
+
+Revision 1.914  2009/03/03 00:46:09  cheshire
+Additional debugging information in ResolveSimultaneousProbe
+
+Revision 1.913  2009/02/27 03:08:47  cheshire
+<rdar://problem/6547720> Crash while shutting down when "local" is in the user's DNS searchlist
+
+Revision 1.912  2009/02/27 02:31:28  cheshire
+Improved "Record not found in list" debugging message
+
+Revision 1.911  2009/02/21 01:42:11  cheshire
+Updated log messages
+
+Revision 1.910  2009/02/19 01:50:53  cheshire
+Converted some LogInfo messages to LogSPS
+
+Revision 1.909  2009/02/14 00:04:59  cheshire
+Left-justify interface names
+
+Revision 1.908  2009/02/13 19:40:07  cheshire
+Improved alignment of LogSPS messages
+
+Revision 1.907  2009/02/13 18:16:05  cheshire
+Fixed some compile warnings
+
+Revision 1.906  2009/02/13 06:10:17  cheshire
+Convert LogOperation messages to LogInfo
+
+Revision 1.905  2009/02/12 20:57:24  cheshire
+Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
+
+Revision 1.904  2009/02/11 02:37:29  cheshire
+m->p->SystemWakeForNetworkAccessEnabled renamed to m->SystemWakeOnLANEnabled
+Moved code to send goodbye packets from mDNSCoreMachineSleep into BeginSleepProcessing,
+so that it happens correctly even when we delay re-sleep due to a very short wakeup.
+
+Revision 1.903  2009/02/09 23:34:31  cheshire
+Additional logging for debugging unknown packets
+
+Revision 1.902  2009/02/07 05:57:01  cheshire
+Fixed debugging log message
+
+Revision 1.901  2009/02/07 02:57:31  cheshire
+<rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
+
+Revision 1.900  2009/02/02 21:29:24  cheshire
+<rdar://problem/4786302> Implement logic to determine when to send dot-local lookups via Unicast
+If Negative response for our special Microsoft Active Directory "local SOA" check has no
+SOA record in the authority section, assume we should cache the negative result for 24 hours
+
+Revision 1.899  2009/01/31 00:37:50  cheshire
+When marking cache records for deletion in response to a uDNS response,
+make sure InterfaceID matches (i.e. it should be NULL for a uDNS cache record)
+
+Revision 1.898  2009/01/30 23:49:20  cheshire
+Exclude mDNSInterface_Unicast from "InterfaceID ... not currently found" test
+
+Revision 1.897  2009/01/30 22:04:49  cheshire
+Workaround to reduce load on root name servers when caching the SOA record for "."
+
+Revision 1.896  2009/01/30 22:00:05  cheshire
+Made mDNS_StartQuery_internal pay attention to mDNSInterface_Unicast
+
+Revision 1.895  2009/01/30 17:46:39  cheshire
+Improved debugging messages for working out why spurious name conflicts are happening
+
+Revision 1.894  2009/01/30 00:22:09  cheshire
+<rdar://problem/6540743> No announcement after probing & no conflict notice
+
+Revision 1.893  2009/01/29 22:27:03  mcguire
+<rdar://problem/6407429> Cleanup: Logs about Unknown DNS packet type 5450
+
+Revision 1.892  2009/01/24 01:38:23  cheshire
+Fixed error in logic for targeted queries
+
+Revision 1.891  2009/01/22 02:14:25  cheshire
+<rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
+
+Revision 1.890  2009/01/22 00:45:02  cheshire
+Improved SPS debugging log messages; we are eligible to start answering ARP requests
+after we send our first announcement, not after we send our last probe
+
+Revision 1.889  2009/01/21 03:43:56  mcguire
+<rdar://problem/6511765> BTMM: Add support for setting kDNSServiceErr_NATPortMappingDisabled in DynamicStore
+
+Revision 1.888  2009/01/20 00:27:43  mcguire
+<rdar://problem/6305725> when removing a uDNS record, if a dup exists, copy information to it
+
+Revision 1.887  2009/01/17 05:14:37  cheshire
+Convert SendQueries Probe messages to LogSPS messages
+
+Revision 1.886  2009/01/17 03:43:09  cheshire
+Added SPSLogging switch to facilitate Sleep Proxy Server debugging
+
+Revision 1.885  2009/01/16 22:44:18  cheshire
+<rdar://problem/6402123> Sleep Proxy: Begin ARP Announcements sooner
+
+Revision 1.884  2009/01/16 21:43:52  cheshire
+Let InitializeLastAPTime compute the correct interval, instead of having it passed in as a parameter
+
+Revision 1.883  2009/01/16 21:11:18  cheshire
+When purging expired Sleep Proxy records, need to check DuplicateRecords list too
+
+Revision 1.882  2009/01/16 19:54:28  cheshire
+Use symbols "SleepProxyServiceType" and "localdomain" instead of literal strings
+
+Revision 1.881  2009/01/14 01:38:38  mcguire
+<rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
+
+Revision 1.880  2009/01/10 01:51:19  cheshire
+q->CurrentAnswers not being incremented/decremented when answering a question with a local AuthRecord
+
+Revision 1.879  2009/01/10 01:43:52  cheshire
+Changed misleading function name 'AnsweredLOQ' to more informative 'AnsweredLocalQ'
+
+Revision 1.878  2009/01/10 01:38:10  cheshire
+Changed misleading function name 'AnswerLocalOnlyQuestionWithResourceRecord' to more informative 'AnswerLocalQuestionWithLocalAuthRecord'
+
+Revision 1.877  2009/01/10 01:36:08  cheshire
+Changed misleading function name 'AnswerLocalOnlyQuestions' to more informative 'AnswerAllLocalQuestionsWithLocalAuthRecord'
+
+Revision 1.876  2009/01/09 22:56:06  cheshire
+Don't touch rr after calling mDNS_Deregister_internal -- the memory may have been free'd
+
+Revision 1.875  2009/01/09 22:54:46  cheshire
+When tranferring record from DuplicateRecords list to ResourceRecords list,
+need to copy across state of 'Answered Local-Only-Questions' flag
+
+Revision 1.874  2009/01/07 23:07:24  cheshire
+<rdar://problem/6479416> SPS Client not canceling outstanding resolve call before sleeping
+
+Revision 1.873  2008/12/17 00:18:59  mkrochma
+Change some LogMsg to LogOperation before submitting
+
+Revision 1.872  2008/12/12 01:30:40  cheshire
+Update platform-layer BPF filters when we add or remove AddressProxy records
+
+Revision 1.871  2008/12/10 02:25:31  cheshire
+Minor fixes to use of LogClientOperations symbol
+
+Revision 1.870  2008/12/10 02:11:41  cheshire
+ARMv5 compiler doesn't like uncommented stuff after #endif
+
+Revision 1.869  2008/12/05 02:35:24  mcguire
+<rdar://problem/6107390> Write to the DynamicStore when a Sleep Proxy server is available on the network
+
+Revision 1.868  2008/12/04 21:08:51  mcguire
+<rdar://problem/6116863> mDNS: Provide mechanism to disable Multicast advertisements
+
+Revision 1.867  2008/11/26 21:19:36  cheshire
+<rdar://problem/6374334> Sleeping Server should choose the best Sleep Proxy by using advertised metrics
+
+Revision 1.866  2008/11/26 20:32:46  cheshire
+<rdar://problem/6374328> Sleep Proxy: Advertise BSP metrics in service name
+Update advertised name when Sleep Proxy "intent" metric changes
+
+Revision 1.865  2008/11/26 19:49:25  cheshire
+Record originally-requested port in sr->NATinfo.IntPort
+
+Revision 1.864  2008/11/26 19:02:37  cheshire
+Don't answer ARP Probes from owner machine as it wakes up and rejoins the network
+
+Revision 1.863  2008/11/26 03:59:03  cheshire
+Wait 30 seconds before starting ARP Announcements
+
+Revision 1.862  2008/11/25 23:43:07  cheshire
+<rdar://problem/5745355> Crashes at ServiceRegistrationGotZoneData + 397
+Made code more defensive to guard against ServiceRegistrationGotZoneData being called with invalid ServiceRecordSet object
+
+Revision 1.861  2008/11/25 22:46:30  cheshire
+For ease of code searching, renamed ZoneData field of ServiceRecordSet_struct from "nta" to "srs_nta"
+
+Revision 1.860  2008/11/25 05:07:15  cheshire
+<rdar://problem/6374328> Advertise Sleep Proxy metrics in service name
+
+Revision 1.859  2008/11/20 02:07:56  cheshire
+<rdar://problem/6387470> Refresh our NAT mappings on wake from sleep
+
+Revision 1.858  2008/11/20 01:38:36  cheshire
+For consistency with other parts of the code, changed code to only check
+that the first 4 bytes of MAC address are zero, not the whole 6 bytes.
+
+Revision 1.857  2008/11/14 22:55:18  cheshire
+Fixed log messages
+
+Revision 1.856  2008/11/14 21:08:28  cheshire
+Only put owner option in query packet if we have a non-zero MAC address to put
+Only process owner options in received query packets if the MAC address in the option is non-zero
+
+Revision 1.855  2008/11/14 02:29:54  cheshire
+If Sleep Proxy client fails to renew proxy records before they expire, remove them from our m->ResourceRecords list
+
+Revision 1.854  2008/11/14 00:00:53  cheshire
+After client machine wakes up, Sleep Proxy machine need to remove any records
+it was temporarily holding as proxy for that client
+
+Revision 1.853  2008/11/13 19:07:30  cheshire
+Added code to put OPT record, containing owner and lease lifetime, into SPS registration packet
+
+Revision 1.852  2008/11/12 23:23:11  cheshire
+Before waking a host, check to see if it has an SRV record advertising
+a service on the port in question, and if not, don't bother waking it.
+
+Revision 1.851  2008/11/12 01:54:15  cheshire
+<rdar://problem/6338021> Add domain back to end of _services._dns-sd._udp PTR records
+It turns out it is beneficial to have the domain on the end, because it allows better name compression
+
+Revision 1.850  2008/11/11 01:56:57  cheshire
+Improved name conflict log messages
+
+Revision 1.849  2008/11/06 23:50:43  cheshire
+Allow plain (non-SYN) ssh data packets to wake sleeping host
+
+Revision 1.848  2008/11/05 02:40:28  mkrochma
+Change mDNS_SetFQDN syslog mesage to debugf
+
+Revision 1.847  2008/11/04 23:06:50  cheshire
+Split RDataBody union definition into RDataBody and RDataBody2, and removed
+SOA from the normal RDataBody union definition, saving 270 bytes per AuthRecord
+
+Revision 1.846  2008/11/04 22:21:44  cheshire
+Changed zone field of AuthRecord_struct from domainname to pointer, saving 252 bytes per AuthRecord
+
+Revision 1.845  2008/11/03 23:52:05  cheshire
+Improved ARP debugging messages to differentiate ARP Announcements from Requests
+
+Revision 1.844  2008/10/31 23:43:51  cheshire
+Fixed compile error in Posix build
+
+Revision 1.843  2008/10/31 22:55:04  cheshire
+Initial support for structured SPS names
+
+Revision 1.842  2008/10/30 00:12:07  cheshire
+Fixed spin when PutSPSRec fails to put a record because it's too big to fit
+
+Revision 1.841  2008/10/29 23:23:38  cheshire
+Refined cache size reporting to go in steps of 1000 when number is above 1000
+
+Revision 1.840  2008/10/29 21:34:10  cheshire
+Removed some old debugging messages
+
+Revision 1.839  2008/10/29 21:31:32  cheshire
+Five seconds not always enough time for machine to go to sleep -- increased to ten seconds
+
+Revision 1.838  2008/10/28 18:30:37  cheshire
+Added debugging message in mDNSCoreReceiveRawPacket
+
+Revision 1.837  2008/10/24 23:58:05  cheshire
+Wake up for Back to My Mac IPSEC packets, except NAT keepalive packets
+
+Revision 1.836  2008/10/24 23:18:18  cheshire
+If we have a Sleep Proxy Server, don't remove service registrations from the DNS server
+
+Revision 1.835  2008/10/24 23:07:59  cheshire
+Wake SPS client if we receive conflicting mDNS respoonse (record with same name as one of our unique records, but different rdata)
+
+Revision 1.834  2008/10/24 23:03:24  cheshire
+Wake SPS client if we receive a conflicting ARP (some other machine claiming to own that IP address)
+
+Revision 1.833  2008/10/24 23:01:26  cheshire
+To reduce spurious wakeups for now, we'll only wake for incoming TCP SYN packets
+
+Revision 1.832  2008/10/24 22:58:24  cheshire
+For now, since we don't get IPv6 ND or data packets, don't advertise AAAA records for our SPS clients
+
+Revision 1.831  2008/10/24 22:50:41  cheshire
+When waking SPS client, include interface name in syslog message
+
+Revision 1.830  2008/10/24 20:50:34  cheshire
+Use "#if USE_SEPARATE_UDNS_SERVICE_LIST" instead of "#if defined(USE_SEPARATE_UDNS_SERVICE_LIST)"
+
+Revision 1.829  2008/10/23 23:55:57  cheshire
+Fixed some missing "const" declarations
+
+Revision 1.828  2008/10/23 22:25:56  cheshire
+Renamed field "id" to more descriptive "updateid"
+
+Revision 1.827  2008/10/23 03:06:25  cheshire
+Fixed "Waking host" log message
+
+Revision 1.826  2008/10/22 23:21:30  cheshire
+Make sure we have enough bytes before reading into the transport-level header
+
+Revision 1.825  2008/10/22 22:31:53  cheshire
+Log SYN/FIN/RST bits from TCP header, and don't wake for FIN/RST
+
+Revision 1.824  2008/10/22 20:00:31  cheshire
+If we ourselves go to sleep, stop advertising sleep proxy service, then re-advertise after we wake up
+
+Revision 1.823  2008/10/22 19:55:35  cheshire
+Miscellaneous fixes; renamed FindFirstAnswerInCache to FindSPSInCache
+
+Revision 1.822  2008/10/22 01:41:39  cheshire
+Set question->ThisQInterval back to -1 after we cancel our NetWakeResolve
+
+Revision 1.821  2008/10/22 01:12:53  cheshire
+Answer ARP Requests for any IP address we're proxying for
+
+Revision 1.820  2008/10/21 01:11:11  cheshire
+Added mDNSCoreReceiveRawPacket for handling raw packets received by platform layer
+
+Revision 1.819  2008/10/20 22:16:27  cheshire
+Updated comments; increased cache shedding threshold from 3000 to 4000
+
+Revision 1.818  2008/10/16 22:01:54  cheshire
+Fix last checkin: Should be "ar->resrec.rdata->u.data", not "ar->resrec.rdata.u.data"
+
+Revision 1.817  2008/10/16 21:40:49  cheshire
+Need to set ar->resrec.rdlength correctly before calling mDNS_Register_internal()
+
+Revision 1.816  2008/10/15 23:12:36  cheshire
+On receiving SPS registration from client, broadcast ARP Announcements claiming ownership of that IP address
+
+Revision 1.815  2008/10/15 20:46:38  cheshire
+When transferring records to SPS, include Lease Option
+
+Revision 1.814  2008/10/15 19:51:27  cheshire
+Change "NOTE:" to "Note:" so that BBEdit 9 stops putting those lines into the funtion popup menu
+
+Revision 1.813  2008/10/15 00:09:23  cheshire
+When acting as Sleep Proxy Server, handle DNS Updates received from SPS clients on the network
+
+Revision 1.812  2008/10/15 00:01:40  cheshire
+When going to sleep, discover and resolve SPS, and if successful, transfer records to it
+
+Revision 1.811  2008/10/14 23:51:57  cheshire
+Created new routine GetRDLengthMem() to compute the in-memory storage requirements for particular rdata
+
+Revision 1.810  2008/10/14 21:37:55  cheshire
+Removed unnecessary m->BeSleepProxyServer variable
+
+Revision 1.809  2008/10/10 23:45:48  cheshire
+For ForceMCast records, SetTargetToHostName should use the dot-local multicast hostname,
+not a wide-area unicast hostname
+
+Revision 1.808  2008/10/09 18:59:19  cheshire
+Added NetWakeResolve code, removed unused m->SendDeregistrations and m->SendImmediateAnswers
+
+Revision 1.807  2008/10/07 15:56:58  cheshire
+Fixed "unused variable" warnings in non-debug builds
+
+Revision 1.806  2008/10/04 00:53:37  cheshire
+On interfaces that support Wake-On-LAN, browse to discover Sleep Proxy Servers
+
+Revision 1.805  2008/10/03 18:17:28  cheshire
+<rdar://problem/6134215> Sleep Proxy: Mac with Internet Sharing should also offer Sleep Proxy service
+Update advertised Sleep Proxy Server name if user changes computer name
+
+Revision 1.804  2008/10/03 01:26:06  mcguire
+<rdar://problem/6266145> mDNS_FinalExit failed to send goodbye for duplicate uDNS records
+Put back Duplicate Record check
+
+Revision 1.803  2008/10/02 23:38:56  mcguire
+<rdar://problem/6266145> mDNS_FinalExit failed to send goodbye for duplicate uDNS records
+
+Revision 1.802  2008/10/02 23:13:48  cheshire
+<rdar://problem/6134215> Sleep Proxy: Mac with Internet Sharing should also offer Sleep Proxy service
+Need to drop lock before calling "mDNSCoreBeSleepProxyServer(m, mDNSfalse);"
+
+Revision 1.801  2008/10/02 22:51:04  cheshire
+<rdar://problem/6134215> Sleep Proxy: Mac with Internet Sharing should also offer Sleep Proxy service
+Added mDNSCoreBeSleepProxyServer() routine to start and stop Sleep Proxy Service
+
+Revision 1.800  2008/10/02 22:13:15  cheshire
+<rdar://problem/6230680> 100ms delay on shutdown
+Additional refinement: Also need to clear m->SuppressSending
+
+Revision 1.799  2008/09/29 20:12:37  cheshire
+Rename 'AnswerLocalQuestions' to more descriptive 'AnswerLocalOnlyQuestions' and 'AnsweredLocalQ' to 'AnsweredLOQ'
+
+Revision 1.798  2008/09/26 19:53:14  cheshire
+Fixed locking error: should not call mDNS_Deregister_internal within "mDNS_DropLock" section
+
+Revision 1.797  2008/09/25 20:40:59  cheshire
+<rdar://problem/6245044> Stop using separate m->ServiceRegistrations list
+In mDNS_SetFQDN, need to update all AutoTarget SRV records, even if m->MulticastHostname hasn't changed
+
+Revision 1.796  2008/09/25 20:17:10  cheshire
+<rdar://problem/6245044> Stop using separate m->ServiceRegistrations list
+Added defensive code to make sure *all* records of a ServiceRecordSet have
+completed deregistering before we pass on the mStatus_MemFree message
+
+Revision 1.795  2008/09/25 00:30:11  cheshire
+<rdar://problem/6245044> Stop using separate m->ServiceRegistrations list
+
+Revision 1.794  2008/09/24 23:48:05  cheshire
+Don't need to pass whole ServiceRecordSet reference to GetServiceTarget;
+it only needs to access the embedded SRV member of the set
+
+Revision 1.793  2008/09/23 04:11:53  cheshire
+<rdar://problem/6238774> Remove "local" from the end of _services._dns-sd._udp PTR records
+
+Revision 1.792  2008/09/23 02:30:07  cheshire
+Get rid of PutResourceRecordCappedTTL()
+
+Revision 1.791  2008/09/20 00:34:21  mcguire
 <rdar://problem/6129039> BTMM: Add support for WANPPPConnection
 
-Revision 1.777.4.4  2008/08/14 20:43:59  cheshire
-<rdar://problem/6143846> Back to My Mac not working with Time Capsule shared volume
+Revision 1.790  2008/09/18 22:46:34  cheshire
+<rdar://problem/6230680> 100ms delay on shutdown
+
+Revision 1.789  2008/09/18 06:15:06  mkrochma
+<rdar://problem/6117156> Cleanup: mDNSResponder logging debugging information to console
+
+Revision 1.788  2008/09/16 21:11:41  cheshire
+<rdar://problem/6223969> mDNS: Duplicate TXT record queries being produced by iPhone Remote
+
+Revision 1.787  2008/09/05 22:53:24  cheshire
+Improve "How is rr->resrec.rroriginalttl <= SecsSinceRcvd" debugging message
+
+Revision 1.786  2008/09/05 22:23:28  cheshire
+Moved initialization of "question->LocalSocket" to more logical place
+
+Revision 1.785  2008/08/14 19:20:55  cheshire
+<rdar://problem/6143846> Negative responses over TCP incorrectly rejected
 
-Revision 1.777.4.3  2008/07/29 20:46:05  mcguire
-<rdar://problem/6090007> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
-merge r1.782 & r1.783 from <rdar://problem/3988320>
+Revision 1.784  2008/08/13 00:47:53  mcguire
+Handle failures when packet logging
 
-Revision 1.777.4.2  2008/07/29 20:13:52  mcguire
-<rdar://problem/6090024> BTMM: alternate SSDP queries between multicast & unicast
-merged r1.781 for <rdar://problem/5736845>
+Revision 1.783  2008/07/25 07:09:51  mcguire
+<rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
 
-Revision 1.777.4.1  2008/07/29 19:17:55  mcguire
-<rdar://problem/6090046> Only trigger reconfirm on hostname if both A and AAAA query fail to elicit a response
-merge r1.779, r.1780 from <rdar://problem/6041178>
+Revision 1.782  2008/07/24 20:23:03  cheshire
+<rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+
+Revision 1.781  2008/07/18 21:37:35  mcguire
+<rdar://problem/5736845> BTMM: alternate SSDP queries between multicast & unicast
+
+Revision 1.780  2008/07/18 02:24:36  cheshire
+<rdar://problem/6041178> Only trigger reconfirm on hostname if both A and AAAA query fail to elicit a response
+Additional fix: Don't want to do the ReconfirmAntecedents() stuff if q->RequestUnicast is set (that indicates
+we're still on our first or second query after an interface registration or wake from sleep).
+
+Revision 1.779  2008/07/18 01:05:23  cheshire
+<rdar://problem/6041178> Only trigger reconfirm on hostname if both A and AAAA query fail to elicit a response
+
+Revision 1.778  2008/06/26 17:24:11  mkrochma
+<rdar://problem/5450912> BTMM: Stop listening on UDP 5351 for NAT Status Announcements
 
 Revision 1.777  2008/06/19 01:20:48  mcguire
 <rdar://problem/4206534> Use all configured DNS servers
@@ -352,7 +961,7 @@ Revision 1.691  2007/09/05 22:25:01  vazquez
 
 Revision 1.690  2007/09/05 21:48:01  cheshire
 <rdar://problem/5385864> BTMM: mDNSResponder flushes wide-area Bonjour records after an hour for a zone.
-Now that we're respecting the TTL of uDNS records in the cache, the LLQ maintenance cod needs
+Now that we're respecting the TTL of uDNS records in the cache, the LLQ maintenance code needs
 to update the cache lifetimes of all relevant records every time it successfully renews an LLQ,
 otherwise those records will expire and vanish from the cache.
 
@@ -635,7 +1244,7 @@ Revision 1.609  2007/04/20 21:17:24  cheshire
 For naming consistency, kDNSRecordTypeNegative should be kDNSRecordTypePacketNegative
 
 Revision 1.608  2007/04/20 19:45:31  cheshire
-In LogAllOperations mode, dump out unknown DNS packets in their entirety
+In LogClientOperations mode, dump out unknown DNS packets in their entirety
 
 Revision 1.607  2007/04/19 23:56:25  cheshire
 Don't do cache-flush processing for LLQ answers
@@ -898,6 +1507,10 @@ Fixes to avoid code generation warning/error on FreeBSD 7
        #pragma warning(disable:4706)
 #endif
 
+// Forward declarations
+mDNSlocal void BeginSleepProcessing(mDNS *const m);
+mDNSlocal void RetrySPSRegistrations(mDNS *const m);
+
 // ***************************************************************************
 #if COMPILER_LIKES_PRAGMA_MARK
 #pragma mark - Program Constants
@@ -1000,26 +1613,43 @@ mDNSlocal mDNSBool AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID Int
        return(mDNSfalse);
        }
 
+mDNSlocal NetworkInterfaceInfo *FirstInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
+       {
+       NetworkInterfaceInfo *intf = m->HostInterfaces;
+       while (intf && intf->InterfaceID != InterfaceID) intf = intf->next;
+       return(intf);
+       }
+
+mDNSlocal char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
+       {
+       NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
+       return(intf ? intf->ifname : "<NULL InterfaceID>");
+       }
+
 // For a single given DNSQuestion, deliver an add/remove result for the single given AuthRecord
-// Used by AnswerLocalQuestions() and AnswerNewLocalOnlyQuestion()
-mDNSlocal void AnswerLocalOnlyQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, QC_result AddRecord)
+// Used by AnswerAllLocalQuestionsWithLocalAuthRecord() and AnswerNewLocalOnlyQuestion()
+mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, QC_result AddRecord)
        {
        // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
        if (AddRecord) rr->AnsweredLocalQ = mDNStrue;
        mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
        if (q->QuestionCallback && !q->NoAnswer)
+               {
+               q->CurrentAnswers += AddRecord ? 1 : -1;
                q->QuestionCallback(m, q, &rr->resrec, AddRecord);
+               }
        mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
        }
 
-// When a new local AuthRecord is created or deleted, AnswerLocalQuestions() runs though our LocalOnlyQuestions delivering answers
-// to each, stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion().
+// When a new local AuthRecord is created or deleted, AnswerAllLocalQuestionsWithLocalAuthRecord() runs though
+// all our local questions (both LocalOnlyQuestions and mDNSInterface_Any questions) delivering answers to each,
+// stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion().
 // If the AuthRecord is marked mDNSInterface_LocalOnly, then we also deliver it to any other questions we have using mDNSInterface_Any.
 // Used by AnswerForNewLocalRecords() and mDNS_Deregister_internal()
-mDNSlocal void AnswerLocalQuestions(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
+mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
        {
        if (m->CurrentQuestion)
-               LogMsg("AnswerLocalQuestions ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+               LogMsg("AnswerAllLocalQuestionsWithLocalAuthRecord ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
 
        m->CurrentQuestion = m->LocalOnlyQuestions;
        while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions)
@@ -1027,7 +1657,7 @@ mDNSlocal void AnswerLocalQuestions(mDNS *const m, AuthRecord *rr, QC_result Add
                DNSQuestion *q = m->CurrentQuestion;
                m->CurrentQuestion = q->next;
                if (ResourceRecordAnswersQuestion(&rr->resrec, q))
-                       AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, AddRecord);                 // MUST NOT dereference q again
+                       AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, AddRecord);                    // MUST NOT dereference q again
                }
 
        // If this AuthRecord is marked LocalOnly, then we want to deliver it to all local 'mDNSInterface_Any' questions
@@ -1039,7 +1669,7 @@ mDNSlocal void AnswerLocalQuestions(mDNS *const m, AuthRecord *rr, QC_result Add
                        DNSQuestion *q = m->CurrentQuestion;
                        m->CurrentQuestion = q->next;
                        if (ResourceRecordAnswersQuestion(&rr->resrec, q))
-                               AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, AddRecord);         // MUST NOT dereference q again
+                               AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, AddRecord);            // MUST NOT dereference q again
                        }
                }
 
@@ -1094,7 +1724,11 @@ mDNSlocal void AnswerLocalQuestions(mDNS *const m, AuthRecord *rr, QC_result Add
 // When sending a unique record, all other records matching "SameResourceRecordSignature" must also be sent
 // When receiving a unique record, all old cache records matching "SameResourceRecordSignature" are flushed
 
-mDNSlocal mDNSBool SameResourceRecordSignature(const AuthRecord *const r1, const AuthRecord *const r2)
+// SameResourceRecordNameClassInterface is functionally the same as SameResourceRecordSignature, except rrtype does not have to match
+
+#define SameResourceRecordSignature(A,B) (A)->resrec.rrtype == (B)->resrec.rrtype && SameResourceRecordNameClassInterface((A),(B))
+
+mDNSlocal mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *const r1, const AuthRecord *const r2)
        {
        if (!r1) { LogMsg("SameResourceRecordSignature ERROR: r1 is NULL"); return(mDNSfalse); }
        if (!r2) { LogMsg("SameResourceRecordSignature ERROR: r2 is NULL"); return(mDNSfalse); }
@@ -1102,7 +1736,6 @@ mDNSlocal mDNSBool SameResourceRecordSignature(const AuthRecord *const r1, const
                r2->resrec.InterfaceID &&
                r1->resrec.InterfaceID != r2->resrec.InterfaceID) return(mDNSfalse);
        return(mDNSBool)(
-               r1->resrec.rrtype   == r2->resrec.rrtype &&
                r1->resrec.rrclass  == r2->resrec.rrclass &&
                r1->resrec.namehash == r2->resrec.namehash &&
                SameDomainName(r1->resrec.name, r2->resrec.name));
@@ -1113,6 +1746,9 @@ mDNSlocal mDNSBool SameResourceRecordSignature(const AuthRecord *const r1, const
 // complete ownership of *all* types for this name, so *any* record type with the same name is a conflict.
 // In addition, when probing we send our questions with the wildcard type kDNSQType_ANY,
 // so a response of any type should match, even if it is not actually the type the client plans to use.
+
+// For now, to make it easier to avoid false conflicts, we treat SPS Proxy records like shared records,
+// and require the rrtypes to match for the rdata to be considered potentially conflicting
 mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, const AuthRecord *const authrr)
        {
        if (!pktrr)  { LogMsg("PacketRRMatchesSignature ERROR: pktrr is NULL"); return(mDNSfalse); }
@@ -1120,7 +1756,8 @@ mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, cons
        if (pktrr->resrec.InterfaceID &&
                authrr->resrec.InterfaceID &&
                pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse);
-       if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) && pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
+       if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0])
+               if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
        return(mDNSBool)(
                pktrr->resrec.rrclass == authrr->resrec.rrclass &&
                pktrr->resrec.namehash == authrr->resrec.namehash &&
@@ -1155,8 +1792,7 @@ mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const r
        {
        if (rr->resrec.RecordType == kDNSRecordTypeUnique)
                {
-               //LogMsg("ProbeCount %d Next %ld %s",
-               //      rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr));
+               //LogMsg("ProbeCount %d Next %ld %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr));
                if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
                        m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval);
                }
@@ -1167,9 +1803,10 @@ mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const r
                }
        }
 
-mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr, mDNSs32 interval)
+mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
        {
-       rr->ThisAPInterval = interval;
+       // For reverse-mapping Sleep Proxy PTR records, probe interval is one second
+       rr->ThisAPInterval = rr->AddressProxy.type ? mDNSPlatformOneSecond : DefaultAPIntervalForRecordType(rr->resrec.RecordType);
 
        // To allow us to aggregate probes when a group of services are registered together,
        // the first probe is delayed 1/4 second. This means the common-case behaviour is:
@@ -1193,7 +1830,7 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr, mDNSs32
                        }
                }
 
-       rr->LastAPTime      = m->SuppressProbes - interval;
+       rr->LastAPTime      = m->SuppressProbes - rr->ThisAPInterval;
        // Set LastMCTime to now, to inhibit multicast responses
        // (no need to send additional multicast responses when we're announcing anyway)
        rr->LastMCTime      = m->timenow;
@@ -1206,12 +1843,25 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr, mDNSs32
        // delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete.
        // When the probing is complete and those records begin to announce, these records will also be picked up and accelerated,
        // because they will meet the criterion of being at least half-way to their scheduled announcement time.
+       if (rr->resrec.RecordType != kDNSRecordTypeUnique)
+               rr->LastAPTime += DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
+
        // The exception is unique records that have already been verified and are just being updated
        // via mDNS_Update() -- for these we want to announce the new value immediately, without delay.
        if (rr->resrec.RecordType == kDNSRecordTypeVerified)
-               rr->LastAPTime = m->timenow - interval;
-       else if (rr->resrec.RecordType != kDNSRecordTypeUnique)
-               rr->LastAPTime += DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + interval / 2;
+               rr->LastAPTime = m->timenow - rr->ThisAPInterval;
+
+       // For reverse-mapping Sleep Proxy PTR records we don't want to start probing instantly -- we
+       // wait one second to give the client a chance to go to sleep, and then start our ARP/NDP probing.
+       // After three probes one second apart with no answer, we conclude the client is now sleeping
+       // and we can begin broadcasting our announcements to take over ownership of that IP address.
+       // If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk
+       // (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address.
+       if (rr->AddressProxy.type) rr->LastAPTime = m->timenow;
+
+       // For now, since we don't yet handle IPv6 ND or data packets, we send deletions for our SPS clients' AAAA records
+       if (rr->WakeUp.HMAC.l[0] && rr->resrec.rrtype == kDNSType_AAAA)
+               rr->LastAPTime = m->timenow - rr->ThisAPInterval + mDNSPlatformOneSecond * 10;
        
        SetNextAnnounceProbeTime(m, rr);
        }
@@ -1220,16 +1870,23 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr, mDNSs32
 // Eventually we should unify this with GetServiceTarget() in uDNS.c
 mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
        {
-       domainname *target = GetRRDomainNameTarget(&rr->resrec);
+       domainname *const target = GetRRDomainNameTarget(&rr->resrec);
+       const domainname *newname = &m->MulticastHostname;
 
        if (!target) debugf("SetTargetToHostName: Don't know how to set the target of rrtype %d", rr->resrec.rrtype);
 
-       if (target && SameDomainName(target, &m->MulticastHostname))
+       if (!(rr->ForceMCast || rr->resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&rr->namestorage)))
+               {
+               const domainname *const n = GetServiceTarget(m, rr);
+               if (n) newname = n;
+               }
+
+       if (target && SameDomainName(target, newname))
                debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name->c, target->c);
        
-       if (target && !SameDomainName(target, &m->MulticastHostname))
+       if (target && !SameDomainName(target, newname))
                {
-               AssignDomainName(target, &m->MulticastHostname);
+               AssignDomainName(target, newname);
                SetNewRData(&rr->resrec, mDNSNULL, 0);          // Update rdlength, rdestimate, rdatahash
                
                // If we're in the middle of probing this record, we need to start again,
@@ -1246,7 +1903,7 @@ mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
 
                rr->AnnounceCount  = InitialAnnounceCount;
                rr->RequireGoodbye = mDNSfalse;
-               InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
+               InitializeLastAPTime(m, rr);
                }
        }
 
@@ -1293,6 +1950,22 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        if (!rr->resrec.RecordType)
                { LogMsg("mDNS_Register_internal: RecordType must be non-zero %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
 
+       if (m->ShutdownTime)
+               { LogMsg("mDNS_Register_internal: Shutting down, can't register %s", ARDisplayString(m, rr)); return(mStatus_ServiceNotRunning); }
+       
+       if (m->DivertMulticastAdvertisements && !AuthRecord_uDNS(rr))
+               {
+               mDNSInterfaceID previousID = rr->resrec.InterfaceID;
+               if (rr->resrec.InterfaceID == mDNSInterface_Any) rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
+               if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
+                       {
+                       NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
+                       if (intf && !intf->Advertise) rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
+                       }
+               if (rr->resrec.InterfaceID != previousID)
+                       LogInfo("mDNS_Register_internal: Diverting record to local-only %s", ARDisplayString(m, rr));
+               }
+
        while (*p && *p != rr) p=&(*p)->next;
        while (*d && *d != rr) d=&(*d)->next;
        if (*d || *p)
@@ -1323,9 +1996,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        // If this resource record is referencing a specific interface, make sure it exists
        if (rr->resrec.InterfaceID && rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
                {
-               NetworkInterfaceInfo *intf;
-               for (intf = m->HostInterfaces; intf; intf = intf->next)
-                       if (intf->InterfaceID == rr->resrec.InterfaceID) break;
+               NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
                if (!intf)
                        {
                        debugf("mDNS_Register_internal: Bogus InterfaceID %p in resource record", rr->resrec.InterfaceID);
@@ -1358,8 +2029,9 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        rr->RequireGoodbye    = mDNSfalse;
        rr->AnsweredLocalQ    = mDNSfalse;
        rr->IncludeInProbe    = mDNSfalse;
-       rr->ImmedAnswer       = mDNSNULL;
        rr->ImmedUnicast      = mDNSfalse;
+       rr->SendNSECNow       = mDNSNULL;
+       rr->ImmedAnswer       = mDNSNULL;
        rr->ImmedAdditional   = mDNSNULL;
        rr->SendRNow          = mDNSNULL;
        rr->v4Requester       = zerov4Addr;
@@ -1367,7 +2039,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        rr->NextResponse      = mDNSNULL;
        rr->NR_AnswerTo       = mDNSNULL;
        rr->NR_AdditionalTo   = mDNSNULL;
-       if (!rr->AutoTarget) InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
+       if (!rr->AutoTarget) InitializeLastAPTime(m, rr);
 //     rr->LastAPTime        = Set for us in InitializeLastAPTime()
 //     rr->LastMCTime        = Set for us in InitializeLastAPTime()
 //     rr->LastMCInterface   = Set for us in InitializeLastAPTime()
@@ -1378,13 +2050,16 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        rr->NextUpdateCredit  = 0;
        rr->UpdateBlocked     = 0;
 
+       // For records we're holding as proxy (except reverse-mapping PTR records) two announcements is sufficient
+       if (rr->WakeUp.HMAC.l[0] && !rr->AddressProxy.type) rr->AnnounceCount = 2;
+
        // Field Group 4: Transient uDNS state for Authoritative Records
        rr->state             = regState_Zero;
        rr->uselease          = 0;
        rr->expire            = 0;
        rr->Private           = 0;
-       rr->id                = zeroID;
-       rr->zone.c[0]         = 0;
+       rr->updateid          = zeroID;
+       rr->zone              = rr->resrec.name;
        rr->UpdateServer      = zeroAddr;
        rr->UpdatePort        = zeroIPPort;
        rr->nta               = mDNSNULL;
@@ -1397,7 +2072,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        rr->QueuedRDLen       = 0;
 
 //     rr->resrec.interface         = already set in mDNS_SetupResourceRecord
-//     rr->resrec.name->c            = MUST be set by client
+//     rr->resrec.name->c           = MUST be set by client
 //     rr->resrec.rrtype            = already set in mDNS_SetupResourceRecord
 //     rr->resrec.rrclass           = already set in mDNS_SetupResourceRecord
 //     rr->resrec.rroriginalttl     = already set in mDNS_SetupResourceRecord
@@ -1435,7 +2110,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
                        for (r = m->ResourceRecords; r; r=r->next)
                                {
                                const AuthRecord *s2 = r->RRSet ? r->RRSet : r;
-                               if (s1 != s2 && SameResourceRecordSignature(r, rr) && !SameRData(&r->resrec, &rr->resrec))
+                               if (s1 != s2 && SameResourceRecordSignature(r, rr) && !IdenticalSameNameRecord(&r->resrec, &rr->resrec))
                                        break;
                                }
                        if (r)  // If we found a conflict, set RecordType = kDNSRecordTypeDeregistering so we'll deliver the callback
@@ -1515,7 +2190,7 @@ mDNSlocal void CompleteRDataUpdate(mDNS *const m, AuthRecord *const rr)
                rr->UpdateCallback(m, rr, OldRData);                                    // ... and let the client know
        }
 
-// NOTE: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list.
+// Note: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
 // Exported so uDNS.c can call this
 mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt)
@@ -1553,6 +2228,7 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
                                dup->ProbeCount      = rr->ProbeCount;
                                dup->AnnounceCount   = rr->AnnounceCount;
                                dup->RequireGoodbye  = rr->RequireGoodbye;
+                               dup->AnsweredLocalQ  = rr->AnsweredLocalQ;
                                dup->ImmedAnswer     = rr->ImmedAnswer;
                                dup->ImmedUnicast    = rr->ImmedUnicast;
                                dup->ImmedAdditional = rr->ImmedAdditional;
@@ -1562,7 +2238,12 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
                                dup->LastAPTime      = rr->LastAPTime;
                                dup->LastMCTime      = rr->LastMCTime;
                                dup->LastMCInterface = rr->LastMCInterface;
+                               dup->UpdateServer    = rr->UpdateServer;
+                               dup->UpdatePort      = rr->UpdatePort;
+                               dup->Private         = rr->Private;
+                               dup->state           = rr->state;
                                rr->RequireGoodbye = mDNSfalse;
+                               rr->AnsweredLocalQ = mDNSfalse;
                                }
                        }
                }
@@ -1581,17 +2262,16 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
                {
                // No need to log an error message if we already know this is a potentially repeated deregistration
                if (drt != mDNS_Dereg_repeat)
-                       LogMsg("mDNS_Deregister_internal: Record %p %##s (%s) not found in list",
-                               rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+                       LogMsg("mDNS_Deregister_internal: Record %p not found in list %s", rr, ARDisplayString(m,rr));
                return(mStatus_BadReferenceErr);
                }
 
        // If this is a shared record and we've announced it at least once,
        // we need to retract that announcement before we delete the record
 
-       // If this is a record (including mDNSInterface_LocalOnly records) for which we've given local answers then
-       // it's tempting to just do "AnswerLocalQuestions(m, rr, mDNSfalse)" here, but that would not not be safe.
-       // The AnswerLocalQuestions routine walks the question list invoking client callbacks, using the "m->CurrentQuestion"
+       // If this is a record (including mDNSInterface_LocalOnly records) for which we've given local-only answers then
+       // it's tempting to just do "AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse)" here, but that would not not be safe.
+       // The AnswerAllLocalQuestionsWithLocalAuthRecord routine walks the question list invoking client callbacks, using the "m->CurrentQuestion"
        // mechanism to cope with the client callback modifying the question list while that's happening.
        // However, mDNS_Deregister could have been called from a client callback (e.g. from the domain enumeration callback FoundDomain)
        // which means that the "m->CurrentQuestion" mechanism is already in use to protect that list, so we can't use it twice.
@@ -1612,7 +2292,7 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
                // process and will complete asynchronously. Either way we don't need to do anything more here.
                return(mStatus_NoError);
                }
-#endif UNICAST_DISABLED
+#endif // UNICAST_DISABLED
 
        if (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->AnsweredLocalQ))
                {
@@ -1655,17 +2335,20 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
                // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
                // In this case the likely client action to the mStatus_MemFree message is to free the memory,
                // so any attempt to touch rr after this is likely to lead to a crash.
-               mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
                if (drt != mDNS_Dereg_conflict)
                        {
+                       mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
                        if (rr->RecordCallback)
                                rr->RecordCallback(m, rr, mStatus_MemFree);                     // MUST NOT touch rr after this
+                       mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
                        }
                else
                        {
                        RecordProbeFailure(m, rr);
+                       mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
                        if (rr->RecordCallback)
                                rr->RecordCallback(m, rr, mStatus_NameConflict);        // MUST NOT touch rr after this
+                       mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
                        // Now that we've finished deregistering rr, check our DuplicateRecords list for any that we marked previously.
                        // Note that with all the client callbacks going on, by the time we get here all the
                        // records we marked may have been explicitly deregistered by the client anyway.
@@ -1676,7 +2359,6 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
                                else { mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict); r2 = m->DuplicateRecords; }
                                }
                        }
-               mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
                }
        return(mStatus_NoError);
        }
@@ -1824,11 +2506,11 @@ mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr)
        // it should go ahead and immediately dispose of this registration
        rr->resrec.RecordType = kDNSRecordTypeShared;
        rr->RequireGoodbye    = mDNSfalse;
-       if (rr->AnsweredLocalQ) { AnswerLocalQuestions(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; }
+       if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; }
        mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);             // Don't touch rr after this
        }
 
-// NOTE: DiscardDeregistrations calls mDNS_Deregister_internal which can call a user callback, which may change
+// Note: DiscardDeregistrations calls mDNS_Deregister_internal which can call a user callback, which may change
 // the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
 mDNSlocal void DiscardDeregistrations(mDNS *const m)
@@ -1847,39 +2529,163 @@ mDNSlocal void DiscardDeregistrations(mDNS *const m)
                }
        }
 
-mDNSlocal void GrantUpdateCredit(AuthRecord *rr)
+mDNSlocal mStatus GetLabelDecimalValue(const mDNSu8 *const src, mDNSu8 *dst)
        {
-       if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0;
-       else rr->NextUpdateCredit = NonZeroTime(rr->NextUpdateCredit + kUpdateCreditRefreshInterval);
+       int i, val = 0;
+       if (src[0] < 1 || src[0] > 3) return(mStatus_Invalid);
+       for (i=1; i<=src[0]; i++)
+               {
+               if (src[i] < '0' || src[i] > '9') return(mStatus_Invalid);
+               val = val * 10 + src[i] - '0';
+               }
+       if (val > 255) return(mStatus_Invalid);
+       *dst = val;
+       return(mStatus_NoError);
        }
 
-// Note about acceleration of announcements to facilitate automatic coalescing of
-// multiple independent threads of announcements into a single synchronized thread:
-// The announcements in the packet may be at different stages of maturity;
-// One-second interval, two-second interval, four-second interval, and so on.
-// After we've put in all the announcements that are due, we then consider
-// whether there are other nearly-due announcements that are worth accelerating.
-// To be eligible for acceleration, a record MUST NOT be older (further along
-// its timeline) than the most mature record we've already put in the packet.
-// In other words, younger records can have their timelines accelerated to catch up
-// with their elder bretheren; this narrows the age gap and helps them eventually get in sync.
-// Older records cannot have their timelines accelerated; this would just widen
-// the gap between them and their younger bretheren and get them even more out of sync.
+mDNSlocal mStatus GetIPv4FromName(mDNSAddr *const a, const domainname *const name)
+       {
+       int skip = CountLabels(name) - 6;
+       if (skip < 0) { LogMsg("GetIPFromName: Need six labels in IPv4 reverse mapping name %##s", name); return mStatus_Invalid; }
+       if (GetLabelDecimalValue(SkipLeadingLabels(name, skip+3)->c, &a->ip.v4.b[0]) ||
+               GetLabelDecimalValue(SkipLeadingLabels(name, skip+2)->c, &a->ip.v4.b[1]) ||
+               GetLabelDecimalValue(SkipLeadingLabels(name, skip+1)->c, &a->ip.v4.b[2]) ||
+               GetLabelDecimalValue(SkipLeadingLabels(name, skip+0)->c, &a->ip.v4.b[3])) return mStatus_Invalid;
+       a->type = mDNSAddrType_IPv4;
+       return(mStatus_NoError);
+       }
 
-// NOTE: SendResponses calls mDNS_Deregister_internal which can call a user callback, which may change
-// the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSlocal void SendResponses(mDNS *const m)
+#define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0'     ) :   \
+                                       ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) :   \
+                                       ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : -1)
+
+mDNSlocal mStatus GetIPv6FromName(mDNSAddr *const a, const domainname *const name)
        {
-       int pktcount = 0;
-       AuthRecord *rr, *r2;
-       mDNSs32 maxExistingAnnounceInterval = 0;
-       const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
+       int i, h, l;
+       const domainname *n;
 
-       m->NextScheduledResponse = m->timenow + 0x78000000;
+       int skip = CountLabels(name) - 34;
+       if (skip < 0) { LogMsg("GetIPFromName: Need 34 labels in IPv6 reverse mapping name %##s", name); return mStatus_Invalid; }
 
-       for (rr = m->ResourceRecords; rr; rr=rr->next)
-               if (rr->ImmedUnicast)
+       n = SkipLeadingLabels(name, skip);
+       for (i=0; i<16; i++)
+               {
+               if (n->c[0] != 1) return mStatus_Invalid;
+               l = HexVal(n->c[1]);
+               n = (const domainname *)(n->c + 2);
+
+               if (n->c[0] != 1) return mStatus_Invalid;
+               h = HexVal(n->c[1]);
+               n = (const domainname *)(n->c + 2);
+
+               if (l<0 || h<0) return mStatus_Invalid;
+               a->ip.v6.b[15-i] = (h << 4) | l;
+               }
+
+       a->type = mDNSAddrType_IPv6;
+       return(mStatus_NoError);
+       }
+
+mDNSlocal mDNSs32 ReverseMapDomainType(const domainname *const name)
+       {
+       int skip = CountLabels(name) - 2;
+       if (skip >= 0)
+               {
+               const domainname *suffix = SkipLeadingLabels(name, skip);
+               if (SameDomainName(suffix, (const domainname*)"\x7" "in-addr" "\x4" "arpa")) return mDNSAddrType_IPv4;
+               if (SameDomainName(suffix, (const domainname*)"\x3" "ip6"     "\x4" "arpa")) return mDNSAddrType_IPv6;
+               }
+       return(mDNSAddrType_None);
+       }
+
+mDNSlocal void SendARP(mDNS *const m, const mDNSu8 op, const AuthRecord *const rr,
+       const mDNSu8 *const spa, const mDNSu8 *const tha, const mDNSu8 *const tpa, const mDNSu8 *const dst)
+       {
+       int i;
+       mDNSu8 *ptr = m->omsg.data;
+       NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
+       if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; }
+
+       // 0x00 Destination address
+       for (i=0; i<6; i++) *ptr++ = dst[i];
+
+       // 0x06 Source address (we just use zero -- driver/hardware will fill in real interface address)
+       for (i=0; i<6; i++) *ptr++ = 0x0;
+
+       // 0x0C ARP Ethertype (0x0806)
+       *ptr++ = 0x08; *ptr++ = 0x06;
+
+       // 0x0E ARP header
+       *ptr++ = 0x00; *ptr++ = 0x01;   // Hardware address space; Ethernet = 1
+       *ptr++ = 0x08; *ptr++ = 0x00;   // Protocol address space; IP = 0x0800
+       *ptr++ = 6;                                             // Hardware address length
+       *ptr++ = 4;                                             // Protocol address length
+       *ptr++ = 0x00; *ptr++ = op;             // opcode; Request = 1, Response = 2
+
+       // 0x16 Sender hardware address (our MAC address)
+       for (i=0; i<6; i++) *ptr++ = intf->MAC.b[i];
+
+       // 0x1C Sender protocol address
+       for (i=0; i<4; i++) *ptr++ = spa[i];
+
+       // 0x20 Target hardware address
+       for (i=0; i<6; i++) *ptr++ = tha[i];
+
+       // 0x26 Target protocol address
+       for (i=0; i<4; i++) *ptr++ = tpa[i];
+
+       // 0x2A Total ARP Packet length 42 bytes
+       mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID);
+       }
+
+mDNSlocal void SetupOwnerOpt(const mDNS *const m, const NetworkInterfaceInfo *const intf, rdataOPT *const owner)
+       {
+       owner->u.owner.vers     = 0;
+       owner->u.owner.seq      = m->SleepSeqNum;
+       owner->u.owner.HMAC     = m->PrimaryMAC;
+       owner->u.owner.IMAC     = intf->MAC;
+       owner->u.owner.password = zeroEthAddr;
+
+       // Don't try to compute the optlen until *after* we've set up the data fields
+       owner->opt              = kDNSOpt_Owner;
+       owner->optlen           = DNSOpt_Owner_Space(owner) - 4;
+       }
+
+mDNSlocal void GrantUpdateCredit(AuthRecord *rr)
+       {
+       if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0;
+       else rr->NextUpdateCredit = NonZeroTime(rr->NextUpdateCredit + kUpdateCreditRefreshInterval);
+       }
+
+// Note about acceleration of announcements to facilitate automatic coalescing of
+// multiple independent threads of announcements into a single synchronized thread:
+// The announcements in the packet may be at different stages of maturity;
+// One-second interval, two-second interval, four-second interval, and so on.
+// After we've put in all the announcements that are due, we then consider
+// whether there are other nearly-due announcements that are worth accelerating.
+// To be eligible for acceleration, a record MUST NOT be older (further along
+// its timeline) than the most mature record we've already put in the packet.
+// In other words, younger records can have their timelines accelerated to catch up
+// with their elder bretheren; this narrows the age gap and helps them eventually get in sync.
+// Older records cannot have their timelines accelerated; this would just widen
+// the gap between them and their younger bretheren and get them even more out of sync.
+
+// Note: SendResponses calls mDNS_Deregister_internal which can call a user callback, which may change
+// the record list and/or question list.
+// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
+mDNSlocal void SendResponses(mDNS *const m)
+       {
+       int pktcount = 0;
+       AuthRecord *rr, *r2;
+       mDNSs32 maxExistingAnnounceInterval = 0;
+       const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
+
+       m->NextScheduledResponse = m->timenow + 0x78000000;
+
+       if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m);
+
+       for (rr = m->ResourceRecords; rr; rr=rr->next)
+               if (rr->ImmedUnicast)
                        {
                        mDNSAddr v4 = { mDNSAddrType_IPv4, {{{0}}} };
                        mDNSAddr v6 = { mDNSAddrType_IPv6, {{{0}}} };
@@ -1904,10 +2710,29 @@ mDNSlocal void SendResponses(mDNS *const m)
                while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
                if (TimeToAnnounceThisRecord(rr, m->timenow) && ResourceRecordIsValidAnswer(rr))
                        {
-                       rr->ImmedAnswer = mDNSInterfaceMark;            // Send on all interfaces
-                       if (maxExistingAnnounceInterval < rr->ThisAPInterval)
-                               maxExistingAnnounceInterval = rr->ThisAPInterval;
-                       if (rr->UpdateBlocked) rr->UpdateBlocked = 0;
+                       if (rr->AddressProxy.type)
+                               {
+                               rr->AnnounceCount--;
+                               rr->ThisAPInterval *= 2;
+                               rr->LastAPTime = m->timenow;
+                               if (rr->AddressProxy.type == mDNSAddrType_IPv4)
+                                       {
+                                       LogSPS("ARP Announcement %d Capturing traffic for H-MAC %.6a I-MAC %.6a %s", rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
+                                       SendARP(m, 1, rr, rr->AddressProxy.ip.v4.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, onesEthAddr.b);
+                                       }
+                               else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
+                                       {
+                                       //LogSPS("NDP Announcement %d %s", rr->AnnounceCount, ARDisplayString(m,rr));
+                                       //SendARP(m, 1, rr, rr->AddressProxy.ip.v4.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, onesEthAddr.b);
+                                       }
+                               }
+                       else
+                               {
+                               rr->ImmedAnswer = mDNSInterfaceMark;            // Send on all interfaces
+                               if (maxExistingAnnounceInterval < rr->ThisAPInterval)
+                                       maxExistingAnnounceInterval = rr->ThisAPInterval;
+                               if (rr->UpdateBlocked) rr->UpdateBlocked = 0;
+                               }
                        }
                }
 
@@ -1917,11 +2742,12 @@ mDNSlocal void SendResponses(mDNS *const m)
                if ((rr->resrec.InterfaceID && rr->ImmedAnswer) ||
                        (rr->ThisAPInterval <= maxExistingAnnounceInterval &&
                        TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2) &&
+                       !rr->AddressProxy.type &&                                       // Don't include ARP Annoucements when considering which records to accelerate
                        ResourceRecordIsValidAnswer(rr)))
                        rr->ImmedAnswer = mDNSInterfaceMark;            // Send on all interfaces
 
        // When sending SRV records (particularly when announcing a new service) automatically add related Address record(s) as additionals
-       // NOTE: Currently all address records are interface-specific, so it's safe to set ImmedAdditional to their InterfaceID,
+       // Note: Currently all address records are interface-specific, so it's safe to set ImmedAdditional to their InterfaceID,
        // which will be non-null. If by some chance there is an address record that's not interface-specific (should never happen)
        // then all that means is that it won't get sent -- which would not be the end of the world.
        for (rr = m->ResourceRecords; rr; rr=rr->next)
@@ -1961,7 +2787,7 @@ mDNSlocal void SendResponses(mDNS *const m)
                                        if (ResourceRecordIsValidAnswer(r2))
                                                if (r2->ImmedAnswer != mDNSInterfaceMark &&
                                                        r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(r2, rr))
-                                                       r2->ImmedAnswer = rr->ImmedAnswer;
+                                                       r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark;
                                }
                        else if (rr->ImmedAdditional)   // If we're sending this as additional, see that its whole RRSet is similarly marked
                                {
@@ -2018,18 +2844,15 @@ mDNSlocal void SendResponses(mDNS *const m)
                // 1. Deregistering records that need to send their goodbye packet
                // 2. Updated records that need to retract their old data
                // 3. Answers and announcements we need to send
-               // In all cases, if we fail, and we've put at least one answer, we break out of the for loop so we can
-               // send this packet and then try again.
-               // If we have not put even one answer, then we don't bail out. We pretend we succeeded anyway,
-               // because otherwise we'll end up in an infinite loop trying to send a record that will never fit.
                for (rr = m->ResourceRecords; rr; rr=rr->next)
+                       {
                        if (rr->SendRNow == intf->InterfaceID)
                                {
+                               newptr = mDNSNULL;
                                if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
                                        {
                                        newptr = PutResourceRecordTTL(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
                                        if (newptr) { responseptr = newptr; numDereg++; }
-                                       else if (m->omsg.h.numAnswers) break;
                                        }
                                else if (rr->NewRData && !m->SleepState)                                        // If we have new data for this record
                                        {
@@ -2040,7 +2863,6 @@ mDNSlocal void SendResponses(mDNS *const m)
                                                {
                                                newptr = PutResourceRecordTTL(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
                                                if (newptr) { responseptr = newptr; numDereg++; rr->RequireGoodbye = mDNSfalse; }
-                                               else if (m->omsg.h.numAnswers) break;
                                                }
                                        // Now try to see if we can fit the update in the same packet (not fatal if we can't)
                                        SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);
@@ -2053,24 +2875,33 @@ mDNSlocal void SendResponses(mDNS *const m)
                                        }
                                else
                                        {
+                                       mDNSu8 active = (m->SleepState != SleepState_Sleeping || intf->SPSAddr[0].type || intf->SPSAddr[1].type || intf->SPSAddr[2].type);
                                        if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
                                                rr->resrec.rrclass |= kDNSClass_UniqueRRSet;            // Temporarily set the cache flush bit so PutResourceRecord will set it
-                                       newptr = PutResourceRecordTTL(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, m->SleepState ? 0 : rr->resrec.rroriginalttl);
+                                       newptr = PutResourceRecordTTL(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, active ? rr->resrec.rroriginalttl : 0);
                                        rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;                   // Make sure to clear cache flush bit back to normal state
                                        if (newptr)
                                                {
                                                responseptr = newptr;
-                                               rr->RequireGoodbye = (mDNSu8) (!m->SleepState);
+                                               rr->RequireGoodbye = active;
                                                if (rr->LastAPTime == m->timenow) numAnnounce++; else numAnswer++;
                                                }
-                                       else if (m->omsg.h.numAnswers) break;
+
+                                       // The first time through (pktcount==0), if this record is verified unique
+                                       // (i.e. typically A, AAAA, SRV and TXT), set the flag to add an NSEC too.
+                                       if (!pktcount && active && rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->SendNSECNow) rr->SendNSECNow = (mDNSInterfaceID)1;
+                                       }
+
+                               if (newptr)             // If succeeded in sending, advance to next interface
+                                       {
+                                       // If sending on all interfaces, go to next interface; else we're finished now
+                                       if (rr->ImmedAnswer == mDNSInterfaceMark && rr->resrec.InterfaceID == mDNSInterface_Any)
+                                               rr->SendRNow = GetNextActiveInterfaceID(intf);
+                                       else
+                                               rr->SendRNow = mDNSNULL;
                                        }
-                               // If sending on all interfaces, go to next interface; else we're finished now
-                               if (rr->ImmedAnswer == mDNSInterfaceMark && rr->resrec.InterfaceID == mDNSInterface_Any)
-                                       rr->SendRNow = GetNextActiveInterfaceID(intf);
-                               else
-                                       rr->SendRNow = mDNSNULL;
                                }
+                       }
        
                // Second Pass. Add additional records, if there's space.
                newptr = responseptr;
@@ -2096,6 +2927,10 @@ mDNSlocal void SendResponses(mDNS *const m)
                                                rr->ImmedAdditional = mDNSNULL;         // then cancel its ImmedAdditional field
                                        else if (newptr)                                                // Else, try to add it if we can
                                                {
+                                               // The first time through (pktcount==0), if this record is verified unique
+                                               // (i.e. typically A, AAAA, SRV and TXT), set the flag to add an NSEC too.
+                                               if (!pktcount && rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->SendNSECNow) rr->SendNSECNow = (mDNSInterfaceID)1;
+
                                                if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
                                                        rr->resrec.rrclass |= kDNSClass_UniqueRRSet;    // Temporarily set the cache flush bit so PutResourceRecord will set it
                                                newptr = PutResourceRecord(&m->omsg, newptr, &m->omsg.h.numAdditionals, &rr->resrec);
@@ -2114,13 +2949,48 @@ mDNSlocal void SendResponses(mDNS *const m)
                                                        }
                                                }
                                        }
-       
+
+               // Third Pass. Add NSEC records, if there's space.
+               for (rr = m->ResourceRecords; rr; rr=rr->next)
+                       if (rr->SendNSECNow == (mDNSInterfaceID)1 || rr->SendNSECNow == intf->InterfaceID)
+                               {
+                               AuthRecord nsec;
+                               mDNS_SetupResourceRecord(&nsec, mDNSNULL, mDNSInterface_Any, kDNSType_NSEC, rr->resrec.rroriginalttl, kDNSRecordTypeUnique, mDNSNULL, mDNSNULL);
+                               nsec.resrec.rrclass |= kDNSClass_UniqueRRSet;
+                               AssignDomainName(&nsec.namestorage, rr->resrec.name);
+                               mDNSPlatformMemZero(nsec.rdatastorage.u.nsec.bitmap, sizeof(nsec.rdatastorage.u.nsec.bitmap));
+                               for (r2 = m->ResourceRecords; r2; r2=r2->next)
+                                       if (ResourceRecordIsValidAnswer(r2) && SameResourceRecordNameClassInterface(r2, rr))
+                                               {
+                                               if (r2->resrec.rrtype >= kDNSQType_ANY) { LogMsg("Can't create NSEC for record %s", ARDisplayString(m, r2)); break; }
+                                               else nsec.rdatastorage.u.nsec.bitmap[r2->resrec.rrtype >> 3] |= 128 >> (r2->resrec.rrtype & 7);
+                                               }
+                               newptr = responseptr;
+                               if (!r2)        // If we successfully built our NSEC record, add it to the packet now
+                                       {
+                                       newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &nsec.resrec);
+                                       if (newptr) responseptr = newptr;
+                                       }
+
+                               // If we successfully put the NSEC record, clear the SendNSECNow flag
+                               // If we consider this NSEC optional, then we unconditionally clear the SendNSECNow flag, even if we fail to put this additional record
+                               if (newptr || rr->SendNSECNow == (mDNSInterfaceID)1)
+                                       {
+                                       rr->SendNSECNow = mDNSNULL;
+                                       // Run through remainder of list clearing SendNSECNow flag for all other records which would generate the same NSEC
+                                       for (r2 = rr->next; r2; r2=r2->next)
+                                               if (SameResourceRecordNameClassInterface(r2, rr))
+                                                       if (r2->SendNSECNow == (mDNSInterfaceID)1 || r2->SendNSECNow == intf->InterfaceID)
+                                                               r2->SendNSECNow = mDNSNULL;
+                                       }
+                               }
+
                if (m->omsg.h.numAnswers > 0 || m->omsg.h.numAdditionals)
                        {
                        debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p",
-                               numDereg,                  numDereg                  == 1 ? "" : "s",
-                               numAnnounce,               numAnnounce               == 1 ? "" : "s",
-                               numAnswer,                 numAnswer                 == 1 ? "" : "s",
+                               numDereg,                 numDereg                 == 1 ? "" : "s",
+                               numAnnounce,              numAnnounce              == 1 ? "" : "s",
+                               numAnswer,                numAnswer                == 1 ? "" : "s",
                                m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s", intf->InterfaceID);
                        if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL);
                        if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL);
@@ -2136,6 +3006,7 @@ mDNSlocal void SendResponses(mDNS *const m)
                        debugf(msg, intf, next);
                        #endif
                        intf = next;
+                       pktcount = 0;           // When we move to a new interface, reset packet count back to zero -- NSEC generation logic uses it
                        }
                }
 
@@ -2244,7 +3115,7 @@ mDNSlocal mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr,
                // For all the reconfirmations in a given batch, we want to use the same random value
                // so that the reconfirmation questions can be grouped into a single query packet
                if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(0x3FFFFFFF);
-               interval += mDNSRandomFromFixedSeed(m->RandomReconfirmDelay, interval/3);
+               interval += m->RandomReconfirmDelay % ((interval/3) + 1);
                rr->TimeRcvd          = m->timenow - (mDNSs32)interval * 3;
                rr->resrec.rroriginalttl     = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond;
                SetNextCacheCheckTime(m, rr);
@@ -2354,7 +3225,7 @@ mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name,
                domainname *crtarget = GetRRDomainNameTarget(&cr->resrec);
                if (crtarget && cr->resrec.rdatahash == namehash && SameDomainName(crtarget, name))
                        {
-                       LogOperation("ReconfirmAntecedents: Reconfirming (depth=%d) %s", depth, CRDisplayString(m, cr));
+                       LogInfo("ReconfirmAntecedents: Reconfirming (depth=%d) %s", depth, CRDisplayString(m, cr));
                        mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
                        if (depth < 5) ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, depth+1);
                        }
@@ -2365,14 +3236,39 @@ mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name,
 // we check if we have an address record for the same name. If we do have an IPv4 address for a given
 // name but not an IPv6 address, that's okay (it just means the device doesn't do IPv6) so the failure
 // to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name.
-mDNSlocal CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
+mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
        {
        CacheGroup *const cg = CacheGroupForName(m, HashSlot(name), namehash, name);
-       CacheRecord *cr = cg ? cg->members : mDNSNULL;
+       const CacheRecord *cr = cg ? cg->members : mDNSNULL;
        while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next;
        return(cr);
        }
 
+mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *const q, const CacheRecord *const c0, const CacheRecord *const c1)
+       {
+       CacheGroup *const cg = CacheGroupForName(m, HashSlot(&q->qname), q->qnamehash, &q->qname);
+       const CacheRecord *cr, *bestcr = mDNSNULL;
+       mDNSu32 bestmetric = 1000000;
+       for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
+               if (cr->resrec.rrtype == kDNSType_PTR && cr->resrec.rdlength >= 6)                                              // If record is PTR type, with long enough name,
+                       if (cr != c0 && cr != c1)                                                                                                                       // that's not one we've seen before,
+                               if (SameNameRecordAnswersQuestion(&cr->resrec, q))                                                              // and answers our browse query,
+                                       if (!IdenticalSameNameRecord(&cr->resrec, &m->SPSRecords.RR_PTR.resrec))        // and is not our own advertised service...
+                                               {
+                                               mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c);
+                                               if (bestmetric > metric) { bestmetric = metric; bestcr = cr; }
+                                               }
+       return(bestcr);
+       }
+
+// Finds the three best Sleep Proxies we currently have in our cache
+mDNSexport void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3])
+       {
+       sps[0] =                      FindSPSInCache1(m, q, mDNSNULL, mDNSNULL);
+       sps[1] = !sps[0] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   mDNSNULL);
+       sps[2] = !sps[1] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   sps[1]);
+       }
+
 // Only DupSuppressInfos newer than the specified 'time' are allowed to remain active
 mDNSlocal void ExpireDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time)
        {
@@ -2438,7 +3334,7 @@ mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q)
                mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4;
                const mDNSu32 slot = HashSlot(&q->qname);
                const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
-               CacheRecord *rr;
+               const CacheRecord *rr;
                for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)                         // If we have a resource record in our cache,
                        if (rr->resrec.rdlength <= SmallRecordLimit &&                                  // which is small enough to sensibly fit in the packet
                                SameNameRecordAnswersQuestion(&rr->resrec, q) &&                        // which answers our question
@@ -2491,7 +3387,7 @@ mDNSlocal void SendQueries(mDNS *const m)
                        if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
                                if (m->timenow + TicksTTL(rr)/50 - rr->NextRequiredQuery >= 0)
                                        {
-                                       LogOperation("Sending %d%% cache expiration query for %s", 80 + 5 * rr->UnansweredQueries, CRDisplayString(m, rr));
+                                       debugf("Sending %d%% cache expiration query for %s", 80 + 5 * rr->UnansweredQueries, CRDisplayString(m, rr));
                                        q = rr->CRActiveQuestion;
                                        ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(rr)/20, rr->resrec.InterfaceID);
                                        // For uDNS queries (TargetQID non-zero) we adjust LastQTime,
@@ -2520,10 +3416,16 @@ mDNSlocal void SendQueries(mDNS *const m)
                                {
                                mDNSu8       *qptr        = m->omsg.data;
                                const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data);
-                               InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags);
-                               qptr = putQuestion(&m->omsg, qptr, limit, &q->qname, q->qtype, q->qclass);
-                               mDNSSendDNSMessage(m, &m->omsg, qptr, mDNSInterface_Any, q->LocalSocket, &q->Target, q->TargetPort, mDNSNULL, mDNSNULL);
-                               q->ThisQInterval    *= QuestionIntervalStep;
+
+                               // If we fail to get a new on-demand socket (should only happen cases of the most extreme resource exhaustion), we'll try again next time
+                               if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
+                               if (q->LocalSocket)
+                                       {
+                                       InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags);
+                                       qptr = putQuestion(&m->omsg, qptr, limit, &q->qname, q->qtype, q->qclass);
+                                       mDNSSendDNSMessage(m, &m->omsg, qptr, mDNSInterface_Any, q->LocalSocket, &q->Target, q->TargetPort, mDNSNULL, mDNSNULL);
+                                       q->ThisQInterval    *= QuestionIntervalStep;
+                                       }
                                if (q->ThisQInterval > MaxQuestionInterval)
                                        q->ThisQInterval = MaxQuestionInterval;
                                q->LastQTime         = m->timenow;
@@ -2534,7 +3436,7 @@ mDNSlocal void SendQueries(mDNS *const m)
                                }
                        else if (mDNSOpaque16IsZero(q->TargetQID) && !q->Target.type && TimeToSendThisQuestion(q, m->timenow))
                                {
-                               //LogOperation("Time to send %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - (q->LastQTime + q->ThisQInterval));
+                               //LogInfo("Time to send %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - (q->LastQTime + q->ThisQInterval));
                                q->SendQNow = mDNSInterfaceMark;                // Mark this question for sending on all interfaces
                                if (maxExistingQuestionInterval < q->ThisQInterval)
                                        maxExistingQuestionInterval = q->ThisQInterval;
@@ -2563,7 +3465,7 @@ mDNSlocal void SendQueries(mDNS *const m)
                                // treat this as logically a repeat of the last transmission, without advancing the interval
                                if (m->timenow - (q->LastQTime + q->ThisQInterval/2) >= 0)
                                        {
-                                       //LogOperation("Accelerating %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - (q->LastQTime + q->ThisQInterval));
+                                       //LogInfo("Accelerating %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - (q->LastQTime + q->ThisQInterval));
                                        q->SendQNow = mDNSInterfaceMark;        // Mark this question for sending on all interfaces
                                        debugf("SendQueries: %##s (%s) next interval %d seconds RequestUnicast = %d",
                                                q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval / InitialQuestionInterval, q->RequestUnicast);
@@ -2628,9 +3530,23 @@ mDNSlocal void SendQueries(mDNS *const m)
                                // 2. else, if it has reached its probe time, mark it for sending and then update m->NextScheduledProbe correctly
                                else if (rr->ProbeCount)
                                        {
+                                       if (rr->AddressProxy.type == mDNSAddrType_IPv4)
+                                               {
+                                               LogSPS("SendQueries ARP Probe %d %s %s", rr->ProbeCount, InterfaceNameForID(m, rr->resrec.InterfaceID), ARDisplayString(m,rr));
+                                               SendARP(m, 1, rr, zerov4Addr.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, rr->WakeUp.IMAC.b);
+                                               }
+                                       else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
+                                               {
+                                               //LogSPS("SendQueries NDP Probe %d %s", rr->ProbeCount, ARDisplayString(m,rr));
+                                               //SendARP(m, 1, rr, rr->AddressProxy.ip.v4.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, onesEthAddr.b);
+                                               }
                                        // Mark for sending. (If no active interfaces, then don't even try.)
-                                       rr->SendRNow   = !intf ? mDNSNULL : (rr->resrec.InterfaceID) ? rr->resrec.InterfaceID : intf->InterfaceID;
+                                       rr->SendRNow   = (!intf || rr->WakeUp.HMAC.l[0]) ? mDNSNULL : rr->resrec.InterfaceID ? rr->resrec.InterfaceID : intf->InterfaceID;
                                        rr->LastAPTime = m->timenow;
+                                       // When we have a late conflict that resets a record to probing state we use a special marker value greater
+                                       // than DefaultProbeCountForTypeUnique. Here we detect that state and reset rr->ProbeCount back to the right value.
+                                       if (rr->ProbeCount > DefaultProbeCountForTypeUnique)
+                                               rr->ProbeCount = DefaultProbeCountForTypeUnique;
                                        rr->ProbeCount--;
                                        SetNextAnnounceProbeTime(m, rr);
                                        if (rr->ProbeCount == 0)
@@ -2678,8 +3594,11 @@ mDNSlocal void SendQueries(mDNS *const m)
        // go through our interface list sending the appropriate queries on each interface
        while (intf)
                {
+               const int os = !intf->MAC.l[0] ? 0 : DNSOpt_Header_Space + mDNSSameEthAddress(&m->PrimaryMAC, &intf->MAC) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space;
+               int OwnerRecordSpace = 0;
                AuthRecord *rr;
                mDNSu8 *queryptr = m->omsg.data;
+               mDNSu8 *limit    = m->omsg.data + AbsoluteMaxDNSMessageData;
                InitializeDNSMessage(&m->omsg.h, zeroID, QueryFlags);
                if (KnownAnswerList) verbosedebugf("SendQueries:   KnownAnswerList set... Will continue from previous packet");
                if (!KnownAnswerList)
@@ -2696,10 +3615,14 @@ mDNSlocal void SendQueries(mDNS *const m)
                                        debugf("SendQueries: %s question for %##s (%s) at %d forecast total %d",
                                                SuppressOnThisInterface(q->DupSuppress, intf) ? "Suppressing" : "Putting    ",
                                                q->qname.c, DNSTypeName(q->qtype), queryptr - m->omsg.data, queryptr + answerforecast - m->omsg.data);
+
                                        // If we're suppressing this question, or we successfully put it, update its SendQNow state
                                        if (SuppressOnThisInterface(q->DupSuppress, intf) ||
                                                BuildQuestion(m, &m->omsg, &queryptr, q, &kalistptr, &answerforecast))
-                                                       q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
+                                               q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
+
+                                       // Once we've put at least one question, cut back our limit to the normal single-packet size
+                                       if (m->omsg.h.numQuestions) limit = m->omsg.data + NormalMaxDNSMessageData;
                                        }
                                }
 
@@ -2709,14 +3632,15 @@ mDNSlocal void SendQueries(mDNS *const m)
                                        {
                                        mDNSBool ucast = (rr->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353;
                                        mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
-                                       const mDNSu8 *const limit = m->omsg.data + ((m->omsg.h.numQuestions) ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData);
                                        mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit, rr->resrec.name, kDNSQType_ANY, (mDNSu16)(rr->resrec.rrclass | ucbit));
                                        // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
                                        mDNSu32 forecast = answerforecast + 12 + rr->resrec.rdestimate;
-                                       if (newptr && newptr + forecast < limit)
+                                       if (newptr && newptr + forecast + os < limit)
                                                {
-                                               queryptr       = newptr;
-                                               answerforecast = forecast;
+                                               queryptr         = newptr;
+                                               limit            = m->omsg.data + NormalMaxDNSMessageData;
+                                               answerforecast   = forecast;
+                                               OwnerRecordSpace = os;
                                                rr->SendRNow = (rr->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
                                                rr->IncludeInProbe = mDNStrue;
                                                verbosedebugf("SendQueries:   Put Question %##s (%s) probecount %d",
@@ -2724,24 +3648,26 @@ mDNSlocal void SendQueries(mDNS *const m)
                                                }
                                        else
                                                {
-                                               verbosedebugf("SendQueries:   Retracting Question %##s (%s)",
-                                                       rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+                                               verbosedebugf("SendQueries:   Retracting Question %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
                                                m->omsg.h.numQuestions--;
                                                }
                                        }
-                               }
+                       }
+
+               if (m->omsg.h.numQuestions) limit = m->omsg.data + NormalMaxDNSMessageData - OwnerRecordSpace;
 
                // Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
                while (KnownAnswerList)
                        {
                        CacheRecord *ka = KnownAnswerList;
                        mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - ka->TimeRcvd)) / mDNSPlatformOneSecond;
-                       mDNSu8 *newptr = PutResourceRecordTTL(&m->omsg, queryptr, &m->omsg.h.numAnswers, &ka->resrec, ka->resrec.rroriginalttl - SecsSinceRcvd);
+                       mDNSu8 *newptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAnswers, &ka->resrec, ka->resrec.rroriginalttl - SecsSinceRcvd, limit);
                        if (newptr)
                                {
                                verbosedebugf("SendQueries:   Put %##s (%s) at %d - %d",
                                        ka->resrec.name->c, DNSTypeName(ka->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data);
                                queryptr = newptr;
+                               limit = m->omsg.data + NormalMaxDNSMessageData - OwnerRecordSpace;
                                KnownAnswerList = ka->NextInKAList;
                                ka->NextInKAList = mDNSNULL;
                                }
@@ -2762,10 +3688,25 @@ mDNSlocal void SendQueries(mDNS *const m)
                                mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, &rr->resrec);
                                rr->IncludeInProbe = mDNSfalse;
                                if (newptr) queryptr = newptr;
-                               else LogMsg("SendQueries:   How did we fail to have space for the Update record %##s (%s)?",
-                                       rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+                               else LogMsg("SendQueries:   How did we fail to have space for the Update record %s", ARDisplayString(m,rr));
                                }
-               
+
+               if (OwnerRecordSpace)
+                       {
+                       AuthRecord opt;
+                       mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
+                       opt.resrec.rrclass    = NormalMaxDNSMessageData;
+                       opt.resrec.rdlength   = sizeof(rdataOPT);       // One option in this OPT record
+                       opt.resrec.rdestimate = sizeof(rdataOPT);
+                       SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
+                       LogSPS("SendQueries putting %s", ARDisplayString(m, &opt));
+                       queryptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAdditionals,
+                               &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
+                       if (!queryptr)
+                               LogMsg("SendQueries: How did we fail to have space for the OPT record (%d/%d/%d/%d) %s",
+                                       m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
+                       }
+
                if (queryptr > m->omsg.data)
                        {
                        if ((m->omsg.h.flags.b[0] & kDNSFlag0_TC) && m->omsg.h.numQuestions > 1)
@@ -2828,13 +3769,50 @@ mDNSlocal void SendQueries(mDNS *const m)
                        }
        }
 
+mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password)
+       {
+       int i, j;
+       mDNSu8 *ptr = m->omsg.data;
+
+       if (!InterfaceID) { LogMsg("SendWakeup: No InterfaceID specified"); return; }
+
+       // 0x00 Destination address
+       for (i=0; i<6; i++) *ptr++ = EthAddr->b[i];
+
+       // 0x06 Source address (we just use zero -- BPF will fill in real interface address)
+       for (i=0; i<6; i++) *ptr++ = 0x0;
+
+       // 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++ = EthAddr->b[i];
+
+       // 0x74 Password
+       for (i=0; i<6; i++) *ptr++ = password->b[i];
+
+       mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
+
+       // For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses,
+       // broadcast is the only reliable way to get a wakeup packet to the intended target machine.
+       // For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast
+       // key rotation, unicast is the only way to get a wakeup packet to the intended target machine.
+       // So, we send one of each, unicast first, then broadcast second.
+       for (i=0; i<6; i++) m->omsg.data[i] = 0xFF;
+       mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
+       }
+
 // ***************************************************************************
 #if COMPILER_LIKES_PRAGMA_MARK
 #pragma mark -
 #pragma mark - RR List Management & Task Management
 #endif
 
-// NOTE: AnswerCurrentQuestionWithResourceRecord can call a user callback, which may change the record list and/or question list.
+// Note: AnswerCurrentQuestionWithResourceRecord can call a user callback, which may change the record list and/or question list.
 // Any code walking either list must use the m->CurrentQuestion (and possibly m->CurrentRecord) mechanism to protect against this.
 // In fact, to enforce this, the routine will *only* answer the question currently pointed to by m->CurrentQuestion,
 // which will be auto-advanced (possibly to NULL) if the client callback cancels the question.
@@ -2880,26 +3858,34 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco
        if (rr->DelayDelivery) return;          // We'll come back later when CacheRecordDeferredAdd() calls us
 
        // Only deliver negative answers if client has explicitly requested them
-       if (rr->resrec.RecordType == kDNSRecordTypePacketNegative && (!AddRecord || !q->ReturnIntermed)) return;
+       if (rr->resrec.RecordType == kDNSRecordTypePacketNegative || (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype)))
+               if (!AddRecord || !q->ReturnIntermed) return;
 
        // For CNAME results to non-CNAME questions, only inform the client if they explicitly requested that
        if (q->QuestionCallback && !q->NoAnswer && (!followcname || q->ReturnIntermed))
                {
                mDNS_DropLockBeforeCallback();          // Allow client (and us) to legally make mDNS API calls
-               q->QuestionCallback(m, q, &rr->resrec, AddRecord);
+               if (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype))
+                       {
+                       CacheRecord neg;
+                       MakeNegativeCacheRecord(m, &neg, &q->qname, q->qnamehash, q->qtype, q->qclass, 1, rr->resrec.InterfaceID);
+                       q->QuestionCallback(m, q, &neg.resrec, AddRecord);
+                       }
+               else
+                       q->QuestionCallback(m, q, &rr->resrec, AddRecord);
                mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
                }
-       // NOTE: Proceed with caution here because client callback function is allowed to do anything,
+       // Note: Proceed with caution here because client callback function is allowed to do anything,
        // including starting/stopping queries, registering/deregistering records, etc.
 
        if (followcname && m->CurrentQuestion == q && q->CNAMEReferrals < 10)
                {
                const mDNSu32 c = q->CNAMEReferrals + 1;
                // Right now we just stop and re-use the existing query. If we really wanted to be 100% perfect,
-               // and track CNAMEs coming and going, we should really create a subbordinate query here,
+               // and track CNAMEs coming and going, we should really create a subordinate query here,
                // which we would subsequently cancel and retract if the CNAME referral record were removed.
                // In reality this is such a corner case we'll ignore it until someone actually needs it.
-               LogOperation("AnswerCurrentQuestionWithResourceRecord: following CNAME referral for %s", CRDisplayString(m, rr));
+               LogInfo("AnswerCurrentQuestionWithResourceRecord: following CNAME referral for %s", CRDisplayString(m, rr));
                mDNS_StopQuery_internal(m, q);                                                          // Stop old query
                AssignDomainName(&q->qname, &rr->resrec.rdata->u.name);         // Update qname
                q->qnamehash = DomainNameHashValue(&q->qname);                          // and namehash
@@ -2931,7 +3917,7 @@ mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *c
        const mDNSs32 start      = m->timenow - 0x10000000;
        mDNSs32 delay = start;
        CacheGroup *cg = CacheGroupForName(m, slot, namehash, name);
-       CacheRecord *rr;
+       const CacheRecord *rr;
        for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
                if (threshhold - RRExpireTime(rr) >= 0)         // If we have records about to expire within a second
                        if (delay - RRExpireTime(rr) < 0)               // then delay until after they've been deleted
@@ -2945,7 +3931,7 @@ mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *c
 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
 // rr is a new CacheRecord just received into our cache
 // (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
-// NOTE: CacheRecordAdd calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
+// Note: CacheRecordAdd calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
 // which may change the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
 mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr)
@@ -3021,7 +4007,7 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr)
 // but we don't have any place to cache it. We'll deliver question 'add' events now, but we won't have any
 // way to deliver 'remove' events in future, nor will we be able to include this in known-answer lists,
 // so we immediately bump ThisQInterval up to MaxQuestionInterval to avoid pounding the network.
-// NOTE: NoCacheAnswer calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
+// Note: NoCacheAnswer calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
 // which may change the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
 mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr)
@@ -3049,7 +4035,7 @@ mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr)
 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
 // rr is an existing cache CacheRecord that just expired and is being deleted
 // (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
-// NOTE: CacheRecordRmv calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
+// Note: CacheRecordRmv calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
 // which may change the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
 mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr)
@@ -3081,7 +4067,7 @@ mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr)
                                {
                                if (q->CurrentAnswers == 0)
                                        {
-                                       LogOperation("CacheRecordRmv: Last answer for %##s (%s) expired from cache; will reconfirm antecedents",
+                                       LogInfo("CacheRecordRmv: Last answer for %##s (%s) expired from cache; will reconfirm antecedents",
                                                q->qname.c, DNSTypeName(q->qtype));
                                        ReconfirmAntecedents(m, &q->qname, q->qnamehash, 0);
                                        }
@@ -3122,7 +4108,7 @@ mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp)
 mDNSlocal void ReleaseCacheRecord(mDNS *const m, CacheRecord *r)
        {
        //LogMsg("ReleaseCacheRecord: Releasing %s", CRDisplayString(m, r));
-       if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->rdatastorage) mDNSPlatformMemFree(r->resrec.rdata);
+       if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->smallrdatastorage) mDNSPlatformMemFree(r->resrec.rdata);
        r->resrec.rdata = mDNSNULL;
        ReleaseCacheEntity(m, (CacheEntity *)r);
        }
@@ -3212,7 +4198,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m)
        if (q->NoAnswer == NoAnswer_Fail)
                {
                LogMsg("AnswerNewQuestion: NoAnswer_Fail %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-               MakeNegativeCacheRecord(m, &q->qname, q->qnamehash, q->qtype, q->qclass, 60);
+               MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any);
                q->NoAnswer = NoAnswer_Normal;          // Temporarily turn off answer suppression
                AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, QC_addnocache);
                q->NoAnswer = NoAnswer_Fail;            // Restore NoAnswer state
@@ -3232,7 +4218,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m)
                        if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
                                if (ResourceRecordAnswersQuestion(&rr->resrec, q))
                                        {
-                                       AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, mDNStrue);
+                                       AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, mDNStrue);
                                        if (m->CurrentQuestion != q) break;             // If callback deleted q, then we're finished here
                                        }
                        }
@@ -3251,8 +4237,8 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m)
                                mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - rr->TimeRcvd)) / mDNSPlatformOneSecond;
                                if (rr->resrec.rroriginalttl <= SecsSinceRcvd)
                                        {
-                                       LogMsg("AnswerNewQuestion: How is rr->resrec.rroriginalttl %lu <= SecsSinceRcvd %lu for %##s (%s) %d %d",
-                                               rr->resrec.rroriginalttl, SecsSinceRcvd, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), m->timenow, rr->TimeRcvd);
+                                       LogMsg("AnswerNewQuestion: How is rr->resrec.rroriginalttl %lu <= SecsSinceRcvd %lu for %s %d %d",
+                                               rr->resrec.rroriginalttl, SecsSinceRcvd, CRDisplayString(m, rr), m->timenow, rr->TimeRcvd);
                                        continue;       // Go to next one in loop
                                        }
        
@@ -3267,8 +4253,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m)
                                if (m->CurrentQuestion != q) break;             // If callback deleted q, then we're finished here
                                }
                        else if (RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype))
-                               if (rr->resrec.namehash == q->qnamehash && SameDomainName(rr->resrec.name, &q->qname))
-                                       ShouldQueryImmediately = mDNSfalse;
+                               ShouldQueryImmediately = mDNSfalse;
                }
 
        if (m->CurrentQuestion != q) debugf("AnswerNewQuestion: question deleted while giving cache answers");
@@ -3295,7 +4280,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m)
        }
 
 // When a NewLocalOnlyQuestion is created, AnswerNewLocalOnlyQuestion runs though our ResourceRecords delivering any
-// appropriate answers, stopping if it reaches a NewLocalRecord -- these will be handled by AnswerLocalQuestions
+// appropriate answers, stopping if it reaches a NewLocalRecord -- these will be handled by AnswerAllLocalQuestionsWithLocalAuthRecord
 mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
        {
        DNSQuestion *q = m->NewLocalOnlyQuestions;              // Grab the question we're going to answer
@@ -3317,7 +4302,7 @@ mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
                m->CurrentRecord = rr->next;
                if (ResourceRecordAnswersQuestion(&rr->resrec, q))
                        {
-                       AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, mDNStrue);
+                       AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, mDNStrue);
                        if (m->CurrentQuestion != q) break;             // If callback deleted q, then we're finished here
                        }
                }
@@ -3345,8 +4330,8 @@ mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const Pre
                // To guard against this, if our cache grows above 512kB (approx 3168 records at 164 bytes each),
                // and we're actively using less than 1/32 of that cache, then we purge all the unused records
                // and recycle them, instead of allocating more memory.
-               if (m->rrcache_size > 3000 && m->rrcache_size / 32 > m->rrcache_active)
-                       LogOperation("Possible denial-of-service attack in progress: m->rrcache_size %lu; m->rrcache_active %lu",
+               if (m->rrcache_size > 5000 && m->rrcache_size / 32 > m->rrcache_active)
+                       LogInfo("Possible denial-of-service attack in progress: m->rrcache_size %lu; m->rrcache_active %lu",
                                m->rrcache_size, m->rrcache_active);
                else
                        {
@@ -3360,9 +4345,7 @@ mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const Pre
        // Enumerating the entire cache is moderately expensive, so when we do it, we reclaim all the records we can in one pass.
        if (!m->rrcache_free)
                {
-               #if LogAllOperations || MDNS_DEBUGMSGS
                mDNSu32 oldtotalused = m->rrcache_totalused;
-               #endif
                mDNSu32 slot;
                for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
                        {
@@ -3390,7 +4373,7 @@ mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const Pre
                                else ReleaseCacheGroup(m, cp);
                                }
                        }
-               LogOperation("GetCacheEntity recycled %d records to reduce cache from %d to %d",
+               LogInfo("GetCacheEntity recycled %d records to reduce cache from %d to %d",
                        oldtotalused - m->rrcache_totalused, oldtotalused, m->rrcache_totalused);
                }
 
@@ -3400,9 +4383,10 @@ mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const Pre
                m->rrcache_free = e->next;
                if (++m->rrcache_totalused >= m->rrcache_report)
                        {
-                       LogOperation("RR Cache now using %ld objects", m->rrcache_totalused);
-                       if (m->rrcache_report < 100) m->rrcache_report += 10;
-                       else                         m->rrcache_report += 100;
+                       LogInfo("RR Cache now using %ld objects", m->rrcache_totalused);
+                       if      (m->rrcache_report <  100) m->rrcache_report += 10;
+                       else if (m->rrcache_report < 1000) m->rrcache_report += 100;
+                       else                               m->rrcache_report += 1000;
                        }
                mDNSPlatformMemZero(e, sizeof(*e));
                }
@@ -3417,7 +4401,7 @@ mDNSlocal CacheRecord *GetCacheRecord(mDNS *const m, CacheGroup *cg, mDNSu16 RDL
        CacheRecord *r = (CacheRecord *)GetCacheEntity(m, cg);
        if (r)
                {
-               r->resrec.rdata = (RData*)&r->rdatastorage;     // By default, assume we're usually going to be using local storage
+               r->resrec.rdata = (RData*)&r->smallrdatastorage;        // By default, assume we're usually going to be using local storage
                if (RDLength > InlineCacheRDSize)                       // If RDLength is too big, allocate extra storage
                        {
                        r->resrec.rdata = (RData*)mDNSPlatformMemAllocate(sizeofRDataHeader + RDLength);
@@ -3458,6 +4442,8 @@ mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const Res
 
 mDNSexport void mDNS_PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr)
        {
+       if (m->mDNS_busy != m->mDNS_reentrancy+1)
+               LogMsg("mDNS_PurgeCacheResourceRecord: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
        // Make sure we mark this record as thoroughly expired -- we don't ever want to give
        // a positive answer using an expired record (e.g. from an interface that has gone away).
        // We don't want to clear CRActiveQuestion here, because that would leave the record subject to
@@ -3485,6 +4471,43 @@ mDNSexport mDNSs32 mDNS_TimeNow(const mDNS *const m)
        return(time);
        }
 
+// To avoid pointless CPU thrash, we use SetSPSProxyListChanged(X) to record the last interface that
+// had its Sleep Proxy client list change, and defer to actual BPF reconfiguration to mDNS_Execute().
+// (GetNextScheduledEvent() returns "now" when m->SPSProxyListChanged is set)
+#define SetSPSProxyListChanged(X) do { \
+       if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m, m->SPSProxyListChanged); \
+       m->SPSProxyListChanged = (X); } while(0)
+
+// Called from mDNS_Execute() to expire stale proxy records
+mDNSlocal void CheckProxyRecords(mDNS *const m, AuthRecord *list)
+       {
+       m->CurrentRecord = list;
+       while (m->CurrentRecord)
+               {
+               AuthRecord *rr = m->CurrentRecord;
+               if (rr->WakeUp.HMAC.l[0])
+                       {
+                       if (m->timenow - rr->TimeExpire < 0)            // If proxy record not expired yet, update m->NextScheduledSPS
+                               {
+                               if (m->NextScheduledSPS - rr->TimeExpire > 0)
+                                       m->NextScheduledSPS = rr->TimeExpire;
+                               }
+                       else                                                                            // else proxy record expired, so remove it
+                               {
+                               LogSPS("mDNS_Execute: Removing %d H-MAC %.6a I-MAC %.6a %d %s",
+                                       m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, ARDisplayString(m, rr));
+                               SetSPSProxyListChanged(rr->resrec.InterfaceID);
+                               mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
+                               // Don't touch rr after this -- memory may have been free'd
+                               }
+                       }
+               // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal,
+               // because the list may have been changed in that call.
+               if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
+                       m->CurrentRecord = rr->next;
+               }
+       }
+
 mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
        {
        mDNS_Lock(m);   // Must grab lock before trying to read m->timenow
@@ -3520,6 +4543,25 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
                                }
                        }
        
+               if (m->timenow - m->NextScheduledSPS >= 0)
+                       {
+                       m->NextScheduledSPS = m->timenow + 0x3FFFFFFF;
+                       CheckProxyRecords(m, m->DuplicateRecords);      // Clear m->DuplicateRecords first, then m->ResourceRecords
+                       CheckProxyRecords(m, m->ResourceRecords);
+                       }
+
+               SetSPSProxyListChanged(mDNSNULL);               // Perform any deferred BPF reconfiguration now
+
+               if (m->DelaySleep && m->timenow - m->DelaySleep >= 0)
+                       {
+                       m->DelaySleep = 0;
+                       if (m->SleepState == SleepState_Transferring)
+                               {
+                               LogSPS("Re-sleep delay passed; now checking for Sleep Proxy Servers");
+                               BeginSleepProcessing(m);
+                               }
+                       }
+
                // 4. See if we can answer any of our new local questions from the cache
                for (i=0; m->NewQuestions && i<1000; i++)
                        {
@@ -3535,13 +4577,14 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
                        {
                        AuthRecord *rr = m->NewLocalRecords;
                        m->NewLocalRecords = m->NewLocalRecords->next;
-                       AnswerLocalQuestions(m, rr, mDNStrue);
+                       AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNStrue);
                        }
                if (i >= 1000) LogMsg("mDNS_Execute: AnswerForNewLocalRecords exceeded loop limit");
 
                // 5. See what packets we need to send
-               if (m->mDNSPlatformStatus != mStatus_NoError || m->SleepState) DiscardDeregistrations(m);
-               else if (m->SuppressSending == 0 || m->timenow - m->SuppressSending >= 0)
+               if (m->mDNSPlatformStatus != mStatus_NoError || (m->SleepState == SleepState_Sleeping))
+                       DiscardDeregistrations(m);
+               if (m->mDNSPlatformStatus == mStatus_NoError && (m->SuppressSending == 0 || m->timenow - m->SuppressSending >= 0))
                        {
                        // If the platform code is ready, and we're not suppressing packet generation right now
                        // then send our responses, probes, and questions.
@@ -3645,7 +4688,7 @@ mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question,
 
        if (!question->DuplicateOf)
                {
-               LogOperation("ActivateUnicastQuery: %##s %s%s%s",
+               debugf("ActivateUnicastQuery: %##s %s%s%s",
                        question->qname.c, DNSTypeName(question->qtype), question->AuthInfo ? " (Private)" : "", ScheduleImmediately ? " ScheduleImmediately" : "");
                if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
                if (question->LongLived)
@@ -3664,107 +4707,527 @@ mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question,
                }
        }
 
-// Call mDNSCoreMachineSleep(m, mDNStrue) when the machine is about to go to sleep.
-// Call mDNSCoreMachineSleep(m, mDNSfalse) when the machine is has just woken up.
-// Normally, the platform support layer below mDNSCore should call this, not the client layer above.
-// Note that sleep/wake calls do not have to be paired one-for-one; it is acceptable to call
-// mDNSCoreMachineSleep(m, mDNSfalse) any time there is reason to believe that the machine may have just
-// found itself in a new network environment. For example, if the Ethernet hardware indicates that the
-// cable has just been connected, the platform support layer should call mDNSCoreMachineSleep(m, mDNSfalse)
-// to make mDNSCore re-issue its outstanding queries, probe for record uniqueness, etc.
-// While it is safe to call mDNSCoreMachineSleep(m, mDNSfalse) at any time, it does cause extra network
-// traffic, so it should only be called when there is legitimate reason to believe the machine
-// may have become attached to a new network.
-mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleepstate)
+mDNSexport void mDNSCoreRestartQueries(mDNS *const m)
        {
-       AuthRecord *rr;
-
-       mDNS_Lock(m);
-
-       m->SleepState = sleepstate;
-       LogOperation("%s at %ld", sleepstate ? "Sleeping" : "Waking", m->timenow);
+       DNSQuestion *q;
 
-       if (sleepstate)
-               {
 #ifndef UNICAST_DISABLED
-               SuspendLLQs(m);
-               SleepServiceRegistrations(m);
-               SleepRecordRegistrations(m);
-#endif
-               // Mark all the records we need to deregister and send them
-               for (rr = m->ResourceRecords; rr; rr=rr->next)
-                       if (rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye)
-                               rr->ImmedAnswer = mDNSInterfaceMark;
-               SendResponses(m);
-               }
-       else
+       // Retrigger all our uDNS questions
+       if (m->CurrentQuestion)
+               LogMsg("mDNSCoreRestartQueries: ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+       m->CurrentQuestion = m->Questions;
+       while (m->CurrentQuestion)
                {
-               DNSQuestion *q;
-               mDNSu32 slot;
-               CacheGroup *cg;
-               CacheRecord *cr;
+               q = m->CurrentQuestion;
+               m->CurrentQuestion = m->CurrentQuestion->next;
+               if (!mDNSOpaque16IsZero(q->TargetQID)) ActivateUnicastQuery(m, q, mDNStrue);
+               }
+#endif
 
-#ifndef UNICAST_DISABLED
-               // On wake, retrigger all our uDNS questions
-               if (m->CurrentQuestion)
-                       LogMsg("RestartQueries: ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-               m->CurrentQuestion = m->Questions;
-               while (m->CurrentQuestion)
+       // Retrigger all our mDNS questions
+       for (q = m->Questions; q; q=q->next)                            // Scan our list of questions
+               if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q))
                        {
-                       q = m->CurrentQuestion;
-                       m->CurrentQuestion = m->CurrentQuestion->next;
-                       if (!mDNSOpaque16IsZero(q->TargetQID)) ActivateUnicastQuery(m, q, mDNStrue);
+                       q->ThisQInterval    = InitialQuestionInterval;  // MUST be > zero for an active question
+                       q->RequestUnicast   = 2;                                                // Set to 2 because is decremented once *before* we check it
+                       q->LastQTime        = m->timenow - q->ThisQInterval;
+                       q->RecentAnswerPkts = 0;
+                       ExpireDupSuppressInfo(q->DupSuppress, m->timenow);
+                       m->NextScheduledQuery = m->timenow;
                        }
-               // and reactivtate service registrations
-               m->NextSRVUpdate = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
-               LogOperation("WakeServiceRegistrations %d %d", m->timenow, m->NextSRVUpdate);
+       }
+
+// ***************************************************************************
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Power Management (Sleep/Wake)
 #endif
-        // 1. Retrigger all our mDNS questions
-               for (q = m->Questions; q; q=q->next)                            // Scan our list of questions
-                       if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q))
-                               {
-                               q->ThisQInterval    = InitialQuestionInterval;  // MUST be > zero for an active question
-                               q->RequestUnicast   = 2;                                                // Set to 2 because is decremented once *before* we check it
-                               q->LastQTime        = m->timenow - q->ThisQInterval;
-                               q->RecentAnswerPkts = 0;
-                               ExpireDupSuppressInfo(q->DupSuppress, m->timenow);
-                               m->NextScheduledQuery = m->timenow;
-                               }
 
-               // 2. Re-validate our cache records
-               m->NextCacheCheck  = m->timenow;
-               FORALL_CACHERECORDS(slot, cg, cr)
-                       mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForWake);
+mDNSlocal void SendSPSRegistration(mDNS *const m, NetworkInterfaceInfo *intf, const mDNSOpaque16 id)
+       {
+       const int ownerspace = mDNSSameEthAddress(&m->PrimaryMAC, &intf->MAC) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space;
+       const int optspace = DNSOpt_Header_Space + DNSOpt_LeaseData_Space + ownerspace;
+       const int sps = intf->NextSPSAttempt / 3;
+       AuthRecord *rr;
 
-               // 3. Retrigger probing and announcing for all our authoritative records
+       if (!intf->SPSAddr[sps].type)
+               {
+               intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond;
+               if (m->NextScheduledSPRetry - intf->NextSPSAttemptTime > 0)
+                       m->NextScheduledSPRetry = intf->NextSPSAttemptTime;
+               LogSPS("SendSPSRegistration: %s SPS %d (%d) %##s not yet resolved", intf->ifname, intf->NextSPSAttempt, sps, intf->NetWakeResolve[sps].qname.c);
+               goto exit;
+               }
+
+       // Mark our mDNS records (not unicast records) for transfer to SPS
+       if (mDNSOpaque16IsZero(id))
                for (rr = m->ResourceRecords; rr; rr=rr->next)
-                       if (AuthRecord_uDNS(rr))
+                       if (rr->resrec.RecordType > kDNSRecordTypeDeregistering)
+                               if (rr->resrec.InterfaceID == intf->InterfaceID || (!rr->resrec.InterfaceID && (rr->ForceMCast || IsLocalDomain(rr->resrec.name))))
+                                       rr->SendRNow = mDNSInterfaceMark;       // mark it now
+
+       while (1)
+               {
+               mDNSu8 *p = m->omsg.data;
+               // To comply with RFC 2782, PutResourceRecord suppresses name compression for SRV records in unicast updates.
+               // For now we follow that same logic for SPS registrations too.
+               // If we decide to compress SRV records in SPS registrations in the future, we can achieve that by creating our
+               // initial DNSMessage with h.flags set to zero, and then update it to UpdateReqFlags right before sending the packet.
+               InitializeDNSMessage(&m->omsg.h, mDNSOpaque16IsZero(id) ? mDNS_NewMessageID(m) : id, UpdateReqFlags);
+
+               for (rr = m->ResourceRecords; rr; rr=rr->next)
+                       if (rr->SendRNow || (!mDNSOpaque16IsZero(id) && !AuthRecord_uDNS(rr) && mDNSSameOpaque16(rr->updateid, id) && m->timenow - (rr->LastAPTime + rr->ThisAPInterval) >= 0))
                                {
-                               ActivateUnicastRegistration(m, rr);
+                               mDNSu8 *newptr;
+                               const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.mDNS_numUpdates ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData) - optspace;
+                               if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
+                                       rr->resrec.rrclass |= kDNSClass_UniqueRRSet;    // Temporarily set the 'unique' bit so PutResourceRecord will set it
+                               newptr = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit);
+                               rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear 'unique' bit back to normal state
+                               if (!newptr)
+                                       LogSPS("SendSPSRegistration put %s FAILED %d/%d %s", intf->ifname, p - m->omsg.data, limit - m->omsg.data, ARDisplayString(m, rr));
+                               else
+                                       {
+                                       LogSPS("SendSPSRegistration put %s %s", intf->ifname, ARDisplayString(m, rr));
+                                       rr->SendRNow       = mDNSNULL;
+                                       rr->ThisAPInterval = mDNSPlatformOneSecond;
+                                       rr->LastAPTime     = m->timenow;
+                                       rr->updateid       = m->omsg.h.id;
+                                       if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
+                                               m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
+                                       p = newptr;
+                                       }
                                }
+
+               if (!m->omsg.h.mDNS_numUpdates) break;
+               else
+                       {
+                       AuthRecord opt;
+                       mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
+                       opt.resrec.rrclass    = NormalMaxDNSMessageData;
+                       opt.resrec.rdlength   = sizeof(rdataOPT) * 2;   // Two options in this OPT record
+                       opt.resrec.rdestimate = sizeof(rdataOPT) * 2;
+                       opt.resrec.rdata->u.opt[0].opt              = kDNSOpt_Lease;
+                       opt.resrec.rdata->u.opt[0].optlen           = DNSOpt_LeaseData_Space - 4;
+                       opt.resrec.rdata->u.opt[0].u.updatelease    = DEFAULT_UPDATE_LEASE;
+                       SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[1]);
+                       LogSPS("SendSPSRegistration put %s %s", intf->ifname, ARDisplayString(m, &opt));
+                       p = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
+                       if (!p)
+                               LogMsg("SendSPSRegistration: Failed to put OPT record (%d updates) %s", m->omsg.h.mDNS_numUpdates, ARDisplayString(m, &opt));
                        else
                                {
-                               if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
-                               rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
-                               rr->AnnounceCount  = InitialAnnounceCount;
-                               InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
+                               mStatus err;
+                               LogSPS("SendSPSRegistration: Sending Update %s %d (%d) id %5d with %d records %d bytes to %#a:%d", intf->ifname, intf->NextSPSAttempt, sps,
+                                       mDNSVal16(m->omsg.h.id), m->omsg.h.mDNS_numUpdates, p - m->omsg.data, &intf->SPSAddr[sps], mDNSVal16(intf->SPSPort[sps]));
+                               // if (intf->NextSPSAttempt < 5) m->omsg.h.flags = zeroID;      // For simulating packet loss
+                               err = mDNSSendDNSMessage(m, &m->omsg, p, intf->InterfaceID, mDNSNULL, &intf->SPSAddr[sps], intf->SPSPort[sps], mDNSNULL, mDNSNULL);
+                               if (err) LogSPS("SendSPSRegistration: mDNSSendDNSMessage err %d", err);
+                               if (err && intf->SPSAddr[sps].type == mDNSAddrType_IPv6 && intf->NetWakeResolve[sps].ThisQInterval == -1)
+                                       {
+                                       LogSPS("SendSPSRegistration %d %##s failed to send to IPv6 address; will try IPv4 instead", sps, intf->NetWakeResolve[sps].qname.c);
+                                       intf->NetWakeResolve[sps].qtype = kDNSType_A;
+                                       mDNS_StartQuery_internal(m, &intf->NetWakeResolve[sps]);
+                                       return;
+                                       }
                                }
+                       }
                }
 
-       mDNS_Unlock(m);
+       intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond * 10;             // If successful, update NextSPSAttemptTime
+
+exit:
+       if (mDNSOpaque16IsZero(id) && intf->NextSPSAttempt < 8) intf->NextSPSAttempt++;
        }
 
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Packet Reception Functions
-#endif
+// RetrySPSRegistrations is called from SendResponses, with the lock held
+mDNSlocal void RetrySPSRegistrations(mDNS *const m)
+       {
+       AuthRecord *rr;
+       NetworkInterfaceInfo *intf;
 
-#define MustSendRecord(RR) ((RR)->NR_AnswerTo || (RR)->NR_AdditionalTo)
+       // First make sure none of our interfaces' NextSPSAttemptTimes are inadvertently set to m->timenow + mDNSPlatformOneSecond * 10
+       for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+               if (intf->NextSPSAttempt && intf->NextSPSAttemptTime == m->timenow + mDNSPlatformOneSecond * 10)
+                       intf->NextSPSAttemptTime++;
 
-mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const mDNSu8 *const end,
-       const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, DNSMessage *const response, AuthRecord *ResponseRecords)
-       {
+       // Retry any record registrations that are due
+       for (rr = m->ResourceRecords; rr; rr=rr->next)
+               if (!AuthRecord_uDNS(rr) && !mDNSOpaque16IsZero(rr->updateid) && m->timenow - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
+                       for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+                               if (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == intf->InterfaceID)
+                                       {
+                                       LogSPS("RetrySPSRegistrations: %s", ARDisplayString(m, rr));
+                                       SendSPSRegistration(m, intf, rr->updateid);
+                                       }
+
+       // For interfaces where we did an SPS registration attempt, increment intf->NextSPSAttempt
+       for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+               if (intf->NextSPSAttempt && intf->NextSPSAttemptTime == m->timenow + mDNSPlatformOneSecond * 10 && intf->NextSPSAttempt < 8)
+                       intf->NextSPSAttempt++;
+       }
+
+mDNSlocal void NetWakeResolve(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
+       {
+       NetworkInterfaceInfo *intf = (NetworkInterfaceInfo *)question->QuestionContext;
+       int sps = question - intf->NetWakeResolve;
+       (void)m;                        // Unused
+       LogSPS("NetWakeResolve: SPS: %d Add: %d %s", sps, AddRecord, RRDisplayString(m, answer));
+
+       if (!AddRecord) return;                                                                                         // Don't care about REMOVE events
+       if (answer->rrtype != question->qtype) return;                                          // Don't care about CNAMEs
+
+       mDNS_StopQuery(m, question);
+       question->ThisQInterval = -1;
+
+       if (answer->rrtype == kDNSType_SRV)
+               {
+               intf->SPSPort[sps] = answer->rdata->u.srv.port;
+               AssignDomainName(&question->qname, &answer->rdata->u.srv.target);
+               question->qtype = kDNSType_AAAA;
+               mDNS_StartQuery(m, question);
+               }
+       else if (answer->rrtype == kDNSType_AAAA && answer->rdlength == sizeof(mDNSv6Addr) && mDNSv6AddressIsLinkLocal(&answer->rdata->u.ipv6))
+               {
+               intf->SPSAddr[sps].type = mDNSAddrType_IPv6;
+               intf->SPSAddr[sps].ip.v6 = answer->rdata->u.ipv6;
+               mDNS_Lock(m);
+               if (sps == intf->NextSPSAttempt/3) SendSPSRegistration(m, intf, zeroID);        // If we're ready for this result, use it now
+               mDNS_Unlock(m);
+               }
+       else if (answer->rrtype == kDNSType_AAAA && answer->rdlength == 0)      // If negative answer for IPv6, look for IPv4 addresses instead
+               {
+               LogSPS("NetWakeResolve: SPS %d %##s has no IPv6 address, will try IPv4 instead", sps, question->qname.c);
+               question->qtype = kDNSType_A;
+               mDNS_StartQuery(m, question);
+               }
+       else if (answer->rrtype == kDNSType_A && answer->rdlength == sizeof(mDNSv4Addr))
+               {
+               intf->SPSAddr[sps].type = mDNSAddrType_IPv4;
+               intf->SPSAddr[sps].ip.v4 = answer->rdata->u.ipv4;
+               mDNS_Lock(m);
+               if (sps == intf->NextSPSAttempt/3) SendSPSRegistration(m, intf, zeroID);        // If we're ready for this result, use it now
+               mDNS_Unlock(m);
+               }
+       }
+
+mDNSexport mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m)
+       {
+       AuthRecord *rr;
+       for (rr = m->ResourceRecords; rr; rr=rr->next)
+               if (rr->resrec.rrtype == kDNSType_SRV && !AuthRecord_uDNS(rr) && !mDNSSameIPPort(rr->resrec.rdata->u.srv.port, DiscardPort))
+                       return mDNStrue;
+       return mDNSfalse;
+       }
+
+// BeginSleepProcessing is called, with the lock held, from either mDNS_Execute or mDNSCoreMachineSleep
+mDNSlocal void BeginSleepProcessing(mDNS *const m)
+       {
+       const CacheRecord *sps[3] = { mDNSNULL };
+
+       m->NextScheduledSPRetry = m->timenow;
+
+       if      (!m->SystemWakeOnLANEnabled)                  LogSPS("BeginSleepProcessing: m->SystemWakeOnLANEnabled is false");
+       else if (!mDNSCoreHaveAdvertisedMulticastServices(m)) LogSPS("BeginSleepProcessing: No advertised services");
+       else    // If we have at least one advertised service
+               {
+               NetworkInterfaceInfo *intf;
+               for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+                       {
+                       if (!intf->NetWake) LogSPS("BeginSleepProcessing: %-6s not capable of magic packet wakeup", intf->ifname);
+                       else
+                               {
+                               FindSPSInCache(m, &intf->NetWakeBrowse, sps);
+                               if (!sps[0]) LogSPS("BeginSleepProcessing: %-6s %#a No Sleep Proxy Server found %d", intf->ifname, &intf->ip, intf->NetWakeBrowse.ThisQInterval);
+                               else
+                                       {
+                                       int i;
+                                       intf->NextSPSAttempt = 0;
+                                       intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond;
+                                       // Don't need to set m->NextScheduledSPRetry here because we already set "m->NextScheduledSPRetry = m->timenow" above
+                                       for (i=0; i<3; i++)
+                                               {
+#if ForceAlerts
+                                               if (intf->SPSAddr[i].type)
+                                                       { LogMsg("BeginSleepProcessing: %s %d intf->SPSAddr[i].type %d", intf->ifname, i, intf->SPSAddr[i].type); *(long*)0 = 0; }
+                                               if (intf->NetWakeResolve[i].ThisQInterval >= 0)
+                                                       { LogMsg("BeginSleepProcessing: %s %d intf->NetWakeResolve[i].ThisQInterval %d", intf->ifname, i, intf->NetWakeResolve[i].ThisQInterval); *(long*)0 = 0; }
+#endif
+                                               intf->SPSAddr[i].type = mDNSAddrType_None;
+                                               if (intf->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery(m, &intf->NetWakeResolve[i]);
+                                               intf->NetWakeResolve[i].ThisQInterval = -1;
+                                               if (sps[i])
+                                                       {
+                                                       LogSPS("BeginSleepProcessing: %-6s Found Sleep Proxy Server %d TTL %d %s", intf->ifname, i, sps[i]->resrec.rroriginalttl, CRDisplayString(m, sps[i]));
+                                                       mDNS_SetupQuestion(&intf->NetWakeResolve[i], intf->InterfaceID, &sps[i]->resrec.rdata->u.name, kDNSType_SRV, NetWakeResolve, intf);
+                                                       intf->NetWakeResolve[i].ReturnIntermed = mDNStrue;
+                                                       mDNS_StartQuery_internal(m, &intf->NetWakeResolve[i]);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+       if (!sps[0])    // If we didn't find even one Sleep Proxy
+               {
+               AuthRecord *rr;
+               LogSPS("BeginSleepProcessing: Not registering with Sleep Proxy Server");
+               m->SleepState = SleepState_Sleeping;
+
+#ifndef UNICAST_DISABLED
+               SleepServiceRegistrations(m);
+               SleepRecordRegistrations(m);    // If we have no SPS, need to deregister our uDNS records
+#endif
+
+               // Mark all the records we need to deregister and send them
+               for (rr = m->ResourceRecords; rr; rr=rr->next)
+                       if (rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye)
+                               rr->ImmedAnswer = mDNSInterfaceMark;
+               SendResponses(m);
+               }
+       }
+
+// Call mDNSCoreMachineSleep(m, mDNStrue) when the machine is about to go to sleep.
+// Call mDNSCoreMachineSleep(m, mDNSfalse) when the machine is has just woken up.
+// Normally, the platform support layer below mDNSCore should call this, not the client layer above.
+mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep)
+       {
+       AuthRecord *rr;
+
+       mDNS_Lock(m);
+
+       LogSPS("%s (old state %d) at %ld", sleep ? "Sleeping" : "Waking", m->SleepState, m->timenow);
+
+       if (sleep && !m->SleepState)            // Going to sleep
+               {
+               // If we're going to sleep, need to stop advertising that we're a Sleep Proxy Server
+               if (m->SPSSocket)
+                       {
+                       mDNSu8 oldstate = m->SPSState;
+                       mDNS_DropLockBeforeCallback();          // mDNS_DeregisterService expects to be called without the lock held, so we emulate that here
+                       m->SPSState = 2;
+                       if (oldstate == 1) mDNS_DeregisterService(m, &m->SPSRecords);
+                       mDNS_ReclaimLockAfterCallback();
+                       }
+
+               m->SleepState = SleepState_Transferring;
+               if (m->SystemWakeOnLANEnabled && m->DelaySleep)
+                       {
+                       // If we just woke up moments ago, allow ten seconds for networking to stabilize before going back to sleep
+                       LogSPS("mDNSCoreMachineSleep: Re-sleeping immediately after waking; will delay for %d ticks", m->DelaySleep - m->timenow);
+                       m->SleepLimit = m->DelaySleep + mDNSPlatformOneSecond * 10;
+                       }
+               else
+                       {
+                       m->DelaySleep = 0;
+                       m->SleepLimit = m->timenow + mDNSPlatformOneSecond * 10;
+                       BeginSleepProcessing(m);
+                       }
+
+#ifndef UNICAST_DISABLED
+               SuspendLLQs(m);
+#endif
+               LogSPS("mDNSCoreMachineSleep: m->SleepState %d (%s) seq %d", m->SleepState,
+                       m->SleepState == SleepState_Transferring ? "Transferring" : 
+                       m->SleepState == SleepState_Sleeping     ? "Sleeping"     : "?", m->SleepSeqNum);
+               }
+       else if (!sleep)                // Waking up
+               {
+               mDNSu32 slot;
+               CacheGroup *cg;
+               CacheRecord *cr;
+               NetworkInterfaceInfo *intf;
+
+               // If we were previously sleeping, but now we're not, increment m->SleepSeqNum to indicate that we're entering a new period of wakefulness
+               if (m->SleepState != SleepState_Awake)
+                       {
+                       m->SleepState = SleepState_Awake;
+                       m->SleepSeqNum++;
+                       // If the machine wakes and then immediately tries to sleep again (e.g. a maintenance wake)
+                       // then we enforce a minimum delay of 16 seconds before we begin sleep processing.
+                       // This is to allow time for the Ethernet link to come up, DHCP to get an address, mDNS to issue queries, etc.,
+                       // before we make our determination of whether there's a Sleep Proxy out there we should register with.
+                       m->DelaySleep = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 16);
+                       }
+
+               if (m->SPSState == 3)
+                       {
+                       mDNS_DropLockBeforeCallback();          // mDNS_DeregisterService expects to be called without the lock held, so we emulate that here
+                       m->SPSState = 0;
+                       mDNSCoreBeSleepProxyServer(m, m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower);
+                       mDNS_ReclaimLockAfterCallback();
+                       }
+
+               // In case we gave up waiting and went to sleep before we got an ack from the Sleep Proxy,
+               // on wake we go through our record list and clear updateid back to zero
+               for (rr = m->ResourceRecords; rr; rr=rr->next) rr->updateid = zeroID;
+
+               // ... and the same for NextSPSAttempt
+               for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) intf->NextSPSAttempt = -1;
+
+               // Restart unicast and multicast queries
+               mDNSCoreRestartQueries(m);
+
+               // and reactivtate service registrations
+               m->NextSRVUpdate = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
+               LogInfo("WakeServiceRegistrations %d %d", m->timenow, m->NextSRVUpdate);
+
+               // 2. Re-validate our cache records
+               m->NextCacheCheck  = m->timenow;
+               FORALL_CACHERECORDS(slot, cg, cr)
+                       mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForWake);
+
+               // 3. Retrigger probing and announcing for all our authoritative records
+               for (rr = m->ResourceRecords; rr; rr=rr->next)
+                       if (AuthRecord_uDNS(rr))
+                               {
+                               ActivateUnicastRegistration(m, rr);
+                               }
+                       else
+                               {
+                               if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
+                               rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
+                               rr->AnnounceCount  = InitialAnnounceCount;
+                               InitializeLastAPTime(m, rr);
+                               }
+
+               // 4. Refresh NAT mappings
+               // We don't want to have to assume that all hardware can necessarily keep accurate
+               // track of passage of time while asleep, so on wake we refresh our NAT mappings
+               m->retryIntervalGetAddr = NATMAP_INIT_RETRY;
+               m->retryGetAddr         = m->timenow;
+               RecreateNATMappings(m);
+               }
+
+       mDNS_Unlock(m);
+       }
+
+mDNSexport mDNSBool mDNSCoreReadyForSleep(mDNS *m)
+       {
+       DNSQuestion *q;
+       AuthRecord *rr;
+       ServiceRecordSet *srs;
+       NetworkInterfaceInfo *intf;
+
+       mDNS_Lock(m);
+
+       if (m->NextScheduledSPRetry - m->timenow > 0) goto notready;
+
+       m->NextScheduledSPRetry = m->timenow + 0x40000000UL;
+
+       if (m->DelaySleep) goto notready;
+
+       // See if we might need to retransmit any lost Sleep Proxy Registrations
+       for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+               if (intf->NextSPSAttempt >= 0)
+                       {
+                       if (m->timenow - intf->NextSPSAttemptTime >= 0)
+                               {
+                               LogSPS("ReadyForSleep retrying SPS %s %d", intf->ifname, intf->NextSPSAttempt);
+                               SendSPSRegistration(m, intf, zeroID);
+                               }
+                       else
+                               if (m->NextScheduledSPRetry - intf->NextSPSAttemptTime > 0)
+                                       m->NextScheduledSPRetry = intf->NextSPSAttemptTime;
+                       }
+
+       // Scan list of private LLQs, and make sure they've all completed their handshake with the server
+       for (q = m->Questions; q; q = q->next)
+               if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->ReqLease == 0 && q->tcp)
+                       {
+                       LogSPS("ReadyForSleep waiting for LLQ %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+                       goto notready;
+                       }
+
+       // Scan list of interfaces
+       for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+               if (intf->NetWakeResolve[0].ThisQInterval >= 0)
+                       {
+                       LogSPS("ReadyForSleep waiting for SPS Resolve %s %##s (%s)", intf->ifname, intf->NetWakeResolve[0].qname.c, DNSTypeName(intf->NetWakeResolve[0].qtype));
+                       goto notready;
+                       }
+
+       // Scan list of registered records
+       for (rr = m->ResourceRecords; rr; rr = rr->next)
+               {
+               if (AuthRecord_uDNS(rr))
+                       {
+                       if (rr->state == regState_Refresh && rr->tcp)
+                               { LogSPS("ReadyForSleep waiting for Record Update ID %d %s", mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; }
+                       }
+               else
+                       {
+                       if (!mDNSOpaque16IsZero(rr->updateid))
+                               { LogSPS("ReadyForSleep waiting for SPS Update ID %d %s", mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; }
+                       }
+               }
+
+       // Scan list of registered services
+       for (srs = m->ServiceRegistrations; srs; srs = srs->uDNS_next)
+               if (srs->state == regState_NoTarget && srs->tcp) goto notready;
+
+       mDNS_Unlock(m);
+       return mDNStrue;
+
+notready:
+       mDNS_Unlock(m);
+       return mDNSfalse;
+       }
+
+mDNSexport mDNSs32 mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now)
+       {
+       AuthRecord *ar;
+
+       // Even when we have no wake-on-LAN-capable interfaces, or we failed to find a sleep proxy, or we have other
+       // failure scenarios, we still want to wake up in at most 120 minutes, to see if the network environment has changed.
+       // E.g. we might wake up and find no wireless network because the base station got rebooted just at that moment,
+       // and if that happens we don't want to just give up and go back to sleep and never try again.
+       mDNSs32 e = now + (120 * 60 * mDNSPlatformOneSecond);           // Sleep for at most 120 minutes
+
+       NATTraversalInfo *nat;
+       for (nat = m->NATTraversals; nat; nat=nat->next)
+               if (nat->Protocol && nat->ExpiryTime && nat->ExpiryTime - now > mDNSPlatformOneSecond*4)
+                       {
+                       mDNSs32 t = nat->ExpiryTime - (nat->ExpiryTime - now) / 10;             // Wake up when 90% of the way to the expiry time
+                       if (e - t > 0) e = t;
+                       LogSPS("ComputeWakeTime: %p %s Int %5d Ext %5d Err %d Retry %5d Interval %5d Expire %5d Wake %5d",
+                               nat, nat->Protocol == NATOp_MapTCP ? "TCP" : "UDP",
+                               mDNSVal16(nat->IntPort), mDNSVal16(nat->ExternalPort), nat->Result,
+                               nat->retryPortMap ? (nat->retryPortMap - now) / mDNSPlatformOneSecond : 0,
+                               nat->retryInterval / mDNSPlatformOneSecond,
+                               nat->ExpiryTime ? (nat->ExpiryTime - now) / mDNSPlatformOneSecond : 0,
+                               (t - now) / mDNSPlatformOneSecond);
+                       }
+
+       // This loop checks both the time we need to renew wide-area registrations,
+       // and the time we need to renew Sleep Proxy registrations
+       for (ar = m->ResourceRecords; ar; ar = ar->next)
+               if (ar->expire && ar->expire - now > mDNSPlatformOneSecond*4)
+                       {
+                       mDNSs32 t = ar->expire - (ar->expire - now) / 10;               // Wake up when 90% of the way to the expiry time
+                       if (e - t > 0) e = t;
+                       LogSPS("ComputeWakeTime: %p Int %7d Next %7d Expire %7d Wake %7d %s",
+                               ar, ar->ThisAPInterval / mDNSPlatformOneSecond,
+                               (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
+                               ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
+                               (t - now) / mDNSPlatformOneSecond, ARDisplayString(m, ar));
+                       }
+
+       return(e - now);
+       }
+
+// ***************************************************************************
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Packet Reception Functions
+#endif
+
+#define MustSendRecord(RR) ((RR)->NR_AnswerTo || (RR)->NR_AdditionalTo)
+
+mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const mDNSu8 *const end,
+       const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, DNSMessage *const response, AuthRecord *ResponseRecords)
+       {
        mDNSu8          *responseptr     = response->data;
        const mDNSu8    *const limit     = response->data + sizeof(response->data);
        const mDNSu8    *ptr             = query->data;
@@ -3807,7 +5270,8 @@ mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const m
        for (rr=ResponseRecords; rr; rr=rr->NextResponse)
                if (rr->NR_AnswerTo)
                        {
-                       mDNSu8 *p = PutResourceRecordCappedTTL(response, responseptr, &response->h.numAnswers, &rr->resrec, maxttl);
+                       mDNSu8 *p = PutResourceRecordTTL(response, responseptr, &response->h.numAnswers, &rr->resrec,
+                               maxttl < rr->resrec.rroriginalttl ? maxttl : rr->resrec.rroriginalttl);
                        if (p) responseptr = p;
                        else { debugf("GenerateUnicastResponse: Ran out of space for answers!"); response->h.flags.b[0] |= kDNSFlag0_TC; }
                        }
@@ -3818,7 +5282,8 @@ mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const m
        for (rr=ResponseRecords; rr; rr=rr->NextResponse)
                if (rr->NR_AdditionalTo && !rr->NR_AnswerTo)
                        {
-                       mDNSu8 *p = PutResourceRecordCappedTTL(response, responseptr, &response->h.numAdditionals, &rr->resrec, maxttl);
+                       mDNSu8 *p = PutResourceRecordTTL(response, responseptr, &response->h.numAdditionals, &rr->resrec,
+                               maxttl < rr->resrec.rroriginalttl ? maxttl : rr->resrec.rroriginalttl);
                        if (p) responseptr = p;
                        else debugf("GenerateUnicastResponse: No more space for additionals");
                        }
@@ -3831,7 +5296,7 @@ mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const m
 // Returns 0 if there is no conflict
 // Returns +1 if there was a conflict and we won
 // Returns -1 if there was a conflict and we lost and have to rename
-mDNSlocal int CompareRData(AuthRecord *our, CacheRecord *pkt)
+mDNSlocal int CompareRData(const AuthRecord *const our, const CacheRecord *const pkt)
        {
        mDNSu8 ourdata[256], *ourptr = ourdata, *ourend;
        mDNSu8 pktdata[256], *pktptr = pktdata, *pktend;
@@ -3914,22 +5379,29 @@ mDNSlocal const AuthRecord *FindRRSet(const mDNS *const m, const CacheRecord *co
 //    are members of the same RRSet, then this is not a conflict.
 mDNSlocal mDNSBool PacketRRConflict(const mDNS *const m, const AuthRecord *const our, const CacheRecord *const pktrr)
        {
-       const AuthRecord *ourset = our->RRSet ? our->RRSet : our;
-
        // If not supposed to be unique, not a conflict
        if (!(our->resrec.RecordType & kDNSRecordTypeUniqueMask)) return(mDNSfalse);
 
        // If a dependent record, not a conflict
        if (our->DependentOn || MatchDependentOn(m, pktrr, our)) return(mDNSfalse);
+       else
+               {
+               // If the pktrr matches a member of ourset, not a conflict
+               const AuthRecord *ourset = our->RRSet ? our->RRSet : our;
+               const AuthRecord *pktset = FindRRSet(m, pktrr);
+               if (pktset == ourset) return(mDNSfalse);
 
-       // If the pktrr matches a member of ourset, not a conflict
-       if (FindRRSet(m, pktrr) == ourset) return(mDNSfalse);
+               // For records we're proxying, where we don't know the full
+               // relationship between the records, having any matching record
+               // in our AuthRecords list is sufficient evidence of non-conflict
+               if (our->WakeUp.HMAC.l[0] && pktset) return(mDNSfalse);
+               }
 
        // Okay, this is a conflict
        return(mDNStrue);
        }
 
-// NOTE: ResolveSimultaneousProbe calls mDNS_Deregister_internal which can call a user callback, which may change
+// Note: ResolveSimultaneousProbe calls mDNS_Deregister_internal which can call a user callback, which may change
 // the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
 mDNSlocal void ResolveSimultaneousProbe(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end,
@@ -3951,20 +5423,36 @@ mDNSlocal void ResolveSimultaneousProbe(mDNS *const m, const DNSMessage *const q
                                int result          = (int)our->resrec.rrclass - (int)m->rec.r.resrec.rrclass;
                                if (!result) result = (int)our->resrec.rrtype  - (int)m->rec.r.resrec.rrtype;
                                if (!result) result = CompareRData(our, &m->rec.r);
-                               if (result > 0)
-                                       LogOperation("ResolveSimultaneousProbe: %##s (%s): We won",  our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
-                               else if (result < 0)
+                               if (result)
                                        {
-                                       LogOperation("ResolveSimultaneousProbe: %##s (%s): We lost", our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
-                                       mDNS_Deregister_internal(m, our, mDNS_Dereg_conflict);
+                                       const char *const msg = (result < 0) ? "lost:" : (result > 0) ? "won: " : "tie: ";
+                                       LogMsg("ResolveSimultaneousProbe: Pkt Record:        %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
+                                       LogMsg("ResolveSimultaneousProbe: Our Record %d %s %08lX %s",   our->ProbeCount, msg, our->resrec.rdatahash, ARDisplayString(m, our));
+                                       }
+                               // If we lost the tie-break for simultaneous probes, we don't immediately give up, because we might be seeing stale packets on the network.
+                               // Instead we pause for one second, to give the other host (if real) a change to establish its name, and then try probing again.
+                               // If there really is another live host out there with the same name, it will answer our probes and we'll then rename.
+                               if (result < 0)
+                                       {
+                                       m->SuppressProbes   = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
+                                       our->ProbeCount     = DefaultProbeCountForTypeUnique;
+                                       our->AnnounceCount  = InitialAnnounceCount;
+                                       InitializeLastAPTime(m, our);
                                        goto exit;
                                        }
                                }
+#if 0
+                       else
+                               {
+                               LogMsg("ResolveSimultaneousProbe: Pkt Record:      %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
+                               LogMsg("ResolveSimultaneousProbe: Our Record ign:  %08lX %s", our->resrec.rdatahash,     ARDisplayString(m, our));
+                               }
+#endif
                        }
                m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
                }
        if (!FoundUpdate)
-               LogOperation("ResolveSimultaneousProbe: %##s (%s): No Update Record found", our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
+               LogInfo("ResolveSimultaneousProbe: %##s (%s): No Update Record found", our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
 exit:
        m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
        }
@@ -3979,6 +5467,28 @@ mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, const Res
        return(rr);
        }
 
+// Called from ProcessQuery when we get an mDNS packet with an owner record in it
+mDNSlocal void ClearProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist)
+       {
+       m->CurrentRecord = thelist;
+       while (m->CurrentRecord)
+               {
+               AuthRecord *const rr = m->CurrentRecord;
+               if (m->rec.r.resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&owner->HMAC, &rr->WakeUp.HMAC))
+                       if (owner->seq != rr->WakeUp.seq || m->timenow - rr->TimeRcvd > mDNSPlatformOneSecond * 60)
+                               {
+                               LogSPS("ClearProxyRecords: Removing %3d H-MAC %.6a I-MAC %.6a %d %d %s",
+                                       m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, owner->seq, ARDisplayString(m, rr));
+                               mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
+                               SetSPSProxyListChanged(m->rec.r.resrec.InterfaceID);
+                               }
+               // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal,
+               // because the list may have been changed in that call.
+               if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
+                       m->CurrentRecord = rr->next;
+               }
+       }
+
 // ProcessQuery examines a received query to see if we have any answers to give
 mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end,
        const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast,
@@ -3993,18 +5503,43 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
        DNSQuestion **dqp                = &DupQuestions;
        mDNSs32       delayresponse      = 0;
        mDNSBool      SendLegacyResponse = mDNSfalse;
-       const mDNSu8 *ptr                = query->data;
+       const mDNSu8 *ptr;
        mDNSu8       *responseptr        = mDNSNULL;
        AuthRecord   *rr;
        int i;
 
        // ***
-       // *** 1. Parse Question Section and mark potential answers
+       // *** 1. Look in Additional Section for an OPT record
+       // ***
+       ptr = LocateOptRR(query, end, DNSOpt_OwnerData_ID_Space);
+       if (ptr)
+               {
+               ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &m->rec);
+               if (m->rec.r.resrec.rrtype == kDNSType_OPT)
+                       {
+                       const rdataOPT *opt;
+                       const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
+                       // Find owner sub-option(s). We verify that the MAC is non-zero, otherwise we could inadvertently
+                       // delete all our own AuthRecords (which are identified by having zero MAC tags on them).
+                       for (opt = &m->rec.r.resrec.rdata->u.opt[0]; opt < e; opt++)
+                               if (opt->opt == kDNSOpt_Owner && opt->u.owner.vers == 0 && opt->u.owner.HMAC.l[0])
+                                       {
+                                       ClearProxyRecords(m, &opt->u.owner, m->DuplicateRecords);
+                                       ClearProxyRecords(m, &opt->u.owner, m->ResourceRecords);
+                                       }
+                       }
+               m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
+               }
+
+       // ***
+       // *** 2. Parse Question Section and mark potential answers
        // ***
+       ptr = query->data;
        for (i=0; i<query->h.numQuestions; i++)                                         // For each question...
                {
                mDNSBool QuestionNeedsMulticastResponse;
                int NumAnswersForThisQuestion = 0;
+               AuthRecord *NSECAnswer = mDNSNULL;
                DNSQuestion pktq, *q;
                ptr = getQuestion(query, ptr, end, InterfaceID, &pktq); // get the question...
                if (!ptr) goto exit;
@@ -4034,42 +5569,67 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
                        {
                        rr = m->CurrentRecord;
                        m->CurrentRecord = rr->next;
-                       if (ResourceRecordAnswersQuestion(&rr->resrec, &pktq) && (QueryWasMulticast || QueryWasLocalUnicast || rr->AllowRemoteQuery))
+                       if (AnyTypeRecordAnswersQuestion(&rr->resrec, &pktq) && (QueryWasMulticast || QueryWasLocalUnicast || rr->AllowRemoteQuery))
                                {
-                               if (rr->resrec.RecordType == kDNSRecordTypeUnique)
-                                       ResolveSimultaneousProbe(m, query, end, &pktq, rr);
-                               else if (ResourceRecordIsValidAnswer(rr))
+                               if (RRTypeAnswersQuestionType(&rr->resrec, pktq.qtype))
                                        {
-                                       NumAnswersForThisQuestion++;
-                                       // Notes:
-                                       // NR_AnswerTo pointing into query packet means "answer via immediate legacy unicast" (may *also* choose to multicast)
-                                       // NR_AnswerTo == (mDNSu8*)~1             means "answer via delayed unicast" (to modern querier; may promote to multicast instead)
-                                       // NR_AnswerTo == (mDNSu8*)~0             means "definitely answer via multicast" (can't downgrade to unicast later)
-                                       // If we're not multicasting this record because the kDNSQClass_UnicastResponse bit was set,
-                                       // but the multicast querier is not on a matching subnet (e.g. because of overalyed subnets on one link)
-                                       // then we'll multicast it anyway (if we unicast, the receiver will ignore it because it has an apparently non-local source)
-                                       if (QuestionNeedsMulticastResponse || (!FromLocalSubnet && QueryWasMulticast && !LegacyQuery))
+                                       if (rr->resrec.RecordType == kDNSRecordTypeUnique)
+                                               ResolveSimultaneousProbe(m, query, end, &pktq, rr);
+                                       else if (ResourceRecordIsValidAnswer(rr))
                                                {
-                                               // We only mark this question for sending if it is at least one second since the last time we multicast it
-                                               // on this interface. If it is more than a second, or LastMCInterface is different, then we may multicast it.
-                                               // This is to guard against the case where someone blasts us with queries as fast as they can.
-                                               if (m->timenow - (rr->LastMCTime + mDNSPlatformOneSecond) >= 0 ||
-                                                       (rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID))
-                                                       rr->NR_AnswerTo = (mDNSu8*)~0;
+                                               NumAnswersForThisQuestion++;
+                                               // Note: We should check here if this is a probe-type query, and if so, generate an immediate
+                                               // unicast answer back to the source, because timeliness in answering probes is important.
+       
+                                               // Notes:
+                                               // NR_AnswerTo pointing into query packet means "answer via immediate legacy unicast" (may *also* choose to multicast)
+                                               // NR_AnswerTo == (mDNSu8*)~1             means "answer via delayed unicast" (to modern querier; may promote to multicast instead)
+                                               // NR_AnswerTo == (mDNSu8*)~0             means "definitely answer via multicast" (can't downgrade to unicast later)
+                                               // If we're not multicasting this record because the kDNSQClass_UnicastResponse bit was set,
+                                               // but the multicast querier is not on a matching subnet (e.g. because of overlaid subnets on one link)
+                                               // then we'll multicast it anyway (if we unicast, the receiver will ignore it because it has an apparently non-local source)
+                                               if (QuestionNeedsMulticastResponse || (!FromLocalSubnet && QueryWasMulticast && !LegacyQuery))
+                                                       {
+                                                       // We only mark this question for sending if it is at least one second since the last time we multicast it
+                                                       // on this interface. If it is more than a second, or LastMCInterface is different, then we may multicast it.
+                                                       // This is to guard against the case where someone blasts us with queries as fast as they can.
+                                                       if (m->timenow - (rr->LastMCTime + mDNSPlatformOneSecond) >= 0 ||
+                                                               (rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID))
+                                                               rr->NR_AnswerTo = (mDNSu8*)~0;
+                                                       }
+                                               else if (!rr->NR_AnswerTo) rr->NR_AnswerTo = LegacyQuery ? ptr : (mDNSu8*)~1;
                                                }
-                                       else if (!rr->NR_AnswerTo) rr->NR_AnswerTo = LegacyQuery ? ptr : (mDNSu8*)~1;
+                                       }
+                               else if (rr->resrec.RecordType == kDNSRecordTypeVerified)
+                                       {
+                                       // If we don't have any answers for this question, but we do own another record with the same name,
+                                       // then mark it to generate an NSEC record on this interface
+                                       if (!NSECAnswer) NSECAnswer = rr;
                                        }
                                }
                        }
 
+               if (NumAnswersForThisQuestion == 0 && NSECAnswer)
+                       {
+                       NumAnswersForThisQuestion++;
+                       NSECAnswer->SendNSECNow = InterfaceID;
+                       m->NextScheduledResponse = m->timenow;
+                       }
+
                // If we couldn't answer this question, someone else might be able to,
                // so use random delay on response to reduce collisions
                if (NumAnswersForThisQuestion == 0) delayresponse = mDNSPlatformOneSecond;      // Divided by 50 = 20ms
 
-               // We only do the following accelerated cache expiration processing and duplicate question suppression processing
-               // for multicast queries with multicast responses.
-               // For any query generating a unicast response we don't do this because we can't assume we will see the response
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
                if (QuestionNeedsMulticastResponse)
+#else
+               // We only do the following accelerated cache expiration and duplicate question suppression processing
+               // for non-truncated multicast queries with multicast responses.
+               // For any query generating a unicast response we don't do this because we can't assume we will see the response.
+               // For truncated queries we don't do this because a response we're expecting might be suppressed by a subsequent
+               // known-answer packet, and when there's packet loss we can't safely assume we'll receive *all* known-answer packets.
+               if (QuestionNeedsMulticastResponse && !(query->h.flags.b[0] & kDNSFlag0_TC))
+#endif
                        {
                        const mDNSu32 slot = HashSlot(&pktq.qname);
                        CacheGroup *cg = CacheGroupForName(m, slot, pktq.qnamehash, &pktq.qname);
@@ -4077,28 +5637,35 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
 
                        // Make a list indicating which of our own cache records we expect to see updated as a result of this query
                        // Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated
-                       for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-                               if (SameNameRecordAnswersQuestion(&cr->resrec, &pktq) && cr->resrec.rdlength <= SmallRecordLimit)
-                                       if (!cr->NextInKAList && eap != &cr->NextInKAList)
-                                               {
-                                               *eap = cr;
-                                               eap = &cr->NextInKAList;
-                                               if (cr->MPUnansweredQ == 0 || m->timenow - cr->MPLastUnansweredQT >= mDNSPlatformOneSecond)
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
+                       if (!(query->h.flags.b[0] & kDNSFlag0_TC))
+#endif
+                               for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
+                                       if (SameNameRecordAnswersQuestion(&cr->resrec, &pktq) && cr->resrec.rdlength <= SmallRecordLimit)
+                                               if (!cr->NextInKAList && eap != &cr->NextInKAList)
                                                        {
-                                                       // Although MPUnansweredQ is only really used for multi-packet query processing,
-                                                       // we increment it for both single-packet and multi-packet queries, so that it stays in sync
-                                                       // with the MPUnansweredKA value, which by necessity is incremented for both query types.
-                                                       cr->MPUnansweredQ++;
-                                                       cr->MPLastUnansweredQT = m->timenow;
-                                                       cr->MPExpectingKA = mDNStrue;
+                                                       *eap = cr;
+                                                       eap = &cr->NextInKAList;
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
+                                                       if (cr->MPUnansweredQ == 0 || m->timenow - cr->MPLastUnansweredQT >= mDNSPlatformOneSecond)
+                                                               {
+                                                               // Although MPUnansweredQ is only really used for multi-packet query processing,
+                                                               // we increment it for both single-packet and multi-packet queries, so that it stays in sync
+                                                               // with the MPUnansweredKA value, which by necessity is incremented for both query types.
+                                                               cr->MPUnansweredQ++;
+                                                               cr->MPLastUnansweredQT = m->timenow;
+                                                               cr->MPExpectingKA = mDNStrue;
+                                                               }
+#endif
                                                        }
-                                               }
        
                        // Check if this question is the same as any of mine.
                        // We only do this for non-truncated queries. Right now it would be too complicated to try
                        // to keep track of duplicate suppression state between multiple packets, especially when we
                        // can't guarantee to receive all of the Known Answer packets that go with a particular query.
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
                        if (!(query->h.flags.b[0] & kDNSFlag0_TC))
+#endif
                                for (q = m->Questions; q; q=q->next)
                                        if (!q->Target.type && ActiveQuestion(q) && m->timenow - q->LastQTxTime > mDNSPlatformOneSecond / 4)
                                                if (!q->InterfaceID || q->InterfaceID == InterfaceID)
@@ -4111,19 +5678,19 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
                }
 
        // ***
-       // *** 2. Now we can safely build the list of marked answers
+       // *** 3. Now we can safely build the list of marked answers
        // ***
        for (rr = m->ResourceRecords; rr; rr=rr->next)                          // Now build our list of potential answers
                if (rr->NR_AnswerTo)                                                                    // If we marked the record...
                        AddRecordToResponseList(&nrp, rr, mDNSNULL);            // ... add it to the list
 
        // ***
-       // *** 3. Add additional records
+       // *** 4. Add additional records
        // ***
        AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID);
 
        // ***
-       // *** 4. Parse Answer Section and cancel any records disallowed by Known-Answer list
+       // *** 5. Parse Answer Section and cancel any records disallowed by Known-Answer list
        // ***
        for (i=0; i<query->h.numAnswers; i++)                                           // For each record in the query's answer section...
                {
@@ -4162,18 +5729,20 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
                                }
                        }
 
+               ourcacherr = FindIdenticalRecordInCache(m, &m->rec.r.resrec);
+
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
                // See if this Known-Answer suppresses any answers we were expecting for our cache records. We do this always,
                // even if the TC bit is not set (the TC bit will *not* be set in the *last* packet of a multi-packet KA list).
-               ourcacherr = FindIdenticalRecordInCache(m, &m->rec.r.resrec);
                if (ourcacherr && ourcacherr->MPExpectingKA && m->timenow - ourcacherr->MPLastUnansweredQT < mDNSPlatformOneSecond)
                        {
                        ourcacherr->MPUnansweredKA++;
                        ourcacherr->MPExpectingKA = mDNSfalse;
                        }
+#endif
 
-               // Having built our ExpectedAnswers list from the questions in this packet, we can definitively
-               // remove from our ExpectedAnswers list any records that are suppressed in the very same packet.
-               // For answers that are suppressed in subsequent KA list packets, we rely on the MPQ/MPKA counting to track them.
+               // Having built our ExpectedAnswers list from the questions in this packet, we then remove
+               // any records that are suppressed by the Known Answer list in this packet.
                eap = &ExpectedAnswers;
                while (*eap)
                        {
@@ -4199,14 +5768,14 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
                }
 
        // ***
-       // *** 5. Cancel any additionals that were added because of now-deleted records
+       // *** 6. Cancel any additionals that were added because of now-deleted records
        // ***
        for (rr=ResponseRecords; rr; rr=rr->NextResponse)
                if (rr->NR_AdditionalTo && !MustSendRecord(rr->NR_AdditionalTo))
                        { rr->NR_AnswerTo = mDNSNULL; rr->NR_AdditionalTo = mDNSNULL; }
 
        // ***
-       // *** 6. Mark the send flags on the records we plan to send
+       // *** 7. Mark the send flags on the records we plan to send
        // ***
        for (rr=ResponseRecords; rr; rr=rr->NextResponse)
                {
@@ -4274,7 +5843,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
                }
 
        // ***
-       // *** 7. If we think other machines are likely to answer these questions, set our packet suppression timer
+       // *** 8. If we think other machines are likely to answer these questions, set our packet suppression timer
        // ***
        if (delayresponse && (!m->SuppressSending || (m->SuppressSending - m->timenow) < (delayresponse + 49) / 50))
                {
@@ -4305,7 +5874,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
                }
 
        // ***
-       // *** 8. If query is from a legacy client, or from a new client requesting a unicast reply, then generate a unicast response too
+       // *** 9. If query is from a legacy client, or from a new client requesting a unicast reply, then generate a unicast response too
        // ***
        if (SendLegacyResponse)
                responseptr = GenerateUnicastResponse(query, end, InterfaceID, LegacyQuery, response, ResponseRecords);
@@ -4314,7 +5883,7 @@ exit:
        m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
        
        // ***
-       // *** 9. Finally, clear our link chains ready for use next time
+       // *** 10. Finally, clear our link chains ready for use next time
        // ***
        while (ResponseRecords)
                {
@@ -4338,9 +5907,11 @@ exit:
                                {
                                cr->UnansweredQueries++;
                                cr->LastUnansweredTime = m->timenow;
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
                                if (cr->UnansweredQueries > 1)
                                        debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s",
                                                cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
+#endif
                                SetNextCacheCheckTime(m, cr);
                                }
 
@@ -4348,12 +5919,15 @@ exit:
                // then mark it to expire in five seconds if we don't get a response by then.
                if (cr->UnansweredQueries >= MaxUnansweredQueries)
                        {
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
                        // Only show debugging message if this record was not about to expire anyway
                        if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond)
                                debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
                                        cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
+#endif
                        mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
                        }
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
                // Make a guess, based on the multi-packet query / known answer counts, whether we think we
                // should have seen an answer for this. (We multiply MPQ by 4 and MPKA by 5, to allow for
                // possible packet loss of up to 20% of the additional KA packets.)
@@ -4384,6 +5958,7 @@ exit:
                                remain = kDefaultReconfirmTimeForNoAnswer;
                        mDNS_Reconfirm_internal(m, cr, remain);
                        }
+#endif
                }
        
        while (DupQuestions)
@@ -4458,15 +6033,16 @@ struct UDPSocket_struct
        mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
        };
 
-mDNSlocal const DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question)
+mDNSlocal DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question)
        {
        DNSQuestion *q;
        for (q = m->Questions; q; q=q->next)
-               if (mDNSSameIPPort(q->LocalSocket ? q->LocalSocket->port : MulticastDNSPort, port) &&
-                       mDNSSameOpaque16(q->TargetQID,         id)         &&
-                       q->qtype                  == question->qtype       &&
-                       q->qclass                 == question->qclass      &&
-                       q->qnamehash              == question->qnamehash   &&
+               if (q->LocalSocket &&
+                       mDNSSameIPPort  (q->LocalSocket->port, port)     &&
+                       mDNSSameOpaque16(q->TargetQID,         id)       &&
+                       q->qtype                  == question->qtype     &&
+                       q->qclass                 == question->qclass    &&
+                       q->qnamehash              == question->qnamehash &&
                        SameDomainName(&q->qname, &question->qname))
                        return(q);
        return(mDNSNULL);
@@ -4478,19 +6054,19 @@ mDNSlocal mDNSBool ExpectingUnicastResponseForRecord(mDNS *const m, const mDNSAd
        (void)id;
        (void)srcaddr;
        for (q = m->Questions; q; q=q->next)
-               if (ResourceRecordAnswersQuestion(&rr->resrec, q))
+               if (!q->DuplicateOf && ResourceRecordAnswersQuestion(&rr->resrec, q))
                        {
                        if (!mDNSOpaque16IsZero(q->TargetQID))
                                {
                                debugf("ExpectingUnicastResponseForRecord msg->h.id %d q->TargetQID %d for %s", mDNSVal16(id), mDNSVal16(q->TargetQID), CRDisplayString(m, rr));
                                if (mDNSSameOpaque16(q->TargetQID, id))
                                        {
-                                       if (mDNSSameIPPort(q->LocalSocket ? q->LocalSocket->port : MulticastDNSPort, port)) return(mDNStrue);
+                                       if (q->LocalSocket && mDNSSameIPPort(q->LocalSocket->port, port)) return(mDNStrue);
                                //      if (mDNSSameAddress(srcaddr, &q->Target))                   return(mDNStrue);
                                //      if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking
                                //      if (TrustedSource(m, srcaddr))                              return(mDNStrue);
-                                       LogOperation("WARNING: Ignoring suspect uDNS response for %##s (%s) [q->Target %#a] from %#a: %s",
-                                               q->qname.c, DNSTypeName(q->qtype), &q->Target, srcaddr, CRDisplayString(m, rr));
+                                       LogInfo("WARNING: Ignoring suspect uDNS response for %##s (%s) [q->Target %#a:%d] from %#a:%d %s",
+                                               q->qname.c, DNSTypeName(q->qtype), &q->Target, mDNSVal16(q->LocalSocket ? q->LocalSocket->port : zeroIPPort), srcaddr, mDNSVal16(port), CRDisplayString(m, rr));
                                        return(mDNSfalse);
                                        }
                                }
@@ -4503,26 +6079,31 @@ mDNSlocal mDNSBool ExpectingUnicastResponseForRecord(mDNS *const m, const mDNSAd
        return(mDNSfalse);
        }
 
-mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg)
+// Certain data types need more space for in-memory storage than their in-packet rdlength would imply
+// Currently this applies only to rdata types containing more than one domainname,
+// or types where the domainname is not the last item in the structure.
+// In addition, NSEC currently requires less space for in-memory storage than its in-packet representation.
+mDNSlocal mDNSu16 GetRDLengthMem(const ResourceRecord *const rr)
        {
-       CacheRecord *rr = mDNSNULL;
-
-       // Certain data types need more space for in-memory storage than their in-packet rdlength would imply
-       // Currently this applies only to rdata types containing more than one domainname,
-       // or types where the domainname is not the last item in the structure
-       mDNSu16 RDLength;
-       switch (m->rec.r.resrec.rrtype)
+       switch (rr->rrtype)
                {
-               case kDNSType_SOA: RDLength = sizeof(rdataSOA);         break;
-               case kDNSType_RP:  RDLength = sizeof(rdataRP);          break;
-               case kDNSType_PX:  RDLength = sizeof(rdataPX);          break;
-               default:           RDLength = m->rec.r.resrec.rdlength; break;
+               case kDNSType_SOA: return sizeof(rdataSOA);
+               case kDNSType_RP:  return sizeof(rdataRP);
+               case kDNSType_PX:  return sizeof(rdataPX);
+               case kDNSType_NSEC:return sizeof(rdataNSEC);
+               default:           return rr->rdlength;
                }
+       }
+
+mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg)
+       {
+       CacheRecord *rr = mDNSNULL;
+       mDNSu16 RDLength = GetRDLengthMem(&m->rec.r.resrec);
 
        if (!m->rec.r.resrec.InterfaceID) debugf("CreateNewCacheEntry %s", CRDisplayString(m, &m->rec.r));
 
        //if (RDLength > InlineCacheRDSize)
-       //      LogOperation("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r));
+       //      LogInfo("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r));
 
        if (!cg) cg = GetCacheGroup(m, slot, &m->rec.r.resrec); // If we don't have a CacheGroup for this name, make one now
        if (cg)  rr = GetCacheRecord(m, cg, RDLength);  // Make a cache record, being careful not to recycle cg
@@ -4535,9 +6116,9 @@ mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, C
                rr->resrec.name  = cg->name;                    // And set rr->resrec.name to point into our CacheGroup header
 
                // If this is an oversized record with external storage allocated, copy rdata to external storage
-               if      (rr->resrec.rdata == (RData*)&rr->rdatastorage && RDLength > InlineCacheRDSize)
+               if      (rr->resrec.rdata == (RData*)&rr->smallrdatastorage && RDLength > InlineCacheRDSize)
                        LogMsg("rr->resrec.rdata == &rr->rdatastorage but length > InlineCacheRDSize %##s", m->rec.r.resrec.name->c);
-               else if (rr->resrec.rdata != (RData*)&rr->rdatastorage && RDLength <= InlineCacheRDSize)
+               else if (rr->resrec.rdata != (RData*)&rr->smallrdatastorage && RDLength <= InlineCacheRDSize)
                        LogMsg("rr->resrec.rdata != &rr->rdatastorage but length <= InlineCacheRDSize %##s", m->rec.r.resrec.name->c);
                if (RDLength > InlineCacheRDSize)
                        mDNSPlatformMemCopy(rr->resrec.rdata, m->rec.r.resrec.rdata, sizeofRDataHeader + RDLength);
@@ -4553,7 +6134,7 @@ mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, C
                else
                        rr->DelayDelivery = CheckForSoonToExpireRecords(m, rr->resrec.name, rr->resrec.namehash, slot);
 
-               CacheRecordAdd(m, rr);  // CacheRecordAdd calls SetNextCacheCheckTime(m, rr); for us
+               CacheRecordAdd(m, rr);  // CacheRecordAdd calls SetNextCacheCheckTime(m, rr); for us
                }
        return(rr);
        }
@@ -4563,9 +6144,11 @@ mDNSlocal void RefreshCacheRecord(mDNS *const m, CacheRecord *rr, mDNSu32 ttl)
        rr->TimeRcvd             = m->timenow;
        rr->resrec.rroriginalttl = ttl;
        rr->UnansweredQueries = 0;
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
        rr->MPUnansweredQ     = 0;
        rr->MPUnansweredKA    = 0;
        rr->MPExpectingKA     = mDNSfalse;
+#endif
        SetNextCacheCheckTime(m, rr);
        }
 
@@ -4577,7 +6160,7 @@ mDNSexport void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 leas
        for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
                if (rr->CRActiveQuestion == q)
                        {
-                       //LogOperation("GrantCacheExtensions: new lease %d / %s", lease, CRDisplayString(m, rr));
+                       //LogInfo("GrantCacheExtensions: new lease %d / %s", lease, CRDisplayString(m, rr));
                        RefreshCacheRecord(m, rr, lease);
                        }
        }
@@ -4618,9 +6201,12 @@ mDNSlocal mDNSu32 GetEffectiveTTL(const uDNS_LLQType LLQType, mDNSu32 ttl)               // T
        return ttl;
        }
 
-// NOTE: mDNSCoreReceiveResponse calls mDNS_Deregister_internal which can call a user callback, which may change
+// Note: mDNSCoreReceiveResponse calls mDNS_Deregister_internal which can call a user callback, which may change
 // the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
+// InterfaceID non-NULL tells us the interface this multicast response was received on
+// InterfaceID NULL tells us this was a unicast response
+// dstaddr NULL tells us we received this over an outgoing TCP connection we made
 mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
        const DNSMessage *const response, const mDNSu8 *end,
        const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
@@ -4643,11 +6229,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
        int firstauthority  =                   response->h.numAnswers;
        int firstadditional = firstauthority  + response->h.numAuthorities;
        int totalrecords    = firstadditional + response->h.numAdditionals;
-       const mDNSu8 *ptr = response->data;
-
-       // Currently used only for display in debugging message
-       (void)srcport;
-       (void)dstport;
+       const mDNSu8 *ptr   = response->data;
 
        debugf("Received Response from %#-15a addressed to %#-15a on %p with "
                "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s LLQType %d",
@@ -4657,6 +6239,21 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                response->h.numAuthorities, response->h.numAuthorities == 1 ? "y,  " : "ies,",
                response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s", LLQType);
 
+       // According to RFC 2181 <http://www.ietf.org/rfc/rfc2181.txt>
+       //    When a DNS client receives a reply with TC
+       //    set, it should ignore that response, and query again, using a
+       //    mechanism, such as a TCP connection, that will permit larger replies.
+       // It feels wrong to be throwing away data after the network went to all the trouble of delivering it to us, but
+       // delivering some records of the RRSet first and then the remainder a couple of milliseconds later was causing
+       // failures in our Microsoft Active Directory client, which expects to get the entire set of answers at once.
+       // <rdar://problem/6690034> Can't bind to Active Directory
+       // In addition, if the client immediately canceled its query after getting the initial partial response, then we'll
+       // abort our TCP connection, and not complete the operation, and end up with an incomplete RRSet in our cache.
+       // Next time there's a query for this RRSet we'll see answers in our cache, and assume we have the whole RRSet already,
+       // and not even do the TCP query.
+       // Accordingly, if we get a uDNS reply with kDNSFlag0_TC set, we bail out and wait for the TCP response containing the entire RRSet.
+       if (!InterfaceID && (response->h.flags.b[0] & kDNSFlag0_TC)) return;
+
        if (LLQType == uDNS_LLQ_Ignore) return;
 
        // 1. We ignore questions (if any) in mDNS response packets
@@ -4671,6 +6268,9 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
        // in this response packet are immediately deemed to be invalid.
        else
                {
+               mDNSu8 rcode = (mDNSu8)(response->h.flags.b[1] & kDNSFlag1_RC_Mask);
+               mDNSBool failure = !(rcode == kDNSFlag1_RC_NoErr || rcode == kDNSFlag1_RC_NXDomain || rcode == kDNSFlag1_RC_NotAuth);
+               mDNSBool returnEarly = mDNSfalse;
                // We could possibly combine this with the similar loop at the end of this function --
                // instead of tagging cache records here and then rescuing them if we find them in the answer section,
                // we could instead use the "m->PktNum" mechanism to tag each cache record with the packet number in
@@ -4679,23 +6279,46 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                // packet number, then we deduce they are old and delete them
                for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++)
                        {
-                       DNSQuestion q;
+                       DNSQuestion q, *qptr = mDNSNULL;
                        ptr = getQuestion(response, ptr, end, InterfaceID, &q);
-                       if (ptr && (!dstaddr || ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q)))
+                       if (ptr && (!dstaddr || (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q))))
                                {
-                               CacheRecord *rr;
-                               const mDNSu32 slot = HashSlot(&q.qname);
-                               CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname);
-                               for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
-                                       if (SameNameRecordAnswersQuestion(&rr->resrec, &q))
+                               if (!failure)
+                                       {
+                                       CacheRecord *rr;
+                                       const mDNSu32 slot = HashSlot(&q.qname);
+                                       CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname);
+                                       for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
+                                               if (q.InterfaceID == rr->resrec.InterfaceID && SameNameRecordAnswersQuestion(&rr->resrec, &q))
+                                                       {
+                                                       debugf("uDNS marking %p %##s (%s) %p %s", q.InterfaceID, q.qname.c, DNSTypeName(q.qtype),
+                                                               rr->resrec.InterfaceID, CRDisplayString(m, rr));
+                                                       // Don't want to disturb rroriginalttl here, because code below might need it for the exponential backoff doubling algorithm
+                                                       rr->TimeRcvd          = m->timenow - TicksTTL(rr) - 1;
+                                                       rr->UnansweredQueries = MaxUnansweredQueries;
+                                                       }
+                                       }
+                               else
+                                       {
+                                       if (qptr)
                                                {
-                                               //LogMsg("uDNS marking %s", CRDisplayString(m, rr));
-                                               // Don't want to disturb rroriginalttl here, because code below might need it for the exponential backoff doubling algorithm
-                                               rr->TimeRcvd          = m->timenow - TicksTTL(rr) - 1;
-                                               rr->UnansweredQueries = MaxUnansweredQueries;
+                                               LogInfo("Server %p responded with code %d to query %##s (%s)", qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype));
+                                               PushDNSServerToEnd(m, qptr);
                                                }
+                                       returnEarly = mDNStrue;
+                                       }
                                }
                        }
+               if (returnEarly)
+                       {
+                       LogInfo("Ignoring %2d Answer%s %2d Authorit%s %2d Additional%s",
+                               response->h.numAnswers,     response->h.numAnswers     == 1 ? ", " : "s,",
+                               response->h.numAuthorities, response->h.numAuthorities == 1 ? "y,  " : "ies,",
+                               response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s");
+                       // not goto exit because we won't have any CacheFlushRecords and we do not want to
+                       // generate negative cache entries (we want to query the next server)
+                       return;
+                       }
                }
 
        for (i = 0; i < totalrecords && ptr && ptr < end; i++)
@@ -4727,7 +6350,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                if (!AcceptableResponse) AcceptableResponse = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r);
 
                // 1. Check that this packet resource record does not conflict with any of ours
-               if (mDNSOpaque16IsZero(response->h.id))
+               if (mDNSOpaque16IsZero(response->h.id) && m->rec.r.resrec.rrtype != kDNSType_NSEC)
                        {
                        if (m->CurrentRecord)
                                LogMsg("mDNSCoreReceiveResponse ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
@@ -4740,10 +6363,11 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                                // For other unicast responses, this code accepts them only for responses with an
                                // (apparently) local source address that pertain to a record of our own that's in probing state
                                if (!AcceptableResponse && !(ResponseSrcLocal && rr->resrec.RecordType == kDNSRecordTypeUnique)) continue;
+
                                if (PacketRRMatchesSignature(&m->rec.r, rr))            // If interface, name, type (if shared record) and class match...
                                        {
                                        // ... check to see if type and rdata are identical
-                                       if (m->rec.r.resrec.rrtype == rr->resrec.rrtype && SameRData(&m->rec.r.resrec, &rr->resrec))
+                                       if (IdenticalSameNameRecord(&m->rec.r.resrec, &rr->resrec))
                                                {
                                                // If the RR in the packet is identical to ours, just check they're not trying to lower the TTL on us
                                                if (m->rec.r.resrec.rroriginalttl >= rr->resrec.rroriginalttl/2 || m->SleepState)
@@ -4760,44 +6384,54 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                                        // else, the packet RR has different type or different rdata -- check to see if this is a conflict
                                        else if (m->rec.r.resrec.rroriginalttl > 0 && PacketRRConflict(m, rr, &m->rec.r))
                                                {
-                                               debugf("mDNSCoreReceiveResponse: Our Record: %08lX %s", rr->     resrec.rdatahash, ARDisplayString(m, rr));
-                                               debugf("mDNSCoreReceiveResponse: Pkt Record: %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
+                                               LogInfo("mDNSCoreReceiveResponse: Pkt Record: %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
+                                               LogInfo("mDNSCoreReceiveResponse: Our Record: %08lX %s", rr->     resrec.rdatahash, ARDisplayString(m, rr));
        
                                                // If this record is marked DependentOn another record for conflict detection purposes,
                                                // then *that* record has to be bumped back to probing state to resolve the conflict
-                                               while (rr->DependentOn) rr = rr->DependentOn;
+                                               if (rr->DependentOn)
+                                                       {
+                                                       while (rr->DependentOn) rr = rr->DependentOn;
+                                                       LogInfo("mDNSCoreReceiveResponse: Dep Record: %08lX %s", rr->     resrec.rdatahash, ARDisplayString(m, rr));
+                                                       }
        
                                                // If we've just whacked this record's ProbeCount, don't need to do it again
-                                               if (rr->ProbeCount <= DefaultProbeCountForTypeUnique)
+                                               if (rr->ProbeCount > DefaultProbeCountForTypeUnique)
+                                                       LogInfo("mDNSCoreReceiveResponse: Already reset to Probing: %s", ARDisplayString(m, rr));
+                                               else if (rr->ProbeCount == DefaultProbeCountForTypeUnique)
+                                                       LogMsg("mDNSCoreReceiveResponse: Ignoring response received before we even began probing: %s", ARDisplayString(m, rr));
+                                               else
                                                        {
+                                                       LogMsg("mDNSCoreReceiveResponse: Received from %#a:%d %s", srcaddr, mDNSVal16(srcport), CRDisplayString(m, &m->rec.r));
                                                        // If we'd previously verified this record, put it back to probing state and try again
                                                        if (rr->resrec.RecordType == kDNSRecordTypeVerified)
                                                                {
-                                                               debugf("mDNSCoreReceiveResponse: Reseting to Probing: %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+                                                               LogMsg("mDNSCoreReceiveResponse: Reseting to Probing: %s", ARDisplayString(m, rr));
                                                                rr->resrec.RecordType     = kDNSRecordTypeUnique;
+                                                               // We set ProbeCount to one more than the usual value so we know we've already touched this record.
+                                                               // This is because our single probe for "example-name.local" could yield a response with (say) two A records and
+                                                               // three AAAA records in it, and we don't want to call RecordProbeFailure() five times and count that as five conflicts.
+                                                               // This special value is recognised and reset to DefaultProbeCountForTypeUnique in SendQueries().
                                                                rr->ProbeCount     = DefaultProbeCountForTypeUnique + 1;
-                                                               InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(kDNSRecordTypeUnique));
+                                                               rr->AnnounceCount  = InitialAnnounceCount;
+                                                               InitializeLastAPTime(m, rr);
                                                                RecordProbeFailure(m, rr);      // Repeated late conflicts also cause us to back off to the slower probing rate
                                                                }
                                                        // If we're probing for this record, we just failed
                                                        else if (rr->resrec.RecordType == kDNSRecordTypeUnique)
                                                                {
-                                                               debugf("mDNSCoreReceiveResponse: Will rename %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+                                                               LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; will rename %s", rr->ProbeCount, ARDisplayString(m, rr));
                                                                mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
                                                                }
-                                                       // We assumed this record must be unique, but we were wrong.
-                                                       // (e.g. There are two mDNSResponders on the same machine giving
-                                                       // different answers for the reverse mapping record.)
-                                                       // This is simply a misconfiguration, and we don't try to recover from it.
+                                                       // We assumed this record must be unique, but we were wrong. (e.g. There are two mDNSResponders on the same machine giving
+                                                       // different answers for the reverse mapping record.) This is simply a misconfiguration, and we don't try to recover from it.
                                                        else if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique)
                                                                {
-                                                               debugf("mDNSCoreReceiveResponse: Unexpected conflict on %##s (%s) -- discarding our record",
-                                                                       rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+                                                               LogMsg("mDNSCoreReceiveResponse: Unexpected conflict discarding %s", ARDisplayString(m, rr));
                                                                mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
                                                                }
                                                        else
-                                                               debugf("mDNSCoreReceiveResponse: Unexpected record type %X %##s (%s)",
-                                                                       rr->resrec.RecordType, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+                                                               LogMsg("mDNSCoreReceiveResponse: Unexpected record type %X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
                                                        }
                                                }
                                        // Else, matching signature, different type or rdata, but not a considered a conflict.
@@ -4813,7 +6447,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
 
                if (!AcceptableResponse)
                        {
-                       CacheRecord *cr;
+                       const CacheRecord *cr;
                        for (cr = CacheFlushRecords; cr != (CacheRecord*)1; cr = cr->NextInCFList)
                                {
                                domainname *target = GetRRDomainNameTarget(&cr->resrec);
@@ -4831,6 +6465,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                        const mDNSu32 slot = HashSlot(m->rec.r.resrec.name);
                        CacheGroup *cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec);
                        CacheRecord *rr;
+
                        // 2a. Check if this packet resource record is already in our cache
                        for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
                                {
@@ -4951,7 +6586,7 @@ exit:
                                                {
                                                if (!(r2->resrec.rroriginalttl == 240 && r1->resrec.rroriginalttl == 60 && r2->resrec.rrtype == kDNSType_TXT) &&
                                                        mDNSOpaque16IsZero(response->h.id))
-                                                       LogOperation("Correcting TTL from %4d to %4d for %s",
+                                                       LogInfo("Correcting TTL from %4d to %4d for %s",
                                                                r2->resrec.rroriginalttl, r1->resrec.rroriginalttl, CRDisplayString(m, r2));
                                                r2->resrec.rroriginalttl = r1->resrec.rroriginalttl;
                                                }
@@ -5012,122 +6647,356 @@ exit:
                ptr = getQuestion(response, ptr, end, InterfaceID, &q);
                if (ptr && (!dstaddr || ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q)))
                        {
-                       CacheRecord *rr, *neg = mDNSNULL;
-                       mDNSu32 slot = HashSlot(&q.qname);
-                       CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname);
-                       for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
-                               if (SameNameRecordAnswersQuestion(&rr->resrec, &q))
-                                       {
-                                       // 1. If we got a fresh answer to this query, then don't need to generate a negative entry
-                                       if (rr->TimeRcvd + TicksTTL(rr) - m->timenow > 0) break;
-                                       // 2. If we already had a negative entry, keep track of it so we can resurrect it instead of creating a new one
-                                       if (rr->resrec.RecordType == kDNSRecordTypePacketNegative) neg = rr;
-                                       }
-
-                       if (!rr)
+                       // When we're doing parallel unicast and multicast queries for dot-local names (for supporting Microsoft
+                       // Active Directory sites) we don't want to waste memory making negative cache entries for all the unicast answers.
+                       // Otherwise we just fill up our cache with negative entries for just about every single multicast name we ever look up
+                       // (since the Microsoft Active Directory server is going to assert that pretty much every single multicast name doesn't exist).
+                       // This is not only a waste of memory, but there's also the problem of those negative entries confusing us later -- e.g. we
+                       // suppress sending our mDNS query packet because we think we already have a valid (negative) answer to that query in our cache.
+                       // The one exception is that we *DO* want to make a negative cache entry for "local. SOA", for the (common) case where we're
+                       // *not* on a Microsoft Active Directory network, and there is no authoritative server for "local". Note that this is not
+                       // in conflict with the mDNS spec, because that spec says, "Multicast DNS Zones have no SOA record," so it's okay to cache
+                       // negative answers for "local. SOA" from a uDNS server, because the mDNS spec already says that such records do not exist :-)
+                       if (!InterfaceID && q.qtype != kDNSType_SOA && IsLocalDomain(&q.qname))
+                               LogInfo("Not generating negative cache entry for %##s (%s)", q.qname.c, DNSTypeName(q.qtype));
+                       else
                                {
-                               // We start off assuming a negative caching TTL of 60 seconds
-                               // but then look to see if we can find an SOA authority record to tell us a better value we should be using
-                               mDNSu32 negttl = 60;
-                               int repeat = 0;
-                               const domainname *name = &q.qname;
-                               mDNSu32           hash = q.qnamehash;
-
-                               // If we're going to make (or update) a negative entry, then look for the appropriate TTL from the SOA record
-                               if (response->h.numAuthorities && (ptr = LocateAuthorities(response, end)) != mDNSNULL)
-                                       {
-                                       ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-                                       if (ptr && m->rec.r.resrec.rrtype == kDNSType_SOA)
+                               CacheRecord *rr, *neg = mDNSNULL;
+                               mDNSu32 slot = HashSlot(&q.qname);
+                               CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname);
+                               for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
+                                       if (SameNameRecordAnswersQuestion(&rr->resrec, &q))
                                                {
-                                               mDNSu32 ttl_s = m->rec.r.resrec.rroriginalttl < m->rec.r.resrec.rdata->u.soa.min ?
-                                                                               m->rec.r.resrec.rroriginalttl : m->rec.r.resrec.rdata->u.soa.min;
-                                               if (negttl < ttl_s) negttl = ttl_s;
+                                               // 1. If we got a fresh answer to this query, then don't need to generate a negative entry
+                                               if (rr->TimeRcvd + TicksTTL(rr) - m->timenow > 0) break;
+                                               // 2. If we already had a negative entry, keep track of it so we can resurrect it instead of creating a new one
+                                               if (rr->resrec.RecordType == kDNSRecordTypePacketNegative) neg = rr;
+                                               }
+       
+                               if (!rr)
+                                       {
+                                       // We start off assuming a negative caching TTL of 60 seconds
+                                       // but then look to see if we can find an SOA authority record to tell us a better value we should be using
+                                       mDNSu32 negttl = 60;
+                                       int repeat = 0;
+                                       const domainname *name = &q.qname;
+                                       mDNSu32           hash = q.qnamehash;
        
-                                               // Special check for SOA queries: If we queried for a.b.c.d.com, and got no answer,
-                                               // with an Authority Section SOA record for d.com, then this is a hint that the authority
-                                               // is d.com, and consequently SOA records b.c.d.com and c.d.com don't exist either.
-                                               // To do this we set the repeat count so the while loop below will make a series of negative cache entries for us
-                                               if (q.qtype == kDNSType_SOA)
+                                       // Special case for our special Microsoft Active Directory "local SOA" check.
+                                       // Some cheap home gateways don't include an SOA record in the authority section when
+                                       // they send negative responses, so we don't know how long to cache the negative result.
+                                       // Because we don't want to keep hitting the root name servers with our query to find
+                                       // if we're on a network using Microsoft Active Directory using "local" as a private
+                                       // internal top-level domain, we make sure to cache the negative result for at least one day.
+                                       if (q.qtype == kDNSType_SOA && SameDomainName(&q.qname, &localdomain)) negttl = 60 * 60 * 24;
+       
+                                       // If we're going to make (or update) a negative entry, then look for the appropriate TTL from the SOA record
+                                       if (response->h.numAuthorities && (ptr = LocateAuthorities(response, end)) != mDNSNULL)
+                                               {
+                                               ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
+                                               if (ptr && m->rec.r.resrec.rrtype == kDNSType_SOA)
                                                        {
-                                                       int qcount = CountLabels(&q.qname);
-                                                       int scount = CountLabels(m->rec.r.resrec.name);
-                                                       if (qcount - 1 > scount)
-                                                               if (SameDomainName(SkipLeadingLabels(&q.qname, qcount - scount), m->rec.r.resrec.name))
-                                                                       repeat = qcount - 1 - scount;
+                                                       const rdataSOA *const soa = (const rdataSOA *)m->rec.r.resrec.rdata->u.data;
+                                                       mDNSu32 ttl_s = soa->min;
+                                                       // We use the lesser of the SOA.MIN field and the SOA record's TTL, *except*
+                                                       // for the SOA record for ".", where the record is reported as non-cacheable
+                                                       // (TTL zero) for some reason, so in this case we just take the SOA record's TTL as-is
+                                                       if (ttl_s > m->rec.r.resrec.rroriginalttl && m->rec.r.resrec.name->c[0])
+                                                               ttl_s = m->rec.r.resrec.rroriginalttl;
+                                                       if (negttl < ttl_s) negttl = ttl_s;
+               
+                                                       // Special check for SOA queries: If we queried for a.b.c.d.com, and got no answer,
+                                                       // with an Authority Section SOA record for d.com, then this is a hint that the authority
+                                                       // is d.com, and consequently SOA records b.c.d.com and c.d.com don't exist either.
+                                                       // To do this we set the repeat count so the while loop below will make a series of negative cache entries for us
+                                                       if (q.qtype == kDNSType_SOA)
+                                                               {
+                                                               int qcount = CountLabels(&q.qname);
+                                                               int scount = CountLabels(m->rec.r.resrec.name);
+                                                               if (qcount - 1 > scount)
+                                                                       if (SameDomainName(SkipLeadingLabels(&q.qname, qcount - scount), m->rec.r.resrec.name))
+                                                                               repeat = qcount - 1 - scount;
+                                                               }
                                                        }
+                                               m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
+                                               }
+       
+                                       // If we already had a negative entry in the cache, then we double our existing negative TTL. This is to avoid
+                                       // the case where the record doesn't exist (e.g. particularly for things like our lb._dns-sd._udp.<domain> query),
+                                       // and the server returns no SOA record (or an SOA record with a small MIN TTL) so we assume a TTL
+                                       // of 60 seconds, and we end up polling the server every minute for a record that doesn't exist.
+                                       // With this fix in place, when this happens, we double the effective TTL each time (up to one hour),
+                                       // so that we back off our polling rate and don't keep hitting the server continually.
+                                       if (neg)
+                                               {
+                                               if (negttl < neg->resrec.rroriginalttl * 2)
+                                                       negttl = neg->resrec.rroriginalttl * 2;
+                                               if (negttl > 3600)
+                                                       negttl = 3600;
+                                               }
+       
+                                       negttl = GetEffectiveTTL(LLQType, negttl);      // Add 25% grace period if necessary
+       
+                                       // If we already had a negative cache entry just update it, else make one or more new negative cache entries
+                                       if (neg)
+                                               {
+                                               debugf("Renewing negative TTL from %d to %d %s", neg->resrec.rroriginalttl, negttl, CRDisplayString(m, neg));
+                                               RefreshCacheRecord(m, neg, negttl);
+                                               }
+                                       else while (1)
+                                               {
+                                               debugf("mDNSCoreReceiveResponse making negative cache entry TTL %d for %##s (%s)", negttl, name->c, DNSTypeName(q.qtype));
+                                               MakeNegativeCacheRecord(m, &m->rec.r, name, hash, q.qtype, q.qclass, negttl, mDNSInterface_Any);
+                                               CreateNewCacheEntry(m, slot, cg);
+                                               m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
+                                               if (!repeat) break;
+                                               repeat--;
+                                               name = (const domainname *)(name->c + 1 + name->c[0]);
+                                               hash = DomainNameHashValue(name);
+                                               slot = HashSlot(name);
+                                               cg   = CacheGroupForName(m, slot, hash, name);
                                                }
-                                       m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
                                        }
+                               }
+                       }
+               }
+       }
 
-                               // If we already had a negative entry in the cache, then we double our existing negative TTL. This is to avoid
-                               // the case where the record doesn't exist (e.g. particularly for things like our lb._dns-sd._udp.<domain> query),
-                               // and the server returns no SOA record (or an SOA record with a small MIN TTL) so we assume a TTL
-                               // of 60 seconds, and we end up polling the server every minute for a record that doesn't exist.
-                               // With this fix in place, when this happens, we double the effective TTL each time (up to one hour),
-                               // so that we back off our polling rate and don't keep hitting the server continually.
-                               if (neg)
-                                       {
-                                       if (negttl < neg->resrec.rroriginalttl * 2)
-                                               negttl = neg->resrec.rroriginalttl * 2;
-                                       if (negttl > 3600)
-                                               negttl = 3600;
-                                       }
+mDNSlocal void SPSRecordCallback(mDNS *const m, AuthRecord *const ar, mStatus result)
+       {
+       if (result && result != mStatus_MemFree)
+               LogInfo("SPS Callback %d %s", result, ARDisplayString(m, ar));
 
-                               negttl = GetEffectiveTTL(LLQType, negttl);      // Add 25% grace period if necessary
+       if (result == mStatus_NameConflict)
+               {
+               LogMsg("Received Conflicting mDNS -- waking %s %.6a %s",
+                       InterfaceNameForID(m, ar->resrec.InterfaceID), &ar->WakeUp.HMAC, ARDisplayString(m, ar));
+               SendWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.IMAC, &ar->WakeUp.password);
+               }
+       else if (result == mStatus_MemFree)
+               {
+               m->ProxyRecords--;
+               mDNSPlatformMemFree(ar);
+               }
+       }
 
-                               // If we already had a negative cache entry just update it, else make one or more new negative cache entries
-                               if (neg)
-                                       {
-                                       LogOperation("Renewing negative TTL from %d to %d %s", neg->resrec.rroriginalttl, negttl, CRDisplayString(m, neg));
-                                       RefreshCacheRecord(m, neg, negttl);
-                                       }
-                               else while (1)
+mDNSlocal void mDNSCoreReceiveUpdate(mDNS *const m,
+       const DNSMessage *const msg, const mDNSu8 *end,
+       const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
+       const mDNSInterfaceID InterfaceID)
+       {
+       int i;
+       AuthRecord opt;
+       mDNSu8 *p = m->omsg.data;
+       OwnerOptData owner;
+       mDNSu32 updatelease = 0;
+       const mDNSu8 *ptr;
+
+       LogSPS("Received Update from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
+               "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s",
+               srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID,
+               msg->h.numQuestions,   msg->h.numQuestions   == 1 ? ", " : "s,",
+               msg->h.numAnswers,     msg->h.numAnswers     == 1 ? ", " : "s,",
+               msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y,  " : "ies,",
+               msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s");
+
+       if (!InterfaceID || !m->SPSSocket || !mDNSSameIPPort(dstport, m->SPSSocket->port)) return;
+
+       if (mDNS_PacketLoggingEnabled)
+               DumpPacket(m, mStatus_NoError, mDNSfalse, "UDP", srcaddr, srcport, dstaddr, dstport, msg, end);
+
+       ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space + DNSOpt_OwnerData_ID_Space);
+       if (ptr)
+               {
+               ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
+               if (ptr && m->rec.r.resrec.rrtype == kDNSType_OPT)
+                       {
+                       const rdataOPT *o;
+                       const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
+                       for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++)
+                               {
+                               if      (o->opt == kDNSOpt_Lease)                         updatelease = o->u.updatelease;
+                               else if (o->opt == kDNSOpt_Owner && o->u.owner.vers == 0) owner       = o->u.owner;
+                               }
+                       }
+               m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
+               }
+
+       InitializeDNSMessage(&m->omsg.h, msg->h.id, UpdateRespFlags);
+
+       if (!updatelease || !owner.HMAC.l[0])
+               {
+               static int msgs = 0;
+               if (msgs < 100)
+                       {
+                       msgs++;
+                       LogMsg("Refusing sleep proxy registration from %#a:%d:%s%s", srcaddr, mDNSVal16(srcport),
+                               !updatelease ? " No lease" : "", !owner.HMAC.l[0] ? " No owner" : "");
+                       }
+               m->omsg.h.flags.b[1] |= kDNSFlag1_RC_FormErr;
+               }
+       else if (m->ProxyRecords + msg->h.mDNS_numUpdates > MAX_PROXY_RECORDS)
+               {
+               static int msgs = 0;
+               if (msgs < 100)
+                       {
+                       msgs++;
+                       LogMsg("Refusing sleep proxy registration from %#a:%d: Too many records %d + %d = %d > %d", srcaddr, mDNSVal16(srcport),
+                               m->ProxyRecords, msg->h.mDNS_numUpdates, m->ProxyRecords + msg->h.mDNS_numUpdates, MAX_PROXY_RECORDS);
+                       }
+               m->omsg.h.flags.b[1] |= kDNSFlag1_RC_Refused;
+               }
+       else
+               {
+               LogSPS("Received Update for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &owner.HMAC, &owner.IMAC, &owner.password, owner.seq);
+       
+               if (updatelease > 24 * 60 * 60)
+                       updatelease = 24 * 60 * 60;
+       
+               if (updatelease > 0x40000000UL / mDNSPlatformOneSecond)
+                       updatelease = 0x40000000UL / mDNSPlatformOneSecond;
+       
+               ptr = LocateAuthorities(msg, end);
+               for (i = 0; i < msg->h.mDNS_numUpdates && ptr && ptr < end; i++)
+                       {
+                       ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
+                       if (ptr)
+                               {
+                               mDNSu16 RDLengthMem = GetRDLengthMem(&m->rec.r.resrec);
+                               AuthRecord *ar = mDNSPlatformMemAllocate(sizeof(AuthRecord) - sizeof(RDataBody) + RDLengthMem);
+                               if (!ar) { m->omsg.h.flags.b[1] |= kDNSFlag1_RC_Refused; break; }
+                               else
                                        {
-                                       LogOperation("mDNSCoreReceiveResponse making negative cache entry TTL %d for %##s (%s)", negttl, name->c, DNSTypeName(q.qtype));
-                                       MakeNegativeCacheRecord(m, name, hash, q.qtype, q.qclass, negttl);
-                                       CreateNewCacheEntry(m, slot, cg);
-                                       m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
-                                       if (!repeat) break;
-                                       repeat--;
-                                       name = (const domainname *)(name->c + 1 + name->c[0]);
-                                       hash = DomainNameHashValue(name);
-                                       slot = HashSlot(name);
-                                       cg   = CacheGroupForName(m, slot, hash, name);
+                                       mDNSu8 RecordType = m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask ? kDNSRecordTypeUnique : kDNSRecordTypeShared;
+                                       m->rec.r.resrec.rrclass &= ~kDNSClass_UniqueRRSet;
+                                       mDNS_SetupResourceRecord(ar, mDNSNULL, InterfaceID, m->rec.r.resrec.rrtype, m->rec.r.resrec.rroriginalttl, RecordType, SPSRecordCallback, ar);
+                                       AssignDomainName(&ar->namestorage, m->rec.r.resrec.name);
+                                       ar->resrec.rdlength = GetRDLength(&m->rec.r.resrec, mDNSfalse);
+                                       ar->resrec.rdata->MaxRDLength = RDLengthMem;
+                                       mDNSPlatformMemCopy(ar->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, RDLengthMem);
+                                       ar->WakeUp = owner;
+                                       if (m->rec.r.resrec.rrtype == kDNSType_PTR)
+                                               {
+                                               mDNSs32 t = ReverseMapDomainType(m->rec.r.resrec.name);
+                                               if      (t == mDNSAddrType_IPv4) GetIPv4FromName(&ar->AddressProxy, m->rec.r.resrec.name);
+                                               else if (t == mDNSAddrType_IPv6) GetIPv6FromName(&ar->AddressProxy, m->rec.r.resrec.name);
+                                               debugf("mDNSCoreReceiveUpdate: PTR %d %d %#a %s", t, ar->AddressProxy.type, &ar->AddressProxy, ARDisplayString(m, ar));
+                                               if (ar->AddressProxy.type) SetSPSProxyListChanged(InterfaceID);
+                                               }
+                                       ar->TimeRcvd   = m->timenow;
+                                       ar->TimeExpire = m->timenow + updatelease * mDNSPlatformOneSecond;
+                                       if (m->NextScheduledSPS - ar->TimeExpire > 0)
+                                               m->NextScheduledSPS = ar->TimeExpire;
+                                       mDNS_Register_internal(m, ar);
+                                       // For now, since we don't get IPv6 ND or data packets, we don't advertise AAAA records for our SPS clients
+                                       if (ar->resrec.rrtype == kDNSType_AAAA) ar->resrec.rroriginalttl = 0;
+                                       m->ProxyRecords++;
+                                       LogSPS("SPS Registered %4d %X %s", m->ProxyRecords, RecordType, ARDisplayString(m,ar));
                                        }
                                }
+                       m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
+                       }
+
+               if (m->omsg.h.flags.b[1] & kDNSFlag1_RC_Mask)
+                       {
+                       LogMsg("Refusing sleep proxy registration from %#a:%d: Out of memory", srcaddr, mDNSVal16(srcport));
+                       ClearProxyRecords(m, &owner, m->DuplicateRecords);
+                       ClearProxyRecords(m, &owner, m->ResourceRecords);
+                       }
+               else
+                       {
+                       mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
+                       opt.resrec.rrclass    = NormalMaxDNSMessageData;
+                       opt.resrec.rdlength   = sizeof(rdataOPT);       // One option in this OPT record
+                       opt.resrec.rdestimate = sizeof(rdataOPT);
+                       opt.resrec.rdata->u.opt[0].opt           = kDNSOpt_Lease;
+                       opt.resrec.rdata->u.opt[0].u.updatelease = updatelease;
+                       p = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
                        }
                }
-       }
 
-mDNSexport void MakeNegativeCacheRecord(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds)
-       {
+       if (p) mDNSSendDNSMessage(m, &m->omsg, p, InterfaceID, m->SPSSocket, srcaddr, srcport, mDNSNULL, mDNSNULL);
+       }
+
+mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSInterfaceID InterfaceID)
+       {
+       if (InterfaceID)
+               {
+               AuthRecord *rr;
+               mDNSu32 updatelease = 60 * 60;          // If SPS fails to indicate lease time, assume one hour
+               const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space);
+               if (ptr)
+                       {
+                       ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
+                       if (ptr && m->rec.r.resrec.rrtype == kDNSType_OPT)
+                               {
+                               const rdataOPT *o;
+                               const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
+                               for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++)
+                                       if (o->opt == kDNSOpt_Lease)
+                                               {
+                                               updatelease = o->u.updatelease;
+                                               LogSPS("Sleep Proxy granted lease time %4d seconds", updatelease);
+                                               }
+                               }
+                       m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
+                       }
+
+               for (rr = m->ResourceRecords; rr; rr=rr->next)
+                       if (rr->resrec.InterfaceID == InterfaceID || (!rr->resrec.InterfaceID && (rr->ForceMCast || IsLocalDomain(rr->resrec.name))))
+                               if (mDNSSameOpaque16(rr->updateid, msg->h.id))
+                                       {
+                                       rr->updateid = zeroID;
+                                       rr->expire   = NonZeroTime(m->timenow + updatelease * mDNSPlatformOneSecond);
+                                       LogSPS("Sleep Proxy registered record %5d %s", updatelease, ARDisplayString(m,rr));
+                                       }
+
+               }
+       // If we were waiting to go to sleep, then this SPS registration or wide-area record deletion
+       // may have been the thing we were waiting for, so schedule another check to see if we can sleep now.
+       if (m->SleepLimit) m->NextScheduledSPRetry = m->timenow;
+       }
+
+mDNSexport void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr,
+       const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds, mDNSInterfaceID InterfaceID)
+       {
+       if (cr == &m->rec.r && m->rec.r.resrec.RecordType)
+               {
+               LogMsg("MakeNegativeCacheRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r));
+#if ForceAlerts
+               *(long*)0 = 0;
+#endif
+               }
+
        // Create empty resource record
-       m->rec.r.resrec.RecordType    = kDNSRecordTypePacketNegative;
-       m->rec.r.resrec.InterfaceID   = mDNSInterface_Any;
-       m->rec.r.resrec.name          = name;   // Will be updated to point to cg->name when we call CreateNewCacheEntry
-       m->rec.r.resrec.rrtype        = rrtype;
-       m->rec.r.resrec.rrclass       = rrclass;
-       m->rec.r.resrec.rroriginalttl = ttl_seconds;
-       m->rec.r.resrec.rdlength      = 0;
-       m->rec.r.resrec.rdestimate    = 0;
-       m->rec.r.resrec.namehash      = namehash;
-       m->rec.r.resrec.rdatahash     = 0;
-       m->rec.r.resrec.rdata = (RData*)&m->rec.r.rdatastorage;
-       m->rec.r.resrec.rdata->MaxRDLength = m->rec.r.resrec.rdlength;
-
-       m->rec.r.NextInKAList       = mDNSNULL;
-       m->rec.r.TimeRcvd           = m->timenow;
-       m->rec.r.DelayDelivery      = 0;
-       m->rec.r.NextRequiredQuery  = m->timenow;
-       m->rec.r.LastUsed           = m->timenow;
-       m->rec.r.CRActiveQuestion   = mDNSNULL;
-       m->rec.r.UnansweredQueries  = 0;
-       m->rec.r.LastUnansweredTime = 0;
-       m->rec.r.MPUnansweredQ      = 0;
-       m->rec.r.MPLastUnansweredQT = 0;
-       m->rec.r.MPUnansweredKA     = 0;
-       m->rec.r.MPExpectingKA      = mDNSfalse;
-       m->rec.r.NextInCFList       = mDNSNULL;
+       cr->resrec.RecordType    = kDNSRecordTypePacketNegative;
+       cr->resrec.InterfaceID   = InterfaceID;
+       cr->resrec.name          = name;        // Will be updated to point to cg->name when we call CreateNewCacheEntry
+       cr->resrec.rrtype        = rrtype;
+       cr->resrec.rrclass       = rrclass;
+       cr->resrec.rroriginalttl = ttl_seconds;
+       cr->resrec.rdlength      = 0;
+       cr->resrec.rdestimate    = 0;
+       cr->resrec.namehash      = namehash;
+       cr->resrec.rdatahash     = 0;
+       cr->resrec.rdata = (RData*)&cr->smallrdatastorage;
+       cr->resrec.rdata->MaxRDLength = 0;
+
+       cr->NextInKAList       = mDNSNULL;
+       cr->TimeRcvd           = m->timenow;
+       cr->DelayDelivery      = 0;
+       cr->NextRequiredQuery  = m->timenow;
+       cr->LastUsed           = m->timenow;
+       cr->CRActiveQuestion   = mDNSNULL;
+       cr->UnansweredQueries  = 0;
+       cr->LastUnansweredTime = 0;
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
+       cr->MPUnansweredQ      = 0;
+       cr->MPLastUnansweredQT = 0;
+       cr->MPUnansweredKA     = 0;
+       cr->MPExpectingKA      = mDNSfalse;
+#endif
+       cr->NextInCFList       = mDNSNULL;
        }
 
 mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *const end,
@@ -5138,6 +7007,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co
        DNSMessage  *msg  = (DNSMessage *)pkt;
        const mDNSu8 StdQ = kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery;
        const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery;
+       const mDNSu8 UpdQ = kDNSFlag0_QR_Query    | kDNSFlag0_OP_Update;
        const mDNSu8 UpdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update;
        mDNSu8 QR_OP;
        mDNSu8 *ptr = mDNSNULL;
@@ -5164,6 +7034,10 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co
                        return;
                        }
                }
+#ifdef _LEGACY_NAT_TRAVERSAL_
+       else if (m->SSDPSocket && mDNSSameIPPort(dstport, m->SSDPSocket->port)) { debugf("Ignoring SSDP response from %#a:%d", srcaddr, mDNSVal16(srcport)); return; }
+#endif
+
 #endif
        if ((unsigned)(end - (mDNSu8 *)pkt) < sizeof(DNSMessageHeader)) { LogMsg("DNS Message too short"); return; }
        QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask);
@@ -5187,18 +7061,31 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co
                if (!mDNSOpaque16IsZero(msg->h.id)) // uDNS_ReceiveMsg only needs to get real uDNS responses, not "QU" mDNS responses
                        {
                        ifid = mDNSInterface_Any;
-                       if (mDNS_LogLevel >= MDNS_LOG_VERBOSE_DEBUG)
-                               DumpPacket(m, mDNSfalse, TLS ? "TLS" : !dstaddr ? "TCP" : "UDP", srcaddr, srcport, dstaddr, dstport, msg, end);
+                       if (mDNS_PacketLoggingEnabled)
+                               DumpPacket(m, mStatus_NoError, mDNSfalse, TLS ? "TLS" : !dstaddr ? "TCP" : "UDP", srcaddr, srcport, dstaddr, dstport, msg, end);
                        uDNS_ReceiveMsg(m, msg, end, srcaddr, srcport);
                        // Note: mDNSCore also needs to get access to received unicast responses
                        }
 #endif
        if      (QR_OP == StdQ) mDNSCoreReceiveQuery   (m, msg, end, srcaddr, srcport, dstaddr, dstport, ifid);
        else if (QR_OP == StdR) mDNSCoreReceiveResponse(m, msg, end, srcaddr, srcport, dstaddr, dstport, ifid);
-       else if (QR_OP != UpdR)
+       else if (QR_OP == UpdQ) mDNSCoreReceiveUpdate  (m, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID);
+       else if (QR_OP == UpdR) mDNSCoreReceiveUpdateR (m, msg, end,                                     InterfaceID);
+       else
                {
-               LogMsg("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d on %p (ignored)",
-                       msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID);
+               LogMsg("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)",
+                       msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end-(mDNSu8 *)pkt, InterfaceID);
+               if (mDNS_LoggingEnabled)
+                       {
+                       int i = 0;
+                       while (i<end-(mDNSu8 *)pkt)
+                               {
+                               char buffer[128];
+                               char *p = buffer + mDNS_snprintf(buffer, sizeof(buffer), "%04X", i);
+                               do if (i<end-(mDNSu8 *)pkt) p += mDNS_snprintf(p, sizeof(buffer), " %02X", ((mDNSu8 *)pkt)[i]); while (++i & 15);
+                               LogInfo("%s", buffer);
+                               }
+                       }
                }
        // Packet reception often causes a change to the task list:
        // 1. Inbound queries can cause us to need to send responses
@@ -5226,6 +7113,12 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co
 // doing a standard DNS query for the _dns-query-tls._tcp SRV record for company.com. If we make the latter (public) query
 // a duplicate of the former (private) query, then it will block forever waiting for an answer that will never come.
 
+// If IsLLQ(Q) is true, it means the question is both:
+// (a) long-lived and
+// (b) being performed by a unicast DNS long-lived query (either full LLQ, or polling)
+// for multicast questions, we don't want to treat LongLived as anything special
+#define IsLLQ(Q) ((Q)->LongLived && !mDNSOpaque16IsZero((Q)->TargetQID))
+
 mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuestion *const question)
        {
        DNSQuestion *q;
@@ -5238,7 +7131,7 @@ mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuest
                        SameQTarget(q, question)                &&                      // and same unicast/multicast target settings
                        q->qtype      == question->qtype        &&                      // type,
                        q->qclass     == question->qclass       &&                      // class,
-                       q->LongLived  == question->LongLived    &&                      // and long-lived status matches
+                       IsLLQ(q)      == IsLLQ(question)        &&                      // and long-lived status matches
                        (!q->AuthInfo || question->AuthInfo)    &&                      // to avoid deadlock, don't make public query dup of a private one
                        q->qnamehash  == question->qnamehash    &&
                        SameDomainName(&q->qname, &question->qname))            // and name
@@ -5285,20 +7178,20 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi
                        //      question->tcp        = mDNSNULL;
 
                                if (q->LocalSocket)
-                                       LogOperation("UpdateQuestionDuplicates transferred LocalSocket pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+                                       debugf("UpdateQuestionDuplicates transferred LocalSocket pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
 
                                if (q->nta)
                                        {
-                                       LogOperation("UpdateQuestionDuplicates transferred nta pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+                                       LogInfo("UpdateQuestionDuplicates transferred nta pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                                        q->nta->ZoneDataContext = q;
                                        }
 
                                // Need to work out how to safely transfer this state too -- appropriate context pointers need to be updated or the code will crash
-                               if (question->tcp) LogOperation("UpdateQuestionDuplicates did not transfer tcp pointer");
+                               if (question->tcp) LogInfo("UpdateQuestionDuplicates did not transfer tcp pointer");
 
                                if (question->state == LLQ_Established)
                                        {
-                                       LogOperation("UpdateQuestionDuplicates transferred LLQ state for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+                                       LogInfo("UpdateQuestionDuplicates transferred LLQ state for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                                        question->state = 0;    // Must zero question->state, or mDNS_StopQuery_internal will clean up and cancel our LLQ from the server
                                        }
 
@@ -5331,7 +7224,7 @@ mDNSlocal void LLQNATCallback(mDNS *m, NATTraversalInfo *n)
        DNSQuestion *q;
        (void)n;    // Unused
        mDNS_Lock(m);
-       LogOperation("LLQNATCallback external address:port %.4a:%u", &n->ExternalAddress, mDNSVal16(n->ExternalPort));
+       LogInfo("LLQNATCallback external address:port %.4a:%u", &n->ExternalAddress, mDNSVal16(n->ExternalPort));
        for (q = m->Questions; q; q=q->next)
                if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived)
                        startLLQHandshake(m, q);        // If ExternalPort is zero, will do StartLLQPolling instead
@@ -5350,15 +7243,13 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
                question->Target.type = mDNSAddrType_None;
                }
 
-       if (!question->Target.type)             // No question->Target specified, so clear TargetPort and TargetQID
-               {
-               question->TargetPort = zeroIPPort;
-               question->TargetQID  = zeroID;
-               }
+       if (!question->Target.type) question->TargetPort = zeroIPPort;  // If question->Target specified clear TargetPort
 
        question->TargetQID =
 #ifndef UNICAST_DISABLED
-               (question->InterfaceID != mDNSInterface_LocalOnly && !question->ForceMCast && !IsLocalDomain(&question->qname)) ? mDNS_NewMessageID(m) :
+               (question->Target.type || (question->InterfaceID == mDNSInterface_Unicast) ||
+               (question->InterfaceID != mDNSInterface_LocalOnly && !question->ForceMCast && !IsLocalDomain(&question->qname)))
+               ? mDNS_NewMessageID(m) :
 #endif // UNICAST_DISABLED
                zeroID;
 
@@ -5384,19 +7275,17 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
 
                if (*q)
                        {
-                       LogMsg("Error! Tried to add a question %##s (%s) that's already in the active list",
-                               question->qname.c, DNSTypeName(question->qtype));
+                       LogMsg("Error! Tried to add a question %##s (%s) %p that's already in the active list",
+                               question->qname.c, DNSTypeName(question->qtype), question);
                        return(mStatus_AlreadyRegistered);
                        }
 
                *q = question;
 
                // If this question is referencing a specific interface, verify it exists
-               if (question->InterfaceID && question->InterfaceID != mDNSInterface_LocalOnly)
+               if (question->InterfaceID && question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_Unicast)
                        {
-                       NetworkInterfaceInfo *intf;
-                       for (intf = m->HostInterfaces; intf; intf = intf->next)
-                               if (intf->InterfaceID == question->InterfaceID) break;
+                       NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID);
                        if (!intf)
                                LogMsg("Note: InterfaceID %p for question %##s (%s) not currently found in active interface list",
                                        question->InterfaceID, question->qname.c, DNSTypeName(question->qtype));
@@ -5429,6 +7318,11 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
                question->LastQTxTime       = m->timenow;
                question->CNAMEReferrals    = 0;
 
+               // We'll create our question->LocalSocket on demand, if needed.
+               // We won't need one for duplicate questions, or from questions answered immediately out of the cache.
+               // We also don't need one for LLQs because (when we're using NAT) we want them all to share a single
+               // NAT mapping for receiving inbound add/remove events.
+               question->LocalSocket       = mDNSNULL;
                question->qDNSServer        = mDNSNULL;
                question->unansweredQueries = 0;
                question->nta               = mDNSNULL;
@@ -5443,8 +7337,6 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
                question->ntries            = 0;
                question->id                = zeroOpaque64;
 
-               question->LocalSocket       = mDNSNULL;
-
                if (question->DuplicateOf) question->AuthInfo = question->DuplicateOf->AuthInfo;
 
                for (i=0; i<DupSuppressInfoSize; i++)
@@ -5472,18 +7364,6 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
                        // this routine with the question list data structures in an inconsistent state.
                        if (!mDNSOpaque16IsZero(question->TargetQID))
                                {
-                               // We don't want to make a separate UDP socket for LLQs because (when we're using NAT)
-                               // they all share a single NAT mapping for receiving inbound add/remove events.
-                               if (!question->DuplicateOf && !question->LongLived)
-                                       {
-                                       question->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
-                                       debugf("mDNS_StartQuery_internal: dup %p %##s (%s) port %d",
-                                               question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype), question->LocalSocket ? mDNSVal16(question->LocalSocket->port) : -1);
-                                       // If we fail to get a new on-demand socket (should only happen cases of the most extreme resource exhaustion)
-                                       // then we don't fail the query; we just let it use our pre-canned permanent socket, which is okay (it should
-                                       // never happen in normal operation, and even if it does we still have our cryptographically strong transaction ID).
-                                       }
-
                                question->qDNSServer = GetServerForName(m, &question->qname);
                                ActivateUnicastQuery(m, question, mDNSfalse);
 
@@ -5514,7 +7394,7 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
 // CancelGetZoneData is an internal routine (i.e. must be called with the lock already held)
 mDNSexport void CancelGetZoneData(mDNS *const m, ZoneData *nta)
        {
-       LogOperation("CancelGetZoneData %##s (%s)", nta->question.qname.c, DNSTypeName(nta->question.qtype));
+       debugf("CancelGetZoneData %##s (%s)", nta->question.qname.c, DNSTypeName(nta->question.qtype));
        mDNS_StopQuery_internal(m, &nta->question);
        mDNSPlatformMemFree(nta);
        }
@@ -5526,7 +7406,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
        CacheRecord *rr;
        DNSQuestion **qp = &m->Questions;
        
-       //LogOperation("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
+       //LogInfo("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
 
        if (question->InterfaceID == mDNSInterface_LocalOnly) qp = &m->LocalOnlyQuestions;
        while (*qp && *qp != question) qp=&(*qp)->next;
@@ -5608,7 +7488,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
                                LogMsg("mDNS_StopQuery ERROR LLQNAT.clientContext NULL");
                        else
                                {
-                               LogOperation("Stopping LLQNAT");
+                               LogInfo("Stopping LLQNAT");
                                mDNS_StopNATOperation_internal(m, &m->LLQNAT);
                                m->LLQNAT.clientContext = mDNSNULL; // Means LLQ NAT Traversal not running
                                }
@@ -5671,10 +7551,10 @@ mDNSexport mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const q
        status = mDNS_StopQuery_internal(m, question);
        if (status == mStatus_NoError && !qq)
                {
-               CacheRecord *rr;
+               const CacheRecord *rr;
                const mDNSu32 slot = HashSlot(&question->qname);
                CacheGroup *const cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname);
-               LogOperation("Generating terminal removes for %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
+               LogInfo("Generating terminal removes for %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
                for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
                        if (rr->resrec.RecordType != kDNSRecordTypePacketNegative && SameNameRecordAnswersQuestion(&rr->resrec, question))
                                {
@@ -5710,7 +7590,7 @@ mDNSexport mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr
        return(status);
        }
 
-mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
+mDNSlocal mStatus mDNS_StartBrowse_internal(mDNS *const m, DNSQuestion *const question,
        const domainname *const srv, const domainname *const domain,
        const mDNSInterfaceID InterfaceID, mDNSBool ForceMCast, mDNSQuestionCallback *Callback, void *Context)
        {
@@ -5734,7 +7614,18 @@ mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
                question->LastQTime     = m->timenow - question->ThisQInterval;
                }
 #endif // UNICAST_DISABLED
-       return(mDNS_StartQuery(m, question));
+       return(mDNS_StartQuery_internal(m, question));
+       }
+
+mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
+       const domainname *const srv, const domainname *const domain,
+       const mDNSInterfaceID InterfaceID, mDNSBool ForceMCast, mDNSQuestionCallback *Callback, void *Context)
+       {
+       mStatus status;
+       mDNS_Lock(m);
+       status = mDNS_StartBrowse_internal(m, question, srv, domain, InterfaceID, ForceMCast, Callback, Context);
+       mDNS_Unlock(m);
+       return(status);
        }
 
 mDNSlocal mDNSBool MachineHasActiveIPv6(mDNS *const m)
@@ -5834,7 +7725,7 @@ mDNSlocal void FoundServiceInfoTXT(mDNS *const m, DNSQuestion *question, const R
 mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
        {
        ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
-       //LogOperation("FoundServiceInfo %d %s", AddRecord, RRDisplayString(m, answer));
+       //LogInfo("FoundServiceInfo %d %s", AddRecord, RRDisplayString(m, answer));
        if (!AddRecord) return;
        
        if (answer->rrtype == kDNSType_A)
@@ -6054,7 +7945,7 @@ mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newt
                // even though there's no actual semantic change, so the mDNSPlatformMemSame() check doesn't help us.
                // To work around this, we simply unilaterally limit all legacy _ichat-type updates to a single announcement.
                if (SameDomainLabel(type.c, (mDNSu8*)"\x6_ichat")) rr->AnnounceCount = 1;
-               InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
+               InitializeLastAPTime(m, rr);
                while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
                if (!rr->UpdateBlocked && rr->UpdateCredits) rr->UpdateCredits--;
                if (!rr->NextUpdateCredit) rr->NextUpdateCredit = NonZeroTime(m->timenow + kUpdateCreditRefreshInterval);
@@ -6075,7 +7966,7 @@ mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newt
        return(mStatus_NoError);
        }
 
-// NOTE: mDNS_Deregister calls mDNS_Deregister_internal which can call a user callback, which may change
+// Note: mDNS_Deregister calls mDNS_Deregister_internal which can call a user callback, which may change
 // the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
 mDNSexport mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr)
@@ -6197,21 +8088,24 @@ mDNSexport void mDNS_SetFQDN(mDNS *const m)
 
        if (!AppendDomainLabel(&newmname, &m->hostlabel))  { LogMsg("ERROR: mDNS_SetFQDN: Cannot create MulticastHostname"); return; }
        if (!AppendLiteralLabelString(&newmname, "local")) { LogMsg("ERROR: mDNS_SetFQDN: Cannot create MulticastHostname"); return; }
-       if (SameDomainNameCS(&m->MulticastHostname, &newmname)) { LogMsg("mDNS_SetFQDN - hostname unchanged"); return; }
 
        mDNS_Lock(m);
 
-       AssignDomainName(&m->MulticastHostname, &newmname);
-       // 1. Stop advertising our address records on all interfaces
-       for (intf = m->HostInterfaces; intf; intf = intf->next)
-               if (intf->Advertise) DeadvertiseInterface(m, intf);
-
-       // 2. Start advertising our address records using the new name
-       for (intf = m->HostInterfaces; intf; intf = intf->next)
-               if (intf->Advertise) AdvertiseInterface(m, intf);
+       if (SameDomainNameCS(&m->MulticastHostname, &newmname)) debugf("mDNS_SetFQDN - hostname unchanged");
+       else
+               {
+               AssignDomainName(&m->MulticastHostname, &newmname);
+       
+               // 1. Stop advertising our address records on all interfaces
+               for (intf = m->HostInterfaces; intf; intf = intf->next)
+                       if (intf->Advertise) DeadvertiseInterface(m, intf);
+       
+               // 2. Start advertising our address records using the new name
+               for (intf = m->HostInterfaces; intf; intf = intf->next)
+                       if (intf->Advertise) AdvertiseInterface(m, intf);
+               }
 
-       // 3. Make sure that any SRV records (and the like) that reference our
-       // host name in their rdata get updated to reference this new host name
+       // 3. Make sure that any AutoTarget SRV records (and the like) get updated
        for (rr = m->ResourceRecords;  rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr);
        for (rr = m->DuplicateRecords; rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr);
        
@@ -6246,9 +8140,9 @@ mDNSlocal void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatu
                        m->MainCallback(m, mStatus_NameConflict);
 
                // 2. If the client callback didn't do it, add (or increment) an index ourselves
-               // This needs to be case-insensitive compare, because we need to know that the name has been changed so as to
+               // This needs to be case-INSENSITIVE compare, because we need to know that the name has been changed so as to
                // remedy the conflict, and a name that differs only in capitalization will just suffer the exact same conflict again.
-               if (SameDomainLabelCS(m->hostlabel.c, oldlabel.c))
+               if (SameDomainLabel(m->hostlabel.c, oldlabel.c))
                        IncrementLabelSuffix(&m->hostlabel, mDNSfalse);
                
                // 3. Generate the FQDNs from the hostlabel,
@@ -6263,7 +8157,7 @@ mDNSlocal void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatu
                debugf("mDNS_HostNameCallback: MemFree (ignored)");
                }
        else
-               LogMsg("mDNS_HostNameCallback: Unknown error %ld for registration of record %s", result,  rr->resrec.name->c);
+               LogMsg("mDNS_HostNameCallback: Unknown error %d for registration of record %s", result,  rr->resrec.name->c);
        }
 
 mDNSlocal void UpdateInterfaceProtocols(mDNS *const m, NetworkInterfaceInfo *active)
@@ -6279,10 +8173,80 @@ mDNSlocal void UpdateInterfaceProtocols(mDNS *const m, NetworkInterfaceInfo *act
                        }
        }
 
-mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping)
+mDNSlocal void RestartRecordGetZoneData(mDNS * const m)
        {
        AuthRecord *rr;
        ServiceRecordSet *s;
+
+       for (rr = m->ResourceRecords; rr; rr=rr->next)
+               if (AuthRecord_uDNS(rr))
+                       {
+                       debugf("RestartRecordGetZoneData: StartGetZoneData for %##s", rr->resrec.name->c);
+                       if (rr->nta) CancelGetZoneData(m, rr->nta);
+                       rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr);
+                       }
+
+       for (s = m->ServiceRegistrations; s; s = s->uDNS_next)
+               {
+               debugf("RestartRecordGetZoneData: StartGetZoneData for %##s", s->RR_SRV.resrec.name->c);
+               if (s->srs_nta) CancelGetZoneData(m, s->srs_nta);
+               s->srs_nta = StartGetZoneData(m, s->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, s);
+               }
+       }
+
+mDNSlocal void InitializeNetWakeState(mDNS *const m, NetworkInterfaceInfo *set)
+       {
+       int i;
+       set->NetWakeBrowse.ThisQInterval = -1;
+       for (i=0; i<3; i++)
+               {
+               set->NetWakeResolve[i].ThisQInterval = -1;
+               set->SPSAddr[i].type = mDNSAddrType_None;
+               }
+       set->NextSPSAttempt     = -1;
+       set->NextSPSAttemptTime = m->timenow;
+       }
+
+mDNSexport void mDNS_ActivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set)
+       {
+       NetworkInterfaceInfo *p = m->HostInterfaces;
+       while (p && p != set) p=p->next;
+       if (!p) { LogMsg("mDNS_ActivateNetWake_internal: NetworkInterfaceInfo %p not found in active list", set); return; }
+
+       if (set->InterfaceActive)
+               {
+               LogSPS("ActivateNetWake for %s (%#a)", set->ifname, &set->ip);
+               mDNS_StartBrowse_internal(m, &set->NetWakeBrowse, &SleepProxyServiceType, &localdomain, set->InterfaceID, mDNSfalse, m->SPSBrowseCallback, set);
+               }
+       }
+
+mDNSexport void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set)
+       {
+       NetworkInterfaceInfo *p = m->HostInterfaces;
+       while (p && p != set) p=p->next;
+       if (!p) { LogMsg("mDNS_DeactivateNetWake_internal: NetworkInterfaceInfo %p not found in active list", set); return; }
+
+       if (set->NetWakeBrowse.ThisQInterval >= 0)
+               {
+               int i;
+               LogSPS("DeactivateNetWake for %s (%#a)", set->ifname, &set->ip);
+
+               // Stop our browse and resolve operations
+               mDNS_StopQuery_internal(m, &set->NetWakeBrowse);
+               for (i=0; i<3; i++) if (set->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery_internal(m, &set->NetWakeResolve[i]);
+
+               // Make special call to the browse callback to let it know it can to remove all records for this interface
+               if (m->SPSBrowseCallback) m->SPSBrowseCallback(m, &set->NetWakeBrowse, mDNSNULL, mDNSfalse);
+
+               // Reset our variables back to initial state, so we're ready for when NetWake is turned back on
+               // (includes resetting NetWakeBrowse.ThisQInterval back to -1)
+               InitializeNetWakeState(m, set);
+               }
+       }
+
+mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping)
+       {
+       AuthRecord *rr;
        mDNSBool FirstOfType = mDNStrue;
        NetworkInterfaceInfo **p = &m->HostInterfaces;
 
@@ -6298,6 +8262,8 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
        set->InterfaceActive = mDNStrue;
        set->IPv4Available   = (set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx);
        set->IPv6Available   = (set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx);
+       
+       InitializeNetWakeState(m, set);
 
        // Scan list to see if this InterfaceID is already represented
        while (*p)
@@ -6327,11 +8293,13 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
        if (set->Advertise)
                AdvertiseInterface(m, set);
 
-       LogOperation("mDNS_RegisterInterface: InterfaceID %p %s (%#a) %s", set->InterfaceID, set->ifname, &set->ip,
+       LogInfo("mDNS_RegisterInterface: InterfaceID %p %s (%#a) %s", set->InterfaceID, set->ifname, &set->ip,
                set->InterfaceActive ?
                        "not represented in list; marking active and retriggering queries" :
                        "already represented in list; marking inactive for now");
        
+       if (set->NetWake) mDNS_ActivateNetWake_internal(m, set);
+
        // In early versions of OS X the IPv6 address remains on an interface even when the interface is turned off,
        // giving the false impression that there's an active representative of this interface when there really isn't.
        // Therefore, when registering an interface, we want to re-trigger our questions and re-probe our Resource Records,
@@ -6342,16 +8310,25 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
                // If flapping, delay between first and second queries is eight seconds instead of one
                mDNSs32 delay    = flapping ? mDNSPlatformOneSecond   * 5 : 0;
                mDNSu8  announce = flapping ? (mDNSu8)1                   : InitialAnnounceCount;
+               mDNSs32 newSS    = 0;
 
                // Use a small amount of randomness:
                // In the case of a network administrator turning on an Ethernet hub so that all the
                // connected machines establish link at exactly the same time, we don't want them all
                // to go and hit the network with identical queries at exactly the same moment.
-               if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval);
+               newSS = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval);
+#if APPLE_OSX_mDNSResponder
+               // We set this to at least 2 seconds, because the MacOSX platform layer typically gets lots
+               // of network change notifications in a row, and we don't know when we're done getting notified.
+               // Note that this will not be set if the interface doesn't do multicast (set->McastTxRx).
+               newSS += mDNSPlatformOneSecond * 2;
+#endif
+               if (!m->SuppressSending || newSS - m->SuppressSending < 0) m->SuppressSending = newSS;
                
                if (flapping)
                        {
-                       LogMsg("Note: Frequent transitions for interface %s (%#a); network traffic reduction measures in effect", set->ifname, &set->ip);
+                       LogMsg("Note: RegisterInterface: Frequent transitions for interface %s (%#a); network traffic reduction measures in effect",
+                               set->ifname, &set->ip);
                        if (!m->SuppressProbes ||
                                m->SuppressProbes - (m->timenow + delay) < 0)
                                m->SuppressProbes = (m->timenow + delay);
@@ -6364,7 +8341,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
                                        mDNSBool dodelay = flapping && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID);
                                        mDNSs32 initial  = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval;
                                        mDNSs32 qdelay   = dodelay ? mDNSPlatformOneSecond * 5 : 0;
-                                       if (dodelay) LogOperation("No cache records expired for %##s (%s); okay to delay questions a little", q->qname.c, DNSTypeName(q->qtype));
+                                       if (dodelay) LogInfo("No cache records expired for %##s (%s); okay to delay questions a little", q->qname.c, DNSTypeName(q->qtype));
                                                
                                        if (!q->ThisQInterval || q->ThisQInterval > initial)
                                                {
@@ -6385,30 +8362,17 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
                                        if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
                                        rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
                                        if (rr->AnnounceCount < announce) rr->AnnounceCount  = announce;
-                                       InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
+                                       InitializeLastAPTime(m, rr);
                                        }
                }
 
-       for (rr = m->ResourceRecords; rr; rr=rr->next)
-               if (AuthRecord_uDNS(rr))
-                       {
-                       LogOperation("mDNS_RegisterInterface: StartGetZoneData for %##s", rr->resrec.name->c);
-                       if (rr->nta) CancelGetZoneData(m, rr->nta);
-                       rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr);
-                       }
-
-       for (s = m->ServiceRegistrations; s; s = s->uDNS_next)
-               {
-               LogOperation("mDNS_RegisterInterface: StartGetZoneData for %##s", s->RR_SRV.resrec.name->c);
-               if (s->nta) CancelGetZoneData(m, s->nta);
-               s->nta = StartGetZoneData(m, s->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, s);
-               }
+       RestartRecordGetZoneData(m);
 
        mDNS_Unlock(m);
        return(mStatus_NoError);
        }
 
-// NOTE: mDNS_DeregisterInterface calls mDNS_Deregister_internal which can call a user callback, which may change
+// Note: mDNS_DeregisterInterface calls mDNS_Deregister_internal which can call a user callback, which may change
 // the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
 mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping)
@@ -6427,6 +8391,8 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se
        while (*p && *p != set) p=&(*p)->next;
        if (!*p) { debugf("mDNS_DeregisterInterface: NetworkInterfaceInfo not found in list"); mDNS_Unlock(m); return; }
 
+       mDNS_DeactivateNetWake_internal(m, set);
+
        // Unlink this record from our list
        *p = (*p)->next;
        set->next = mDNSNULL;
@@ -6441,16 +8407,17 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se
                }
        else
                {
-               NetworkInterfaceInfo *intf;
-               for (intf = m->HostInterfaces; intf; intf = intf->next)
-                       if (intf->InterfaceID == set->InterfaceID)
-                               break;
+               NetworkInterfaceInfo *intf = FirstInterfaceForID(m, set->InterfaceID);
                if (intf)
                        {
-                       LogOperation("mDNS_DeregisterInterface: Another representative of InterfaceID %p %s (%#a) exists;"
+                       LogInfo("mDNS_DeregisterInterface: Another representative of InterfaceID %p %s (%#a) exists;"
                                " making it active", set->InterfaceID, set->ifname, &set->ip);
+                       if (intf->InterfaceActive)
+                               LogMsg("mDNS_DeregisterInterface: ERROR intf->InterfaceActive already set for %s (%#a)", set->ifname, &set->ip);
                        intf->InterfaceActive = mDNStrue;
                        UpdateInterfaceProtocols(m, intf);
+
+                       if (intf->NetWake) mDNS_ActivateNetWake_internal(m, intf);
                        
                        // See if another representative *of the same type* exists. If not, we mave have gone from
                        // dual-stack to v6-only (or v4-only) so we need to reconfirm which records are still valid.
@@ -6467,11 +8434,11 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se
                        DNSQuestion *q;
                        DNSServer *s;
 
-                       LogOperation("mDNS_DeregisterInterface: Last representative of InterfaceID %p %s (%#a) deregistered;"
+                       LogInfo("mDNS_DeregisterInterface: Last representative of InterfaceID %p %s (%#a) deregistered;"
                                " marking questions etc. dormant", set->InterfaceID, set->ifname, &set->ip);
 
                        if (flapping)
-                               LogMsg("Note: Frequent transitions for interface %s (%#a); network traffic reduction measures in effect",
+                               LogMsg("Note: DeregisterInterface: Frequent transitions for interface %s (%#a); network traffic reduction measures in effect",
                                        set->ifname, &set->ip);
 
                        // 1. Deactivate any questions specific to this interface, and tag appropriate questions
@@ -6546,7 +8513,7 @@ mDNSlocal void ServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus resu
                if      (result == mStatus_NoError)      msg = "Name Registered";
                else if (result == mStatus_NameConflict) msg = "Name Conflict";
                else if (result == mStatus_MemFree)      msg = "Memory Free";
-               debugf("ServiceCallback: %##s (%s) %s (%ld)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), msg, result);
+               debugf("ServiceCallback: %##s (%s) %s (%d)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), msg, result);
                }
        #endif
 
@@ -6563,15 +8530,26 @@ mDNSlocal void ServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus resu
        
        if (result == mStatus_MemFree)
                {
-               // If the PTR record or any of the subtype PTR records are still in the process of deregistering,
-               // don't pass on the NameConflict/MemFree message until every record is finished cleaning up.
+               // If the SRV/TXT/PTR records, or the _services._dns-sd._udp record, or any of the subtype PTR records,
+               // are still in the process of deregistering, don't pass on the NameConflict/MemFree message until
+               // every record is finished cleaning up.
                mDNSu32 i;
+               if (sr->RR_SRV.resrec.RecordType != kDNSRecordTypeUnregistered) return;
+               if (sr->RR_TXT.resrec.RecordType != kDNSRecordTypeUnregistered) return;
                if (sr->RR_PTR.resrec.RecordType != kDNSRecordTypeUnregistered) return;
+               if (sr->RR_ADV.resrec.RecordType != kDNSRecordTypeUnregistered) return;
                for (i=0; i<sr->NumSubTypes; i++) if (sr->SubTypes[i].resrec.RecordType != kDNSRecordTypeUnregistered) return;
 
                // If this ServiceRecordSet was forcibly deregistered, and now its memory is ready for reuse,
                // then we can now report the NameConflict to the client
                if (sr->Conflict) result = mStatus_NameConflict;
+
+               if (sr->srs_nta)
+                       {
+                       LogMsg("ServiceCallback ERROR Got mStatus_MemFree with srs_nta still set for %s", ARDisplayString(m, &sr->RR_SRV));
+                       CancelGetZoneData(m, sr->srs_nta);
+                       sr->srs_nta = mDNSNULL;
+                       }
                }
 
        // CAUTION: MUST NOT do anything more with sr after calling sr->Callback(), because the client's callback
@@ -6587,6 +8565,7 @@ mDNSlocal void NSSCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
                sr->ServiceCallback(m, sr, result);
        }
 
+#if !defined(UNICAST_DISABLED) && USE_SEPARATE_UDNS_SERVICE_LIST
 mDNSlocal mStatus uDNS_RegisterService(mDNS *const m, ServiceRecordSet *srs)
        {
        mDNSu32 i;
@@ -6613,20 +8592,19 @@ mDNSlocal mStatus uDNS_RegisterService(mDNS *const m, ServiceRecordSet *srs)
                if (!AuthInfo || !AuthInfo->AutoTunnel) srs->RR_SRV.AutoTarget = Target_AutoHostAndNATMAP;
                }
 
-       if (!GetServiceTarget(m, srs))
+       if (!GetServiceTarget(m, &srs->RR_SRV))
                {
                // defer registration until we've got a target
-               LogOperation("uDNS_RegisterService - no target for %##s", srs->RR_SRV.resrec.name->c);
-               srs->state = regState_NoTarget;
-               srs->nta   = mDNSNULL;
+               LogInfo("uDNS_RegisterService - no target for %##s", srs->RR_SRV.resrec.name->c);
+               srs->state   = regState_NoTarget;
                return mStatus_NoError;
                }
 
        ActivateUnicastRegistration(m, &srs->RR_SRV);
        srs->state = regState_FetchingZoneData;
-       srs->nta   = mDNSNULL;
        return mStatus_NoError;
        }
+#endif
 
 // Note:
 // Name is first label of domain name (any dots in the name are actual dots, not label separators)
@@ -6655,6 +8633,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
        sr->SRSUpdateServer        = zeroAddr;
        sr->SRSUpdatePort          = zeroIPPort;
        mDNSPlatformMemZero(&sr->NATinfo, sizeof(sr->NATinfo));
+       sr->NATinfo.IntPort        = port;              // Record originally-requested port
        sr->ClientCallbackDeferred = 0;
        sr->DeferredStatus         = 0;
        sr->SRVUpdateDeferred      = 0;
@@ -6739,7 +8718,9 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
                }
        sr->RR_TXT.DependentOn = &sr->RR_SRV;
 
-#ifndef UNICAST_DISABLED
+       sr->srs_nta = mDNSNULL;
+
+#if !defined(UNICAST_DISABLED) && USE_SEPARATE_UDNS_SERVICE_LIST
        // If the client has specified an explicit InterfaceID,
        // then we do a multicast registration on that interface, even for unicast domains.
        if (!(InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&sr->RR_SRV.namestorage)))
@@ -6757,6 +8738,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
                return(status);
                }
 #endif
+
        mDNS_Lock(m);
        err = mDNS_Register_internal(m, &sr->RR_SRV);
        if (!err) err = mDNS_Register_internal(m, &sr->RR_TXT);
@@ -6780,7 +8762,7 @@ mDNSlocal void DummyCallback(mDNS *const m, AuthRecord *rr, mStatus result)
        (void)m;                // Unused
        (void)rr;               // Unused
        (void)result;   // Unused
-       LogOperation("DummyCallback %d %s", result, ARDisplayString(m, rr));
+       LogInfo("DummyCallback %d %s", result, ARDisplayString(m, rr));
        }
 
 mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr,
@@ -6851,7 +8833,7 @@ mDNSexport mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet
 
 mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname)
        {
-       // NOTE: Don't need to use mDNS_Lock(m) here, because this code is just using public routines
+       // Note: Don't need to use mDNS_Lock(m) here, because this code is just using public routines
        // mDNS_RegisterService() and mDNS_AddRecordToService(), which do the right locking internally.
        domainlabel name1, name2;
        domainname type, domain;
@@ -6868,8 +8850,8 @@ mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordS
                }
        
        if (SameDomainName(&domain, &localdomain))
-               LogMsg("%##s service renamed from \"%#s\" to \"%#s\"", type.c, name1.c, newname->c);
-       else LogMsg("%##s service (domain %##s) renamed from \"%#s\" to \"%#s\"",type.c, domain.c, name1.c, newname->c);
+               debugf("%##s service renamed from \"%#s\" to \"%#s\"", type.c, name1.c, newname->c);
+       else debugf("%##s service (domain %##s) renamed from \"%#s\" to \"%#s\"",type.c, domain.c, name1.c, newname->c);
 
        err = mDNS_RegisterService(m, sr, newname, &type, &domain,
                host, sr->RR_SRV.resrec.rdata->u.srv.port, sr->RR_TXT.resrec.rdata->u.txt.c, sr->RR_TXT.resrec.rdlength,
@@ -6889,7 +8871,7 @@ mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordS
        return(err);
        }
 
-// NOTE: mDNS_DeregisterService calls mDNS_Deregister_internal which can call a user callback,
+// Note: mDNS_DeregisterService calls mDNS_Deregister_internal which can call a user callback,
 // which may change the record list and/or question list.
 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
 mDNSexport mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr)
@@ -6897,7 +8879,7 @@ mDNSexport mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr)
        // If port number is zero, that means this was actually registered using mDNS_RegisterNoSuchService()
        if (mDNSIPPortIsZero(sr->RR_SRV.resrec.rdata->u.srv.port)) return(mDNS_DeregisterNoSuchService(m, &sr->RR_SRV));
 
-#ifndef UNICAST_DISABLED
+#if !defined(UNICAST_DISABLED) && USE_SEPARATE_UDNS_SERVICE_LIST
        if (!(sr->RR_SRV.resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(sr->RR_SRV.resrec.name)))
                {
                mStatus status;
@@ -7005,7 +8987,7 @@ mDNSexport mDNSOpaque16 mDNS_NewMessageID(mDNS * const m)
                AuthRecord *r;
                DNSQuestion *q;
                id = mDNSOpaque16fromIntVal(1 + mDNSRandom(0xFFFE));
-               for (r = m->ResourceRecords; r; r=r->next) if (mDNSSameOpaque16(id, r->id       )) continue;
+               for (r = m->ResourceRecords; r; r=r->next) if (mDNSSameOpaque16(id, r->updateid )) continue;
                for (q = m->Questions;       q; q=q->next) if (mDNSSameOpaque16(id, q->TargetQID)) continue;
                break;
                }
@@ -7013,6 +8995,267 @@ mDNSexport mDNSOpaque16 mDNS_NewMessageID(mDNS * const m)
        return id;
        }
 
+// ***************************************************************************
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Sleep Proxy Server
+#endif
+
+mDNSlocal void RestartProbing(mDNS *const m, AuthRecord *const rr)
+       {
+       // We reset ProbeCount, so we'll suppress our own answers for a while, to avoid generating ARP conflicts with a waking machine.
+       // If the machine does wake properly then we'll discard our records when we see the first new mDNS probe from that machine.
+       // If it does not wake (perhaps we just picked up a stray delayed packet sent before it went to sleep)
+       // then we'll transition out of probing state and start answering ARPs again.
+       rr->resrec.RecordType = kDNSRecordTypeUnique;
+       rr->ProbeCount        = DefaultProbeCountForTypeUnique;
+       rr->AnnounceCount     = InitialAnnounceCount;
+       InitializeLastAPTime(m, rr);
+       }
+
+mDNSexport void mDNSCoreReceiveRawPacket(mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID)
+       {
+       static const mDNSOpaque16 Ethertype_IP = { { 0x08, 0x00 } };
+       static const mDNSOpaque32 ARP_EthIP_h0 = { { 0x08, 0x06, 0x00, 0x01 } };        // Ethertype (ARP = 0x0806), Hardware address space (Ethernet = 1)
+       static const mDNSOpaque32 ARP_EthIP_h1 = { { 0x08, 0x00, 0x06, 0x04 } };        // Protocol address space (IP = 0x0800), hlen, plen
+       static const mDNSOpaque16 ARP_op_request = { { 0, 1 } };
+       const EthernetHeader *const eth = (const EthernetHeader *)p;
+       const ARP_EthIP      *const arp = (const ARP_EthIP      *)(eth+1);
+       const IPv4Header     *const v4  = (const IPv4Header     *)(eth+1);
+       const IPv6Header     *const v6  = (const IPv6Header     *)(eth+1);
+       if (end >= p+42 && *(mDNSu32*)(p+12) == ARP_EthIP_h0.NotAnInteger && *(mDNSu32*)(p+16) == ARP_EthIP_h1.NotAnInteger)
+               {
+               AuthRecord *rr;
+               NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
+               if (!intf) return;
+
+               debugf("Got ARP from %.4a/%.6a for %.4a", &arp->spa, &arp->sha, &arp->tpa);
+
+               mDNS_Lock(m);
+
+               // Pass 1:
+               // Process ARP Requests and Probes (but not Announcements), and generate an ARP Reply if necessary.
+               // We also process and answer ARPs from our own kernel (no special treatment for localhost).
+               // We ignore ARP Announcements here -- Announcements are not questions, they're assertions, so we don't need to answer them.
+               // The only time we might need to respond to an ARP Announcement is if it's a conflict -- and we check for that in Pass 2 below.
+               if (mDNSSameOpaque16(arp->op, ARP_op_request) && !mDNSSameIPv4Address(arp->spa, arp->tpa))
+                       for (rr = m->ResourceRecords; rr; rr=rr->next)
+                               if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, arp->tpa))
+                                       {
+                                       static const char msg1[] = "ARP Req from owner -- re-probing";
+                                       static const char msg2[] = "Ignoring  ARP Request from      ";
+                                       static const char msg3[] = "Creating Local ARP Cache entry  ";
+                                       static const char msg4[] = "Answering ARP Request from      ";
+                                       const char *const msg = mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC) ? msg1 :
+                                                                                       (rr->AnnounceCount == InitialAnnounceCount)     ? msg2 :
+                                                                                       mDNSSameEthAddress(&arp->sha, &intf->MAC)       ? msg3 : msg4;
+                                       LogSPS("%-7s %s %.6a %.4a for %.4a -- H-MAC %.6a I-MAC %.6a %s",
+                                               InterfaceNameForID(m, InterfaceID), msg, &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
+                                       if      (msg == msg1) RestartProbing(m, rr);
+                                       else if (msg == msg3) mDNSPlatformSetLocalARP(&arp->tpa, &rr->WakeUp.IMAC, InterfaceID);
+                                       else if (msg == msg4) SendARP(m, 2, rr, arp->tpa.b, arp->sha.b, arp->spa.b, arp->sha.b);
+                                       }
+
+               // Pass 2:
+               // For all types of ARP packet we check the Sender IP address to make sure it doesn't conflict with any AddressProxy record we're holding.
+               // (Strictly speaking we're only checking Announcement/Request/Reply packets, since ARP Probes have zero Sender IP address,
+               // so by definition (and by design) they can never conflict with any real (i.e. non-zero) IP address).
+               // We ignore ARPs we sent ourselves (Sender MAC address is our MAC address) because our own proxy ARPs do not constitute a conflict that we need to handle.
+               // If we see an apparently conflicting ARP, we check the sender hardware address:
+               //   If the sender hardware address is the original owner this is benign, so we just suppress our own proxy answering for a while longer.
+               //   If the sender hardware address is *not* the original owner, then this is a conflict, and we need to wake the sleeping machine to handle it.
+               if (mDNSSameEthAddress(&arp->sha, &intf->MAC))
+                       debugf("ARP from self for %.4a", &arp->tpa);
+               else
+                       {
+                       if (!mDNSSameIPv4Address(arp->spa, zerov4Addr))
+                               for (rr = m->ResourceRecords; rr; rr=rr->next)
+                                       if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, arp->spa))
+                                               {
+                                               RestartProbing(m, rr);
+                                               if (mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC))
+                                                       LogSPS("%-7s ARP %s from owner %.6a %.4a for %-15.4a -- re-starting probing for %s",
+                                                               InterfaceNameForID(m, InterfaceID),
+                                                               mDNSSameIPv4Address(arp->spa, arp->tpa) ? "Announcement" : mDNSSameOpaque16(arp->op, ARP_op_request) ? "Request     " : "Response    ",
+                                                               &arp->sha, &arp->spa, &arp->tpa, ARDisplayString(m, rr));
+                                               else
+                                                       {
+                                                       LogMsg("%-7s Conflicting ARP from %.6a %.4a for %.4a -- waking H-MAC %.6a I-MAC %.6a %s",
+                                                               InterfaceNameForID(m, InterfaceID), &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
+                                                       SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password);
+                                                       }
+                                               }
+                       }
+
+               mDNS_Unlock(m);
+               }
+       else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IP) && (v4->flagsfrags.b[0] & 0x1F) == 0 && v4->flagsfrags.b[1] == 0)
+               {
+               const mDNSu8 *const trans = p + 14 + (v4->vlen & 0xF) * 4;
+               const mDNSu8 *const required = trans + (v4->protocol == 1 ? 4 : v4->protocol == 6 ? 20 : v4->protocol == 17 ? 8 : 0);
+               debugf("Got IPv4 from %.4a to %.4a", &v4->src, &v4->dst);
+               if (end >= required)
+                       {
+                       #define SSH_AsNumber 22
+                       #define ARD_AsNumber 3283
+                       #define IPSEC_AsNumber 4500
+                       static const mDNSIPPort SSH   = { { SSH_AsNumber   >> 8, SSH_AsNumber   & 0xFF } };
+                       static const mDNSIPPort ARD   = { { ARD_AsNumber   >> 8, ARD_AsNumber   & 0xFF } };
+                       static const mDNSIPPort IPSEC = { { IPSEC_AsNumber >> 8, IPSEC_AsNumber & 0xFF } };
+
+                       mDNSBool wake = mDNSfalse;
+                       mDNSIPPort port = zeroIPPort;
+       
+                       switch (v4->protocol)
+                               {
+                               #define XX wake ? "Received" : "Ignoring", end-p
+                               case  1:        LogSPS("%s %d-byte ICMP from %.4a to %.4a", XX, &v4->src, &v4->dst);
+                                                       break;
+
+                               case  6:        {
+                                                       const TCPHeader *const tcp = (const TCPHeader *)trans;
+                                                       port = tcp->dst;
+
+                                                       // Plan to wake if
+                                                       // (a) RST is not set, AND
+                                                       // (b) packet is SYN, SYN+FIN, or plain data packet (no SYN or FIN). We won't wake for FIN alone.
+                                                       wake = (!(tcp->flags & 4) && (tcp->flags & 3) != 1);
+
+                                                       // For now, to reduce spurious wakeups, we wake only for TCP SYN,
+                                                       // except for ssh connections, where we'll wake for plain data packets too
+                                                       if (!mDNSSameIPPort(port, SSH) && !(tcp->flags & 2)) wake = mDNSfalse;
+
+                                                       LogSPS("%s %d-byte TCP from %.4a:%d to %.4a:%d%s%s%s", XX,
+                                                               &v4->src, mDNSVal16(tcp->src), &v4->dst, mDNSVal16(port),
+                                                               (tcp->flags & 2) ? " SYN" : "",
+                                                               (tcp->flags & 1) ? " FIN" : "",
+                                                               (tcp->flags & 4) ? " RST" : "");
+                                                       }
+                                                       break;
+
+                               case 17:        {
+                                                       const UDPHeader *const udp = (const UDPHeader *)trans;
+                                                       mDNSu16 len = (mDNSu16)((mDNSu16)trans[4] << 8 | trans[5]);
+                                                       port = udp->dst;
+                                                       wake = mDNStrue;
+
+                                                       // For Back to My Mac UDP port 4500 (IPSEC) packets, we specially ignore NAT keepalive packets
+                                                       if (mDNSSameIPPort(port, IPSEC)) wake = (len != 9 || end < trans + 9 || trans[8] != 0xFF);
+
+                                                       // For now, because we haven't yet worked out a clean elegant way to do this, we just special-case the
+                                                       // Apple Remote Desktop port number -- we ignore all packets to UDP 3283 (the "Net Assistant" port),
+                                                       // except for Apple Remote Desktop's explicit manual wakeup packet, which looks like this:
+                                                       // UDP header (8 bytes) 13 88 00 6a 41 4e 41 20 (8 bytes) ffffffffffff (6 bytes) 16xMAC (96 bytes) = 118 bytes total
+                                                       if (mDNSSameIPPort(port, ARD)) wake = (len >= 118 && end >= trans+10 && trans[8] == 0x13 && trans[9] == 0x88);
+
+                                                       LogSPS("%s %d-byte UDP from %.4a:%d to %.4a:%d", XX, &v4->src, mDNSVal16(udp->src), &v4->dst, mDNSVal16(port));
+                                                       }
+                                                       break;
+
+                               default:        LogSPS("%s %d-byte IP packet unknown protocol %d from %.4a to %.4a", XX, v4->protocol, &v4->src, &v4->dst);
+                                                       break;
+                               }
+       
+                       if (wake)
+                               {
+                               AuthRecord *rr, *r2;
+
+                               mDNS_Lock(m);
+                               for (rr = m->ResourceRecords; rr; rr=rr->next)
+                                       if (rr->resrec.InterfaceID == InterfaceID &&
+                                               rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, v4->dst))
+                                               {
+                                               const mDNSu8 *const tp = (v4->protocol == 6) ? (mDNSu8 *)"\x4_tcp" : (mDNSu8 *)"\x4_udp";
+                                               for (r2 = m->ResourceRecords; r2; r2=r2->next)
+                                                       if (r2->resrec.InterfaceID == InterfaceID && mDNSSameEthAddress(&r2->WakeUp.HMAC, &rr->WakeUp.HMAC) &&
+                                                               r2->resrec.rrtype == kDNSType_SRV && mDNSSameIPPort(r2->resrec.rdata->u.srv.port, port) &&
+                                                               SameDomainLabel(SkipLeadingLabels(r2->resrec.name, 2)->c, tp))
+                                                               break;
+                                               if (!r2 && mDNSSameIPPort(port, IPSEC)) r2 = rr;        // So that we wake for BTMM IPSEC packets, even without a matching SRV record
+                                               if (r2)
+                                                       {
+                                                       rr->AnnounceCount = 0;
+                                                       LogMsg("Waking host at %s %.4a H-MAC %.6a I-MAC %.6a for %s",
+                                                               InterfaceNameForID(m, rr->resrec.InterfaceID), &v4->dst, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, r2));
+                                                       SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password);
+                                                       }
+                                               else
+                                                       LogSPS("Sleeping host at %s %.4a %.6a has no service on %#s %d",
+                                                               InterfaceNameForID(m, rr->resrec.InterfaceID), &v4->dst, &rr->WakeUp.HMAC, tp, mDNSVal16(port));
+                                               }
+                               mDNS_Unlock(m);
+                               }
+                       }
+               }
+       else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IP) && (v4->flagsfrags.b[0] & 0x1F) == 0 && v4->flagsfrags.b[1] == 0)
+               {
+               debugf("Got IPv6 from %.16a to %.16a", &v4->src, &v6->dst);
+               (void)v6;
+               }
+       }
+
+mDNSlocal void ConstructSleepProxyServerName(mDNS *const m, domainlabel *name)
+       {
+       name->c[0] = mDNS_snprintf((char*)name->c+1, 62, "%d-%d-%d-%d %#s",
+               m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower, &m->nicelabel);
+       }
+
+mDNSlocal void SleepProxyServerCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
+       {
+       if (result == mStatus_NameConflict)
+               mDNS_RenameAndReregisterService(m, srs, mDNSNULL);
+       else if (result == mStatus_MemFree)
+               {
+               if (m->SleepState)
+                       m->SPSState = 3;
+               else
+                       {
+                       m->SPSState = (m->SPSSocket != mDNSNULL);
+                       if (m->SPSState)
+                               {
+                               domainlabel name;
+                               ConstructSleepProxyServerName(m, &name);
+                               mDNS_RegisterService(m, srs,
+                                       &name, &SleepProxyServiceType, &localdomain,
+                                       mDNSNULL, m->SPSSocket->port,                           // Host, port
+                                       (mDNSu8 *)"", 1,                                                        // TXT data, length
+                                       mDNSNULL, 0,                                                            // Subtypes (none)
+                                       mDNSInterface_Any,                                                      // Interface ID
+                                       SleepProxyServerCallback, mDNSNULL);            // Callback and context
+                               }
+                       LogSPS("Sleep Proxy Server %#s %s", srs->RR_SRV.resrec.name->c, m->SPSState ? "started" : "stopped");
+                       }
+               }
+       }
+
+mDNSexport void mDNSCoreBeSleepProxyServer(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower)
+       {
+       // If turning off SPS, close our socket
+       // (Do this first, BEFORE calling mDNS_DeregisterService below)
+       if (!sps && m->SPSSocket) { mDNSPlatformUDPClose(m->SPSSocket); m->SPSSocket = mDNSNULL; }
+
+       // If turning off, or changing type, deregister old name
+       if (m->SPSState == 1 && sps != m->SPSType)
+               { m->SPSState = 2; mDNS_DeregisterService(m, &m->SPSRecords); }
+
+       // Record our new SPS parameters
+       m->SPSType          = sps;
+       m->SPSPortability   = port;
+       m->SPSMarginalPower = marginalpower;
+       m->SPSTotalPower    = totpower;
+
+       // If turning on, open socket and advertise service
+       if (sps)
+               {
+               if (!m->SPSSocket)
+                       {
+                       m->SPSSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
+                       if (!m->SPSSocket) { LogMsg("mDNSCoreBeSleepProxyServer: Failed to allocate SPSSocket"); return; }
+                       }
+               if (m->SPSState == 0) SleepProxyServerCallback(m, &m->SPSRecords, mStatus_MemFree);
+               }
+       }
+
 // ***************************************************************************
 #if COMPILER_LIKES_PRAGMA_MARK
 #pragma mark -
@@ -7049,16 +9292,18 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
        
        if (!rrcachestorage) rrcachesize = 0;
        
-       m->p                       = p;
-       m->KnownBugs               = 0;
-       m->CanReceiveUnicastOn5353 = mDNSfalse; // Assume we can't receive unicasts on 5353, unless platform layer tells us otherwise
-       m->AdvertiseLocalAddresses = AdvertiseLocalAddresses;
-       m->mDNSPlatformStatus      = mStatus_Waiting;
-       m->UnicastPort4            = zeroIPPort;
-       m->UnicastPort6            = zeroIPPort;
-       m->MainCallback            = Callback;
-       m->MainContext             = Context;
-       m->rec.r.resrec.RecordType = 0;
+       m->p                             = p;
+       m->KnownBugs                     = 0;
+       m->CanReceiveUnicastOn5353       = mDNSfalse; // Assume we can't receive unicasts on 5353, unless platform layer tells us otherwise
+       m->AdvertiseLocalAddresses       = AdvertiseLocalAddresses;
+       m->DivertMulticastAdvertisements = mDNSfalse;
+       m->mDNSPlatformStatus            = mStatus_Waiting;
+       m->UnicastPort4                  = zeroIPPort;
+       m->UnicastPort6                  = zeroIPPort;
+       m->PrimaryMAC                    = zeroEthAddr;
+       m->MainCallback                  = Callback;
+       m->MainContext                   = Context;
+       m->rec.r.resrec.RecordType       = 0;
 
        // For debugging: To catch and report locking failures
        m->mDNS_busy               = 0;
@@ -7083,12 +9328,15 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
        m->NextScheduledProbe      = timenow + 0x78000000;
        m->NextScheduledResponse   = timenow + 0x78000000;
        m->NextScheduledNATOp      = timenow + 0x78000000;
+       m->NextScheduledSPS        = timenow + 0x78000000;
        m->RandomQueryDelay        = 0;
        m->RandomReconfirmDelay    = 0;
        m->PktNum                  = 0;
-       m->SendDeregistrations     = mDNSfalse;
-       m->SendImmediateAnswers    = mDNSfalse;
-       m->SleepState              = mDNSfalse;
+       m->SleepState              = SleepState_Awake;
+       m->SleepSeqNum             = 0;
+       m->SystemWakeOnLANEnabled  = mDNSfalse;
+       m->DelaySleep              = 0;
+       m->SleepLimit              = 0;
 
        // These fields only required for mDNS Searcher...
        m->Questions               = mDNSNULL;
@@ -7153,9 +9401,9 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
        m->ExternalAddress          = zerov4Addr;
 
        m->NATMcastRecvskt          = mDNSNULL;
-       m->NATMcastRecvsk2          = mDNSNULL;
        m->LastNATupseconds         = 0;
        m->LastNATReplyLocalTime    = timenow;
+       m->LastNATMapResultCode     = NATErr_None;
 
        m->UPnPInterfaceID          = 0;
        m->SSDPSocket               = mDNSNULL;
@@ -7167,6 +9415,16 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
        m->UPnPSOAPURL              = mDNSNULL;
        m->UPnPRouterAddressString  = mDNSNULL;
        m->UPnPSOAPAddressString    = mDNSNULL;
+       m->SPSType                  = 0;
+       m->SPSPortability           = 0;
+       m->SPSMarginalPower         = 0;
+       m->SPSTotalPower            = 0;
+       m->SPSState                 = 0;
+       m->SPSProxyListChanged      = mDNSNULL;
+       m->SPSSocket                = mDNSNULL;
+       m->SPSBrowseCallback        = mDNSNULL;
+       m->ProxyRecords             = 0;
+
 #endif
 
 #if APPLE_OSX_mDNSResponder
@@ -7184,6 +9442,28 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
        return(result);
        }
 
+mDNSexport void mDNS_ConfigChanged(mDNS *const m)
+       {
+       if (m->SPSState == 1)
+               {
+               domainlabel name, newname;
+               domainname type, domain;
+               DeconstructServiceName(m->SPSRecords.RR_SRV.resrec.name, &name, &type, &domain);
+               ConstructSleepProxyServerName(m, &newname);
+               if (!SameDomainLabelCS(name.c, newname.c))
+                       {
+                       LogSPS("Renaming SPS from “%#s” to “%#s”", name.c, newname.c);
+                       // When SleepProxyServerCallback gets the mStatus_MemFree message,
+                       // it will reregister the service under the new name
+                       m->SPSState = 2;
+                       mDNS_DeregisterService(m, &m->SPSRecords);
+                       }
+               }
+       
+       if (m->MainCallback)
+               m->MainCallback(m, mStatus_ConfigChanged);
+       }
+
 mDNSlocal void DynDNSHostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
        {
        (void)m;        // unused
@@ -7191,6 +9471,21 @@ mDNSlocal void DynDNSHostNameCallback(mDNS *const m, AuthRecord *const rr, mStat
        mDNSPlatformDynDNSHostNameStatusChanged(rr->resrec.name, result);
        }
 
+mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr, const DNSServer * const ptr, mDNSBool lameduck)
+       {
+       mDNSBool purge = cr->resrec.RecordType == kDNSRecordTypePacketNegative ||
+                                        cr->resrec.rrtype     == kDNSType_A ||
+                                        cr->resrec.rrtype     == kDNSType_AAAA ||
+                                        cr->resrec.rrtype     == kDNSType_SRV;
+
+       (void) lameduck;
+       (void) ptr;
+       debugf("uDNS_SetupDNSConfig: %s cache record due to %s server %p %#a:%d (%##s): %s", purge ? "purging" : "reconfirming", lameduck ? "lame duck" : "new", ptr, &ptr->addr, mDNSVal16(ptr->port), ptr->domain.c, CRDisplayString(m, cr));
+
+       if (purge) mDNS_PurgeCacheResourceRecord(m, cr);
+       else mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
+       }
+       
 mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
        {
        mDNSu32 slot;
@@ -7202,6 +9497,8 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
        DNSServer   *ptr, **p = &m->DNSServers;
        const DNSServer *oldServers = m->DNSServers;
        DNSQuestion *q;
+       
+       debugf("uDNS_SetupDNSConfig: entry");
 
        if (m->RegisterSearchDomains) uDNS_RegisterSearchDomains(m);
 
@@ -7223,7 +9520,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
                        if (t != s)
                                {
                                // If DNS Server for this question has changed, reactivate it
-                               LogOperation("Updating DNS Server from %p %#a:%d (%##s) to %p %#a:%d (%##s) for %##s (%s)",
+                               debugf("uDNS_SetupDNSConfig: Updating DNS Server from %p %#a:%d (%##s) to %p %#a:%d (%##s) for %##s (%s)",
                                        t, t ? &t->addr : mDNSNULL, mDNSVal16(t ? t->port : zeroIPPort), t ? t->domain.c : (mDNSu8*)"",
                                        s, s ? &s->addr : mDNSNULL, mDNSVal16(s ? s->port : zeroIPPort), s ? s->domain.c : (mDNSu8*)"",
                                        q->qname.c, DNSTypeName(q->qtype));
@@ -7238,12 +9535,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
                {
                ptr = GetServerForName(m, cr->resrec.name);
                if (ptr && (ptr->flags & DNSServer_FlagNew) && !cr->resrec.InterfaceID)
-                       {
-                       if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
-                               mDNS_PurgeCacheResourceRecord(m, cr);
-                       else
-                               mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
-                       }
+                       PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNSfalse);
                }
        
        while (*p)
@@ -7257,8 +9549,9 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
                        ptr->flags &= ~DNSServer_FlagDelete;    // Clear del so GetServerForName will (temporarily) find this server again before it's finally deleted
                        FORALL_CACHERECORDS(slot, cg, cr)
                                if (!cr->resrec.InterfaceID && GetServerForName(m, cr->resrec.name) == ptr)
-                                       mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
+                                       PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNStrue);
                        *p = (*p)->next;
+                       debugf("uDNS_SetupDNSConfig: Deleting server %p %#a:%d (%##s)", ptr, &ptr->addr, mDNSVal16(ptr->port), ptr->domain.c);
                        mDNSPlatformMemFree(ptr);
                        }
                else
@@ -7276,10 +9569,14 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
                {
                int count = 0;
                FORALL_CACHERECORDS(slot, cg, cr) if (!cr->resrec.InterfaceID) { mDNS_PurgeCacheResourceRecord(m, cr); count++; }
-               LogOperation("uDNS_SetupDNSConfig: %s available; purged %d unicast DNS records from cache",
+               LogInfo("uDNS_SetupDNSConfig: %s available; purged %d unicast DNS records from cache",
                        m->DNSServers ? "DNS server became" : "No DNS servers", count);
                }
 
+       // If we no longer have any DNS servers, we need to force anything that needs to get zone data
+       // to get that information again (which will fail, since we have no more DNS servers)
+       if ((m->DNSServers == mDNSNULL) && (oldServers != mDNSNULL))    RestartRecordGetZoneData(m);
+       
        // Did our FQDN change?
        if (!SameDomainName(&fqdn, &m->FQDN))
                {
@@ -7331,6 +9628,24 @@ mDNSexport void mDNSCoreInitComplete(mDNS *const m, mStatus result)
 
 extern ServiceRecordSet *CurrentServiceRecordSet;
 
+mDNSlocal void DeregLoop(mDNS *const m, AuthRecord *const start)
+       {
+       m->CurrentRecord = start;
+       while (m->CurrentRecord)
+               {
+               AuthRecord *rr = m->CurrentRecord;
+               if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
+                       {
+                       LogInfo("DeregLoop: Deregistering %p %02X %s", rr, rr->resrec.RecordType, ARDisplayString(m, rr));
+                       mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
+                       }
+               // Note: We mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
+               // the list may have been changed in that call.
+               if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
+                       m->CurrentRecord = rr->next;
+               }
+       }
+
 mDNSexport void mDNS_StartExit(mDNS *const m)
        {
        NetworkInterfaceInfo *intf;
@@ -7340,11 +9655,29 @@ mDNSexport void mDNS_StartExit(mDNS *const m)
 
        m->ShutdownTime = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
 
+       mDNS_DropLockBeforeCallback();          // mDNSCoreBeSleepProxyServer expects to be called without the lock held, so we emulate that here
+       mDNSCoreBeSleepProxyServer(m, 0, 0, 0, 0);
+       mDNS_ReclaimLockAfterCallback();
+
 #ifndef UNICAST_DISABLED
+       {
+       SearchListElem *s;
        SuspendLLQs(m);
        // Don't need to do SleepRecordRegistrations() or SleepServiceRegistrations() here,
        // because we deregister all records and services later in this routine
        while (m->Hostnames) mDNS_RemoveDynDNSHostName(m, &m->Hostnames->fqdn);
+
+       // For each member of our SearchList, deregister any records it may have created, and cut them from the list.
+       // Otherwise they'll be forcibly deregistered for us (without being cut them from the appropriate list)
+       // and we may crash because the list still contains dangling pointers.
+       for (s = SearchList; s; s = s->next)
+               while (s->AuthRecs)
+                       {
+                       ARListElem *dereg = s->AuthRecs;
+                       s->AuthRecs = s->AuthRecs->next;
+                       mDNS_Deregister_internal(m, &dereg->ar, mDNS_Dereg_normal);     // Memory will be freed in the FreeARElemCallback
+                       }
+       }
 #endif
 
        for (intf = m->HostInterfaces; intf; intf = intf->next)
@@ -7370,63 +9703,52 @@ mDNSexport void mDNS_StartExit(mDNS *const m)
 
        // Make sure there are nothing but deregistering records remaining in the list
        if (m->CurrentRecord)
-               LogMsg("mDNS_StartExit ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-
-       // First we deregister any non-shared records. In particular, we want to make sure we deregister
-       // any extra records added to a Service Record Set first, before we deregister its PTR record,
-       // because the freeing of the memory is triggered off the mStatus_MemFree for the PTR record.
-       m->CurrentRecord = m->ResourceRecords;
-       while (m->CurrentRecord)
-               {
-               rr = m->CurrentRecord;
-               if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-                       mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-               // Note: We mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because when
-               // we have records on the DuplicateRecords list, the duplicate gets inserted in place of the record
-               // we're removing, and if we've already advanced to rr->next we'll miss the newly activated duplicate
-               if (m->CurrentRecord == rr)             // If m->CurrentRecord was not auto-advanced, do it ourselves now
-                       m->CurrentRecord = rr->next;
-               }
-
-       // Now deregister any remaining records we didn't get the first time through
-       m->CurrentRecord = m->ResourceRecords;
-       while (m->CurrentRecord)
+               LogMsg("mDNS_StartExit: ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
+
+       // We're in the process of shutting down, so queries, etc. are no longer available.
+       // Consequently, determining certain information, e.g. the uDNS update server's IP
+       // address, will not be possible.  The records on the main list are more likely to
+       // already contain such information, so we deregister the duplicate records first.
+       LogInfo("mDNS_StartExit: Deregistering duplicate resource records");
+       DeregLoop(m, m->DuplicateRecords);
+       LogInfo("mDNS_StartExit: Deregistering resource records");
+       DeregLoop(m, m->ResourceRecords);
+       
+       // If we scheduled a response to send goodbye packets, we set NextScheduledResponse to now. Normally when deregistering records,
+       // we allow up to 100ms delay (to help improve record grouping) but when shutting down we don't want any such delay.
+       if (m->NextScheduledResponse - m->timenow < mDNSPlatformOneSecond)
                {
-               rr = m->CurrentRecord;
-               if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
-                       {
-                       //LogOperation("mDNS_StartExit: Deregistering %s", ARDisplayString(m, rr));
-                       mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-                       }
-               // Note: We mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because when
-               // we have records on the DuplicateRecords list, the duplicate gets inserted in place of the record
-               // we're removing, and if we've already advanced to rr->next we'll miss the newly activated duplicate
-               if (m->CurrentRecord == rr)             // If m->CurrentRecord was not auto-advanced, do it ourselves now
-                       m->CurrentRecord = rr->next;
+               m->NextScheduledResponse = m->timenow;
+               m->SuppressSending = 0;
                }
 
+#if !defined(UNICAST_DISABLED) && USE_SEPARATE_UDNS_SERVICE_LIST
        CurrentServiceRecordSet = m->ServiceRegistrations;
        while (CurrentServiceRecordSet)
                {
                ServiceRecordSet *srs = CurrentServiceRecordSet;
-               LogOperation("mDNS_StartExit: Deregistering %##s", srs->RR_SRV.resrec.name->c);
+               LogInfo("mDNS_StartExit: Deregistering uDNS service %##s", srs->RR_SRV.resrec.name->c);
                uDNS_DeregisterService(m, srs);
                if (CurrentServiceRecordSet == srs)
                        CurrentServiceRecordSet = srs->uDNS_next;
                }
+#endif
+
+       if (m->ResourceRecords) LogInfo("mDNS_StartExit: Sending final record deregistrations");
+       else                    LogInfo("mDNS_StartExit: No deregistering records remain");
 
-       if (m->ResourceRecords) LogOperation("mDNS_StartExit: Sending final record deregistrations");
-       else                    LogOperation("mDNS_StartExit: No deregistering records remain");
+       if (m->ServiceRegistrations) LogInfo("mDNS_StartExit: Sending final uDNS service deregistrations");
+       else                         LogInfo("mDNS_StartExit: No deregistering uDNS services remain");
 
-       if (m->ServiceRegistrations) LogOperation("mDNS_StartExit: Sending final service deregistrations");
-       else                         LogOperation("mDNS_StartExit: No deregistering services remain");
+       for (rr = m->DuplicateRecords; rr; rr = rr->next)
+               LogMsg("mDNS_StartExit: Should not still have Duplicate Records remaining: %02X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
 
        // If any deregistering records remain, send their deregistration announcements before we exit
        if (m->mDNSPlatformStatus != mStatus_NoError) DiscardDeregistrations(m);
 
        mDNS_Unlock(m);
 
-       LogOperation("mDNS_StartExit: done");
+       LogInfo("mDNS_StartExit: done");
        }
 
 mDNSexport void mDNS_FinalExit(mDNS *const m)
@@ -7437,7 +9759,7 @@ mDNSexport void mDNS_FinalExit(mDNS *const m)
        AuthRecord *rr;
        ServiceRecordSet *srs;
 
-       LogOperation("mDNS_FinalExit: mDNSPlatformClose");
+       LogInfo("mDNS_FinalExit: mDNSPlatformClose");
        mDNSPlatformClose(m);
 
        rrcache_totalused = m->rrcache_totalused;
@@ -7457,15 +9779,15 @@ mDNSexport void mDNS_FinalExit(mDNS *const m)
                        ReleaseCacheGroup(m, &m->rrcache_hash[slot]);
                        }
                }
-       debugf("mDNS_StartExit: RR Cache was using %ld records, %lu active", rrcache_totalused, rrcache_active);
+       debugf("mDNS_FinalExit: RR Cache was using %ld records, %lu active", rrcache_totalused, rrcache_active);
        if (rrcache_active != m->rrcache_active)
                LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active);
 
        for (rr = m->ResourceRecords; rr; rr = rr->next)
-               LogMsg("mDNS_FinalExit failed to send goodbye for: %02X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
+               LogMsg("mDNS_FinalExit failed to send goodbye for: %p %02X %s", rr, rr->resrec.RecordType, ARDisplayString(m, rr));
 
        for (srs = m->ServiceRegistrations; srs; srs = srs->uDNS_next)
-               LogMsg("mDNS_FinalExit failed to deregister service: %##s", srs->RR_SRV.resrec.name->c);
+               LogMsg("mDNS_FinalExit failed to deregister service: %p %##s", srs, srs->RR_SRV.resrec.name->c);
 
-       LogOperation("mDNS_FinalExit: done");
+       LogInfo("mDNS_FinalExit: done");
        }
index 73010874edb655c971ec9edc7377222e13164bcd..36cbc439b208ce2f855b22ecbae47f6db23d5849 100755 (executable)
     Change History (most recent first):
 
 $Log: mDNSDebug.h,v $
+Revision 1.51  2009/06/25 23:36:59  cheshire
+To facilitate testing, added command-line switch "-OfferSleepProxyService"
+to re-enable the previously-supported mode of operation where we offer
+sleep proxy service on desktop Macs that are set to never sleep.
+
+Revision 1.50  2009/05/19 23:34:06  cheshire
+Updated comment to show correct metric of 80 for a low-priority sleep proxy
+
+Revision 1.49  2009/04/24 23:32:28  cheshire
+To facilitate testing, put back code to be a sleep proxy when set to never sleep, compiled out by compile-time switch
+
+Revision 1.48  2009/04/11 01:43:27  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.47  2009/04/11 00:19:41  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.46  2009/02/13 06:36:50  cheshire
+Update LogSPS definition
+
+Revision 1.45  2009/02/13 06:03:12  cheshire
+Added LogInfo for informational message logging
+
+Revision 1.44  2009/02/12 20:57:25  cheshire
+Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
+
+Revision 1.43  2008/12/10 02:27:14  cheshire
+Commented out definitions of LogClientOperations, LogTimeStamps, ForceAlerts and MACOSX_MDNS_MALLOC_DEBUGGING
+to allow overriding values to be easily defined in a Makefile or similar build environment
+
+Revision 1.42  2008/11/02 21:22:05  cheshire
+Changed mallocL size parameter back to "unsigned int"
+
+Revision 1.41  2008/11/02 21:14:58  cheshire
+Fixes to make mallocL/freeL debugging checks work on 64-bit
+
+Revision 1.40  2008/10/24 20:53:37  cheshire
+For now, define USE_SEPARATE_UDNS_SERVICE_LIST, so that we use the old service list code for this submission
+
 Revision 1.39  2008/02/26 21:17:11  cheshire
 Grouped all user settings together near the start of the file; added LogTimeStamps option
 
@@ -142,26 +181,24 @@ Merge in license terms from Quinn's copy, in preparation for Darwin release
 
 typedef enum
        {
-       MDNS_LOG_NONE,
-//     MDNS_LOG_ERROR,
-//     MDNS_LOG_WARN,
-//     MDNS_LOG_INFO,
-//     MDNS_LOG_DEBUG,
-       MDNS_LOG_VERBOSE_DEBUG
-       } LogLevel_t;
-
-#define MDNS_LOG_INITIAL_LEVEL MDNS_LOG_NONE
+       MDNS_LOG_MSG,
+       MDNS_LOG_OPERATION,
+       MDNS_LOG_SPS,
+       MDNS_LOG_INFO,
+       MDNS_LOG_DEBUG,
+       } mDNSLogLevel_t;
 
 // Set this symbol to 1 to answer remote queries for our Address, reverse mapping PTR, and HINFO records
 #define ANSWER_REMOTE_HOSTNAME_QUERIES 0
 
 // Set this symbol to 1 to do extra debug checks on malloc() and free()
 // Set this symbol to 2 to write a log message for every malloc() and free()
-#define MACOSX_MDNS_MALLOC_DEBUGGING 0
+//#define MACOSX_MDNS_MALLOC_DEBUGGING 1
+
+//#define ForceAlerts 1
+//#define LogTimeStamps 1
 
-#define LogAllOperations 0
-#define LogTimeStamps 0
-#define ForceAlerts 0
+#define USE_SEPARATE_UDNS_SERVICE_LIST 1
 
 // Developer-settings section ends here
 
@@ -171,7 +208,7 @@ typedef enum
 #define IS_A_PRINTF_STYLE_FUNCTION(F,A)
 #endif
 
-#ifdef __cplusplus
+#ifdef __cplusplus
        extern "C" {
 #endif
 
@@ -179,62 +216,78 @@ typedef enum
 
 #if (defined(__GNUC__))
        #if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 2)))
-               #define MDNS_C99_VA_ARGS                1
-               #define MDNS_GNU_VA_ARGS                0
+               #define MDNS_C99_VA_ARGS        1
+               #define MDNS_GNU_VA_ARGS        0
        #else
-               #define MDNS_C99_VA_ARGS                0
-               #define MDNS_GNU_VA_ARGS                1
+               #define MDNS_C99_VA_ARGS        0
+               #define MDNS_GNU_VA_ARGS        1
        #endif
-       #define MDNS_HAS_VA_ARG_MACROS          1
+       #define MDNS_HAS_VA_ARG_MACROS      1
 #elif (_MSC_VER >= 1400) // Visual Studio 2005 and later
-       #define MDNS_C99_VA_ARGS                        1
-       #define MDNS_GNU_VA_ARGS                        0
-       #define MDNS_HAS_VA_ARG_MACROS          1
+       #define MDNS_C99_VA_ARGS            1
+       #define MDNS_GNU_VA_ARGS            0
+       #define MDNS_HAS_VA_ARG_MACROS      1
 #elif (defined(__MWERKS__))
-       #define MDNS_C99_VA_ARGS                        1
-       #define MDNS_GNU_VA_ARGS                        0
-       #define MDNS_HAS_VA_ARG_MACROS          1
+       #define MDNS_C99_VA_ARGS            1
+       #define MDNS_GNU_VA_ARGS            0
+       #define MDNS_HAS_VA_ARG_MACROS      1
 #else
-       #define MDNS_C99_VA_ARGS                        0
-       #define MDNS_GNU_VA_ARGS                        0
-       #define MDNS_HAS_VA_ARG_MACROS          0
+       #define MDNS_C99_VA_ARGS            0
+       #define MDNS_GNU_VA_ARGS            0
+       #define MDNS_HAS_VA_ARG_MACROS      0
 #endif
 
-#if MDNS_DEBUGMSGS
-#define debugf debugf_
-extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-#else // If debug breaks are off, use a preprocessor trick to optimize those calls out of the code
+#if (MDNS_HAS_VA_ARG_MACROS)
        #if (MDNS_C99_VA_ARGS)
-               #define debugf( ... ) ((void)0)
+               #define debug_noop( ... ) ((void)0)
+               #define LogMsg( ... ) LogMsgWithLevel(MDNS_LOG_MSG, __VA_ARGS__)
+               #define LogOperation( ... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_OPERATION, __VA_ARGS__); } while (0)
+               #define LogSPS( ... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_SPS, __VA_ARGS__); } while (0)
+               #define LogInfo( ... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_INFO, __VA_ARGS__); } while (0)
        #elif (MDNS_GNU_VA_ARGS)
-               #define debugf( ARGS... ) ((void)0)
+               #define debug_noop( ARGS... ) ((void)0)
+               #define LogMsg( ARGS... ) LogMsgWithLevel(MDNS_LOG_MSG, ARGS)
+               #define LogOperation( ARGS... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_OPERATION, ARGS); } while (0)
+               #define LogSPS( ARGS... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_SPS, ARGS); } while (0)
+               #define LogInfo( ARGS... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_INFO, ARGS); } while (0)
        #else
-               #define debugf 1 ? ((void)0) : (void)
+               #error Unknown variadic macros
        #endif
+#else
+       // If your platform does not support variadic macros, you need to define the following variadic functions.
+       // See mDNSShared/mDNSDebug.c for sample implementation
+       extern void debug_noop(const char *format, ...);
+       #define LogMsg LogMsg_
+       #define LogOperation mDNS_LoggingEnabled == 0 ? ((void)0) : LogOperation_
+       #define LogSPS mDNS_LoggingEnabled == 0 ? ((void)0) : LogSPS_
+       #define LogInfo mDNS_LoggingEnabled == 0 ? ((void)0) : LogInfo_
+       extern void LogMsg_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
+       extern void LogOperation_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
+       extern void LogSPS_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
+       extern void LogInfo_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
+#endif
+
+#if MDNS_DEBUGMSGS
+#define debugf debugf_
+extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
+#else
+#define debugf debug_noop
 #endif
 
 #if MDNS_DEBUGMSGS > 1
 #define verbosedebugf verbosedebugf_
 extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
 #else
-       #if (MDNS_C99_VA_ARGS)
-               #define verbosedebugf( ... ) ((void)0)
-       #elif (MDNS_GNU_VA_ARGS)
-               #define verbosedebugf( ARGS... ) ((void)0)
-       #else
-               #define verbosedebugf 1 ? ((void)0) : (void)
-       #endif
+#define verbosedebugf debug_noop
 #endif
 
-// LogMsg is used even in shipping code, to write truly serious error messages to syslog (or equivalent)
-extern LogLevel_t mDNS_LogLevel;
+extern int           mDNS_LoggingEnabled;
+extern int           mDNS_PacketLoggingEnabled;
 extern int        mDNS_DebugMode;      // If non-zero, LogMsg() writes to stderr instead of syslog
-extern const char ProgramName[];       // Program Name for use with LogMsgIdent
+extern const char ProgramName[];
 
-extern void LogMsg(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-extern void LogMsgIdent(const char *ident, const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(2,3);
-extern void LogMsgNoIdent(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-extern void SigLogLevel(void);
+extern void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(2,3);
+#define LogMsgNoIdent LogMsg
 
 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
 extern void *mallocL(char *msg, unsigned int size);
@@ -247,13 +300,7 @@ extern void udns_validatelists(void *const v);
 #define freeL(X,Y) free(Y)
 #endif
 
-#if LogAllOperations
-#define LogOperation LogMsg
-#else
-#define        LogOperation debugf
-#endif
-
-#ifdef __cplusplus
+#ifdef __cplusplus
        }
 #endif
 
index 8b46b3b7ec23a2eb24d9b8b63154cce6fbfd9d52..c02cea4a5bb1e542ed2b2df829c13d9423b72937 100755 (executable)
     Change History (most recent first):
 
 $Log: mDNSEmbeddedAPI.h,v $
-Revision 1.468.2.4  2008/09/30 18:03:02  mcguire
+Revision 1.573  2009/06/30 18:17:45  herscher
+Add to 64 bit macro check for 64 bit Windows OSes
+
+Revision 1.572  2009/06/27 00:52:27  cheshire
+<rdar://problem/6959273> mDNSResponder taking up 13% CPU with 400 KBps incoming bonjour requests
+Removed overly-complicate and ineffective multi-packet known-answer snooping code
+(Bracketed it with "#if ENABLE_MULTI_PACKET_QUERY_SNOOPING" for now; will delete actual code later)
+
+Revision 1.571  2009/06/26 01:55:54  cheshire
+<rdar://problem/6890712> mDNS: iChat's Buddy photo always appears as the "shadow person" over Bonjour
+Additional refinements -- except for the case of explicit queries for record types we don't have (for names we own),
+add additional NSEC records only when there's space to do that without having to generate an additional packet
+
+Revision 1.570  2009/06/24 22:14:21  cheshire
+<rdar://problem/6911445> Plugging and unplugging the power cable shouldn't cause a network change event
+
+Revision 1.569  2009/06/03 23:07:12  cheshire
+<rdar://problem/6890712> mDNS: iChat's Buddy photo always appears as the "shadow person" over Bonjour
+Large records were not being added in cases where an NSEC record was also required
+
+Revision 1.568  2009/05/19 22:37:04  cheshire
+<rdar://problem/6903507> Sleep Proxy: Retransmission logic not working reliably on quiet networks
+Added NextScheduledSPRetry field
+
+Revision 1.567  2009/05/13 17:25:33  mkrochma
+<rdar://problem/6879926> Should not schedule maintenance wake when machine has no advertised services
+Sleep proxy client should only look for services being advertised via Multicast
+
+Revision 1.566  2009/05/12 23:09:24  cheshire
+<rdar://problem/6879926> Should not schedule maintenance wake when machine has no advertised services
+Declare mDNSCoreHaveAdvertisedServices routine so it can be called from daemon.c
+
+Revision 1.565  2009/05/09 00:10:58  jessic2
+Change expected size of NetworkInterfaceInfo to fix build failure
+
+Revision 1.564  2009/05/07 23:31:26  cheshire
+<rdar://problem/6601427> Sleep Proxy: Retransmit and retry Sleep Proxy Server requests
+Added NextSPSAttempt and NextSPSAttemptTime fields to NetworkInterfaceInfo_struct
+
+Revision 1.563  2009/04/24 21:06:38  cheshire
+Added comment about UDP length field (includes UDP header, so minimum value is 8 bytes)
+
+Revision 1.562  2009/04/24 00:22:23  cheshire
+<rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
+Added definition of rdataNSEC
+
+Revision 1.561  2009/04/23 22:06:29  cheshire
+Added CacheRecord and InterfaceID parameters to MakeNegativeCacheRecord, in preparation for:
+<rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
+
+Revision 1.560  2009/04/23 21:54:50  cheshire
+Updated comments
+
+Revision 1.559  2009/04/22 00:37:38  cheshire
+<rdar://problem/6814427> Remove unused kDNSType_MAC
+
+Revision 1.558  2009/04/21 23:36:25  cheshire
+<rdar://problem/6814427> Remove unused kDNSType_MAC
+
+Revision 1.557  2009/04/15 20:42:51  mcguire
+<rdar://problem/6768947> uDNS: Treat RCODE 5 (Refused) responses as failures
+
+Revision 1.556  2009/04/11 00:19:43  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.555  2009/04/01 21:12:27  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows.
+
+Revision 1.554  2009/04/01 17:50:11  mcguire
+cleanup mDNSRandom
+
+Revision 1.553  2009/03/26 03:59:00  jessic2
+Changes for <rdar://problem/6492552&6492593&6492609&6492613&6492628&6492640&6492699>
+
+Revision 1.552  2009/03/20 23:53:03  jessic2
+<rdar://problem/6646228> SIGHUP should restart all in-progress queries
+
+Revision 1.551  2009/03/18 20:41:04  cheshire
+Added definition of the all-ones mDNSOpaque16 ID
+
+Revision 1.550  2009/03/17 19:10:29  mcguire
+Fix sizechecks for x86_64
+
+Revision 1.549  2009/03/17 01:22:56  cheshire
+<rdar://problem/6601427> Sleep Proxy: Retransmit and retry Sleep Proxy Server requests
+Initial support for resolving up to three Sleep Proxies in parallel
+
+Revision 1.548  2009/03/14 01:42:56  mcguire
+<rdar://problem/5457116> BTMM: Fix issues with multiple .Mac accounts on the same machine
+
+Revision 1.547  2009/03/10 01:14:30  cheshire
+Sleep Proxies with invalid names need to be ignored (score 10000),
+not treated as "Sleep Proxy of last resort" (score 9999)
+
+Revision 1.546  2009/03/06 23:51:51  mcguire
+Fix broken build by defining DiscardPort
+
+Revision 1.545  2009/03/06 22:39:23  cheshire
+<rdar://problem/6655850> Ignore prototype base stations when picking Sleep Proxy to register with
+
+Revision 1.544  2009/03/04 01:33:30  cheshire
+Add m->ProxyRecords counter
+
+Revision 1.543  2009/03/03 23:04:43  cheshire
+For clarity, renamed "MAC" field to "HMAC" (Host MAC, as opposed to Interface MAC)
+
+Revision 1.542  2009/03/03 22:51:53  cheshire
+<rdar://problem/6504236> Sleep Proxy: Waking on same network but different interface will cause conflicts
+
+Revision 1.541  2009/03/03 00:45:19  cheshire
+Added m->PrimaryMAC field
+
+Revision 1.540  2009/02/27 02:56:57  cheshire
+Moved struct SearchListElem definition from uDNS.c into mDNSEmbeddedAPI.h
+
+Revision 1.539  2009/02/17 23:29:01  cheshire
+Throttle logging to a slower rate when running on SnowLeopard
+
+Revision 1.538  2009/02/11 02:31:57  cheshire
+Moved SystemWakeOnLANEnabled from mDNSMacOSX.h, so it's accessible to mDNSCore routines
+
+Revision 1.537  2009/02/07 02:51:48  cheshire
+<rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
+Added new functions and timing variables
+
+Revision 1.536  2009/01/30 23:50:31  cheshire
+Added LastLabel() routine to get the last label of a domainname
+
+Revision 1.535  2009/01/23 00:38:36  mcguire
+<rdar://problem/5570906> BTMM: Doesn't work with Linksys WRT54GS firmware 4.71.1
+
+Revision 1.534  2009/01/22 02:14:25  cheshire
+<rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
+
+Revision 1.533  2009/01/21 03:43:57  mcguire
+<rdar://problem/6511765> BTMM: Add support for setting kDNSServiceErr_NATPortMappingDisabled in DynamicStore
+
+Revision 1.532  2009/01/16 19:50:36  cheshire
+Oops. Fixed definition of SleepProxyServiceType.
+
+Revision 1.531  2009/01/16 19:48:09  cheshire
+Added definition of SleepProxyServiceType
+
+Revision 1.530  2009/01/15 00:22:49  mcguire
+<rdar://problem/6437092> NAT-PMP: mDNSResponder needs to listen on 224.0.0.1:5350/UDP with REUSEPORT
+
+Revision 1.529  2009/01/13 00:31:44  cheshire
+Fixed off-by-one error in computing the implicit limit pointer in the "DomainNameLength(name)" macro
+
+Revision 1.528  2009/01/10 01:43:52  cheshire
+Changed misleading function name 'AnsweredLOQ' to more informative 'AnsweredLocalQ'
+
+Revision 1.527  2008/12/12 01:23:19  cheshire
+Added m->SPSProxyListChanged state variable to flag when we need to update our BPF filter program
+
+Revision 1.526  2008/12/12 00:51:14  cheshire
+Added structure definitions for IPv6Header, etc.
+
+Revision 1.525  2008/12/10 02:18:31  cheshire
+Increased MaxMsg to 160 for showing longer TXT records in SIGINFO output
+
+Revision 1.524  2008/12/10 01:49:39  cheshire
+Fixes for alignment issues on ARMv5
+
+Revision 1.523  2008/12/05 02:35:24  mcguire
+<rdar://problem/6107390> Write to the DynamicStore when a Sleep Proxy server is available on the network
+
+Revision 1.522  2008/12/04 21:08:51  mcguire
+<rdar://problem/6116863> mDNS: Provide mechanism to disable Multicast advertisements
+
+Revision 1.521  2008/12/04 02:19:24  cheshire
+Updated comment
+
+Revision 1.520  2008/11/26 20:28:05  cheshire
+Added new SSHPort constant
+
+Revision 1.519  2008/11/25 22:46:30  cheshire
+For ease of code searching, renamed ZoneData field of ServiceRecordSet_struct from "nta" to "srs_nta"
+
+Revision 1.518  2008/11/25 05:07:15  cheshire
+<rdar://problem/6374328> Advertise Sleep Proxy metrics in service name
+
+Revision 1.517  2008/11/20 01:51:19  cheshire
+Exported RecreateNATMappings so it's callable from other files
+
+Revision 1.516  2008/11/16 16:49:25  cheshire
+<rdar://problem/6375808> LLQs broken in mDNSResponder-184
+DNSOpt_LLQData_Space was incorrectly defined to be 18 instead of 22
+
+Revision 1.515  2008/11/14 20:59:41  cheshire
+Added mDNSEthAddressIsZero(A) macro
+
+Revision 1.514  2008/11/14 02:17:41  cheshire
+Added NextScheduledSPS task scheduling variable
+
+Revision 1.513  2008/11/14 00:47:19  cheshire
+Added TimeRcvd and TimeExpire fields to AuthRecord_struct
+
+Revision 1.512  2008/11/14 00:00:53  cheshire
+After client machine wakes up, Sleep Proxy machine need to remove any records
+it was temporarily holding as proxy for that client
+
+Revision 1.511  2008/11/13 19:04:44  cheshire
+Added definition of OwnerOptData
+
+Revision 1.510  2008/11/06 23:48:32  cheshire
+Changed SleepProxyServerType to mDNSu8
+
+Revision 1.509  2008/11/04 23:06:50  cheshire
+Split RDataBody union definition into RDataBody and RDataBody2, and removed
+SOA from the normal RDataBody union definition, saving 270 bytes per AuthRecord
+
+Revision 1.508  2008/11/04 22:21:43  cheshire
+Changed zone field of AuthRecord_struct from domainname to pointer, saving 252 bytes per AuthRecord
+
+Revision 1.507  2008/11/04 22:13:43  cheshire
+Made RDataBody parameter to GetRRDisplayString_rdb "const"
+
+Revision 1.506  2008/11/04 20:06:19  cheshire
+<rdar://problem/6186231> Change MAX_DOMAIN_NAME to 256
+
+Revision 1.505  2008/11/03 23:49:47  mkrochma
+Increase NATMAP_DEFAULT_LEASE to 2 hours so we do maintenance wake less often
+
+Revision 1.504  2008/10/31 22:55:04  cheshire
+Initial support for structured SPS names
+
+Revision 1.503  2008/10/24 23:58:47  cheshire
+Ports should be mDNSIPPort, not mDNSOpaque16
+
+Revision 1.502  2008/10/23 22:25:56  cheshire
+Renamed field "id" to more descriptive "updateid"
+
+Revision 1.501  2008/10/22 22:22:27  cheshire
+Added packet structure definitions
+
+Revision 1.500  2008/10/22 19:55:35  cheshire
+Miscellaneous fixes; renamed FindFirstAnswerInCache to FindSPSInCache
+
+Revision 1.499  2008/10/22 17:15:47  cheshire
+Updated definitions of mDNSIPv4AddressIsZero/mDNSIPv4AddressIsOnes, etc.
+
+Revision 1.498  2008/10/22 01:01:52  cheshire
+Added onesEthAddr constant, used for sending ARP broadcasts
+
+Revision 1.497  2008/10/21 00:51:11  cheshire
+Added declaration of mDNSPlatformSetBPF(), used by uds_daemon.c to pass BPF fd to mDNSMacOSX.c
+
+Revision 1.496  2008/10/16 22:38:52  cheshire
+Added declaration of mDNSCoreReceiveRawPacket()
+
+Revision 1.495  2008/10/15 22:53:51  cheshire
+Removed unused "#define LocalReverseMapDomain"
+
+Revision 1.494  2008/10/15 20:37:17  cheshire
+Added "#define DNSOpt_Lease_Space 19"
+
+Revision 1.493  2008/10/14 21:37:56  cheshire
+Removed unnecessary m->BeSleepProxyServer variable
+
+Revision 1.492  2008/10/14 20:26:36  cheshire
+Added definition of a new kDNSType_MAC rdata type
+
+Revision 1.491  2008/10/09 22:29:04  cheshire
+Added "mDNSEthAddr MAC" to NetworkInterfaceInfo_struct
+
+Revision 1.490  2008/10/09 21:39:20  cheshire
+Update list of DNS types
+
+Revision 1.489  2008/10/09 18:59:19  cheshire
+Added NetWakeResolve code, removed unused m->SendDeregistrations and m->SendImmediateAnswers
+
+Revision 1.488  2008/10/08 01:02:03  cheshire
+Added mDNS_SetupQuestion() convenience function
+
+Revision 1.487  2008/10/07 21:41:57  mcguire
+Increase sizecheck limits to account for DNSQuestion added to NetworkInterfaceInfo_struct in 64bit builds
+
+Revision 1.486  2008/10/07 15:56:24  cheshire
+Increase sizecheck limits to account for DNSQuestion added to NetworkInterfaceInfo_struct
+
+Revision 1.485  2008/10/04 00:48:37  cheshire
+Added DNSQuestion to NetworkInterfaceInfo_struct, used for browsing for Sleep Proxy Servers
+
+Revision 1.484  2008/10/04 00:01:45  cheshire
+Move NetworkInterfaceInfo_struct further down in file (we'll need to add a DNSQuestion to it later)
+
+Revision 1.483  2008/10/03 23:28:41  cheshire
+Added declaration of mDNSPlatformSendRawPacket
+
+Revision 1.482  2008/10/03 17:30:05  cheshire
+Added declaration of mDNS_ConfigChanged(mDNS *const m);
+
+Revision 1.481  2008/10/02 22:38:58  cheshire
+Added SleepProxyServer fields, and mDNSCoreBeSleepProxyServer() call for turning SleepProxyServer on and off
+
+Revision 1.480  2008/10/01 21:22:17  cheshire
+Added NetWake field to NetworkInterfaceInfo structure, to signal when Wake-On-Magic-Packet is enabled for that interface
+
+Revision 1.479  2008/09/29 20:12:37  cheshire
+Rename 'AnswerLocalQuestions' to more descriptive 'AnswerLocalOnlyQuestions' and 'AnsweredLocalQ' to 'AnsweredLOQ'
+
+Revision 1.478  2008/09/23 02:37:10  cheshire
+Added FirstLabel/SecondLabel macros
+
+Revision 1.477  2008/09/20 00:34:22  mcguire
 <rdar://problem/6129039> BTMM: Add support for WANPPPConnection
 
-Revision 1.468.2.3  2008/07/29 20:46:57  mcguire
-<rdar://problem/6090007> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
-merge r1.474 from <rdar://problem/3988320>
+Revision 1.476  2008/09/05 22:22:01  cheshire
+Move "UDPSocket *LocalSocket" field to more logical place in DNSQuestion_struct
+
+Revision 1.475  2008/07/25 22:34:11  mcguire
+fix sizecheck issues for 64bit
 
-Revision 1.468.2.2  2008/07/29 19:44:38  mcguire
-<rdar://problem/6090024> BTMM: alternate SSDP queries between multicast & unicast
-merge r1.472, r1.473 for <rdar://problem/5736845>
+Revision 1.474  2008/07/24 20:23:03  cheshire
+<rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
 
-Revision 1.468.2.1  2008/07/29 19:10:53  mcguire
-<rdar://problem/6090041> Use all configured DNS servers
-merege 1.470 from <rdar://problem/4206534>
+Revision 1.473  2008/07/18 21:37:42  mcguire
+<rdar://problem/5736845> BTMM: alternate SSDP queries between multicast & unicast
+
+Revision 1.472  2008/07/01 01:39:59  mcguire
+<rdar://problem/5823010> 64-bit fixes
+
+Revision 1.471  2008/06/26 17:24:11  mkrochma
+<rdar://problem/5450912> BTMM: Stop listening on UDP 5351 for NAT Status Announcements
+
+Revision 1.470  2008/06/19 01:20:49  mcguire
+<rdar://problem/4206534> Use all configured DNS servers
+
+Revision 1.469  2008/03/07 18:56:02  cheshire
+<rdar://problem/5777647> dnsbugtest query every three seconds when source IP address of response doesn't match
 
 Revision 1.468  2008/03/06 02:48:34  mcguire
 <rdar://problem/5321824> write status to the DS
@@ -195,7 +512,7 @@ Add new symbol "NATPMPAnnouncementPort" (5350)
 
 Revision 1.428  2007/09/05 21:48:01  cheshire
 <rdar://problem/5385864> BTMM: mDNSResponder flushes wide-area Bonjour records after an hour for a zone.
-Now that we're respecting the TTL of uDNS records in the cache, the LLQ maintenance cod needs
+Now that we're respecting the TTL of uDNS records in the cache, the LLQ maintenance code needs
 to update the cache lifetimes of all relevant records every time it successfully renews an LLQ,
 otherwise those records will expire and vanish from the cache.
 
@@ -679,6 +996,9 @@ Fixes to avoid code generation warning/error on FreeBSD 7
 #endif
 
 #include "mDNSDebug.h"
+#if APPLE_OSX_mDNSResponder
+#include <uuid/uuid.h>
+#endif
 
 #ifdef __cplusplus
        extern "C" {
@@ -767,51 +1087,62 @@ typedef enum                             // From RFC 1035
        kDNSType_MINFO,                 // 14 Mailbox information
        kDNSType_MX,                    // 15 Mail Exchanger
        kDNSType_TXT,                   // 16 Arbitrary text string
-       kDNSType_RP,                    // 17 Responsible person.
-       kDNSType_AFSDB,                 // 18 AFS cell database.
-       kDNSType_X25,                   // 19 X_25 calling address.
-       kDNSType_ISDN,                  // 20 ISDN calling address.
-       kDNSType_RT,                    // 21 Router.
-       kDNSType_NSAP,                  // 22 NSAP address.
-       kDNSType_NSAP_PTR,              // 23 Reverse NSAP lookup (deprecated).
-       kDNSType_SIG,                   // 24 Security signature.
-       kDNSType_KEY,                   // 25 Security key.
-       kDNSType_PX,                    // 26 X.400 mail mapping.
-       kDNSType_GPOS,                  // 27 Geographical position (withdrawn).
-       kDNSType_AAAA,                  // 28 IPv6 Address.
-       kDNSType_LOC,                   // 29 Location Information.
-       kDNSType_NXT,                   // 30 Next domain (security).
-       kDNSType_EID,                   // 31 Endpoint identifier.
-       kDNSType_NIMLOC,                // 32 Nimrod Locator.
-       kDNSType_SRV,                   // 33 Service record.
+       kDNSType_RP,                    // 17 Responsible person
+       kDNSType_AFSDB,                 // 18 AFS cell database
+       kDNSType_X25,                   // 19 X_25 calling address
+       kDNSType_ISDN,                  // 20 ISDN calling address
+       kDNSType_RT,                    // 21 Router
+       kDNSType_NSAP,                  // 22 NSAP address
+       kDNSType_NSAP_PTR,              // 23 Reverse NSAP lookup (deprecated)
+       kDNSType_SIG,                   // 24 Security signature
+       kDNSType_KEY,                   // 25 Security key
+       kDNSType_PX,                    // 26 X.400 mail mapping
+       kDNSType_GPOS,                  // 27 Geographical position (withdrawn)
+       kDNSType_AAAA,                  // 28 IPv6 Address
+       kDNSType_LOC,                   // 29 Location Information
+       kDNSType_NXT,                   // 30 Next domain (security)
+       kDNSType_EID,                   // 31 Endpoint identifier
+       kDNSType_NIMLOC,                // 32 Nimrod Locator
+       kDNSType_SRV,                   // 33 Service record
        kDNSType_ATMA,                  // 34 ATM Address
        kDNSType_NAPTR,                 // 35 Naming Authority PoinTeR
        kDNSType_KX,                    // 36 Key Exchange
        kDNSType_CERT,                  // 37 Certification record
        kDNSType_A6,                    // 38 IPv6 Address (deprecated)
        kDNSType_DNAME,                 // 39 Non-terminal DNAME (for IPv6)
-       kDNSType_SINK,                  // 40 Kitchen sink (experimentatl)
+       kDNSType_SINK,                  // 40 Kitchen sink (experimental)
        kDNSType_OPT,                   // 41 EDNS0 option (meta-RR)
        kDNSType_APL,                   // 42 Address Prefix List
        kDNSType_DS,                    // 43 Delegation Signer
        kDNSType_SSHFP,                 // 44 SSH Key Fingerprint
        kDNSType_IPSECKEY,              // 45 IPSECKEY
        kDNSType_RRSIG,                 // 46 RRSIG
-       kDNSType_NSEC,                  // 47 NSEC
+       kDNSType_NSEC,                  // 47 Denial of Existence
        kDNSType_DNSKEY,                // 48 DNSKEY
-       kDNSType_DHCID,                 // 49 DHCID
+       kDNSType_DHCID,                 // 49 DHCP Client Identifier
+       kDNSType_NSEC3,                 // 50 Hashed Authenticated Denial of Existence
+       kDNSType_NSEC3PARAM,    // 51 Hashed Authenticated Denial of Existence
+
+       kDNSType_HIP = 55,              // 55 Host Identity Protocol
+
+       kDNSType_SPF = 99,              // 99 Sender Policy Framework for E-Mail
+       kDNSType_UINFO,                 // 100 IANA-Reserved
+       kDNSType_UID,                   // 101 IANA-Reserved
+       kDNSType_GID,                   // 102 IANA-Reserved
+       kDNSType_UNSPEC,                // 103 IANA-Reserved
 
        kDNSType_TKEY = 249,    // 249 Transaction key
-       kDNSType_TSIG,                  // 250 Transaction signature.
-       kDNSType_IXFR,                  // 251 Incremental zone transfer.
-       kDNSType_AXFR,                  // 252 Transfer zone of authority.
-       kDNSType_MAILB,                 // 253 Transfer mailbox records.
-       kDNSType_MAILA,                 // 254 Transfer mail agent records.
+       kDNSType_TSIG,                  // 250 Transaction signature
+       kDNSType_IXFR,                  // 251 Incremental zone transfer
+       kDNSType_AXFR,                  // 252 Transfer zone of authority
+       kDNSType_MAILB,                 // 253 Transfer mailbox records
+       kDNSType_MAILA,                 // 254 Transfer mail agent records
        kDNSQType_ANY                   // Not a DNS type, but a DNS query type, meaning "all types"
        } DNS_TypeValues;
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - Simple types
 #endif
 
@@ -856,11 +1187,17 @@ typedef struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID;
 // less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers,
 // and if you make the mistake of trying to do those using the NotAnInteger field, then you'll
 // find you get code that doesn't work consistently on big-endian and little-endian machines.
-typedef packedunion { mDNSu8 b[ 2]; mDNSu16 NotAnInteger; } mDNSOpaque16;
-typedef packedunion { mDNSu8 b[ 4]; mDNSu32 NotAnInteger; } mDNSOpaque32;
+#if defined(_WIN32)
+ #pragma pack(push,2)
+#endif
+typedef       union { mDNSu8 b[ 2]; mDNSu16 NotAnInteger; } mDNSOpaque16;
+typedef       union { mDNSu8 b[ 4]; mDNSu32 NotAnInteger; } mDNSOpaque32;
 typedef packedunion { mDNSu8 b[ 6]; mDNSu16 w[3]; mDNSu32 l[1]; } mDNSOpaque48;
-typedef packedunion { mDNSu8 b[ 8]; mDNSu16 w[4]; mDNSu32 l[2]; } mDNSOpaque64;
-typedef packedunion { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128;
+typedef       union { mDNSu8 b[ 8]; mDNSu16 w[4]; mDNSu32 l[2]; } mDNSOpaque64;
+typedef       union { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128;
+#if defined(_WIN32)
+ #pragma pack(pop)
+#endif
 
 typedef mDNSOpaque16  mDNSIPPort;              // An IP port is a two-byte opaque identifier (not an integer)
 typedef mDNSOpaque32  mDNSv4Addr;              // An IP address is a four-byte opaque identifier (not an integer)
@@ -946,26 +1283,26 @@ typedef mDNSs32 mStatus;
 #define MAX_DOMAIN_LABEL 63
 typedef struct { mDNSu8 c[ 64]; } domainlabel;         // One label: length byte and up to 63 characters
 
-// RFC 1034/1035 specify that a domain name, including length bytes, data bytes, and terminating zero, may be up to 255 bytes long
-#define MAX_DOMAIN_NAME 255
-typedef struct { mDNSu8 c[256]; } domainname;          // Up to 255 bytes of length-prefixed domainlabels
+// RFC 1034/1035/2181 specify that a domain name, including length bytes, data bytes, and terminating zero, may be up to 256 bytes long
+#define MAX_DOMAIN_NAME 256
+typedef struct { mDNSu8 c[256]; } domainname;          // Up to 256 bytes of length-prefixed domainlabels
 
 typedef struct { mDNSu8 c[256]; } UTF8str255;          // Null-terminated C string
 
-// The longest legal textual form of a DNS name is 1005 bytes, including the C-string terminating NULL at the end.
+// The longest legal textual form of a DNS name is 1009 bytes, including the C-string terminating NULL at the end.
 // Explanation:
 // When a native domainname object is converted to printable textual form using ConvertDomainNameToCString(),
 // non-printing characters are represented in the conventional DNS way, as '\ddd', where ddd is a three-digit decimal number.
-// The longest legal domain name is 255 bytes, in the form of four labels as shown below:
-// Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 61 data bytes, zero byte.
+// The longest legal domain name is 256 bytes, in the form of four labels as shown below:
+// Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 62 data bytes, zero byte.
 // Each label is encoded textually as characters followed by a trailing dot.
 // If every character has to be represented as a four-byte escape sequence, then this makes the maximum textual form four labels
 // plus the C-string terminating NULL as shown below:
-// 63*4+1 + 63*4+1 + 63*4+1 + 61*4+1 + 1 = 1005.
+// 63*4+1 + 63*4+1 + 63*4+1 + 62*4+1 + 1 = 1009.
 // Note that MAX_ESCAPED_DOMAIN_LABEL is not normally used: If you're only decoding a single label, escaping is usually not required.
 // It is for domain names, where dots are used as label separators, that proper escaping is vital.
 #define MAX_ESCAPED_DOMAIN_LABEL 254
-#define MAX_ESCAPED_DOMAIN_NAME 1005
+#define MAX_ESCAPED_DOMAIN_NAME 1009
 
 // MAX_REVERSE_MAPPING_NAME
 // For IPv4: "123.123.123.123.in-addr.arpa."  30 bytes including terminating NUL
@@ -996,12 +1333,13 @@ typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
 typedef struct NATTraversalInfo_struct NATTraversalInfo;
 
 // Structure to abstract away the differences between TCP/SSL sockets, and one for UDP sockets
-// The actual definition of these structures in the in the appropriate platform support code
+// The actual definition of these structures appear in the appropriate platform support code
 typedef struct TCPSocket_struct TCPSocket;
 typedef struct UDPSocket_struct UDPSocket;
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - DNS Message structures
 #endif
 
@@ -1049,6 +1387,87 @@ typedef struct tcpInfo_t
 
 // ***************************************************************************
 #if 0
+#pragma mark -
+#pragma mark - Other Packet Format Structures
+#endif
+
+typedef packedstruct
+       {
+       mDNSEthAddr  dst;
+       mDNSEthAddr  src;
+       mDNSOpaque16 ethertype;
+       } EthernetHeader;               // 14 bytes
+
+typedef packedstruct
+       {
+       mDNSOpaque16 hrd;
+       mDNSOpaque16 pro;
+       mDNSu8       hln;
+       mDNSu8       pln;
+       mDNSOpaque16 op;
+       mDNSEthAddr  sha;
+       mDNSv4Addr   spa;
+       mDNSEthAddr  tha;
+       mDNSv4Addr   tpa;
+       } ARP_EthIP;                    // 28 bytes
+
+typedef packedstruct
+       {
+       mDNSu8       vlen;
+       mDNSu8       tos;
+       mDNSu16      totlen;
+       mDNSOpaque16 id;
+       mDNSOpaque16 flagsfrags;
+       mDNSu8       ttl;
+       mDNSu8       protocol;
+       mDNSu16      checksum;
+       mDNSv4Addr   src;
+       mDNSv4Addr   dst;
+       } IPv4Header;                   // 20 bytes
+
+typedef packedstruct
+       {
+       mDNSu32      vcf;               // Version, Traffic Class, Flow Label
+       mDNSu16      len;               // Payload Length
+       mDNSu8       protocol;  // Type of next header: 0x06 = TCP, 0x11 = UDP, 0x3A = ICMPv6
+       mDNSu8       ttl;               // Hop Limit
+       mDNSv6Addr   src;
+       mDNSv6Addr   dst;
+       } IPv6Header;                   // 40 bytes
+
+typedef packedstruct
+       {
+       mDNSu8       type;              // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
+       mDNSu8       code;
+       mDNSu16      checksum;
+       mDNSu32      reserved;
+       mDNSv6Addr   target;
+       } IPv6ND;                               // 24 bytes
+
+typedef packedstruct
+       {
+       mDNSIPPort   src;
+       mDNSIPPort   dst;
+       mDNSu16      len;               // Length including UDP header (ie. minimum value is 8 bytes)
+       mDNSu16      checksum;
+       } UDPHeader;                    // 8 bytes
+
+typedef packedstruct
+       {
+       mDNSIPPort   src;
+       mDNSIPPort   dst;
+       mDNSu32      seq;
+       mDNSu32      ack;
+       mDNSu8       offset;
+       mDNSu8       flags;
+       mDNSu16      window;
+       mDNSu16      checksum;
+       mDNSu16      urgent;
+       } TCPHeader;                    // 20 bytes
+
+// ***************************************************************************
+#if 0
+#pragma mark -
 #pragma mark - Resource Record structures
 #endif
 
@@ -1149,30 +1568,82 @@ typedef packedstruct
        mDNSu32 min;            // Nominally the minimum record TTL for this zone, in seconds; also used for negative caching.
        } rdataSOA;
 
-typedef packedstruct
+// EDNS Option Code registrations are recorded in the "DNS EDNS0 Options" section of
+// <http://www.iana.org/assignments/dns-parameters>
+
+#define kDNSOpt_LLQ   1
+#define kDNSOpt_Lease 2
+#define kDNSOpt_NSID  3
+#define kDNSOpt_Owner 4
+
+typedef struct
        {
        mDNSu16      vers;
        mDNSu16      llqOp;
        mDNSu16      err;       // Or UDP reply port, in setup request
+       // Note: In the in-memory form, there's typically a two-byte space here, so that the following 64-bit id is word-aligned
        mDNSOpaque64 id;
        mDNSu32      llqlease;
        } LLQOptData;
 
-// Windows adds pad bytes to sizeof(LLQOptData).
-// Use this macro when setting length fields or validating option rdata from off the wire.
-// Use sizeof(LLQOptData) when dealing with structures (e.g. memcpy).
-// Never memcpy between on-the-wire representation and a structure.
-
-#define LLQ_OPTLEN ((3 * sizeof(mDNSu16)) + 8 + sizeof(mDNSu32))
-
-// NOTE: rdataOPT format may be repeated an arbitrary number of times in a single resource record
+typedef struct
+       {
+       mDNSu8       vers;              // Version number of this Owner OPT record
+       mDNSs8       seq;               // Sleep/wake epoch
+       mDNSEthAddr  HMAC;              // Host's primary identifier (e.g. MAC of on-board Ethernet)
+       mDNSEthAddr  IMAC;              // Interface's MAC address (if different to primary MAC)
+       mDNSOpaque48 password;  // Optional password
+       } OwnerOptData;
+
+// Note: rdataOPT format may be repeated an arbitrary number of times in a single resource record
 typedef packedstruct
        {
        mDNSu16 opt;
        mDNSu16 optlen;
-       union { LLQOptData llq; mDNSu32 updatelease; } OptData;
+       union { LLQOptData llq; mDNSu32 updatelease; OwnerOptData owner; } u;
        } rdataOPT;
 
+// Space needed to put OPT records into a packet:
+// Header      11 bytes (name 1, type 2, class 2, TTL 4, length 2)
+// LLQ rdata   18 bytes (opt 2, len 2, vers 2, op 2, err 2, id 8, lease 4)
+// Lease rdata  8 bytes (opt 2, len 2, lease 4)
+// Owner rdata 12-24    (opt 2, len 2, owner 8-20)
+
+#define DNSOpt_Header_Space                 11
+#define DNSOpt_LLQData_Space               (4 + 2 + 2 + 2 + 8 + 4)
+#define DNSOpt_LeaseData_Space             (4 + 4)
+#define DNSOpt_OwnerData_ID_Space          (4 + 2 + 6)
+#define DNSOpt_OwnerData_ID_Wake_Space     (4 + 2 + 6 + 6)
+#define DNSOpt_OwnerData_ID_Wake_PW4_Space (4 + 2 + 6 + 6 + 4)
+#define DNSOpt_OwnerData_ID_Wake_PW6_Space (4 + 2 + 6 + 6 + 6)
+
+#define ValidOwnerLength(X) (  (X) == DNSOpt_OwnerData_ID_Space          - 4 || \
+                                                               (X) == DNSOpt_OwnerData_ID_Wake_Space     - 4 || \
+                                                               (X) == DNSOpt_OwnerData_ID_Wake_PW4_Space - 4 || \
+                                                               (X) == DNSOpt_OwnerData_ID_Wake_PW6_Space - 4    )
+
+#define ValidDNSOpt(O) (((O)->opt == kDNSOpt_LLQ   && (O)->optlen == DNSOpt_LLQData_Space   - 4) || \
+                                               ((O)->opt == kDNSOpt_Lease && (O)->optlen == DNSOpt_LeaseData_Space - 4) || \
+                                               ((O)->opt == kDNSOpt_Owner && ValidOwnerLength((O)->optlen)            )    )
+
+#define DNSOpt_Owner_Space(O) (mDNSSameEthAddress(&(O)->u.owner.HMAC, &(O)->u.owner.IMAC) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space)
+
+#define DNSOpt_Data_Space(O) (                                  \
+       (O)->opt == kDNSOpt_LLQ   ? DNSOpt_LLQData_Space   :        \
+       (O)->opt == kDNSOpt_Lease ? DNSOpt_LeaseData_Space :        \
+       (O)->opt == kDNSOpt_Owner ? DNSOpt_Owner_Space(O)  : 0x10000)
+
+// A maximal NSEC record is:
+//   256 bytes domainname 'nextname'
+// + 256 * 34 = 8704 bytes of bitmap data
+// = 8960 bytes total
+// For now we only support NSEC records encoding DNS types 0-255 and ignore the nextname (we always set it to be the same as the rrname),
+// which gives us a fixed in-memory size of 32 bytes (256 bits)
+typedef struct
+       {
+       mDNSu8 bitmap[32];
+       } rdataNSEC;
+
 // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
 // MaximumRDSize is 8K the absolute maximum we support (at least for now)
 #define StandardAuthRDSize 264
@@ -1192,30 +1663,70 @@ typedef packedstruct
 // have them both be the same size. Making one smaller without making the other smaller won't actually save any memory.
 #define InlineCacheRDSize 68
 
-#define InlineCacheGroupNameSize 144
+// On 64-bit, the pointers in a CacheRecord are bigger, and that creates 8 bytes more space for the name in a CacheGroup
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
+       #if defined(_ILP64) || defined(__ILP64__) || defined(_LP64) || defined(__LP64__) || defined(_WIN64)
+       #define InlineCacheGroupNameSize 152
+       #else
+       #define InlineCacheGroupNameSize 144
+       #endif
+#else
+       #if defined(_ILP64) || defined(__ILP64__) || defined(_LP64) || defined(__LP64__) || defined(_WIN64)
+       #define InlineCacheGroupNameSize 136
+       #else
+       #define InlineCacheGroupNameSize 128
+       #endif
+#endif
 
+// The RDataBody union defines the common rdata types that fit into our 264-byte limit
 typedef union
        {
        mDNSu8      data[StandardAuthRDSize];
        mDNSv4Addr  ipv4;               // For 'A' record
        domainname  name;               // For PTR, NS, CNAME, DNAME
-       rdataSOA    soa;
        UTF8str255  txt;
        rdataMX     mx;
-       rdataRP     rp;
-       rdataPX     px;
        mDNSv6Addr  ipv6;               // For 'AAAA' record
        rdataSRV    srv;
-       rdataOPT    opt;                // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
+       rdataOPT    opt[2];             // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
+       rdataNSEC   nsec;
        } RDataBody;
 
+// The RDataBody2 union is the same as above, except it includes fields for the larger types like soa, rp, px
+typedef union
+       {
+       mDNSu8      data[StandardAuthRDSize];
+       mDNSv4Addr  ipv4;               // For 'A' record
+       domainname  name;               // For PTR, NS, CNAME, DNAME
+       rdataSOA    soa;                // This is large; not included in the normal RDataBody definition
+       UTF8str255  txt;
+       rdataMX     mx;
+       rdataRP     rp;                 // This is large; not included in the normal RDataBody definition
+       rdataPX     px;                 // This is large; not included in the normal RDataBody definition
+       mDNSv6Addr  ipv6;               // For 'AAAA' record
+       rdataSRV    srv;
+       rdataOPT    opt[2];             // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
+       rdataNSEC   nsec;
+       } RDataBody2;
+
 typedef struct
        {
        mDNSu16    MaxRDLength; // Amount of storage allocated for rdata (usually sizeof(RDataBody))
+       mDNSu16    padding;             // So that RDataBody is aligned on 32-bit boundary
        RDataBody  u;
        } RData;
+
+// sizeofRDataHeader should be 4 bytes
 #define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
 
+// RData_small is a smaller version of the RData object, used for inline data storage embedded in a CacheRecord_struct
+typedef struct
+       {
+       mDNSu16    MaxRDLength; // Storage allocated for data (may be greater than InlineCacheRDSize if additional storage follows this object)
+       mDNSu16    padding;             // So that data is aligned on 32-bit boundary
+       mDNSu8     data[InlineCacheRDSize];
+       } RData_small;
+
 // Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
 typedef void mDNSRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
 
@@ -1227,13 +1738,14 @@ typedef void mDNSRecordUpdateCallback(mDNS *const m, AuthRecord *const rr, RData
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - NAT Traversal structures and constants
 #endif
 
-#define NATMAP_MAX_RETRY_INTERVAL    ((mDNSPlatformOneSecond * 60) * 15) // Max retry interval is 15 minutes
-#define NATMAP_MIN_RETRY_INTERVAL     (mDNSPlatformOneSecond * 2)             // Min retry interval is 2 seconds
-#define NATMAP_INIT_RETRY                     (mDNSPlatformOneSecond / 4)             // start at 250ms w/ exponential decay
-#define NATMAP_DEFAULT_LEASE (60 * 60)                             // lease life in seconds
+#define NATMAP_MAX_RETRY_INTERVAL    ((mDNSPlatformOneSecond * 60) * 15)    // Max retry interval is 15 minutes
+#define NATMAP_MIN_RETRY_INTERVAL     (mDNSPlatformOneSecond * 2)           // Min retry interval is 2 seconds
+#define NATMAP_INIT_RETRY             (mDNSPlatformOneSecond / 4)           // start at 250ms w/ exponential decay
+#define NATMAP_DEFAULT_LEASE          (60 * 60 * 2)                         // 2 hour lease life in seconds
 #define NATMAP_VERS 0
 
 typedef enum
@@ -1361,26 +1873,22 @@ struct NATTraversalInfo_struct
        // Client API fields: The client must set up these fields *before* making any NAT traversal API calls
        mDNSu8                      Protocol;                   // NATOp_MapUDP or NATOp_MapTCP, or zero if just requesting the external IP address
        mDNSIPPort                  IntPort;                    // Client's internal port number (doesn't change)
-       mDNSIPPort                  RequestedPort;              // Requested public port mapping; may be updated with actual value assigned by gateway
+       mDNSIPPort                  RequestedPort;              // Requested external port; may be updated with actual value assigned by gateway
        mDNSu32                     NATLease;                   // Requested lifetime in seconds (doesn't change)
        NATTraversalClientCallback  clientCallback;
        void                       *clientContext;
        };
 
-typedef struct
+typedef struct                                                 // Size is 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
        {
        mDNSu8           RecordType;            // See enum above
-       mDNSInterfaceID  InterfaceID;           // Set if this RR is specific to one interface
-                                                                               // For records received off the wire, InterfaceID is *always* set to the receiving interface
-                                                                               // For our authoritative records, InterfaceID is usually zero, except for those few records
-                                                                               // that are interface-specific (e.g. address records, especially linklocal addresses)
-       const domainname *name;
        mDNSu16          rrtype;
        mDNSu16          rrclass;
        mDNSu32          rroriginalttl;         // In seconds
        mDNSu16          rdlength;                      // Size of the raw rdata, in bytes, in the on-the-wire format
-                                                                               // (in-memory storage may be larger, for structures containing 'holes', like SOA)
-       mDNSu16          rdestimate;            // Upper bound on size of rdata after name compression
+                                                                               // (In-memory storage may be larger, for structures containing 'holes', like SOA,
+                                                                               // or smaller, for NSEC where we don't bother storing the nextname field)
+       mDNSu16          rdestimate;            // Upper bound on on-the-wire size of rdata after name compression
        mDNSu32          namehash;                      // Name-based (i.e. case-insensitive) hash of name
        mDNSu32          rdatahash;                     // For rdata containing domain name (e.g. PTR, SRV, CNAME etc.), case-insensitive name hash
                                                                                // else, for all other rdata, 32-bit hash of the raw rdata
@@ -1388,6 +1896,13 @@ typedef struct
                                                                                // ReconfirmAntecedents(), etc., use rdatahash as a pre-flight check to see
                                                                                // whether it's worth doing a full SameDomainName() call. If the rdatahash
                                                                                // is not a correct case-insensitive name hash, they'll get false negatives.
+
+       // Grouping pointers together at the end of the structure improves the memory layout efficiency
+       mDNSInterfaceID  InterfaceID;           // Set if this RR is specific to one interface
+                                                                               // For records received off the wire, InterfaceID is *always* set to the receiving interface
+                                                                               // For our authoritative records, InterfaceID is usually zero, except for those few records
+                                                                               // that are interface-specific (e.g. address records, especially linklocal addresses)
+       const domainname *name;
        RData           *rdata;                         // Pointer to storage for this rdata
        } ResourceRecord;
 
@@ -1425,11 +1940,11 @@ struct AuthRecord_struct
 
        AuthRecord     *next;                           // Next in list; first element of structure for efficiency reasons
        // Field Group 1: Common ResourceRecord fields
-       ResourceRecord  resrec;
+       ResourceRecord  resrec;                         // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
 
        // Field Group 2: Persistent metadata for Authoritative Records
        AuthRecord     *Additional1;            // Recommended additional record to include in response (e.g. SRV for PTR record)
-       AuthRecord     *Additional2;            // Another additional (e.g. TXT for record)
+       AuthRecord     *Additional2;            // Another additional (e.g. TXT for PTR record)
        AuthRecord     *DependentOn;            // This record depends on another for its uniqueness checking
        AuthRecord     *RRSet;                          // This unique record is part of an RRSet
        mDNSRecordCallback *RecordCallback;     // Callback function to call for state changes, and to free memory asynchronously on deregistration
@@ -1438,15 +1953,22 @@ struct AuthRecord_struct
        mDNSu8          AllowRemoteQuery;       // Set if we allow hosts not on the local link to query this record
        mDNSu8          ForceMCast;                     // Set by client to advertise solely via multicast, even for apparently unicast names
 
+       OwnerOptData    WakeUp;                         // Fpr Sleep Proxy records, MAC address of original owner (so we can wake it)
+       mDNSAddr        AddressProxy;           // For reverse-mapping Sleep Proxy PTR records, address in question
+       mDNSs32         TimeRcvd;                       // In platform time units
+       mDNSs32         TimeExpire;                     // In platform time units
+       
+
        // Field Group 3: Transient state for Authoritative Records
        mDNSu8          Acknowledged;           // Set if we've given the success callback to the client
        mDNSu8          ProbeCount;                     // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
        mDNSu8          AnnounceCount;          // Number of announcements remaining (kDNSRecordTypeShared)
        mDNSu8          RequireGoodbye;         // Set if this RR has been announced on the wire and will require a goodbye packet
-       mDNSu8          AnsweredLocalQ;         // Set if this RR has been delivered to LocalOnly questions
+       mDNSu8          AnsweredLocalQ;         // Set if this AuthRecord has been delivered to any local question (LocalOnly or mDNSInterface_Any)
        mDNSu8          IncludeInProbe;         // Set if this RR is being put into a probe right now
-       mDNSInterfaceID ImmedAnswer;            // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
        mDNSu8          ImmedUnicast;           // Set if we may send our response directly via unicast to the requester
+       mDNSInterfaceID SendNSECNow;            // Set if we need to generate associated NSEC data for this rrname
+       mDNSInterfaceID ImmedAnswer;            // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
        mDNSs32         ImmedAnswerMarkTime;
 #endif
@@ -1474,10 +1996,10 @@ struct AuthRecord_struct
                                                                // and rr->state can be regState_Unregistered
                                                                // What if we find one of those statements is true and the other false? What does that mean?
        mDNSBool     uselease;          // dynamic update contains (should contain) lease option
-       mDNSs32      expire;            // expiration of lease (-1 for static)
+       mDNSs32      expire;            // In platform time units: expiration of lease (-1 for static)
        mDNSBool     Private;           // If zone is private, DNS updates may have to be encrypted to prevent eavesdropping
-       mDNSOpaque16 id;                        // identifier to match update request and response
-       domainname   zone;                      // the zone that is updated
+       mDNSOpaque16 updateid;          // Identifier to match update request and response -- also used when transferring records to Sleep Proxy
+       const domainname *zone;         // the zone that is updated
        mDNSAddr     UpdateServer;      // DNS server that handles updates for this zone
        mDNSIPPort   UpdatePort;        // port on which server accepts dynamic updates
                                                                // !!!KRS not technically correct to cache longer than TTL
@@ -1487,12 +2009,12 @@ struct AuthRecord_struct
 
        // uDNS_UpdateRecord support fields
        // Do we really need all these in *addition* to NewRData and newrdlength above?
-       RData *OrigRData;
        mDNSu16 OrigRDLen;              // previously registered, being deleted
-       RData *InFlightRData;
        mDNSu16 InFlightRDLen;  // currently being registered
-       RData *QueuedRData;             // if the client call Update while an update is in flight, we must finish the
        mDNSu16 QueuedRDLen;    // pending operation (re-transmitting if necessary) THEN register the queued update
+       RData *OrigRData;
+       RData *InFlightRData;
+       RData *QueuedRData;
 
        // Field Group 5: Large data objects go at the end
        domainname      namestorage;
@@ -1519,13 +2041,14 @@ struct CacheGroup_struct                                // Header object for a list of CacheRecords with the
        CacheRecord    *members;                        // List of CacheRecords with this same name
        CacheRecord   **rrcache_tail;           // Tail end of that list
        domainname     *name;                           // Common name for all CacheRecords in this list
+       // Size to here is 20 bytes when compiling 32-bit; 40 bytes when compiling 64-bit
        mDNSu8          namestorage[InlineCacheGroupNameSize];
        };
 
 struct CacheRecord_struct
        {
        CacheRecord    *next;                           // Next in list; first element of structure for efficiency reasons
-       ResourceRecord  resrec;
+       ResourceRecord  resrec;                         // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
 
        // Transient state for Cache Records
        CacheRecord    *NextInKAList;           // Link to the next element in the chain of known answers to send
@@ -1536,16 +2059,19 @@ struct CacheRecord_struct
        DNSQuestion    *CRActiveQuestion;       // Points to an active question referencing this answer
        mDNSu32         UnansweredQueries;      // Number of times we've issued a query for this record without getting an answer
        mDNSs32         LastUnansweredTime;     // In platform time units; last time we incremented UnansweredQueries
+#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
        mDNSu32         MPUnansweredQ;          // Multi-packet query handling: Number of times we've seen a query for this record
        mDNSs32         MPLastUnansweredQT;     // Multi-packet query handling: Last time we incremented MPUnansweredQ
        mDNSu32         MPUnansweredKA;         // Multi-packet query handling: Number of times we've seen this record in a KA list
        mDNSBool        MPExpectingKA;          // Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA
+#endif
        CacheRecord    *NextInCFList;           // Set if this is in the list of records we just received with the cache flush bit set
-
-       struct { mDNSu16 MaxRDLength; mDNSu8 data[InlineCacheRDSize]; } rdatastorage;   // Storage for small records is right here
+       // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit
+       RData_small     smallrdatastorage;      // Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes)
        };
 
 // Storage sufficient to hold either a CacheGroup header or a CacheRecord
+// -- for best efficiency (to avoid wasted unused storage) they should be the same size
 typedef union CacheEntity_union CacheEntity;
 union CacheEntity_union { CacheEntity *next; CacheGroup cg; CacheRecord cr; };
 
@@ -1587,46 +2113,13 @@ typedef struct DNSServer
        mDNSInterfaceID interface;      // For specialized uses; we can have DNS servers reachable over specific interfaces
        mDNSAddr        addr;
        mDNSIPPort      port;
+       mDNSOpaque16    testid;
        mDNSu32         flags;          // Set when we're planning to delete this from the list
        mDNSu32         teststate;      // Have we sent bug-detection query to this server?
        mDNSs32         lasttest;       // Time we sent last bug-detection query to this server
        domainname      domain;         // name->server matching for "split dns"
        } DNSServer;
 
-typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
-
-// A NetworkInterfaceInfo_struct serves two purposes:
-// 1. It holds the address, PTR and HINFO records to advertise a given IP address on a given physical interface
-// 2. It tells mDNSCore which physical interfaces are available; each physical interface has its own unique InterfaceID.
-//    Since there may be multiple IP addresses on a single physical interface,
-//    there may be multiple NetworkInterfaceInfo_structs with the same InterfaceID.
-//    In this case, to avoid sending the same packet n times, when there's more than one
-//    struct with the same InterfaceID, mDNSCore picks one member of the set to be the
-//    active representative of the set; all others have the 'InterfaceActive' flag unset.
-
-struct NetworkInterfaceInfo_struct
-       {
-       // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
-       NetworkInterfaceInfo *next;
-
-       mDNSBool        InterfaceActive;        // Set if interface is sending & receiving packets (see comment above)
-       mDNSBool        IPv4Available;          // If InterfaceActive, set if v4 available on this InterfaceID
-       mDNSBool        IPv6Available;          // If InterfaceActive, set if v6 available on this InterfaceID
-
-       // Standard AuthRecords that every Responder host should have (one per active IP address)
-       AuthRecord RR_A;                                        // 'A' or 'AAAA' (address) record for our ".local" name
-       AuthRecord RR_PTR;                                      // PTR (reverse lookup) record
-       AuthRecord RR_HINFO;
-
-       // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
-       mDNSInterfaceID InterfaceID;            // Identifies physical interface; MUST NOT be 0, -1, or -2
-       mDNSAddr        ip;                                     // The IPv4 or IPv6 address to advertise
-       mDNSAddr        mask;
-       char            ifname[64];                     // Windows uses a GUID string for the interface name, which doesn't fit in 16 bytes
-       mDNSBool        Advertise;                      // False if you are only searching on this interface
-       mDNSBool        McastTxRx;                      // Send/Receive multicast on this { InterfaceID, address family } ?
-       };
-
 typedef struct ExtraResourceRecord_struct ExtraResourceRecord;
 struct ExtraResourceRecord_struct
        {
@@ -1659,9 +2152,9 @@ struct ServiceRecordSet_struct
        // all required data is passed as parameters to that function.
 
        // Begin uDNS info ****************
-       // Hopefully much of this stuff can be simplified or eliminated
+       // All of these fields should be eliminated
 
-       // NOTE: The current uDNS code keeps an explicit list of registered services, and handles them
+       // Note: The current uDNS code keeps an explicit list of registered services, and handles them
        // differently to how individual records are treated (this is probably a mistake). What this means is
        // that ServiceRecordSets for uDNS are kept in a linked list, whereas ServiceRecordSets for mDNS exist
        // just as a convenient placeholder to group the component records together and are not kept on any list.
@@ -1670,7 +2163,7 @@ struct ServiceRecordSet_struct
        mDNSBool          srs_uselease;                         // dynamic update contains (should contain) lease option
        mDNSBool          TestForSelfConflict;          // on name conflict, check if we're just seeing our own orphaned records
        mDNSBool          Private;                                      // If zone is private, DNS updates may have to be encrypted to prevent eavesdropping
-       ZoneData         *nta;
+       ZoneData         *srs_nta;
        mDNSOpaque16      id;
        domainname        zone;                                         // the zone that is updated
        mDNSAddr          SRSUpdateServer;                      // primary name server for the record's zone  !!!KRS not technically correct to cache longer than TTL
@@ -1701,6 +2194,7 @@ struct ServiceRecordSet_struct
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - Question structures
 #endif
 
@@ -1726,8 +2220,6 @@ typedef enum
        } LLQ_State;
 
 // LLQ constants
-#define kDNSOpt_LLQ       1
-#define kDNSOpt_Lease  2
 #define kLLQ_Vers      1
 #define kLLQ_DefLease  7200 // 2 hours
 #define kLLQ_MAX_TRIES 3    // retry an operation 3 times max
@@ -1737,9 +2229,6 @@ typedef enum
 #define kLLQOp_Refresh   2
 #define kLLQOp_Event     3
 
-#define LLQ_OPT_RDLEN   ((2 * sizeof(mDNSu16)) + LLQ_OPTLEN     )
-#define LEASE_OPT_RDLEN ((2 * sizeof(mDNSu16)) + sizeof(mDNSs32))
-
 // LLQ Errror Codes
 enum
        {
@@ -1815,6 +2304,7 @@ struct DNSQuestion_struct
        mDNSu32               CNAMEReferrals;   // Count of how many CNAME redirections we've done
 
        // Wide Area fields. These are used internally by the uDNS core
+       UDPSocket            *LocalSocket;
        DNSServer            *qDNSServer;               // Caching server for this query (in the absence of an SRV saying otherwise)
        mDNSu8                unansweredQueries;// The number of unanswered queries to this server
 
@@ -1826,7 +2316,7 @@ struct DNSQuestion_struct
 
        // LLQ-specific fields. These fields are only meaningful when LongLived flag is set
        LLQ_State             state;
-       mDNSu32               ReqLease;         // seconds (relative)
+       mDNSu32               ReqLease;                 // seconds (relative)
        mDNSs32               expire;                   // ticks (absolute)
        mDNSs16               ntries;
        mDNSOpaque64          id;
@@ -1836,7 +2326,6 @@ struct DNSQuestion_struct
        mDNSAddr              Target;                   // Non-zero if you want to direct queries to a specific unicast target address
        mDNSIPPort            TargetPort;               // Must be set if Target is set
        mDNSOpaque16          TargetQID;                // Must be set if Target is set
-       UDPSocket            *LocalSocket;
        domainname            qname;
        mDNSu16               qtype;
        mDNSu16               qclass;
@@ -1925,13 +2414,82 @@ typedef struct ClientTunnel
        mDNSv6Addr rmt_inner;
        mDNSv4Addr rmt_outer;
        mDNSIPPort rmt_outer_port;
-       char b64keydata[32];
        DNSQuestion q;
        } ClientTunnel;
 #endif
 
 // ***************************************************************************
 #if 0
+#pragma mark -
+#pragma mark - NetworkInterfaceInfo_struct
+#endif
+
+typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
+
+// A NetworkInterfaceInfo_struct serves two purposes:
+// 1. It holds the address, PTR and HINFO records to advertise a given IP address on a given physical interface
+// 2. It tells mDNSCore which physical interfaces are available; each physical interface has its own unique InterfaceID.
+//    Since there may be multiple IP addresses on a single physical interface,
+//    there may be multiple NetworkInterfaceInfo_structs with the same InterfaceID.
+//    In this case, to avoid sending the same packet n times, when there's more than one
+//    struct with the same InterfaceID, mDNSCore picks one member of the set to be the
+//    active representative of the set; all others have the 'InterfaceActive' flag unset.
+
+struct NetworkInterfaceInfo_struct
+       {
+       // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
+       NetworkInterfaceInfo *next;
+
+       mDNSu8          InterfaceActive;        // Set if interface is sending & receiving packets (see comment above)
+       mDNSu8          IPv4Available;          // If InterfaceActive, set if v4 available on this InterfaceID
+       mDNSu8          IPv6Available;          // If InterfaceActive, set if v6 available on this InterfaceID
+
+       DNSQuestion     NetWakeBrowse;
+       DNSQuestion     NetWakeResolve[3];      // For fault-tolerance, we try up to three Sleep Proxies
+       mDNSAddr        SPSAddr[3];
+       mDNSIPPort      SPSPort[3];
+       mDNSs32         NextSPSAttempt;         // -1 if we're not currently attempting to register with any Sleep Proxy
+       mDNSs32         NextSPSAttemptTime;
+
+       // Standard AuthRecords that every Responder host should have (one per active IP address)
+       AuthRecord RR_A;                                        // 'A' or 'AAAA' (address) record for our ".local" name
+       AuthRecord RR_PTR;                                      // PTR (reverse lookup) record
+       AuthRecord RR_HINFO;
+
+       // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
+       mDNSInterfaceID InterfaceID;            // Identifies physical interface; MUST NOT be 0, -1, or -2
+       mDNSAddr        ip;                                     // The IPv4 or IPv6 address to advertise
+       mDNSAddr        mask;
+       mDNSEthAddr     MAC;
+       char            ifname[64];                     // Windows uses a GUID string for the interface name, which doesn't fit in 16 bytes
+       mDNSu8          Advertise;                      // False if you are only searching on this interface
+       mDNSu8          McastTxRx;                      // Send/Receive multicast on this { InterfaceID, address family } ?
+       mDNSu8          NetWake;                        // Set if Wake-On-Magic-Packet is enabled on this interface
+       };
+
+typedef struct SearchListElem
+       {
+       struct SearchListElem *next;
+       domainname domain;
+       int flag;               // -1 means delete, 0 means unchanged, +1 means newly added
+       DNSQuestion BrowseQ;
+       DNSQuestion DefBrowseQ;
+       DNSQuestion AutomaticBrowseQ;
+       DNSQuestion RegisterQ;
+       DNSQuestion DefRegisterQ;
+       ARListElem *AuthRecs;
+       } SearchListElem;
+
+// For domain enumeration and automatic browsing
+// This is the user's DNS search list.
+// In each of these domains we search for our special pointer records (lb._dns-sd._udp.<domain>, etc.)
+// to discover recommended domains for domain enumeration (browse, default browse, registration,
+// default registration) and possibly one or more recommended automatic browsing domains.
+extern SearchListElem *SearchList;             // This really ought to be part of mDNS_struct -- SC
+
+// ***************************************************************************
+#if 0
+#pragma mark -
 #pragma mark - Main mDNS object, used to hold all the mDNS state
 #endif
 
@@ -1941,7 +2499,15 @@ typedef void mDNSCallback(mDNS *const m, mStatus result);
 
 enum
        {
-       mDNS_KnownBug_PhantomInterfaces = 1
+       mDNS_KnownBug_PhantomInterfaces = 1,
+       mDNS_KnownBug_LossySyslog       = 2             // <rdar://problem/6561888>
+       };
+
+enum
+       {
+       SleepState_Awake = 0,
+       SleepState_Transferring = 1,
+       SleepState_Sleeping = 2
        };
 
 struct mDNS_struct
@@ -1955,9 +2521,11 @@ struct mDNS_struct
        mDNSu32  KnownBugs;
        mDNSBool CanReceiveUnicastOn5353;
        mDNSBool AdvertiseLocalAddresses;
+       mDNSBool DivertMulticastAdvertisements; // from interfaces that do not advertise local addresses to local-only
        mStatus mDNSPlatformStatus;
        mDNSIPPort UnicastPort4;
        mDNSIPPort UnicastPort6;
+       mDNSEthAddr PrimaryMAC;                         // Used as unique host ID
        mDNSCallback *MainCallback;
        void         *MainContext;
 
@@ -1967,7 +2535,9 @@ struct mDNS_struct
        mDNSu8  lock_rrcache;                           // For debugging: Set at times when these lists may not be modified
        mDNSu8  lock_Questions;
        mDNSu8  lock_Records;
-       #define MaxMsg 120
+#ifndef MaxMsg
+       #define MaxMsg 160
+#endif
        char MsgBuffer[MaxMsg];                         // Temp storage used while building error log messages
 
        // Task Scheduling variables
@@ -1975,19 +2545,24 @@ struct mDNS_struct
        mDNSs32  timenow;                                       // The time that this particular activation of the mDNS code started
        mDNSs32  timenow_last;                          // The time the last time we ran
        mDNSs32  NextScheduledEvent;            // Derived from values below
-       mDNSs32  ShutdownTime;                          // Set when we're shutting down, allows us to skip some unnecessary steps
+       mDNSs32  ShutdownTime;                          // Set when we're shutting down; allows us to skip some unnecessary steps
        mDNSs32  SuppressSending;                       // Don't send *any* packets during this time
        mDNSs32  NextCacheCheck;                        // Next time to refresh cache record before it expires
        mDNSs32  NextScheduledQuery;            // Next time to send query in its exponential backoff sequence
        mDNSs32  NextScheduledProbe;            // Next time to probe for new authoritative record
        mDNSs32  NextScheduledResponse;         // Next time to send authoritative record(s) in responses
        mDNSs32  NextScheduledNATOp;            // Next time to send NAT-traversal packets
+       mDNSs32  NextScheduledSPS;                      // Next time to purge expiring Sleep Proxy records
        mDNSs32  RandomQueryDelay;                      // For de-synchronization of query packets on the wire
        mDNSu32  RandomReconfirmDelay;          // For de-synchronization of reconfirmation queries on the wire
        mDNSs32  PktNum;                                        // Unique sequence number assigned to each received packet
-       mDNSBool SendDeregistrations;           // Set if we need to send deregistrations (immediately)
-       mDNSBool SendImmediateAnswers;          // Set if we need to send answers (immediately -- or as soon as SuppressSending clears)
-       mDNSBool SleepState;                            // Set if we're sleeping (send no more packets)
+       mDNSu8   SleepState;                            // Set if we're sleeping
+       mDNSu8   SleepSeqNum;                           // "Epoch number" of our current period of wakefulness
+       mDNSu8   SystemWakeOnLANEnabled;        // Set if we want to register with a Sleep Proxy before going to sleep
+       mDNSs32  DelaySleep;                            // To inhibit re-sleeping too quickly right after wake
+       mDNSs32  SleepLimit;                            // Time window to allow deregistrations, etc.,
+                                                                               // during which underying platform layer should inhibit system sleep
+       mDNSs32  NextScheduledSPRetry;          // Time next sleep proxy registration action is required. Only valid if SleepLimit is nonzero.
 
        // These fields only required for mDNS Searcher...
        DNSQuestion *Questions;                         // List of all registered questions, active and inactive
@@ -2018,7 +2593,7 @@ struct mDNS_struct
        mDNSu32 NumFailedProbes;
        mDNSs32 SuppressProbes;
 
-       // unicast-specific data
+       // Unicast-specific data
        mDNSs32           NextuDNSEvent;                // uDNS next event
        mDNSs32           NextSRVUpdate;        // Time to perform delayed update
        mDNSs32 SuppressStdPort53Queries;       // Wait before allowing the next standard unicast query to the user's configured DNS server
@@ -2043,7 +2618,7 @@ struct mDNS_struct
 
        mDNSBool          RegisterSearchDomains;
 
-       // NAT traversal fields
+       // NAT-Traversal fields
        NATTraversalInfo  LLQNAT;                                       // Single shared NAT Traversal to receive inbound LLQ notifications
        NATTraversalInfo *NATTraversals;
        NATTraversalInfo *CurrentNATTraversal;
@@ -2052,9 +2627,9 @@ struct mDNS_struct
        mDNSv4Addr        ExternalAddress;
 
        UDPSocket        *NATMcastRecvskt;                      // For receiving NAT-PMP AddrReply multicasts from router on port 5350
-       UDPSocket        *NATMcastRecvsk2;                      // For backwards compatibility, same as above but listening on port 5351
        mDNSu32           LastNATupseconds;                     // NAT engine uptime in seconds, from most recent NAT packet
        mDNSs32           LastNATReplyLocalTime;        // Local time in ticks when most recent NAT packet was received
+       mDNSu16           LastNATMapResultCode;         // Most recent error code for mappings
 
        tcpLNTInfo        tcpAddrInfo;                          // legacy NAT traversal TCP connection info for external address
        tcpLNTInfo        tcpDeviceInfo;                        // legacy NAT traversal TCP connection info for device info
@@ -2070,12 +2645,27 @@ struct mDNS_struct
        mDNSu8           *UPnPRouterAddressString;      // holds both the router's address and port
        mDNSu8           *UPnPSOAPAddressString;        // holds both address and port for SOAP messages
 
+       // Sleep Proxy Server fields
+       mDNSu8            SPSType;                                      // 0 = off, 10-99 encodes desirability metric
+       mDNSu8            SPSPortability;                       // 10-99
+       mDNSu8            SPSMarginalPower;                     // 10-99
+       mDNSu8            SPSTotalPower;                        // 10-99
+       mDNSu8            SPSState;                                     // 0 = off, 1 = running, 2 = shutting down, 3 = suspended during sleep
+       mDNSInterfaceID   SPSProxyListChanged;
+       UDPSocket        *SPSSocket;
+       ServiceRecordSet  SPSRecords;
+       mDNSQuestionCallback *SPSBrowseCallback;    // So the platform layer can do something useful with SPS browse results
+       int               ProxyRecords;                         // Total number of records we're holding as proxy
+       #define           MAX_PROXY_RECORDS 10000       /* DOS protection: 400 machines at 25 records each */
+
 #if APPLE_OSX_mDNSResponder
        ClientTunnel     *TunnelClients;
+       uuid_t           asl_uuid;                                      // uuid for ASL logging
 #endif
 
        // Fixed storage, to avoid creating large objects on the stack
-       DNSMessage        imsg;                 // Incoming message received from wire
+       // The imsg is declared as a union with a pointer type to enforce CPU-appropriate alignment
+       union { DNSMessage m; void *p; } imsg;  // Incoming message received from wire
        DNSMessage        omsg;                 // Outgoing message we're building
        LargeCacheRecord  rec;                  // Resource Record extracted from received message
        };
@@ -2087,6 +2677,7 @@ struct mDNS_struct
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - Useful Static Constants
 #endif
 
@@ -2096,29 +2687,34 @@ extern const mDNSv6Addr      zerov6Addr;
 extern const mDNSEthAddr     zeroEthAddr;
 extern const mDNSv4Addr      onesIPv4Addr;
 extern const mDNSv6Addr      onesIPv6Addr;
+extern const mDNSEthAddr     onesEthAddr;
 extern const mDNSAddr        zeroAddr;
 
+extern const OwnerOptData    zeroOwner;
+
 extern const mDNSInterfaceID mDNSInterface_Any;                                // Zero
 extern const mDNSInterfaceID mDNSInterface_LocalOnly;          // Special value
 extern const mDNSInterfaceID mDNSInterface_Unicast;                    // Special value
 
-extern const mDNSIPPort   SSDPPort;
-
+extern const mDNSIPPort   DiscardPort;
+extern const mDNSIPPort   SSHPort;
 extern const mDNSIPPort   UnicastDNSPort;
+extern const mDNSIPPort   SSDPPort;
+extern const mDNSIPPort   NSIPCPort;
 extern const mDNSIPPort   NATPMPAnnouncementPort;
 extern const mDNSIPPort   NATPMPPort;
 extern const mDNSIPPort   DNSEXTPort;
 extern const mDNSIPPort   MulticastDNSPort;
 extern const mDNSIPPort   LoopbackIPCPort;
-
-extern const mDNSIPPort   NSIPCPort;
 extern const mDNSIPPort   PrivateDNSPort;
 
 extern const mDNSv4Addr   AllDNSAdminGroup;
+extern const mDNSv4Addr   AllSystemsMcast;
 extern const mDNSAddr     AllDNSLinkGroup_v4;
 extern const mDNSAddr     AllDNSLinkGroup_v6;
 
 extern const mDNSOpaque16 zeroID;
+extern const mDNSOpaque16 onesID;
 extern const mDNSOpaque16 QueryFlags;
 extern const mDNSOpaque16 uQueryFlags;
 extern const mDNSOpaque16 ResponseFlags;
@@ -2127,12 +2723,13 @@ extern const mDNSOpaque16 UpdateRespFlags;
 
 extern const mDNSOpaque64 zeroOpaque64;
 
-#define localdomain (*(const domainname *)"\x5" "local")
-#define LocalReverseMapDomain (*(const domainname *)"\x3" "254" "\x3" "169" "\x7" "in-addr" "\x4" "arpa")
-#define DeviceInfoName (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp")
+#define localdomain           (*(const domainname *)"\x5" "local")
+#define DeviceInfoName        (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp")
+#define SleepProxyServiceType (*(const domainname *)"\xC" "_sleep-proxy" "\x4" "_udp")
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - Inline functions
 #endif
 
@@ -2173,6 +2770,7 @@ mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v)
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - Main Client Functions
 #endif
 
@@ -2197,6 +2795,10 @@ mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v)
 // In principle, a proxy-like registration service could manually create address records for its own machine too,
 // but this would be pointless extra effort when using mDNS_Init_AdvertiseLocalAddresses does that for you.
 //
+// Note that a client-only device that wishes to prohibit multicast advertisements (e.g. from
+// higher-layer API calls) must also set DivertMulticastAdvertisements in the mDNS structure and
+// advertise local address(es) on a loopback interface.
+//
 // When mDNS has finished setting up the client's callback is called
 // A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
 //
@@ -2235,6 +2837,7 @@ extern mStatus mDNS_Init      (mDNS *const m, mDNS_PlatformSupport *const p,
 #define mDNS_Init_NoInitCallback              mDNSNULL
 #define mDNS_Init_NoInitCallbackContext       mDNSNULL
 
+extern void    mDNS_ConfigChanged(mDNS *const m);
 extern void    mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords);
 extern void    mDNS_StartExit (mDNS *const m);
 extern void    mDNS_FinalExit (mDNS *const m);
@@ -2264,6 +2867,7 @@ extern DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const name)
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - Platform support functions that are accessible to the client layer too
 #endif
 
@@ -2271,6 +2875,7 @@ extern mDNSs32  mDNSPlatformOneSecond;
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - General utility and helper functions
 #endif
 
@@ -2315,6 +2920,9 @@ extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
                const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context);
 #define        mDNS_DeregisterNoSuchService mDNS_Deregister
 
+extern void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID InterfaceID, const domainname *const name,
+               const mDNSu16 qtype, mDNSQuestionCallback *const callback, void *const context);
+
 extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
                const domainname *const srv, const domainname *const domain,
                const mDNSInterfaceID InterfaceID, mDNSBool ForceMCast, mDNSQuestionCallback *Callback, void *Context);
@@ -2348,6 +2956,7 @@ extern DNSServer *GetServerForName(mDNS *m, const domainname *name);
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - DNS name utility functions
 #endif
 
@@ -2370,10 +2979,14 @@ extern mDNSBool SameDomainName(const domainname *const d1, const domainname *con
 extern mDNSBool SameDomainNameCS(const domainname *const d1, const domainname *const d2);
 extern mDNSBool IsLocalDomain(const domainname *d);     // returns true for domains that by default should be looked up using link-local multicast
 
+#define FirstLabel(X)  ((const domainlabel *)(X))
+#define SecondLabel(X) ((const domainlabel *)&(X)->c[1 + (X)->c[0]])
+extern const mDNSu8 *LastLabel(const domainname *d);
+
 // Get total length of domain name, in native DNS format, including terminal root label
 //   (e.g. length of "com." is 5 (length byte, three data bytes, final zero)
 extern mDNSu16  DomainNameLengthLimit(const domainname *const name, const mDNSu8 *limit);
-#define DomainNameLength(name) DomainNameLengthLimit((name), (name)->c + MAX_DOMAIN_NAME + 1)
+#define DomainNameLength(name) DomainNameLengthLimit((name), (name)->c + MAX_DOMAIN_NAME)
 
 // Append functions to append one or more labels to an existing native format domain name:
 //   AppendLiteralLabelString adds a single label from a literal C string, with no escape character interpretation.
@@ -2398,7 +3011,7 @@ extern mDNSu8  *MakeDomainNameFromDNSNameString (domainname  *const name,  const
 // When using ConvertDomainLabelToCString, the target buffer must be MAX_ESCAPED_DOMAIN_LABEL (254) bytes long
 // to guarantee there will be no buffer overrun. It is only safe to use a buffer shorter than this in rare cases
 // where the label is known to be constrained somehow (for example, if the label is known to be either "_tcp" or "_udp").
-// Similarly, when using ConvertDomainNameToCString, the target buffer must be MAX_ESCAPED_DOMAIN_NAME (1005) bytes long.
+// Similarly, when using ConvertDomainNameToCString, the target buffer must be MAX_ESCAPED_DOMAIN_NAME (1009) bytes long.
 // See definitions of MAX_ESCAPED_DOMAIN_LABEL and MAX_ESCAPED_DOMAIN_NAME for more detailed explanation.
 extern char    *ConvertDomainLabelToCString_withescape(const domainlabel *const name, char *cstr, char esc);
 #define         ConvertDomainLabelToCString_unescaped(D,C) ConvertDomainLabelToCString_withescape((D), (C), 0)
@@ -2425,6 +3038,7 @@ extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - Other utility functions and macros
 #endif
 
@@ -2437,7 +3051,7 @@ extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va
 extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
 extern mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterfaceID id);
 extern char *DNSTypeName(mDNSu16 rrtype);
-extern char *GetRRDisplayString_rdb(const ResourceRecord *rr, RDataBody *rd, char *buffer);
+extern char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RDataBody *const rd1, char *const buffer);
 #define RRDisplayString(m, rr) GetRRDisplayString_rdb(rr, &(rr)->rdata->u, (m)->MsgBuffer)
 #define ARDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
 #define CRDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
@@ -2448,20 +3062,22 @@ extern mDNSBool mDNSv4AddrIsRFC1918(mDNSv4Addr *addr);  // returns true for RFC1
 
 #define mDNSSameIPPort(A,B)      ((A).NotAnInteger == (B).NotAnInteger)
 #define mDNSSameOpaque16(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
+#define mDNSSameOpaque32(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
+#define mDNSSameOpaque64(A,B)    ((A)->l[0] == (B)->l[0] && (A)->l[1] == (B)->l[1])
+
 #define mDNSSameIPv4Address(A,B) ((A).NotAnInteger == (B).NotAnInteger)
 #define mDNSSameIPv6Address(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1] && (A).l[2] == (B).l[2] && (A).l[3] == (B).l[3])
 #define mDNSSameEthAddress(A,B)  ((A)->w[0] == (B)->w[0] && (A)->w[1] == (B)->w[1] && (A)->w[2] == (B)->w[2])
 
-#define mDNSSameOpaque64(A,B)    ((A)->l[0] == (B)->l[0] && (A)->l[1] == (B)->l[1])
-#define mDNSOpaque64IsZero(A)    ((A)->l[0] == 0 && (A)->l[1] == 0)
-
-#define mDNSIPPortIsZero(A)      mDNSSameIPPort((A), zeroIPPort)
-#define mDNSOpaque16IsZero(A)    mDNSSameOpaque16((A), zeroIPPort)
-#define mDNSIPv4AddressIsZero(A) mDNSSameIPv4Address((A), zerov4Addr)
-#define mDNSIPv6AddressIsZero(A) mDNSSameIPv6Address((A), zerov6Addr)
+#define mDNSIPPortIsZero(A)      ((A).NotAnInteger                            == 0)
+#define mDNSOpaque16IsZero(A)    ((A).NotAnInteger                            == 0)
+#define mDNSOpaque64IsZero(A)    (((A)->l[0] | (A)->l[1]                    ) == 0)
+#define mDNSIPv4AddressIsZero(A) ((A).NotAnInteger                            == 0)
+#define mDNSIPv6AddressIsZero(A) (((A).l[0] | (A).l[1] | (A).l[2] | (A).l[3]) == 0)
+#define mDNSEthAddressIsZero(A)  (((A).w[0] | (A).w[1] | (A).w[2]           ) == 0)
 
-#define mDNSIPv4AddressIsOnes(A) mDNSSameIPv4Address((A), onesIPv4Addr)
-#define mDNSIPv6AddressIsOnes(A) mDNSSameIPv6Address((A), onesIPv6Addr)
+#define mDNSIPv4AddressIsOnes(A) ((A).NotAnInteger == 0xFFFFFFFF)
+#define mDNSIPv6AddressIsOnes(A) (((A).l[0] & (A).l[1] & (A).l[2] & (A).l[3]) == 0xFFFFFFFF)
 
 #define mDNSAddressIsAllDNSLinkGroup(X) (                                                            \
        ((X)->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address((X)->ip.v4, AllDNSLinkGroup_v4.ip.v4)) || \
@@ -2492,6 +3108,7 @@ extern mDNSBool mDNSv4AddrIsRFC1918(mDNSv4Addr *addr);  // returns true for RFC1
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - Authentication Support
 #endif
 
@@ -2507,6 +3124,8 @@ extern mDNSBool mDNSv4AddrIsRFC1918(mDNSv4Addr *addr);  // returns true for RFC1
 extern mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
        const domainname *domain, const domainname *keyname, const char *b64keydata, mDNSBool AutoTunnel);
 
+extern void RecreateNATMappings(mDNS *const m);
+
 // Hostname/Unicast Interface Configuration
 
 // All hostnames advertised point to one IPv4 address and/or one IPv6 address, set via SetPrimaryInterfaceInfo.  Invoking this routine
@@ -2528,6 +3147,7 @@ extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCa
 extern void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn);
 extern void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr,  const mDNSAddr *v6addr, const mDNSAddr *router);
 extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port);
+extern void PushDNSServerToEnd(mDNS *const m, DNSQuestion *q);
 extern void mDNS_AddSearchDomain(const domainname *const domain);
 
 // We use ((void *)0) here instead of mDNSNULL to avoid compile warnings on gcc 4.2
@@ -2563,6 +3183,7 @@ extern mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCache
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - PlatformSupport interface
 #endif
 
@@ -2581,7 +3202,7 @@ extern mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCache
 // Note: mDNSPlatformMemAllocate/mDNSPlatformMemFree are only required for handling oversized resource records and unicast DNS.
 // If your target platform has a well-defined specialized application, and you know that all the records it uses
 // are InlineCacheRDSize or less, then you can just make a simple mDNSPlatformMemAllocate() stub that always returns
-// NULL. InlineCacheRDSize is a compile-time constant, which is set by default to 64. If you need to handle records
+// NULL. InlineCacheRDSize is a compile-time constant, which is set by default to 68. If you need to handle records
 // a little larger than this and you don't want to have to implement run-time allocation and freeing, then you
 // can raise the value of this constant to a suitable value (at the expense of increased memory usage).
 //
@@ -2614,7 +3235,19 @@ extern void     mDNSPlatformMemZero     (      void *dst,                  mDNSu
 extern void *   mDNSPlatformMemAllocate (mDNSu32 len);
 #endif
 extern void     mDNSPlatformMemFree     (void *mem);
+
+// If the platform doesn't have a strong PRNG, we define a naive multiply-and-add based on a seed
+// from the platform layer.  Long-term, we should embed an arc4 implementation, but the strength
+// will still depend on the randomness of the seed.
+#if !defined(_PLATFORM_HAS_STRONG_PRNG_) && (_BUILDING_XCODE_PROJECT_ || defined(_WIN32))
+#define _PLATFORM_HAS_STRONG_PRNG_ 1
+#endif
+#if _PLATFORM_HAS_STRONG_PRNG_
+extern mDNSu32  mDNSPlatformRandomNumber(void);
+#else
 extern mDNSu32  mDNSPlatformRandomSeed  (void);
+#endif // _PLATFORM_HAS_STRONG_PRNG_
+
 extern mStatus  mDNSPlatformTimeInit    (void);
 extern mDNSs32  mDNSPlatformRawTime     (void);
 extern mDNSs32  mDNSPlatformUTC         (void);
@@ -2623,7 +3256,12 @@ extern mDNSs32  mDNSPlatformUTC         (void);
 #if MDNS_DEBUGMSGS
 extern void    mDNSPlatformWriteDebugMsg(const char *msg);
 #endif
-extern void    mDNSPlatformWriteLogMsg(const char *ident, const char *msg, int flags);
+extern void    mDNSPlatformWriteLogMsg(const char *ident, const char *msg, mDNSLogLevel_t loglevel);
+
+#if APPLE_OSX_mDNSResponder
+// Utility function for ASL logging
+mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *result, const char *signature, const char *fmt, ...);
+#endif
 
 // Platform support modules should provide the following functions to map between opaque interface IDs
 // and interface indexes in order to support the DNS-SD API. If your target platform does not support
@@ -2665,6 +3303,10 @@ extern long       mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long
 extern long       mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len);
 extern UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport);
 extern void       mDNSPlatformUDPClose(UDPSocket *sock);
+extern void       mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd);
+extern void       mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID);
+extern void       mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID);
+extern void       mDNSPlatformSetLocalARP(const mDNSv4Addr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID);
 extern void       mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst);
 
 // mDNSPlatformTLSSetupCerts/mDNSPlatformTLSTearDownCerts used by dnsextd
@@ -2685,6 +3327,7 @@ extern void     LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID Interface
 extern mStatus  LNT_GetExternalAddress(mDNS *m);
 extern mStatus  LNT_MapPort(mDNS *m, NATTraversalInfo *n);
 extern mStatus  LNT_UnmapPort(mDNS *m, NATTraversalInfo *n);
+extern void     LNT_ClearState(mDNS *const m);
 #endif // _LEGACY_NAT_TRAVERSAL_
 
 // The core mDNS code provides these functions, for the platform support code to call at appropriate times
@@ -2723,20 +3366,37 @@ extern mStatus  LNT_UnmapPort(mDNS *m, NATTraversalInfo *n);
 // not lightweight second-by-second CPU power management modes.)
 
 extern void     mDNS_SetFQDN(mDNS *const m);
+extern void     mDNS_ActivateNetWake_internal  (mDNS *const m, NetworkInterfaceInfo *set);
+extern void     mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set);
 extern mStatus  mDNS_RegisterInterface  (mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping);
 extern void     mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping);
 extern void     mDNSCoreInitComplete(mDNS *const m, mStatus result);
 extern void     mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end,
                                                                const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
                                                                const mDNSAddr *const dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID);
+extern void    mDNSCoreRestartQueries(mDNS *const m);
+extern mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m);
 extern void     mDNSCoreMachineSleep(mDNS *const m, mDNSBool wake);
+extern mDNSBool mDNSCoreReadyForSleep(mDNS *m);
+extern mDNSs32  mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now);
+
+extern void     mDNSCoreBeSleepProxyServer(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower);
+extern void     mDNSCoreReceiveRawPacket  (mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID);
 
 extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip);
 
 extern CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg);
 extern void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease);
-extern void MakeNegativeCacheRecord(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds);
+extern void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr,
+       const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds, mDNSInterfaceID InterfaceID);
 extern void CompleteDeregistration(mDNS *const m, AuthRecord *rr);
+extern void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3]);
+#define PrototypeSPSName(X) ((X)[0] >= 11 && (X)[3] == '-' && (X)[ 4] == '9' && (X)[ 5] == '9' && \
+                                             (X)[6] == '-' && (X)[ 7] == '9' && (X)[ 8] == '9' && \
+                                             (X)[9] == '-' && (X)[10] == '9' && (X)[11] == '9'    )
+#define ValidSPSName(X) ((X)[0] >= 5 && mDNSIsDigit((X)[1]) && mDNSIsDigit((X)[2]) && mDNSIsDigit((X)[4]) && mDNSIsDigit((X)[5]))
+#define SPSMetric(X) (!ValidSPSName(X) || PrototypeSPSName(X) ? 1000000 : \
+       ((X)[1]-'0') * 100000 + ((X)[2]-'0') * 10000 + ((X)[4]-'0') * 1000 + ((X)[5]-'0') * 100 + ((X)[7]-'0') * 10 + ((X)[8]-'0'))
 extern void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord);
 
 // For now this AutoTunnel stuff is specific to Mac OS X.
@@ -2750,6 +3410,7 @@ extern void UpdateAutoTunnelDomainStatuses(const mDNS *const m);
 
 // ***************************************************************************
 #if 0
+#pragma mark -
 #pragma mark - Compile-Time assertion checks
 #endif
 
@@ -2775,28 +3436,36 @@ struct CompileTimeAssertionChecks_mDNS
        char assert9[(sizeof(mDNSOpaque16)     ==   2                          ) ? 1 : -1];
        char assertA[(sizeof(mDNSOpaque32)     ==   4                          ) ? 1 : -1];
        char assertB[(sizeof(mDNSOpaque128)    ==  16                          ) ? 1 : -1];
-       char assertC[(sizeof(CacheRecord  )    >=  sizeof(CacheGroup)          ) ? 1 : -1];
+       char assertC[(sizeof(CacheRecord  )    ==  sizeof(CacheGroup)          ) ? 1 : -1];
        char assertD[(sizeof(int)              >=  4                           ) ? 1 : -1];
        char assertE[(StandardAuthRDSize       >=  256                         ) ? 1 : -1];
+       char assertF[(sizeof(EthernetHeader)   ==   14                         ) ? 1 : -1];
+       char assertG[(sizeof(ARP_EthIP     )   ==   28                         ) ? 1 : -1];
+       char assertH[(sizeof(IPv4Header    )   ==   20                         ) ? 1 : -1];
+       char assertI[(sizeof(IPv6Header    )   ==   40                         ) ? 1 : -1];
+       char assertJ[(sizeof(IPv6ND        )   ==   24                         ) ? 1 : -1];
+       char assertK[(sizeof(UDPHeader     )   ==    8                         ) ? 1 : -1];
+       char assertL[(sizeof(TCPHeader     )   ==   20                         ) ? 1 : -1];
 
        // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
        // other overly-large structures instead of having a pointer to them, can inadvertently
        // cause structure sizes (and therefore memory usage) to balloon unreasonably.
+       char sizecheck_RDataBody           [(sizeof(RDataBody)            ==   264) ? 1 : -1];
        char sizecheck_ResourceRecord      [(sizeof(ResourceRecord)       <=    56) ? 1 : -1];
-       char sizecheck_AuthRecord          [(sizeof(AuthRecord)           <=  1416) ? 1 : -1];
-       char sizecheck_CacheRecord         [(sizeof(CacheRecord)          <=   200) ? 1 : -1];
-       char sizecheck_CacheGroup          [(sizeof(CacheGroup)           <=   184) ? 1 : -1];
-       char sizecheck_DNSQuestion         [(sizeof(DNSQuestion)          <=   720) ? 1 : -1];
-       char sizecheck_ZoneData            [(sizeof(ZoneData)             <=  1552) ? 1 : -1];
+       char sizecheck_AuthRecord          [(sizeof(AuthRecord)           <=  1000) ? 1 : -1];
+       char sizecheck_CacheRecord         [(sizeof(CacheRecord)          <=   176) ? 1 : -1];
+       char sizecheck_CacheGroup          [(sizeof(CacheGroup)           <=   176) ? 1 : -1];
+       char sizecheck_DNSQuestion         [(sizeof(DNSQuestion)          <=   728) ? 1 : -1];
+       char sizecheck_ZoneData            [(sizeof(ZoneData)             <=  1560) ? 1 : -1];
        char sizecheck_NATTraversalInfo    [(sizeof(NATTraversalInfo)     <=   192) ? 1 : -1];
-       char sizecheck_HostnameInfo        [(sizeof(HostnameInfo)         <=  3304) ? 1 : -1];
+       char sizecheck_HostnameInfo        [(sizeof(HostnameInfo)         <=  2800) ? 1 : -1];
        char sizecheck_DNSServer           [(sizeof(DNSServer)            <=   312) ? 1 : -1];
-       char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <=  4392) ? 1 : -1];
-       char sizecheck_ServiceRecordSet    [(sizeof(ServiceRecordSet)     <=  6248) ? 1 : -1];
-       char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=  6544) ? 1 : -1];
-       char sizecheck_ServiceInfoQuery    [(sizeof(ServiceInfoQuery)     <=  2912) ? 1 : -1];
+       char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <=  5968) ? 1 : -1];
+       char sizecheck_ServiceRecordSet    [(sizeof(ServiceRecordSet)     <=  5500) ? 1 : -1];
+       char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=  5500) ? 1 : -1];
+       char sizecheck_ServiceInfoQuery    [(sizeof(ServiceInfoQuery)     <=  2944) ? 1 : -1];
 #if APPLE_OSX_mDNSResponder
-       char sizecheck_ClientTunnel        [(sizeof(ClientTunnel)         <=  1064) ? 1 : -1];
+       char sizecheck_ClientTunnel        [(sizeof(ClientTunnel)         <=  1072) ? 1 : -1];
 #endif
        };
 
index d649f19074c7565ef3da5c3f1335361b9f5b5f93..962c53656df50a89641612a0d2aa3db92b1ad64a 100755 (executable)
        Change History (most recent first):
 
 $Log: uDNS.c,v $
-Revision 1.553.2.4  2008/07/29 20:47:44  mcguire
-<rdar://problem/6090007> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
-merge r1.567 & r1.568 from <rdar://problem/3988320>
+Revision 1.617  2009/06/30 20:51:02  cheshire
+Improved "Error! Tried to add a NAT traversal that's already in the active list" debugging message
 
-Revision 1.553.2.3  2008/07/29 19:09:21  mcguire
-<rdar://problem/6090041> Use all configured DNS servers
-merge r1.558-r1.565 from <rdar://problem/4206534>
+Revision 1.616  2009/05/27 20:29:36  cheshire
+<rdar://problem/6926465> Sleep is delayed by 10 seconds if BTMM is on
+After receiving confirmation of LLQ deletion, need to schedule another evaluation of whether we're ready to sleep yet
 
-Revision 1.553.2.2  2008/07/29 18:50:09  mcguire
-<rdar://problem/6090002> LLQ refresh randomization not working properly
-merge r1.555 & r1.556 from <rdar://problem/5787898>
+Revision 1.615  2009/05/05 01:32:50  jessic2
+<rdar://problem/6830541> regservice_callback: instance->request is NULL 0 -- Clean up spurious logs resulting from fixing this bug.
 
-Revision 1.553.2.1  2008/03/14 20:11:25  mcguire
+Revision 1.614  2009/04/24 02:17:57  mcguire
+<rdar://problem/5264124> uDNS: Not always respecting preference order of DNS servers
+
+Revision 1.613  2009/04/23 22:06:29  cheshire
+Added CacheRecord and InterfaceID parameters to MakeNegativeCacheRecord, in preparation for:
+<rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
+
+Revision 1.612  2009/04/22 01:19:57  jessic2
+<rdar://problem/6814585> Daemon: mDNSResponder is logging garbage for error codes because it's using %ld for int 32
+
+Revision 1.611  2009/04/15 20:42:51  mcguire
+<rdar://problem/6768947> uDNS: Treat RCODE 5 (Refused) responses as failures
+
+Revision 1.610  2009/04/15 01:10:39  jessic2
+<rdar://problem/6466541> BTMM: Add support for setting kDNSServiceErr_NoSuchRecord in DynamicStore
+
+Revision 1.609  2009/04/11 00:19:45  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.608  2009/04/06 23:44:59  cheshire
+<rdar://problem/6757838> mDNSResponder thrashing kernel lock in the UDP close path, hurting SPECweb performance
+
+Revision 1.607  2009/04/02 22:36:34  jessic2
+Fix crash when calling debugf with null opt
+
+Revision 1.606  2009/03/26 03:59:00  jessic2
+Changes for <rdar://problem/6492552&6492593&6492609&6492613&6492628&6492640&6492699>
+
+Revision 1.605  2009/03/04 00:40:14  cheshire
+Updated DNS server error codes to be more consistent with definitions at
+<http://www.iana.org/assignments/dns-parameters>
+
+Revision 1.604  2009/02/27 03:08:47  cheshire
+<rdar://problem/6547720> Crash while shutting down when "local" is in the user's DNS searchlist
+
+Revision 1.603  2009/02/27 02:56:57  cheshire
+Moved struct SearchListElem definition from uDNS.c into mDNSEmbeddedAPI.h
+
+Revision 1.602  2009/02/13 06:29:54  cheshire
+Converted LogOperation messages to LogInfo
+
+Revision 1.601  2009/02/12 20:57:25  cheshire
+Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
+
+Revision 1.600  2009/01/31 21:05:12  cheshire
+Improved "Failed to obtain NAT port mapping" debugging log message
+
+Revision 1.599  2009/01/23 00:38:36  mcguire
+<rdar://problem/5570906> BTMM: Doesn't work with Linksys WRT54GS firmware 4.71.1
+
+Revision 1.598  2009/01/21 03:43:57  mcguire
+<rdar://problem/6511765> BTMM: Add support for setting kDNSServiceErr_NATPortMappingDisabled in DynamicStore
+
+Revision 1.597  2009/01/10 01:55:49  cheshire
+Added LogOperation message showing when domains are added and removed in FoundDomain
+
+Revision 1.596  2008/12/19 20:23:33  mcguire
+<rdar://problem/6459269> Lots of duplicate log messages about failure to bind to NAT-PMP Announcement port
+
+Revision 1.595  2008/12/18 23:32:19  mcguire
+<rdar://problem/6019470> BTMM: Include the question in the LLQ notification acknowledgment
+
+Revision 1.594  2008/12/10 02:25:31  cheshire
+Minor fixes to use of LogClientOperations symbol
+
+Revision 1.593  2008/12/10 02:11:42  cheshire
+ARMv5 compiler doesn't like uncommented stuff after #endif
+
+Revision 1.592  2008/12/06 01:42:55  mcguire
+<rdar://problem/6418958> Need to exponentially back-off after failure to get public address
+
+Revision 1.591  2008/12/06 00:17:11  cheshire
+<rdar://problem/6380477> mDNS_StopNATOperation doesn't handle duplicate NAT mapping requests properly
+Refinement: For duplicate ssh mappings we want to suppress the syslog warning message, but not the "unmap = mDNSfalse"
+
+Revision 1.590  2008/12/04 20:57:36  mcguire
+fix build
+
+Revision 1.589  2008/12/04 02:24:09  cheshire
+Improved NAT-PMP debugging messages
+
+Revision 1.588  2008/11/26 20:38:08  cheshire
+Changed some "LogOperation" debugging messages to "debugf"
+
+Revision 1.587  2008/11/26 19:53:26  cheshire
+Don't overwrite srs->NATinfo.IntPort in StartSRVNatMap()
+
+Revision 1.586  2008/11/25 23:43:07  cheshire
+<rdar://problem/5745355> Crashes at ServiceRegistrationGotZoneData + 397
+Made code more defensive to guard against ServiceRegistrationGotZoneData being called with invalid ServiceRecordSet object
+
+Revision 1.585  2008/11/25 22:46:30  cheshire
+For ease of code searching, renamed ZoneData field of ServiceRecordSet_struct from "nta" to "srs_nta"
+
+Revision 1.584  2008/11/24 19:46:40  cheshire
+When sending query over TCP, don't include LLQ option when we're talking to a conventional DNS server or cache
+
+Revision 1.583  2008/11/21 00:34:58  cheshire
+<rdar://problem/6380477> mDNS_StopNATOperation doesn't handle duplicate NAT mapping requests properly
+
+Revision 1.582  2008/11/20 02:23:37  mcguire
+<rdar://problem/6041208> need to handle URLBase
+
+Revision 1.581  2008/11/20 01:51:19  cheshire
+Exported RecreateNATMappings so it's callable from other files
+
+Revision 1.580  2008/11/13 19:08:45  cheshire
+Fixed code to handle rdataOPT properly
+
+Revision 1.579  2008/11/07 00:18:01  mcguire
+<rdar://problem/6351068> uDNS: Supress reverse DNS query until required
+
+Revision 1.578  2008/11/04 22:21:46  cheshire
+Changed zone field of AuthRecord_struct from domainname to pointer, saving 252 bytes per AuthRecord
+
+Revision 1.577  2008/10/29 21:37:01  cheshire
+Removed some old debugging messages
+
+Revision 1.576  2008/10/23 22:25:57  cheshire
+Renamed field "id" to more descriptive "updateid"
+
+Revision 1.575  2008/10/20 02:07:49  mkrochma
+<rdar://problem/6296804> Remove Note: DNS Server <ip> for domain <d> registered more than once
+
+Revision 1.574  2008/10/14 19:06:45  cheshire
+In uDNS_ReceiveMsg(), only do checkUpdateResult() for uDNS records
+
+Revision 1.573  2008/09/25 20:43:44  cheshire
+<rdar://problem/6245044> Stop using separate m->ServiceRegistrations list
+In UpdateSRVRecords, call mDNS_SetFQDN(m) to update AutoTarget SRV records on the main m->ResourceRecords list
+
+Revision 1.572  2008/09/24 23:48:05  cheshire
+Don't need to pass whole ServiceRecordSet reference to GetServiceTarget;
+it only needs to access the embedded SRV member of the set
+
+Revision 1.571  2008/09/23 22:56:53  cheshire
+<rdar://problem/5298845> Remove dnsbugtest query
+
+Revision 1.570  2008/09/23 01:30:18  cheshire
+The putLLQ() routine was not setting the OPT record's rrclass to NormalMaxDNSMessageData
+
+Revision 1.569  2008/07/25 22:34:11  mcguire
+fix sizecheck issues for 64bit
+
+Revision 1.568  2008/07/24 20:23:03  cheshire
+<rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+
+Revision 1.567  2008/07/01 01:40:00  mcguire
+<rdar://problem/5823010> 64-bit fixes
+
+Revision 1.566  2008/06/26 17:24:11  mkrochma
+<rdar://problem/5450912> BTMM: Stop listening on UDP 5351 for NAT Status Announcements
+
+Revision 1.565  2008/06/21 19:06:58  mcguire
+<rdar://problem/4206534> Use all configured DNS servers
+
+Revision 1.564  2008/06/19 23:42:03  mcguire
+<rdar://problem/4206534> Use all configured DNS servers
+
+Revision 1.563  2008/06/19 17:46:14  mcguire
+<rdar://problem/4206534> Use all configured DNS servers
+Don't do extra work for log messages if we're not going to log
+
+Revision 1.562  2008/06/19 17:35:19  mcguire
+<rdar://problem/4206534> Use all configured DNS servers
+cleanup log messages
+check for null pointers
+
+Revision 1.561  2008/06/19 01:20:49  mcguire
+<rdar://problem/4206534> Use all configured DNS servers
+
+Revision 1.560  2008/05/31 01:51:09  mcguire
+fixed typo in log message
+
+Revision 1.559  2008/04/15 22:37:58  mkrochma
+Change LogMsg to LogOperation
+
+Revision 1.558  2008/03/17 18:02:35  mkrochma
+Add space to log message for consistency
+
+Revision 1.557  2008/03/14 19:58:38  mcguire
 <rdar://problem/5500969> BTMM: Need ability to identify version of mDNSResponder client
 Make sure we add the record when sending LLQ refreshes
 
+Revision 1.556  2008/03/07 23:55:05  cheshire
+<rdar://problem/5787898> LLQ refresh randomization not working properly
+
+Revision 1.555  2008/03/07 23:25:56  cheshire
+Improved debugging messages
+
+Revision 1.554  2008/03/07 18:56:03  cheshire
+<rdar://problem/5777647> dnsbugtest query every three seconds when source IP address of response doesn't match
+
 Revision 1.553  2008/03/06 02:48:34  mcguire
 <rdar://problem/5321824> write status to the DS
 
@@ -361,7 +548,7 @@ Fixed minor error introduced in 1.379 (an "if" statement was deleted but the "el
 
 Revision 1.457  2007/09/05 21:48:01  cheshire
 <rdar://problem/5385864> BTMM: mDNSResponder flushes wide-area Bonjour records after an hour for a zone.
-Now that we're respecting the TTL of uDNS records in the cache, the LLQ maintenance cod needs
+Now that we're respecting the TTL of uDNS records in the cache, the LLQ maintenance code needs
 to update the cache lifetimes of all relevant records every time it successfully renews an LLQ,
 otherwise those records will expire and vanish from the cache.
 
@@ -1144,25 +1331,12 @@ Revision 1.227  2006/01/09 20:47:05  cheshire
        #pragma warning(disable:4706)
 #endif
 
-typedef struct SearchListElem
-       {
-       struct SearchListElem *next;
-       domainname domain;
-       int flag;               // -1 means delete, 0 means unchanged, +1 means newly added
-       DNSQuestion BrowseQ;
-       DNSQuestion DefBrowseQ;
-       DNSQuestion AutomaticBrowseQ;
-       DNSQuestion RegisterQ;
-       DNSQuestion DefRegisterQ;
-       ARListElem *AuthRecs;
-       } SearchListElem;
-
 // For domain enumeration and automatic browsing
 // This is the user's DNS search list.
 // In each of these domains we search for our special pointer records (lb._dns-sd._udp.<domain>, etc.)
 // to discover recommended domains for domain enumeration (browse, default browse, registration,
 // default registration) and possibly one or more recommended automatic browsing domains.
-static SearchListElem *SearchList = mDNSNULL;
+mDNSexport SearchListElem *SearchList = mDNSNULL;
 
 // Temporary workaround to make ServiceRecordSet list management safe.
 // Ideally a ServiceRecordSet shouldn't be a special entity that's given special treatment by the uDNS code
@@ -1233,7 +1407,7 @@ mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mStatus SendErr)
        // Code for stress-testing registration renewal code
        if (rr->expire && rr->expire - m->timenow > mDNSPlatformOneSecond * 120)
                {
-               LogOperation("Adjusting expiry from %d to 120 seconds for %s",
+               LogInfo("Adjusting expiry from %d to 120 seconds for %s",
                        (rr->expire - m->timenow) / mDNSPlatformOneSecond, ARDisplayString(m, rr));
                rr->expire = m->timenow + mDNSPlatformOneSecond * 120;
                }
@@ -1243,10 +1417,8 @@ mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mStatus SendErr)
                {
                mDNSs32 remaining = rr->expire - m->timenow;
                rr->ThisAPInterval = remaining/2 + mDNSRandom(remaining/10);
-               LogOperation("SetRecordRetry refresh in %4d of %4d for %s",
-                       rr->ThisAPInterval / mDNSPlatformOneSecond,
-                       (rr->expire - m->timenow) / mDNSPlatformOneSecond,
-                       ARDisplayString(m, rr));
+               debugf("SetRecordRetry refresh in %4d of %4d for %s",
+                       rr->ThisAPInterval / mDNSPlatformOneSecond, (rr->expire - m->timenow) / mDNSPlatformOneSecond, ARDisplayString(m, rr));
                return;
                }
 
@@ -1262,7 +1434,7 @@ mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mStatus SendErr)
        if (rr->ThisAPInterval > 30 * 60 * mDNSPlatformOneSecond)
                rr->ThisAPInterval = 30 * 60 * mDNSPlatformOneSecond;
 
-       LogOperation("SetRecordRetry retry   in %4d for %s", rr->ThisAPInterval / mDNSPlatformOneSecond, ARDisplayString(m, rr));
+       LogInfo("SetRecordRetry retry   in %4d for %s", rr->ThisAPInterval / mDNSPlatformOneSecond, ARDisplayString(m, rr));
        }
 
 // ***************************************************************************
@@ -1273,44 +1445,53 @@ mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mStatus SendErr)
 mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port)
        {
        DNSServer **p = &m->DNSServers;
-
+       DNSServer *tmp = mDNSNULL;
+       
        if (!d) d = (const domainname *)"";
 
-       LogOperation("mDNS_AddDNSServer: Adding %#a for %##s", addr, d->c);
+       LogInfo("mDNS_AddDNSServer: Adding %#a for %##s", addr, d->c);
        if (m->mDNS_busy != m->mDNS_reentrancy+1)
                LogMsg("mDNS_AddDNSServer: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
-       while (*p)      // Check if we already have this {server,domain} pair registered
+       while (*p)      // Check if we already have this {interface,address,port,domain} tuple registered
                {
                if ((*p)->interface == interface && (*p)->teststate != DNSServer_Disabled &&
                        mDNSSameAddress(&(*p)->addr, addr) && mDNSSameIPPort((*p)->port, port) && SameDomainName(&(*p)->domain, d))
                        {
-                       if (!((*p)->flags & DNSServer_FlagDelete)) LogMsg("Note: DNS Server %#a for domain %##s registered more than once", addr, d->c);
+                       if (!((*p)->flags & DNSServer_FlagDelete)) debugf("Note: DNS Server %#a:%d for domain %##s (%p) registered more than once", addr, mDNSVal16(port), d->c, interface);
                        (*p)->flags &= ~DNSServer_FlagDelete;
-                       return(*p);
+                       tmp = *p;
+                       *p = tmp->next;
+                       tmp->next = mDNSNULL;
                        }
-               p=&(*p)->next;
+               else
+                       p=&(*p)->next;
                }
 
-       // allocate, add to list
-       *p = mDNSPlatformMemAllocate(sizeof(**p));
-       if (!*p) LogMsg("Error: mDNS_AddDNSServer - malloc");
+       if (tmp) *p = tmp; // move to end of list, to ensure ordering from platform layer
        else
                {
-               (*p)->interface = interface;
-               (*p)->addr      = *addr;
-               (*p)->port      = port;
-               (*p)->flags     = DNSServer_FlagNew;
-               (*p)->teststate = DNSServer_Untested;
-               (*p)->lasttest  = m->timenow - INIT_UCAST_POLL_INTERVAL;
-               AssignDomainName(&(*p)->domain, d);
-               (*p)->next = mDNSNULL;
+               // allocate, add to list
+               *p = mDNSPlatformMemAllocate(sizeof(**p));
+               if (!*p) LogMsg("Error: mDNS_AddDNSServer - malloc");
+               else
+                       {
+                       (*p)->interface = interface;
+                       (*p)->addr      = *addr;
+                       (*p)->port      = port;
+                       (*p)->flags     = DNSServer_FlagNew;
+                       (*p)->teststate = /* DNSServer_Untested */ DNSServer_Passed;
+                       (*p)->lasttest  = m->timenow - INIT_UCAST_POLL_INTERVAL;
+                       AssignDomainName(&(*p)->domain, d);
+                       (*p)->next = mDNSNULL;
+                       }
                }
        return(*p);
        }
 
-mDNSlocal void PushDNSServerToEnd(mDNS *const m, DNSQuestion *q)
+mDNSexport void PushDNSServerToEnd(mDNS *const m, DNSQuestion *q)
        {
+       DNSServer *orig = q->qDNSServer;
        DNSServer **p = &m->DNSServers;
        
        if (m->mDNS_busy != m->mDNS_reentrancy+1)
@@ -1319,10 +1500,11 @@ mDNSlocal void PushDNSServerToEnd(mDNS *const m, DNSQuestion *q)
        if (!q->qDNSServer)
                {
                LogMsg("PushDNSServerToEnd: Null DNS server for %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), q->unansweredQueries);
-               return;
+               goto end;
                }
 
-       LogOperation("PushDNSServerToEnd: Pushing DNS server %#a:%d (%##s) due to %d unanswered queries for %##s (%s)", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c, q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype));
+       LogInfo("PushDNSServerToEnd: Pushing DNS server %#a:%d (%##s) due to %d unanswered queries for %##s (%s)",
+               &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c, q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype));
 
        while (*p)
                {
@@ -1331,7 +1513,17 @@ mDNSlocal void PushDNSServerToEnd(mDNS *const m, DNSQuestion *q)
                }
 
        *p = q->qDNSServer;
-       q->qDNSServer->next = mDNSNULL; 
+       q->qDNSServer->next = mDNSNULL;
+
+end:
+       q->qDNSServer = GetServerForName(m, &q->qname);
+
+       if (q->qDNSServer != orig)
+               {
+               if (q->qDNSServer) LogInfo("PushDNSServerToEnd: Server for %##s (%s) changed to %#a:%d (%##s)", q->qname.c, DNSTypeName(q->qtype), &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c);
+               else               LogInfo("PushDNSServerToEnd: Server for %##s (%s) changed to <null>",        q->qname.c, DNSTypeName(q->qtype));
+               q->ThisQInterval = q->ThisQInterval / QuestionIntervalStep; // Decrease interval one step so we don't quickly bounce between servers for queries that will not be answered.
+               }
        }
 
 // ***************************************************************************
@@ -1353,7 +1545,7 @@ mDNSlocal DomainAuthInfo *GetAuthInfoForName_direct(mDNS *m, const domainname *c
                                }
                n = (const domainname *)(n->c + 1 + n->c[0]);
                }
-       //LogOperation("GetAuthInfoForName none found for %##s", name->c);
+       //LogInfo("GetAuthInfoForName none found for %##s", name->c);
        return mDNSNULL;
        }
 
@@ -1372,7 +1564,7 @@ mDNSexport DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname
                        {
                        DNSQuestion *q;
                        DomainAuthInfo *info = *p;
-                       LogOperation("GetAuthInfoForName_internal deleting expired key %##s %##s", info->domain.c, info->keyname.c);
+                       LogInfo("GetAuthInfoForName_internal deleting expired key %##s %##s", info->domain.c, info->keyname.c);
                        *p = info->next;        // Cut DomainAuthInfo from list *before* scanning our question list updating AuthInfo pointers
                        for (q = m->Questions; q; q=q->next)
                                if (q->AuthInfo == info)
@@ -1412,7 +1604,7 @@ mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
        DomainAuthInfo **p = &m->AuthInfoList;
        if (!info || !b64keydata) { LogMsg("mDNS_SetSecretForDomain: ERROR: info %p b64keydata %p", info, b64keydata); return(mStatus_BadParamErr); }
 
-       LogOperation("mDNS_SetSecretForDomain: domain %##s key %##s%s", domain->c, keyname->c, AutoTunnel ? " AutoTunnel" : "");
+       LogInfo("mDNS_SetSecretForDomain: domain %##s key %##s%s", domain->c, keyname->c, AutoTunnel ? " AutoTunnel" : "");
 
        info->AutoTunnel = AutoTunnel;
        AssignDomainName(&info->domain,  domain);
@@ -1421,8 +1613,7 @@ mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
 
        if (DNSDigest_ConstructHMACKeyfromBase64(info, b64keydata) < 0)
                {
-               LogMsg("mDNS_SetSecretForDomain: ERROR: Could not convert shared secret from base64: domain %##s key %##s %s",
-                       domain->c, keyname->c, LogAllOperations ? b64keydata : "");
+               LogMsg("mDNS_SetSecretForDomain: ERROR: Could not convert shared secret from base64: domain %##s key %##s %s", domain->c, keyname->c, mDNS_LoggingEnabled ? b64keydata : "");
                return(mStatus_BadParamErr);
                }
 
@@ -1492,7 +1683,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info)
                err = mDNSPlatformSendUDP(m, (mDNSu8 *)&u, end, 0, mDNSNULL, &m->Router, NATPMPPort);
 
 #ifdef _LEGACY_NAT_TRAVERSAL_
-               if (mDNSIPPortIsZero(m->UPnPSOAPPort)) LNT_SendDiscoveryMsg(m);
+               if (mDNSIPPortIsZero(m->UPnPRouterPort) || mDNSIPPortIsZero(m->UPnPSOAPPort)) LNT_SendDiscoveryMsg(m);
                else if (info) err = LNT_MapPort(m, info);
                else err = LNT_GetExternalAddress(m);
 #endif // _LEGACY_NAT_TRAVERSAL_
@@ -1500,7 +1691,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info)
        return(err);
        }
 
-mDNSlocal void RecreateNATMappings(mDNS *const m)
+mDNSexport void RecreateNATMappings(mDNS *const m)
        {
        NATTraversalInfo *n;
        for (n = m->NATTraversals; n; n=n->next)
@@ -1516,35 +1707,35 @@ mDNSlocal void RecreateNATMappings(mDNS *const m)
        m->NextScheduledNATOp = m->timenow;             // Need to send packets immediately
        }
 
-#ifdef _LEGACY_NAT_TRAVERSAL_
-mDNSlocal void ClearUPnPState(mDNS *const m)
-       {
-       if (m->tcpAddrInfo.sock)   { mDNSPlatformTCPCloseConnection(m->tcpAddrInfo.sock);   m->tcpAddrInfo.sock   = mDNSNULL; }
-       if (m->tcpDeviceInfo.sock) { mDNSPlatformTCPCloseConnection(m->tcpDeviceInfo.sock); m->tcpDeviceInfo.sock = mDNSNULL; }
-       m->UPnPSOAPPort = m->UPnPRouterPort = zeroIPPort;       // Reset UPnP ports
-       }
-#else
-#define ClearUPnPState(X)
-#endif // _LEGACY_NAT_TRAVERSAL_
-
 mDNSexport void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv4Addr ExtAddr)
        {
-       static mDNSu16 last_err;
+       static mDNSu16 last_err = 0;
+       
        if (err)
                {
                if (err != last_err) LogMsg("Error getting external address %d", err);
+               ExtAddr = zerov4Addr;
                }
-       else if (!mDNSSameIPv4Address(m->ExternalAddress, ExtAddr))
+       else
                {
-               LogOperation("Received external IP address %.4a from NAT", &ExtAddr);
+               LogInfo("Received external IP address %.4a from NAT", &ExtAddr);
                if (mDNSv4AddrIsRFC1918(&ExtAddr))
                        LogMsg("Double NAT (external NAT gateway address %.4a is also a private RFC 1918 address)", &ExtAddr);
+               if (mDNSIPv4AddressIsZero(ExtAddr))
+                       err = NATErr_NetFail; // fake error to handle routers that pathologically report success with the zero address
+               }
+               
+       if (!mDNSSameIPv4Address(m->ExternalAddress, ExtAddr))
+               {
                m->ExternalAddress = ExtAddr;
                RecreateNATMappings(m);         // Also sets NextScheduledNATOp for us
                }
 
-       if (err || mDNSIPv4AddressIsZero(ExtAddr)) m->retryIntervalGetAddr = NATMAP_INIT_RETRY * 32;            // 8 seconds
-       else                                       m->retryIntervalGetAddr = NATMAP_MAX_RETRY_INTERVAL;
+       if (!err) // Success, back-off to maximum interval
+               m->retryIntervalGetAddr = NATMAP_MAX_RETRY_INTERVAL;
+       else if (!last_err) // Failure after success, retry quickly (then back-off exponentially)
+               m->retryIntervalGetAddr = NATMAP_INIT_RETRY;
+       // else back-off normally in case of pathological failures
 
        m->retryGetAddr = m->timenow + m->retryIntervalGetAddr;
        if (m->NextScheduledNATOp - m->retryIntervalGetAddr > 0)
@@ -1565,10 +1756,13 @@ mDNSlocal void NATSetNextRenewalTime(mDNS *const m, NATTraversalInfo *n)
 // Note: When called from handleLNTPortMappingResponse() only pkt->err, pkt->extport and pkt->NATRep_lease fields are filled in
 mDNSexport void natTraversalHandlePortMapReply(mDNS *const m, NATTraversalInfo *n, const mDNSInterfaceID InterfaceID, mDNSu16 err, mDNSIPPort extport, mDNSu32 lease)
        {
+       const char *prot = n->Protocol == NATOp_MapUDP ? "UDP" : n->Protocol == NATOp_MapTCP ? "TCP" : "?";
+       (void)prot;
        n->NewResult = err;
        if (err || lease == 0 || mDNSIPPortIsZero(extport))
                {
-               LogOperation("natTraversalHandlePortMapReply: received error making port mapping error %d port %d", err, mDNSVal16(extport));
+               LogInfo("natTraversalHandlePortMapReply: %p Response %s Port %5d External Port %5d lease %d error %d",
+                       n, prot, mDNSVal16(n->IntPort), mDNSVal16(extport), lease, err);
                n->retryInterval = NATMAP_MAX_RETRY_INTERVAL;
                n->retryPortMap = m->timenow + NATMAP_MAX_RETRY_INTERVAL;
                // No need to set m->NextScheduledNATOp here, since we're only ever extending the m->retryPortMap time
@@ -1582,14 +1776,14 @@ mDNSexport void natTraversalHandlePortMapReply(mDNS *const m, NATTraversalInfo *
                n->ExpiryTime = NonZeroTime(m->timenow + lease * mDNSPlatformOneSecond);
        
                if (!mDNSSameIPPort(n->RequestedPort, extport))
-                       LogOperation("natTraversalHandlePortMapReply: public port changed from %d to %d", mDNSVal16(n->RequestedPort), mDNSVal16(extport));
+                       LogInfo("natTraversalHandlePortMapReply: %p Response %s Port %5d External Port %5d changed to %5d",
+                               n, prot, mDNSVal16(n->IntPort), mDNSVal16(n->RequestedPort), mDNSVal16(extport));
 
                n->InterfaceID   = InterfaceID;
                n->RequestedPort = extport;
        
-               LogOperation("natTraversalHandlePortMapReply %p %s Internal Port %d External Port %d", n,
-                       n->Protocol == NATOp_MapUDP ? "UDP Response" :
-                       n->Protocol == NATOp_MapTCP ? "TCP Response" : "?", mDNSVal16(n->IntPort), mDNSVal16(n->RequestedPort));
+               LogInfo("natTraversalHandlePortMapReply: %p Response %s Port %5d External Port %5d lease %d",
+                       n, prot, mDNSVal16(n->IntPort), mDNSVal16(extport), lease);
        
                NATSetNextRenewalTime(m, n);                    // Got our port mapping; now set timer to renew it at halfway point
                m->NextScheduledNATOp = m->timenow;             // May need to invoke client callback immediately
@@ -1601,13 +1795,25 @@ mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalIn
        {
        NATTraversalInfo **n;
        
-       LogOperation("mDNS_StartNATOperation_internal %d %d %d %d",
+       LogInfo("mDNS_StartNATOperation_internal Protocol %d IntPort %d RequestedPort %d NATLease %d",
                traversal->Protocol, mDNSVal16(traversal->IntPort), mDNSVal16(traversal->RequestedPort), traversal->NATLease);
 
        // Note: It important that new traversal requests are appended at the *end* of the list, not prepended at the start
-       n = &m->NATTraversals;
-       while (*n && *n != traversal) n=&(*n)->next;
-       if (*n) { LogMsg("Error! Tried to add a NAT traversal that's already in the active list"); return(mStatus_AlreadyRegistered); }
+       for (n = &m->NATTraversals; *n; n=&(*n)->next)
+               {
+               if (traversal == *n)
+                       {
+                       LogMsg("Error! Tried to add a NAT traversal that's already in the active list: request %p Prot %d Int %d TTL %d",
+                               traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease);
+                       return(mStatus_AlreadyRegistered);
+                       }
+               if (traversal->Protocol && traversal->Protocol == (*n)->Protocol && mDNSSameIPPort(traversal->IntPort, (*n)->IntPort) &&
+                       !mDNSSameIPPort(traversal->IntPort, SSHPort))
+                       LogMsg("Warning: Created port mapping request %p Prot %d Int %d TTL %d "
+                               "duplicates existing port mapping request %p Prot %d Int %d TTL %d",
+                               traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease,
+                               *n,        (*n)     ->Protocol, mDNSVal16((*n)     ->IntPort), (*n)     ->NATLease);
+               }
 
        // Initialize necessary fields
        traversal->next            = mDNSNULL;
@@ -1625,7 +1831,7 @@ mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalIn
 
 #ifdef _LEGACY_NAT_TRAVERSAL_
        mDNSPlatformMemZero(&traversal->tcpInfo, sizeof(traversal->tcpInfo));
-#endif _LEGACY_NAT_TRAVERSAL_
+#endif // _LEGACY_NAT_TRAVERSAL_
 
        if (!m->NATTraversals)          // If this is our first NAT request, kick off an address request too
                {
@@ -1643,8 +1849,10 @@ mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalIn
 // Must be called with the mDNS_Lock held
 mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal)
        {
+       mDNSBool unmap = mDNStrue;
+       NATTraversalInfo *p;
        NATTraversalInfo **ptr = &m->NATTraversals;
-       
+
        while (*ptr && *ptr != traversal) ptr=&(*ptr)->next;
        if (*ptr) *ptr = (*ptr)->next;          // If we found it, cut this NATTraversalInfo struct from our list
        else
@@ -1653,25 +1861,39 @@ mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *tra
                return(mStatus_BadReferenceErr);
                }
 
-       LogOperation("mDNS_StopNATOperation_internal %d %d %d %d",
+       LogInfo("mDNS_StopNATOperation_internal %d %d %d %d",
                traversal->Protocol, mDNSVal16(traversal->IntPort), mDNSVal16(traversal->RequestedPort), traversal->NATLease);
 
        if (m->CurrentNATTraversal == traversal)
                m->CurrentNATTraversal = m->CurrentNATTraversal->next;
 
-       if (traversal->ExpiryTime)
+       if (traversal->Protocol)
+               for (p = m->NATTraversals; p; p=p->next)
+                       if (traversal->Protocol == p->Protocol && mDNSSameIPPort(traversal->IntPort, p->IntPort))
+                               {
+                               if (!mDNSSameIPPort(traversal->IntPort, SSHPort))
+                                       LogMsg("Warning: Removed port mapping request %p Prot %d Int %d TTL %d "
+                                               "duplicates existing port mapping request %p Prot %d Int %d TTL %d",
+                                               traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease,
+                                               p,         p        ->Protocol, mDNSVal16(p        ->IntPort), p        ->NATLease);
+                               unmap = mDNSfalse;
+                               }
+
+       if (traversal->ExpiryTime && unmap)
                {
                traversal->NATLease = 0;
                traversal->retryInterval = 0;
                uDNS_SendNATMsg(m, traversal);
                }
+
        // Even if we DIDN'T make a successful UPnP mapping yet, we might still have a partially-open TCP connection we need to clean up
        #ifdef _LEGACY_NAT_TRAVERSAL_
                {
                mStatus err = LNT_UnmapPort(m, traversal);
-               if (err) LogMsg("Legacy NAT Traversal - unmap request failed with error %ld", err);
+               if (err) LogMsg("Legacy NAT Traversal - unmap request failed with error %d", err);
                }
        #endif // _LEGACY_NAT_TRAVERSAL_
+
        return(mStatus_NoError);
        }
 
@@ -1702,7 +1924,7 @@ mDNSexport mStatus mDNS_StopNATOperation(mDNS *m, NATTraversalInfo *traversal)
 // Lock must be held -- otherwise m->timenow is undefined
 mDNSlocal void StartLLQPolling(mDNS *const m, DNSQuestion *q)
        {
-       LogOperation("StartLLQPolling: %##s", q->qname.c);
+       debugf("StartLLQPolling: %##s", q->qname.c);
        q->state = LLQ_Poll;
        q->ThisQInterval = INIT_UCAST_POLL_INTERVAL;
        // We want to send our poll query ASAP, but the "+ 1" is because if we set the time to now,
@@ -1714,30 +1936,28 @@ mDNSlocal void StartLLQPolling(mDNS *const m, DNSQuestion *q)
 #endif
        }
 
-mDNSlocal mDNSu8 *putLLQ(DNSMessage *const msg, mDNSu8 *ptr, const DNSQuestion *const question, const LLQOptData *const data, mDNSBool includeQuestion)
+mDNSlocal mDNSu8 *putLLQ(DNSMessage *const msg, mDNSu8 *ptr, const DNSQuestion *const question, const LLQOptData *const data)
        {
        AuthRecord rr;
        ResourceRecord *opt = &rr.resrec;
        rdataOPT *optRD;
 
        //!!!KRS when we implement multiple llqs per message, we'll need to memmove anything past the question section
-       if (includeQuestion)
-               {
-               ptr = putQuestion(msg, ptr, msg->data + AbsoluteMaxDNSMessageData, &question->qname, question->qtype, question->qclass);
-               if (!ptr) { LogMsg("ERROR: putLLQ - putQuestion"); return mDNSNULL; }
-               }
+       ptr = putQuestion(msg, ptr, msg->data + AbsoluteMaxDNSMessageData, &question->qname, question->qtype, question->qclass);
+       if (!ptr) { LogMsg("ERROR: putLLQ - putQuestion"); return mDNSNULL; }
+
        // locate OptRR if it exists, set pointer to end
        // !!!KRS implement me
 
        // format opt rr (fields not specified are zero-valued)
        mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
-       opt->rdlength   = LLQ_OPT_RDLEN;
-       opt->rdestimate = LLQ_OPT_RDLEN;
+       opt->rrclass    = NormalMaxDNSMessageData;
+       opt->rdlength   = sizeof(rdataOPT);     // One option in this OPT record
+       opt->rdestimate = sizeof(rdataOPT);
 
-       optRD = &rr.resrec.rdata->u.opt;
+       optRD = &rr.resrec.rdata->u.opt[0];
        optRD->opt = kDNSOpt_LLQ;
-       optRD->optlen = LLQ_OPTLEN;
-       optRD->OptData.llq = *data;
+       optRD->u.llq = *data;
        ptr = PutResourceRecordTTLJumbo(msg, ptr, &msg->h.numAdditionals, opt, 0);
        if (!ptr) { LogMsg("ERROR: putLLQ - PutResourceRecordTTLJumbo"); return mDNSNULL; }
 
@@ -1792,8 +2012,7 @@ mDNSlocal void sendChallengeResponse(mDNS *const m, DNSQuestion *const q, const
        //if (q->ntries == 1) return;
 
        InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
-       responsePtr = putQuestion(&m->omsg, responsePtr, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
-       if (responsePtr) responsePtr = putLLQ(&m->omsg, responsePtr, q, llq, mDNSfalse);
+       responsePtr = putLLQ(&m->omsg, responsePtr, q, llq);
        if (responsePtr)
                {
                mStatus err = mDNSSendDNSMessage(m, &m->omsg, responsePtr, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, q->AuthInfo);
@@ -1830,7 +2049,7 @@ mDNSlocal void recvSetupResponse(mDNS *const m, mDNSu8 rcode, DNSQuestion *const
 
        if (q->state == LLQ_InitialRequest)
                {
-               //LogOperation("Got LLQ_InitialRequest");
+               //LogInfo("Got LLQ_InitialRequest");
 
                if (llq->err) { LogMsg("recvSetupResponse - received llq->err %d from server", llq->err); StartLLQPolling(m,q); return; }
        
@@ -1849,7 +2068,7 @@ mDNSlocal void recvSetupResponse(mDNS *const m, mDNSu8 rcode, DNSQuestion *const
                }
        else if (q->state == LLQ_SecondaryRequest)
                {
-               //LogOperation("Got LLQ_SecondaryRequest");
+               //LogInfo("Got LLQ_SecondaryRequest");
 
                // Fix this immediately if not sooner.  Copy the id from the LLQOptData into our DNSQuestion struct.  This is only
                // an issue for private LLQs, because we skip parts 2 and 3 of the handshake.  This is related to a bigger
@@ -1857,7 +2076,7 @@ mDNSlocal void recvSetupResponse(mDNS *const m, mDNSu8 rcode, DNSQuestion *const
                // if the server sends back SERVFULL or STATIC.
                if (q->AuthInfo)
                        {
-                       LogOperation("Private LLQ_SecondaryRequest; copying id %08X%08X", llq->id.l[0], llq->id.l[1]);
+                       LogInfo("Private LLQ_SecondaryRequest; copying id %08X%08X", llq->id.l[0], llq->id.l[1]);
                        q->id = llq->id;
                        }
 
@@ -1886,12 +2105,12 @@ mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *co
                                {
                                debugf("uDNS_recvLLQResponse found %##s (%s) %d %#a %#a %X %X %X %X %d",
                                        q->qname.c, DNSTypeName(q->qtype), q->state, srcaddr, &q->servAddr,
-                                       opt->OptData.llq.id.l[0], opt->OptData.llq.id.l[1], q->id.l[0], q->id.l[1], opt->OptData.llq.llqOp);
+                                       opt ? opt->u.llq.id.l[0] : 0, opt ? opt->u.llq.id.l[1] : 0, q->id.l[0], q->id.l[1], opt ? opt->u.llq.llqOp : 0);
                                if (q->state == LLQ_Poll) debugf("uDNS_LLQ_Events: q->state == LLQ_Poll msg->h.id %d q->TargetQID %d", mDNSVal16(msg->h.id), mDNSVal16(q->TargetQID));
                                if (q->state == LLQ_Poll && mDNSSameOpaque16(msg->h.id, q->TargetQID))
                                        {
                                        m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
-                                       LogOperation("uDNS_recvLLQResponse got poll response; moving to LLQ_InitialRequest for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+                                       debugf("uDNS_recvLLQResponse got poll response; moving to LLQ_InitialRequest for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                                        q->state         = LLQ_InitialRequest;
                                        q->servPort      = zeroIPPort;          // Clear servPort so that startLLQHandshake will retry the GetZoneData processing
                                        q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10);        // Retry LLQ setup in approx 15 minutes
@@ -1900,12 +2119,12 @@ mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *co
                                        return uDNS_LLQ_Entire;         // uDNS_LLQ_Entire means flush stale records; assume a large effective TTL
                                        }
                                // Note: In LLQ Event packets, the msg->h.id does not match our q->TargetQID, because in that case the msg->h.id nonce is selected by the server
-                               else if (opt && q->state == LLQ_Established && opt->OptData.llq.llqOp == kLLQOp_Event && mDNSSameOpaque64(&opt->OptData.llq.id, &q->id))
+                               else if (opt && q->state == LLQ_Established && opt->u.llq.llqOp == kLLQOp_Event && mDNSSameOpaque64(&opt->u.llq.id, &q->id))
                                        {
                                        mDNSu8 *ackEnd;
                                        //debugf("Sending LLQ ack for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                                        InitializeDNSMessage(&m->omsg.h, msg->h.id, ResponseFlags);
-                                       ackEnd = putLLQ(&m->omsg, m->omsg.data, mDNSNULL, &opt->OptData.llq, mDNSfalse);
+                                       ackEnd = putLLQ(&m->omsg, m->omsg.data, q, &opt->u.llq);
                                        if (ackEnd) mDNSSendDNSMessage(m, &m->omsg, ackEnd, mDNSInterface_Any, q->LocalSocket, srcaddr, srcport, mDNSNULL, mDNSNULL);
                                        m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
                                        debugf("uDNS_LLQ_Events: q->state == LLQ_Established msg->h.id %d q->TargetQID %d", mDNSVal16(msg->h.id), mDNSVal16(q->TargetQID));
@@ -1913,14 +2132,17 @@ mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *co
                                        }
                                if (opt && mDNSSameOpaque16(msg->h.id, q->TargetQID))
                                        {
-                                       if (q->state == LLQ_Established && opt->OptData.llq.llqOp == kLLQOp_Refresh && mDNSSameOpaque64(&opt->OptData.llq.id, &q->id) && msg->h.numAdditionals && !msg->h.numAnswers)
+                                       if (q->state == LLQ_Established && opt->u.llq.llqOp == kLLQOp_Refresh && mDNSSameOpaque64(&opt->u.llq.id, &q->id) && msg->h.numAdditionals && !msg->h.numAnswers)
                                                {
-                                               if (opt->OptData.llq.err != LLQErr_NoError) LogMsg("recvRefreshReply: received error %d from server", opt->OptData.llq.err);
+                                               if (opt->u.llq.err != LLQErr_NoError) LogMsg("recvRefreshReply: received error %d from server", opt->u.llq.err);
                                                else
                                                        {
-                                                       //LogOperation("Received refresh confirmation ntries %d for %##s (%s)", q->ntries, q->qname.c, DNSTypeName(q->qtype));
-                                                       GrantCacheExtensions(m, q, opt->OptData.llq.llqlease);
-                                                       SetLLQTimer(m, q, &opt->OptData.llq);
+                                                       //LogInfo("Received refresh confirmation ntries %d for %##s (%s)", q->ntries, q->qname.c, DNSTypeName(q->qtype));
+                                                       // If we're waiting to go to sleep, then this LLQ deletion may have been the thing
+                                                       // we were waiting for, so schedule another check to see if we can sleep now.
+                                                       if (opt->u.llq.llqlease == 0 && m->SleepLimit) m->NextScheduledSPRetry = m->timenow;
+                                                       GrantCacheExtensions(m, q, opt->u.llq.llqlease);
+                                                       SetLLQTimer(m, q, &opt->u.llq);
                                                        q->ntries = 0;
                                                        }
                                                m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
@@ -1929,10 +2151,10 @@ mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *co
                                        if (q->state < LLQ_Established && mDNSSameAddress(srcaddr, &q->servAddr))
                                                {
                                                LLQ_State oldstate = q->state;
-                                               recvSetupResponse(m, msg->h.flags.b[1] & kDNSFlag1_RC_Mask, q, &opt->OptData.llq);
+                                               recvSetupResponse(m, msg->h.flags.b[1] & kDNSFlag1_RC_Mask, q, &opt->u.llq);
                                                m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
                                                // We have a protocol anomaly here in the LLQ definition.
-                                               // Both the challenge packet from the server and the ack+answers packet have opt->OptData.llq.llqOp == kLLQOp_Setup.
+                                               // Both the challenge packet from the server and the ack+answers packet have opt->u.llq.llqOp == kLLQOp_Setup.
                                                // However, we need to treat them differently:
                                                // The challenge packet has no answers in it, and tells us nothing about whether our cache entries
                                                // are still valid, so this packet should not cause us to do anything that messes with our cache.
@@ -1993,7 +2215,7 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs
                        {
                        end = ((mDNSu8*) &tcpInfo->request) + tcpInfo->requestLen;
                        }
-               else if (q && q->LongLived && q->state != LLQ_Poll && !mDNSIPPortIsZero(m->LLQNAT.ExternalPort))
+               else if (q && q->LongLived && q->state != LLQ_Poll && !mDNSIPPortIsZero(m->LLQNAT.ExternalPort) && !mDNSIPPortIsZero(q->servPort))
                        {
                        // Notes:
                        // If we have a NAT port mapping, ExternalPort is the external port
@@ -2003,11 +2225,11 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs
                        llqData.vers  = kLLQ_Vers;
                        llqData.llqOp = kLLQOp_Setup;
                        llqData.err   = GetLLQEventPort(m, &tcpInfo->Addr);     // We're using TCP; tell server what UDP port to send notifications to
-                       LogOperation("tcpCallback: eventPort %d", llqData.err);
+                       LogInfo("tcpCallback: eventPort %d", llqData.err);
                        llqData.id    = zeroOpaque64;
                        llqData.llqlease = kLLQ_DefLease;
                        InitializeDNSMessage(&tcpInfo->request.h, q->TargetQID, uQueryFlags);
-                       end = putLLQ(&tcpInfo->request, tcpInfo->request.data, q, &llqData, mDNStrue);
+                       end = putLLQ(&tcpInfo->request, tcpInfo->request.data, q, &llqData);
                        if (!end) { LogMsg("ERROR: tcpCallback - putLLQ"); err = mStatus_UnknownErr; goto exit; }
                        AuthInfo = q->AuthInfo;         // Need to add TSIG to this message
                        }
@@ -2019,7 +2241,7 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs
                        }
 
                err = mDNSSendDNSMessage(m, &tcpInfo->request, end, mDNSInterface_Any, mDNSNULL, &tcpInfo->Addr, tcpInfo->Port, sock, AuthInfo);
-               if (err) { debugf("ERROR: tcpCallback: mDNSSendDNSMessage - %ld", err); err = mStatus_UnknownErr; goto exit; }
+               if (err) { debugf("ERROR: tcpCallback: mDNSSendDNSMessage - %d", err); err = mStatus_UnknownErr; goto exit; }
 
                // Record time we sent this question
                if (q)
@@ -2091,7 +2313,7 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs
                        if (rr && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
                                {
                                mDNS_Lock(m);
-                               LogOperation("tcpCallback: CompleteDeregistration %s", ARDisplayString(m, rr));
+                               LogInfo("tcpCallback: CompleteDeregistration %s", ARDisplayString(m, rr));
                                CompleteDeregistration(m, rr);          // Don't touch rr after this
                                mDNS_Unlock(m);
                                }
@@ -2180,7 +2402,7 @@ mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, con
 
        // Don't need to log "connection failed" in customer builds -- it happens quite often during sleep, wake, configuration changes, etc.
        if      (err == mStatus_ConnEstablished) { tcpCallback(info->sock, info, mDNStrue, mStatus_NoError); }
-       else if (err != mStatus_ConnPending    ) { LogOperation("MakeTCPConnection: connection failed"); DisposeTCPConn(info); return(mDNSNULL); }
+       else if (err != mStatus_ConnPending    ) { LogInfo("MakeTCPConnection: connection failed"); DisposeTCPConn(info); return(mDNSNULL); }
        return(info);
        }
 
@@ -2196,7 +2418,7 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
        {
        if (mDNSIPv4AddressIsOnes(m->LLQNAT.ExternalAddress))
                {
-               LogOperation("startLLQHandshake: waiting for NAT status for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+               LogInfo("startLLQHandshake: waiting for NAT status for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10);        // Retry in approx 15 minutes
                q->LastQTime = m->timenow;
                SetNextQueryTime(m, q);
@@ -2205,19 +2427,19 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
 
        if (mDNSIPPortIsZero(m->LLQNAT.ExternalPort))
                {
-               LogOperation("startLLQHandshake: Cannot receive inbound packets; will poll for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+               LogInfo("startLLQHandshake: Cannot receive inbound packets; will poll for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                StartLLQPolling(m, q);
                return;
                }
 
        if (mDNSIPPortIsZero(q->servPort))
                {
-               LogOperation("startLLQHandshake: StartGetZoneData for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+               debugf("startLLQHandshake: StartGetZoneData for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10);        // Retry in approx 15 minutes
                q->LastQTime     = m->timenow;
                SetNextQueryTime(m, q);
                q->servAddr = zeroAddr;
-               q->servPort = zeroIPPort;
+               // We know q->servPort is zero because of check above
                if (q->nta) CancelGetZoneData(m, q->nta);
                q->nta = StartGetZoneData(m, &q->qname, ZoneServiceLLQ, LLQGotZoneData, q);
                return;
@@ -2225,7 +2447,7 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
 
        if (q->AuthInfo)
                {
-               if (q->tcp) LogOperation("startLLQHandshake: Disposing existing TCP connection for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+               if (q->tcp) LogInfo("startLLQHandshake: Disposing existing TCP connection for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                if (q->tcp) DisposeTCPConn(q->tcp);
                q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_UseTLS, &q->servAddr, q->servPort, q, mDNSNULL, mDNSNULL);
                if (!q->tcp)
@@ -2241,7 +2463,7 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
                }
        else
                {
-               LogOperation("startLLQHandshake m->AdvertisedV4 %#a%s Server %#a:%d%s %##s (%s)",
+               debugf("startLLQHandshake: m->AdvertisedV4 %#a%s Server %#a:%d%s %##s (%s)",
                        &m->AdvertisedV4,                     mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) ? " (RFC 1918)" : "",
                        &q->servAddr, mDNSVal16(q->servPort), mDNSAddrIsRFC1918(&q->servAddr)             ? " (RFC 1918)" : "",
                        q->qname.c, DNSTypeName(q->qtype));
@@ -2264,7 +2486,7 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
                        llqData.llqlease = kLLQ_DefLease;
        
                        InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
-                       end = putLLQ(&m->omsg, m->omsg.data, q, &llqData, mDNStrue);
+                       end = putLLQ(&m->omsg, m->omsg.data, q, &llqData);
                        if (!end) { LogMsg("ERROR: startLLQHandshake - putLLQ"); StartLLQPolling(m,q); return; }
        
                        mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, mDNSNULL, mDNSNULL);
@@ -2279,16 +2501,19 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
                }
        }
 
-mDNSexport const domainname *GetServiceTarget(mDNS *m, ServiceRecordSet *srs)
+// forward declaration so GetServiceTarget can do reverse lookup if needed
+mDNSlocal void GetStaticHostname(mDNS *m);
+
+mDNSexport const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr)
        {
-       LogOperation("GetServiceTarget %##s", srs->RR_SRV.resrec.name->c);
+       debugf("GetServiceTarget %##s", rr->resrec.name->c);
 
-       if (!srs->RR_SRV.AutoTarget)            // If not automatically tracking this host's current name, just return the existing target
-               return(&srs->RR_SRV.resrec.rdata->u.srv.target);
+       if (!rr->AutoTarget)            // If not automatically tracking this host's current name, just return the existing target
+               return(&rr->resrec.rdata->u.srv.target);
        else
                {
 #if APPLE_OSX_mDNSResponder
-               DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name);
+               DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name);
                if (AuthInfo && AuthInfo->AutoTunnel)
                        {
                        // If this AutoTunnel is not yet active, start it now (which entails activating its NAT Traversal request,
@@ -2299,9 +2524,9 @@ mDNSexport const domainname *GetServiceTarget(mDNS *m, ServiceRecordSet *srs)
                        return(&AuthInfo->AutoTunnelHostRecord.namestorage);
                        }
                else
-#endif APPLE_OSX_mDNSResponder
+#endif // APPLE_OSX_mDNSResponder
                        {
-                       const int srvcount = CountLabels(srs->RR_SRV.resrec.name);
+                       const int srvcount = CountLabels(rr->resrec.name);
                        HostnameInfo *besthi = mDNSNULL, *hi;
                        int best = 0;
                        for (hi = m->Hostnames; hi; hi = hi->next)
@@ -2310,13 +2535,14 @@ mDNSexport const domainname *GetServiceTarget(mDNS *m, ServiceRecordSet *srs)
                                        {
                                        int x, hostcount = CountLabels(&hi->fqdn);
                                        for (x = hostcount < srvcount ? hostcount : srvcount; x > 0 && x > best; x--)
-                                               if (SameDomainName(SkipLeadingLabels(srs->RR_SRV.resrec.name, srvcount - x), SkipLeadingLabels(&hi->fqdn, hostcount - x)))
+                                               if (SameDomainName(SkipLeadingLabels(rr->resrec.name, srvcount - x), SkipLeadingLabels(&hi->fqdn, hostcount - x)))
                                                        { best = x; besthi = hi; }
                                        }
        
                        if (besthi) return(&besthi->fqdn);
                        }
                if (m->StaticHostname.c[0]) return(&m->StaticHostname);
+               else GetStaticHostname(m); // asynchronously do reverse lookup for primary IPv4 address
                return(mDNSNULL);
                }
        }
@@ -2398,10 +2624,10 @@ mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs)
        else
                if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &srs->RR_TXT.resrec, srs->RR_TXT.resrec.rroriginalttl))) { err = mStatus_UnknownErr; goto exit; }
 
-       target = GetServiceTarget(m, srs);
+       target = GetServiceTarget(m, &srs->RR_SRV);
        if (!target || target->c[0] == 0)
                {
-               LogOperation("SendServiceRegistration - no target for %##s", srs->RR_SRV.resrec.name->c);
+               debugf("SendServiceRegistration - no target for %##s", srs->RR_SRV.resrec.name->c);
                srs->state = regState_NoTarget;
                return;
                }
@@ -2425,7 +2651,7 @@ mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs)
 
        if (srs->Private)
                {
-               if (srs->tcp) LogOperation("SendServiceRegistration: Disposing existing TCP connection for %s", ARDisplayString(m, &srs->RR_SRV));
+               if (srs->tcp) LogInfo("SendServiceRegistration: Disposing existing TCP connection for %s", ARDisplayString(m, &srs->RR_SRV));
                if (srs->tcp) DisposeTCPConn(srs->tcp);
                srs->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, srs, mDNSNULL);
                if (!srs->tcp) srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 5; // If failed to make TCP connection, try again in ten seconds (5*2)
@@ -2434,7 +2660,7 @@ mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs)
        else
                {
                err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name));
-               if (err) debugf("ERROR: SendServiceRegistration - mDNSSendDNSMessage - %ld", err);
+               if (err) debugf("ERROR: SendServiceRegistration - mDNSSendDNSMessage - %d", err);
                }
 
        SetRecordRetry(m, &srs->RR_SRV, err);
@@ -2501,7 +2727,7 @@ mDNSlocal void GetZoneData_QuestionCallback(mDNS *const m, DNSQuestion *question
                        }
                else
                        {
-                       LogOperation("GetZoneData recursed to root label of %##s without finding SOA", zd->ChildName.c);
+                       LogInfo("GetZoneData recursed to root label of %##s without finding SOA", zd->ChildName.c);
                        zd->ZoneDataCallback(m, mStatus_NoSuchNameErr, zd);
                        mDNSPlatformMemFree(zd);
                        }
@@ -2568,7 +2794,7 @@ mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qt
                {
                AssignDomainName(&zd->question.qname, ZoneDataSRV(zd));
                AppendDomainName(&zd->question.qname, &zd->ZoneName);
-               LogOperation("lookupDNSPort %##s", zd->question.qname.c);
+               debugf("lookupDNSPort %##s", zd->question.qname.c);
                }
 
        zd->question.ThisQInterval       = -1;          // So that GetZoneData_QuestionCallback() knows whether to cancel this question (Is this necessary?)
@@ -2639,7 +2865,7 @@ mDNSexport DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *co
 mDNSlocal void CompleteSRVNatMap(mDNS *m, NATTraversalInfo *n)
        {
        ServiceRecordSet *srs = (ServiceRecordSet *)n->clientContext;
-       LogOperation("SRVNatMap complete %.4a %u %u TTL %u", &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), n->NATLease);
+       debugf("SRVNatMap complete %.4a IntPort %u ExternalPort %u NATLease %u", &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), n->NATLease);
 
        if (!srs) { LogMsg("CompleteSRVNatMap called with unknown ServiceRecordSet object"); return; }
        if (!n->NATLease) return;
@@ -2650,10 +2876,10 @@ mDNSlocal void CompleteSRVNatMap(mDNS *m, NATTraversalInfo *n)
        else
                {
                // SHOULD NEVER HAPPEN!
-               LogOperation("ERROR: CompleteSRVNatMap called but srs->SRSUpdateServer.ip.v4 is zero!");
+               LogInfo("ERROR: CompleteSRVNatMap called but srs->SRSUpdateServer.ip.v4 is zero!");
                srs->state = regState_FetchingZoneData;
-               if (srs->nta) CancelGetZoneData(m, srs->nta); // Make sure we cancel old one before we start a new one
-               srs->nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs);
+               if (srs->srs_nta) CancelGetZoneData(m, srs->srs_nta); // Make sure we cancel old one before we start a new one
+               srs->srs_nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs);
                }
        mDNS_Unlock(m);
        }
@@ -2667,7 +2893,9 @@ mDNSlocal void StartSRVNatMap(mDNS *m, ServiceRecordSet *srs)
        else { LogMsg("StartSRVNatMap: could not determine transport protocol of service %##s", srs->RR_SRV.resrec.name->c); return; }
        
        if (srs->NATinfo.clientContext) mDNS_StopNATOperation_internal(m, &srs->NATinfo);
-       srs->NATinfo.IntPort        = srs->RR_SRV.resrec.rdata->u.srv.port;
+       // Don't try to set IntPort here --
+       // SendServiceRegistration overwrites srs->RR_SRV.resrec.rdata->u.srv.port with external (mapped) port number
+       //srs->NATinfo.IntPort      = srs->RR_SRV.resrec.rdata->u.srv.port;
        srs->NATinfo.RequestedPort  = srs->RR_SRV.resrec.rdata->u.srv.port;
        srs->NATinfo.NATLease       = 0;                // Request default lease
        srs->NATinfo.clientCallback = CompleteSRVNatMap;
@@ -2683,7 +2911,10 @@ mDNSexport void ServiceRegistrationGotZoneData(mDNS *const m, mStatus err, const
        if (m->mDNS_busy != m->mDNS_reentrancy)
                LogMsg("ServiceRegistrationGotZoneData: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
-       srs->nta = mDNSNULL;
+       if (!srs->RR_SRV.resrec.rdata)
+               { LogMsg("ServiceRegistrationGotZoneData: ERROR: srs->RR_SRV.resrec.rdata is NULL"); return; }
+
+       srs->srs_nta = mDNSNULL;
 
        // Start off assuming we're going to use a lease
        // If we get an error from the server, and the update port as given in the SRV record is 53, then we'll retry without the lease option
@@ -2703,17 +2934,21 @@ mDNSexport void ServiceRegistrationGotZoneData(mDNS *const m, mStatus err, const
        srs->RR_SRV.LastAPTime     = m->timenow;
        srs->RR_SRV.ThisAPInterval = 0;
 
-       LogOperation("ServiceRegistrationGotZoneData My IPv4 %#a%s Server %#a:%d%s for %##s",
+       debugf("ServiceRegistrationGotZoneData My IPv4 %#a%s Server %#a:%d%s for %##s",
                &m->AdvertisedV4, mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) ? " (RFC1918)" : "",
                &srs->SRSUpdateServer, mDNSVal16(srs->SRSUpdatePort), mDNSAddrIsRFC1918(&srs->SRSUpdateServer) ? " (RFC1918)" : "",
                srs->RR_SRV.resrec.name->c);
 
+       // If we have non-zero service port (always?)
+       // and a private address, and update server is non-private
+       // and this service is AutoTarget
+       // then initiate a NAT mapping request. On completion it will do SendServiceRegistration() for us
        if (!mDNSIPPortIsZero(srs->RR_SRV.resrec.rdata->u.srv.port) &&
                mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) && !mDNSAddrIsRFC1918(&srs->SRSUpdateServer) &&
                srs->RR_SRV.AutoTarget == Target_AutoHostAndNATMAP)
                {
                srs->state = regState_NATMap;
-               LogOperation("ServiceRegistrationGotZoneData StartSRVNatMap");
+               debugf("ServiceRegistrationGotZoneData StartSRVNatMap");
                StartSRVNatMap(m, srs);
                }
        else
@@ -2758,8 +2993,8 @@ mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs)
 
        if (srs->Private)
                {
-               LogOperation("SendServiceDeregistration TCP %p %s", srs->tcp, ARDisplayString(m, &srs->RR_SRV));
-               if (srs->tcp) LogOperation("SendServiceDeregistration: Disposing existing TCP connection for %s", ARDisplayString(m, &srs->RR_SRV));
+               LogInfo("SendServiceDeregistration TCP %p %s", srs->tcp, ARDisplayString(m, &srs->RR_SRV));
+               if (srs->tcp) LogInfo("SendServiceDeregistration: Disposing existing TCP connection for %s", ARDisplayString(m, &srs->RR_SRV));
                if (srs->tcp) DisposeTCPConn(srs->tcp);
                srs->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, srs, mDNSNULL);
                if (!srs->tcp) srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 5; // If failed to make TCP connection, try again in ten seconds (5*2)
@@ -2768,7 +3003,7 @@ mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs)
        else
                {
                err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name));
-               if (err && err != mStatus_TransientErr) { debugf("ERROR: SendServiceDeregistration - mDNSSendDNSMessage - %ld", err); goto exit; }
+               if (err && err != mStatus_TransientErr) { debugf("ERROR: SendServiceDeregistration - mDNSSendDNSMessage - %d", err); goto exit; }
                }
 
        SetRecordRetry(m, &srs->RR_SRV, err);
@@ -2794,14 +3029,14 @@ mDNSlocal void UpdateSRV(mDNS *m, ServiceRecordSet *srs)
        // The target has changed
 
        domainname *curtarget = &srs->RR_SRV.resrec.rdata->u.srv.target;
-       const domainname *const nt = GetServiceTarget(m, srs);
+       const domainname *const nt = GetServiceTarget(m, &srs->RR_SRV);
        const domainname *const newtarget = nt ? nt : (domainname*)"";
        mDNSBool TargetChanged = (newtarget->c[0] && srs->state == regState_NoTarget) || !SameDomainName(curtarget, newtarget);
        mDNSBool HaveZoneData  = !mDNSIPv4AddressIsZero(srs->SRSUpdateServer.ip.v4);
 
        // Nat state change if:
        // We were behind a NAT, and now we are behind a new NAT, or
-       // We're not behind a NAT but our port was previously mapped to a different public port
+       // We're not behind a NAT but our port was previously mapped to a different external port
        // We were not behind a NAT and now we are
 
        mDNSIPPort port        = srs->RR_SRV.resrec.rdata->u.srv.port;
@@ -2810,7 +3045,7 @@ mDNSlocal void UpdateSRV(mDNS *m, ServiceRecordSet *srs)
        mDNSBool PortWasMapped = (srs->NATinfo.clientContext && !mDNSSameIPPort(srs->NATinfo.RequestedPort, port));             // I think this is always false -- SC Sept 07
        mDNSBool NATChanged    = (!WereBehindNAT && NowNeedNATMAP) || (!NowNeedNATMAP && PortWasMapped);
 
-       LogOperation("UpdateSRV %##s newtarget %##s TargetChanged %d HaveZoneData %d port %d NowNeedNATMAP %d WereBehindNAT %d PortWasMapped %d NATChanged %d",
+       debugf("UpdateSRV %##s newtarget %##s TargetChanged %d HaveZoneData %d port %d NowNeedNATMAP %d WereBehindNAT %d PortWasMapped %d NATChanged %d",
                srs->RR_SRV.resrec.name->c, newtarget,
                TargetChanged, HaveZoneData, mDNSVal16(port), NowNeedNATMAP, WereBehindNAT, PortWasMapped, NATChanged);
 
@@ -2849,8 +3084,8 @@ mDNSlocal void UpdateSRV(mDNS *m, ServiceRecordSet *srs)
                                if (!HaveZoneData)
                                        {
                                        srs->state = regState_FetchingZoneData;
-                                       if (srs->nta) CancelGetZoneData(m, srs->nta); // Make sure we cancel old one before we start a new one
-                                       srs->nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs);
+                                       if (srs->srs_nta) CancelGetZoneData(m, srs->srs_nta); // Make sure we cancel old one before we start a new one
+                                       srs->srs_nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs);
                                        }
                                else
                                        {
@@ -2881,7 +3116,7 @@ mDNSlocal void UpdateSRV(mDNS *m, ServiceRecordSet *srs)
 // Called with lock held
 mDNSlocal void UpdateSRVRecords(mDNS *m)
        {
-       LogOperation("UpdateSRVRecords%s", m->SleepState ? " (ignored due to SleepState)" : "");
+       debugf("UpdateSRVRecords%s", m->SleepState ? " (ignored due to SleepState)" : "");
        if (m->SleepState) return;
 
        if (CurrentServiceRecordSet)
@@ -2894,6 +3129,10 @@ mDNSlocal void UpdateSRVRecords(mDNS *m)
                CurrentServiceRecordSet = CurrentServiceRecordSet->uDNS_next;
                UpdateSRV(m, s);
                }
+
+       mDNS_DropLockBeforeCallback();          // mDNS_SetFQDN expects to be called without the lock held, so we emulate that here
+       mDNS_SetFQDN(m);
+       mDNS_ReclaimLockAfterCallback();
        }
 
 // Forward reference: AdvertiseHostname references HostnameCallback, and HostnameCallback calls AdvertiseHostname
@@ -2913,12 +3152,13 @@ mDNSlocal void hostnameGetPublicAddressCallback(mDNS *m, NATTraversalInfo *n)
                if (h->arv4.resrec.RecordType)
                        {
                        if (mDNSSameIPv4Address(h->arv4.resrec.rdata->u.ipv4, n->ExternalAddress)) return;      // If address unchanged, do nothing
-                       LogOperation("Updating hostname %##s IPv4 from %.4a to %.4a (NAT gateway's external address)", h->arv4.resrec.name->c, &h->arv4.resrec.rdata->u.ipv4, &n->ExternalAddress);
+                       LogInfo("Updating hostname %##s IPv4 from %.4a to %.4a (NAT gateway's external address)",
+                               h->arv4.resrec.name->c, &h->arv4.resrec.rdata->u.ipv4, &n->ExternalAddress);
                        mDNS_Deregister(m, &h->arv4);   // mStatus_MemFree callback will re-register with new address
                        }
                else
                        {
-                       LogOperation("Advertising hostname %##s IPv4 %.4a (NAT gateway's external address)", h->arv4.resrec.name->c, &n->ExternalAddress);
+                       LogInfo("Advertising hostname %##s IPv4 %.4a (NAT gateway's external address)", h->arv4.resrec.name->c, &n->ExternalAddress);
                        h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique;
                        h->arv4.resrec.rdata->u.ipv4 = n->ExternalAddress;
                        mDNS_Register(m, &h->arv4);
@@ -2949,7 +3189,7 @@ mDNSlocal void AdvertiseHostname(mDNS *m, HostnameInfo *h)
                        }
                else
                        {
-                       LogOperation("Advertising hostname %##s IPv4 %.4a", h->arv4.resrec.name->c, &m->AdvertisedV4.ip.v4);
+                       LogInfo("Advertising hostname %##s IPv4 %.4a", h->arv4.resrec.name->c, &m->AdvertisedV4.ip.v4);
                        h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique;
                        mDNS_Register_internal(m, &h->arv4);
                        }
@@ -2961,7 +3201,7 @@ mDNSlocal void AdvertiseHostname(mDNS *m, HostnameInfo *h)
                AssignDomainName(&h->arv6.namestorage, &h->fqdn);
                h->arv6.resrec.rdata->u.ipv6 = m->AdvertisedV6.ip.v6;
                h->arv6.state = regState_Unregistered;
-               LogOperation("Advertising hostname %##s IPv6 %.16a", h->arv6.resrec.name->c, &m->AdvertisedV6.ip.v6);
+               LogInfo("Advertising hostname %##s IPv6 %.16a", h->arv6.resrec.name->c, &m->AdvertisedV6.ip.v6);
                mDNS_Register_internal(m, &h->arv6);
                }
        }
@@ -2976,7 +3216,7 @@ mDNSlocal void HostnameCallback(mDNS *const m, AuthRecord *const rr, mStatus res
                        {
                        // If we're still in the Hostnames list, update to new address
                        HostnameInfo *i;
-                       LogOperation("HostnameCallback: Got mStatus_MemFree for %p %p %s", hi, rr, ARDisplayString(m, rr));
+                       LogInfo("HostnameCallback: Got mStatus_MemFree for %p %p %s", hi, rr, ARDisplayString(m, rr));
                        for (i = m->Hostnames; i; i = i->next)
                                if (rr == &i->arv4 || rr == &i->arv6)
                                        { mDNS_Lock(m); AdvertiseHostname(m, i); mDNS_Unlock(m); return; }
@@ -2997,9 +3237,9 @@ mDNSlocal void HostnameCallback(mDNS *const m, AuthRecord *const rr, mStatus res
                {
                // don't unlink or free - we can retry when we get a new address/router
                if (rr->resrec.rrtype == kDNSType_A)
-                       LogMsg("HostnameCallback: Error %ld for registration of %##s IP %.4a", result, rr->resrec.name->c, &rr->resrec.rdata->u.ipv4);
+                       LogMsg("HostnameCallback: Error %d for registration of %##s IP %.4a", result, rr->resrec.name->c, &rr->resrec.rdata->u.ipv4);
                else
-                       LogMsg("HostnameCallback: Error %ld for registration of %##s IP %.16a", result, rr->resrec.name->c, &rr->resrec.rdata->u.ipv6);
+                       LogMsg("HostnameCallback: Error %d for registration of %##s IP %.16a", result, rr->resrec.name->c, &rr->resrec.rdata->u.ipv6);
                if (!hi) { mDNSPlatformMemFree(rr); return; }
                if (rr->state != regState_Unregistered) LogMsg("Error: HostnameCallback invoked with error code for record not in regState_Unregistered!");
 
@@ -3023,9 +3263,9 @@ mDNSlocal void HostnameCallback(mDNS *const m, AuthRecord *const rr, mStatus res
        // Deliver success to client
        if (!hi) { LogMsg("HostnameCallback invoked with orphaned address record"); return; }
        if (rr->resrec.rrtype == kDNSType_A)
-               LogOperation("Registered hostname %##s IP %.4a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv4);
+               LogInfo("Registered hostname %##s IP %.4a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv4);
        else
-               LogOperation("Registered hostname %##s IP %.16a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv6);
+               LogInfo("Registered hostname %##s IP %.16a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv6);
 
        rr->RecordContext = (void *)hi->StatusContext;
        if (hi->StatusCallback)
@@ -3077,10 +3317,9 @@ mDNSlocal void GetStaticHostname(mDNS *m)
        mDNSu8 *ip = m->AdvertisedV4.ip.v4.b;
        mStatus err;
 
-       if (m->ReverseMap.ThisQInterval != -1) mDNS_StopQuery_internal(m, q);
-
-       m->StaticHostname.c[0] = 0;
+       if (m->ReverseMap.ThisQInterval != -1) return; // already running
        if (mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4)) return;
+
        mDNSPlatformMemZero(q, sizeof(*q));
        // 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.", ip[3], ip[2], ip[1], ip[0]);
@@ -3097,6 +3336,7 @@ mDNSlocal void GetStaticHostname(mDNS *m)
        q->QuestionCallback = FoundStaticHostname;
        q->QuestionContext  = mDNSNULL;
 
+       LogInfo("GetStaticHostname: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
        err = mDNS_StartQuery_internal(m, q);
        if (err) LogMsg("Error: GetStaticHostname - StartQuery returned error %d", err);
        }
@@ -3105,7 +3345,7 @@ mDNSexport void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSReco
    {
        HostnameInfo **ptr = &m->Hostnames;
 
-       LogOperation("mDNS_AddDynDNSHostName %##s", fqdn);
+       LogInfo("mDNS_AddDynDNSHostName %##s", fqdn);
 
        while (*ptr && !SameDomainName(fqdn, &(*ptr)->fqdn)) ptr = &(*ptr)->next;
        if (*ptr) { LogMsg("DynDNSHostName %##s already in list", fqdn->c); return; }
@@ -3128,7 +3368,7 @@ mDNSexport void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn)
        {
        HostnameInfo **ptr = &m->Hostnames;
 
-       LogOperation("mDNS_RemoveDynDNSHostName %##s", fqdn);
+       LogInfo("mDNS_RemoveDynDNSHostName %##s", fqdn);
 
        while (*ptr && !SameDomainName(fqdn, &(*ptr)->fqdn)) ptr = &(*ptr)->next;
        if (!*ptr) LogMsg("mDNS_RemoveDynDNSHostName: no such domainname %##s", fqdn->c);
@@ -3139,8 +3379,8 @@ mDNSexport void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn)
                // below could free the memory, and we have to make sure we don't touch hi fields after that.
                mDNSBool f4 = hi->arv4.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv4.state != regState_Unregistered;
                mDNSBool f6 = hi->arv6.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv6.state != regState_Unregistered;
-               if (f4) LogOperation("mDNS_RemoveDynDNSHostName removing v4 %##s", fqdn);
-               if (f6) LogOperation("mDNS_RemoveDynDNSHostName removing v6 %##s", fqdn);
+               if (f4) LogInfo("mDNS_RemoveDynDNSHostName removing v4 %##s", fqdn);
+               if (f6) LogInfo("mDNS_RemoveDynDNSHostName removing v6 %##s", fqdn);
                *ptr = (*ptr)->next; // unlink
                if (f4) mDNS_Deregister_internal(m, &hi->arv4, mDNS_Dereg_normal);
                if (f6) mDNS_Deregister_internal(m, &hi->arv6, mDNS_Dereg_normal);
@@ -3181,26 +3421,26 @@ mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, co
        if (v4Changed || RouterChanged || v6Changed)
                {
                HostnameInfo *i;
-               LogOperation("mDNS_SetPrimaryInterfaceInfo: %s%s%s%#a %#a %#a",
+               LogInfo("mDNS_SetPrimaryInterfaceInfo: %s%s%s%#a %#a %#a",
                        v4Changed     ? "v4Changed "     : "",
                        RouterChanged ? "RouterChanged " : "",
                        v6Changed     ? "v6Changed "     : "", v4addr, v6addr, router);
 
                for (i = m->Hostnames; i; i = i->next)
                        {
-                       LogOperation("mDNS_SetPrimaryInterfaceInfo updating host name registrations for %##s", i->fqdn.c);
+                       LogInfo("mDNS_SetPrimaryInterfaceInfo updating host name registrations for %##s", i->fqdn.c);
        
                        if (i->arv4.resrec.RecordType > kDNSRecordTypeDeregistering &&
                                !mDNSSameIPv4Address(i->arv4.resrec.rdata->u.ipv4, m->AdvertisedV4.ip.v4))
                                {
-                               LogOperation("mDNS_SetPrimaryInterfaceInfo deregistering %s", ARDisplayString(m, &i->arv4));
+                               LogInfo("mDNS_SetPrimaryInterfaceInfo deregistering %s", ARDisplayString(m, &i->arv4));
                                mDNS_Deregister_internal(m, &i->arv4, mDNS_Dereg_normal);
                                }
        
                        if (i->arv6.resrec.RecordType > kDNSRecordTypeDeregistering &&
                                !mDNSSameIPv6Address(i->arv6.resrec.rdata->u.ipv6, m->AdvertisedV6.ip.v6))
                                {
-                               LogOperation("mDNS_SetPrimaryInterfaceInfo deregistering %s", ARDisplayString(m, &i->arv6));
+                               LogInfo("mDNS_SetPrimaryInterfaceInfo deregistering %s", ARDisplayString(m, &i->arv6));
                                mDNS_Deregister_internal(m, &i->arv6, mDNS_Dereg_normal);
                                }
 
@@ -3215,12 +3455,19 @@ mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, co
                        m->retryIntervalGetAddr = NATMAP_INIT_RETRY;
                        m->retryGetAddr         = m->timenow;
                        m->NextScheduledNATOp   = m->timenow;
-                       ClearUPnPState(m);
+                       m->LastNATMapResultCode = NATErr_None;
+#ifdef _LEGACY_NAT_TRAVERSAL_
+                       LNT_ClearState(m);
+#endif // _LEGACY_NAT_TRAVERSAL_
                        }
 
-               UpdateSRVRecords(m);
-               GetStaticHostname(m);   // look up reverse map record to find any static hostnames for our IP address
+               if (m->ReverseMap.ThisQInterval != -1) mDNS_StopQuery_internal(m, &m->ReverseMap);
+               m->StaticHostname.c[0] = 0;
+               
+               UpdateSRVRecords(m); // Will call GetStaticHostname if needed
+               
 #if APPLE_OSX_mDNSResponder
+               if (RouterChanged)      uuid_generate(m->asl_uuid);
                UpdateAutoTunnelDomainStatuses(m);
 #endif
                }
@@ -3303,7 +3550,7 @@ mDNSlocal mStatus checkUpdateResult(mDNS *const m, const domainname *const displ
                }
        else if (rcode == kDNSFlag1_RC_NotAuth)
                {
-               // TSIG errors should come with FmtErr as per RFC 2845, but BIND 9 sends them with NotAuth so we look here too
+               // TSIG errors should come with FormErr as per RFC 2845, but BIND 9 sends them with NotAuth so we look here too
                mStatus tsigerr = ParseTSIGError(m, msg, end, displayname);
                if (!tsigerr)
                        {
@@ -3312,7 +3559,7 @@ mDNSlocal mStatus checkUpdateResult(mDNS *const m, const domainname *const displ
                        }
                else return tsigerr;
                }
-       else if (rcode == kDNSFlag1_RC_FmtErr)
+       else if (rcode == kDNSFlag1_RC_FormErr)
                {
                mStatus tsigerr = ParseTSIGError(m, msg, end, displayname);
                if (!tsigerr)
@@ -3348,11 +3595,11 @@ mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr)
                }
 
        rr->RequireGoodbye = mDNStrue;
-       rr->id = mDNS_NewMessageID(m);
-       InitializeDNSMessage(&m->omsg.h, rr->id, UpdateReqFlags);
+       rr->updateid = mDNS_NewMessageID(m);
+       InitializeDNSMessage(&m->omsg.h, rr->updateid, UpdateReqFlags);
 
        // set zone
-       ptr = putZone(&m->omsg, ptr, end, &rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
+       ptr = putZone(&m->omsg, ptr, end, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
        if (!ptr) { err = mStatus_UnknownErr; goto exit; }
 
        if (rr->state == regState_UpdatePending)
@@ -3377,7 +3624,8 @@ mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr)
 
                else if (rr->resrec.RecordType != kDNSRecordTypeShared)
                        {
-                       ptr = putPrereqNameNotInUse(rr->resrec.name, &m->omsg, ptr, end);
+                       // For now don't do this, until we have the logic for intelligent grouping of individual recors into logical service record sets
+                       //ptr = putPrereqNameNotInUse(rr->resrec.name, &m->omsg, ptr, end);
                        if (!ptr) { err = mStatus_UnknownErr; goto exit; }
                        }
 
@@ -3392,8 +3640,8 @@ mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr)
 
        if (rr->Private)
                {
-               LogOperation("SendRecordRegistration TCP %p %s", rr->tcp, ARDisplayString(m, rr));
-               if (rr->tcp) LogOperation("SendRecordRegistration: Disposing existing TCP connection for %s", ARDisplayString(m, rr));
+               LogInfo("SendRecordRegistration TCP %p %s", rr->tcp, ARDisplayString(m, rr));
+               if (rr->tcp) LogInfo("SendRecordRegistration: Disposing existing TCP connection for %s", ARDisplayString(m, rr));
                if (rr->tcp) DisposeTCPConn(rr->tcp);
                rr->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, mDNSNULL, rr);
                if (!rr->tcp) rr->ThisAPInterval = mDNSPlatformOneSecond * 5; // If failed to make TCP connection, try again in ten seconds (5*2)
@@ -3402,7 +3650,7 @@ mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr)
        else
                {
                err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name));
-               if (err) debugf("ERROR: SendRecordRegistration - mDNSSendDNSMessage - %ld", err);
+               if (err) debugf("ERROR: SendRecordRegistration - mDNSSendDNSMessage - %d", err);
                }
 
        SetRecordRetry(m, rr, err);
@@ -3426,7 +3674,7 @@ mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs,  mSt
        if (m->mDNS_busy != m->mDNS_reentrancy+1)
                LogMsg("hndlServiceUpdateReply: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
-       LogOperation("hndlServiceUpdateReply: err %d state %d %##s", err, srs->state, srs->RR_SRV.resrec.name->c);
+       debugf("hndlServiceUpdateReply: err %d state %d %##s", err, srs->state, srs->RR_SRV.resrec.name->c);
 
        SetRecordRetry(m, &srs->RR_SRV, mStatus_NoError);
 
@@ -3458,7 +3706,7 @@ mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs,  mSt
                        else
                                {
                                //!!!KRS make sure all structs will still get cleaned up when client calls DeregisterService with this state
-                               if (err) LogMsg("Error %ld for registration of service %##s", err, srs->RR_SRV.resrec.name->c);
+                               if (err) LogMsg("Error %d for registration of service %##s", err, srs->RR_SRV.resrec.name->c);
                                else srs->state = regState_Registered;
                                InvokeCallback = mDNStrue;
                                break;
@@ -3466,13 +3714,13 @@ mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs,  mSt
                case regState_Refresh:
                        if (err)
                                {
-                               LogMsg("Error %ld for refresh of service %##s", err, srs->RR_SRV.resrec.name->c);
+                               LogMsg("Error %d for refresh of service %##s", err, srs->RR_SRV.resrec.name->c);
                                InvokeCallback = mDNStrue;
                                }
                        else srs->state = regState_Registered;
                        break;
                case regState_DeregPending:
-                       if (err) LogMsg("Error %ld for deregistration of service %##s", err, srs->RR_SRV.resrec.name->c);
+                       if (err) LogMsg("Error %d for deregistration of service %##s", err, srs->RR_SRV.resrec.name->c);
                        if (srs->SRVChanged)
                                {
                                srs->state = regState_NoTarget; // NoTarget will allow us to pick up new target OR nat traversal state
@@ -3491,7 +3739,7 @@ mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs,  mSt
                case regState_DeregDeferred:
                        if (err)
                                {
-                               debugf("Error %ld received prior to deferred derigstration of %##s", err, srs->RR_SRV.resrec.name->c);
+                               debugf("Error %d received prior to deferred deregistration of %##s", err, srs->RR_SRV.resrec.name->c);
                                err = mStatus_MemFree;
                                InvokeCallback = mDNStrue;
                                srs->state = regState_Unregistered;
@@ -3529,7 +3777,7 @@ mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs,  mSt
                case regState_NATMap:
                case regState_ExtraQueued:
                case regState_NATError:
-                       LogMsg("hndlServiceUpdateReply called for service %##s in unexpected state %d with error %ld.  Unlinking.",
+                       LogMsg("hndlServiceUpdateReply called for service %##s in unexpected state %d with error %d.  Unlinking.",
                                   srs->RR_SRV.resrec.name->c, srs->state, err);
                        err = mStatus_UnknownErr;
                default: LogMsg("hndlServiceUpdateReply: Unknown state %d for %##s", srs->state, srs->RR_SRV.resrec.name->c);
@@ -3537,7 +3785,7 @@ mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs,  mSt
 
        if ((srs->SRVChanged || srs->SRVUpdateDeferred) && (srs->state == regState_NoTarget || srs->state == regState_Registered))
                {
-               LogOperation("hndlServiceUpdateReply: SRVChanged %d SRVUpdateDeferred %d state %d", srs->SRVChanged, srs->SRVUpdateDeferred, srs->state);
+               debugf("hndlServiceUpdateReply: SRVChanged %d SRVUpdateDeferred %d state %d", srs->SRVChanged, srs->SRVUpdateDeferred, srs->state);
                if (InvokeCallback)
                        {
                        srs->ClientCallbackDeferred = mDNStrue;
@@ -3555,7 +3803,7 @@ mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs,  mSt
                        if (srs->state == regState_Registered && !err)
                                {
                                // extra resource record queued for this service - copy zone srs and register
-                               AssignDomainName(&(*e)->r.zone, &srs->zone);
+                               (*e)->r.zone = &srs->zone;
                                (*e)->r.UpdateServer    = srs->SRSUpdateServer;
                                (*e)->r.UpdatePort  = srs->SRSUpdatePort;
                                (*e)->r.uselease = srs->srs_uselease;
@@ -3619,7 +3867,7 @@ mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err)
        if (m->mDNS_busy != m->mDNS_reentrancy+1)
                LogMsg("hndlRecordUpdateReply: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
-       LogOperation("hndlRecordUpdateReply: err %d state %d %s", err, rr->state, ARDisplayString(m, rr));
+       LogInfo("hndlRecordUpdateReply: err %d state %d %s", err, rr->state, ARDisplayString(m, rr));
 
        if (m->SleepState) return;              // If we just sent a deregister on going to sleep, no further action required
 
@@ -3639,7 +3887,7 @@ mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err)
        if (rr->state == regState_DeregPending)
                {
                debugf("Received reply for deregister record %##s type %d", rr->resrec.name->c, rr->resrec.rrtype);
-               if (err) LogMsg("ERROR: Deregistration of record %##s type %d failed with error %ld",
+               if (err) LogMsg("ERROR: Deregistration of record %##s type %d failed with error %d",
                                                rr->resrec.name->c, rr->resrec.rrtype, err);
                err = mStatus_MemFree;
                rr->state = regState_Unregistered;
@@ -3649,7 +3897,7 @@ mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err)
                {
                if (err)
                        {
-                       LogMsg("Cancelling deferred deregistration record %##s type %d due to registration error %ld",
+                       LogMsg("Cancelling deferred deregistration record %##s type %d due to registration error %d",
                                   rr->resrec.name->c, rr->resrec.rrtype, err);
                        rr->state = regState_Unregistered;
                        }
@@ -3675,7 +3923,7 @@ mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err)
                                SendRecordRegistration(m, rr);
                                return;
                                }
-                       LogMsg("hndlRecordUpdateReply: Registration of record %##s type %d failed with error %ld", rr->resrec.name->c, rr->resrec.rrtype, err);
+                       LogMsg("hndlRecordUpdateReply: Registration of record %##s type %d failed with error %d", rr->resrec.name->c, rr->resrec.rrtype, err);
                        return;
                        }
                }
@@ -3725,7 +3973,7 @@ mDNSexport void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interfac
 
        nat_elapsed = AddrReply->upseconds - m->LastNATupseconds;
        our_elapsed = (m->timenow - m->LastNATReplyLocalTime) / mDNSPlatformOneSecond;
-       LogOperation("uDNS_ReceiveNATPMPPacket %X upseconds %u nat_elapsed %d our_elapsed %d", AddrReply->opcode, AddrReply->upseconds, nat_elapsed, our_elapsed);
+       debugf("uDNS_ReceiveNATPMPPacket %X upseconds %u nat_elapsed %d our_elapsed %d", AddrReply->opcode, AddrReply->upseconds, nat_elapsed, our_elapsed);
 
        // We compute a conservative estimate of how much the NAT gateways's clock should have advanced
        // 1. We subtract 12.5% from our own measured elapsed time, to allow for NAT gateways that have an inacurate clock that runs slowly
@@ -3739,22 +3987,39 @@ mDNSexport void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interfac
 
        m->LastNATupseconds      = AddrReply->upseconds;
        m->LastNATReplyLocalTime = m->timenow;
-       ClearUPnPState(m);              // We know this is a NAT-PMP base station, so discard any prior UPnP state
+#ifdef _LEGACY_NAT_TRAVERSAL_
+       LNT_ClearState(m);
+#endif // _LEGACY_NAT_TRAVERSAL_
 
        if (AddrReply->opcode == NATOp_AddrResponse)
                {
+#if APPLE_OSX_mDNSResponder
+               static char msgbuf[16];
+               mDNS_snprintf(msgbuf, sizeof(msgbuf), "%d", AddrReply->err);
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.natpmp.AddressRequest", AddrReply->err ? "failure" : "success", msgbuf, "");
+#endif
                if (!AddrReply->err && len < sizeof(NATAddrReply)) { LogMsg("NAT Traversal AddrResponse message too short (%d bytes)", len); return; }
                natTraversalHandleAddressReply(m, AddrReply->err, AddrReply->ExtAddr);
                }
        else if (AddrReply->opcode == NATOp_MapUDPResponse || AddrReply->opcode == NATOp_MapTCPResponse)
                {
                mDNSu8 Protocol = AddrReply->opcode & 0x7F;
+#if APPLE_OSX_mDNSResponder
+               static char msgbuf[16];
+               mDNS_snprintf(msgbuf, sizeof(msgbuf), "%s - %d", AddrReply->opcode == NATOp_MapUDPResponse ? "UDP" : "TCP", PortMapReply->err);
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.natpmp.PortMapRequest", PortMapReply->err ? "failure" : "success", msgbuf, "");
+#endif
                if (!PortMapReply->err)
                        {
                        if (len < sizeof(NATPortMapReply)) { LogMsg("NAT Traversal PortMapReply message too short (%d bytes)", len); return; }
                        PortMapReply->NATRep_lease = (mDNSu32) ((mDNSu32)pkt[12] << 24 | (mDNSu32)pkt[13] << 16 | (mDNSu32)pkt[14] << 8 | pkt[15]);
                        }
 
+               // Since some NAT-PMP server implementations don't return the requested internal port in
+               // the reply, we can't associate this reply with a particular NATTraversalInfo structure.
+               // We globally keep track of the most recent error code for mappings.
+               m->LastNATMapResultCode = PortMapReply->err;
+               
                for (ptr = m->NATTraversals; ptr; ptr=ptr->next)
                        if (ptr->Protocol == Protocol && mDNSSameIPPort(ptr->IntPort, PortMapReply->intport))
                                natTraversalHandlePortMapReply(m, ptr, InterfaceID, PortMapReply->err, PortMapReply->extport, PortMapReply->NATRep_lease);
@@ -3762,7 +4027,7 @@ mDNSexport void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interfac
        else { LogMsg("Received NAT Traversal response with version unknown opcode 0x%X", AddrReply->opcode); return; }
 
        // Don't need an SSDP socket if we get a NAT-PMP packet
-       if (m->SSDPSocket) { LogOperation("uDNS_ReceiveNATPMPPacket destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
+       if (m->SSDPSocket) { debugf("uDNS_ReceiveNATPMPPacket destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
        }
 
 // <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
@@ -3857,12 +4122,25 @@ mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *c
 
        // 3. Find occurrences of this server in our list, and mark them appropriately
        for (s = m->DNSServers; s; s = s->next)
-               if (mDNSSameAddress(srcaddr, &s->addr) && mDNSSameIPPort(srcport, s->port) && s->teststate != result)
+               {
+               mDNSBool matchaddr = (s->teststate != result && mDNSSameAddress(srcaddr, &s->addr) && mDNSSameIPPort(srcport, s->port));
+               mDNSBool matchid   = (s->teststate == DNSServer_Untested && mDNSSameOpaque16(msg->h.id, s->testid));
+               if (matchaddr || matchid)
                        {
                        DNSQuestion *q;
                        s->teststate = result;
-                       if (result == DNSServer_Passed) LogOperation("DNS Server %#a:%d passed", srcaddr, mDNSVal16(srcport));
-                       else LogMsg("NOTE: Wide-Area Service Discovery disabled to avoid crashing defective DNS relay %#a:%d", srcaddr, mDNSVal16(srcport));
+                       if (result == DNSServer_Passed)
+                               {
+                               LogInfo("DNS Server %#a:%d (%#a:%d) %d passed%s",
+                                       &s->addr, mDNSVal16(s->port), srcaddr, mDNSVal16(srcport), mDNSVal16(s->testid),
+                                       matchaddr ? "" : " NOTE: Reply did not come from address to which query was sent");
+                               }
+                       else
+                               {
+                               LogMsg("NOTE: Wide-Area Service Discovery disabled to avoid crashing defective DNS relay %#a:%d (%#a:%d) %d%s",
+                                       &s->addr, mDNSVal16(s->port), srcaddr, mDNSVal16(srcport), mDNSVal16(s->testid),
+                                       matchaddr ? "" : " NOTE: Reply did not come from address to which query was sent");
+                               }
 
                        // If this server has just changed state from DNSServer_Untested to DNSServer_Passed, then retrigger any waiting questions.
                        // We use the NoTestQuery() test so that we only retrigger questions that were actually blocked waiting for this test to complete.
@@ -3876,6 +4154,7 @@ mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *c
                                                m->NextScheduledQuery = m->timenow;
                                                }
                        }
+               }
 
        return(mDNStrue); // Return mDNStrue to tell uDNS_ReceiveMsg it doesn't need to process this packet further
        }
@@ -3914,7 +4193,7 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS
                                        // There may be a race condition here, if the server decides to drop the connection just as we decide to reuse it
                                        // For now it should not be serious because our normal retry logic (as used to handle UDP packet loss)
                                        // should take care of it but later we may want to look at handling this case explicitly
-                                       LogOperation("uDNS_ReceiveMsg: Using existing TCP connection for %##s (%s)", qptr->qname.c, DNSTypeName(qptr->qtype));
+                                       LogInfo("uDNS_ReceiveMsg: Using existing TCP connection for %##s (%s)", qptr->qname.c, DNSTypeName(qptr->qtype));
                                        mDNS_DropLockBeforeCallback();
                                        tcpCallback(qptr->tcp->sock, qptr->tcp, mDNStrue, mStatus_NoError);
                                        mDNS_ReclaimLockAfterCallback();
@@ -3928,7 +4207,7 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS
                mDNSu32 lease = GetPktLease(m, msg, end);
                mDNSs32 expire = m->timenow + (mDNSs32)lease * mDNSPlatformOneSecond;
 
-               //rcode = kDNSFlag1_RC_SrvErr;  // Simulate server failure (rcode 2)
+               //rcode = kDNSFlag1_RC_ServFail;        // Simulate server failure (rcode 2)
 
                if (CurrentServiceRecordSet)
                        LogMsg("uDNS_ReceiveMsg ERROR CurrentServiceRecordSet already set");
@@ -3958,7 +4237,7 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS
                        {
                        AuthRecord *rptr = m->CurrentRecord;
                        m->CurrentRecord = m->CurrentRecord->next;
-                       if (mDNSSameOpaque16(rptr->id, msg->h.id))
+                       if (AuthRecord_uDNS(rptr) && mDNSSameOpaque16(rptr->updateid, msg->h.id))
                                {
                                err = checkUpdateResult(m, rptr->resrec.name, rcode, msg, end);
                                if (!err && rptr->uselease && lease)
@@ -3998,7 +4277,7 @@ mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q)
        llq.llqlease = q->ReqLease;
 
        InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
-       end = putLLQ(&m->omsg, m->omsg.data, q, &llq, mDNStrue);
+       end = putLLQ(&m->omsg, m->omsg.data, q, &llq);
        if (!end) { LogMsg("sendLLQRefresh: putLLQ failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; }
 
        // Note that we (conditionally) add HINFO and TSIG here, since the question might be going away,
@@ -4014,7 +4293,7 @@ mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q)
 
        if (q->AuthInfo && !q->tcp)
                {
-               LogOperation("sendLLQRefresh setting up new TLS session %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+               LogInfo("sendLLQRefresh setting up new TLS session %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                q->tcp = MakeTCPConn(m, &m->omsg, end, kTCPSocketFlags_UseTLS, &q->servAddr, q->servPort, q, mDNSNULL, mDNSNULL);
                }
        else
@@ -4054,11 +4333,19 @@ mDNSexport void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneI
                q->servPort = zoneInfo->Port;
                q->AuthInfo = zoneInfo->ZonePrivate ? GetAuthInfoForName_internal(m, &q->qname) : mDNSNULL;
                q->ntries = 0;
-               LogOperation("LLQGotZoneData %#a:%d", &q->servAddr, mDNSVal16(q->servPort));
+               debugf("LLQGotZoneData %#a:%d", &q->servAddr, mDNSVal16(q->servPort));
                startLLQHandshake(m, q);
                }
        else
+               {
                StartLLQPolling(m,q);
+               if (err == mStatus_NoSuchNameErr) 
+                       {
+                       // this actually failed, so mark it by setting address to all ones 
+                       q->servAddr.type = mDNSAddrType_IPv4; 
+                       q->servAddr.ip.v4 = onesIPv4Addr; 
+                       }
+               }
 
        mDNS_Unlock(m);
        }
@@ -4068,7 +4355,7 @@ mDNSlocal void PrivateQueryGotZoneData(mDNS *const m, mStatus err, const ZoneDat
        {
        DNSQuestion *q = (DNSQuestion *) zoneInfo->ZoneDataContext;
 
-       LogOperation("PrivateQueryGotZoneData %##s (%s) err %d Zone %##s Private %d", q->qname.c, DNSTypeName(q->qtype), err, zoneInfo->ZoneName.c, zoneInfo->ZonePrivate);
+       LogInfo("PrivateQueryGotZoneData %##s (%s) err %d Zone %##s Private %d", q->qname.c, DNSTypeName(q->qtype), err, zoneInfo->ZoneName.c, zoneInfo->ZonePrivate);
 
        // If we get here it means that the GetZoneData operation has completed, and is is about to cancel
        // its question and free the ZoneData memory. We no longer need to hold onto our pointer (which
@@ -4077,7 +4364,7 @@ mDNSlocal void PrivateQueryGotZoneData(mDNS *const m, mStatus err, const ZoneDat
 
        if (err || !zoneInfo || mDNSAddressIsZero(&zoneInfo->Addr) || mDNSIPPortIsZero(zoneInfo->Port))
                {
-               LogOperation("ERROR: PrivateQueryGotZoneData %##s (%s) invoked with error code %ld %p %#a:%d",
+               LogInfo("ERROR: PrivateQueryGotZoneData %##s (%s) invoked with error code %d %p %#a:%d",
                        q->qname.c, DNSTypeName(q->qtype), err, zoneInfo,
                        zoneInfo ? &zoneInfo->Addr : mDNSNULL,
                        zoneInfo ? mDNSVal16(zoneInfo->Port) : 0);
@@ -4118,6 +4405,7 @@ mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const
        {
        AuthRecord *newRR = (AuthRecord*)zoneData->ZoneDataContext;
        AuthRecord *ptr;
+       int c1, c2;
 
        if (m->mDNS_busy != m->mDNS_reentrancy)
                LogMsg("RecordRegistrationGotZoneData: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
@@ -4135,7 +4423,7 @@ mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const
        // check error/result
        if (err)
                {
-               if (err != mStatus_NoSuchNameErr) LogMsg("RecordRegistrationGotZoneData: error %ld", err);
+               if (err != mStatus_NoSuchNameErr) LogMsg("RecordRegistrationGotZoneData: error %d", err);
                return;
                }
 
@@ -4152,12 +4440,24 @@ mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const
        // organizations use their own private pseudo-TLD, like ".home", etc, and we don't want to block that.
        if (zoneData->ZoneName.c[0] == 0)
                {
-               LogOperation("RecordRegistrationGotZoneData: No name server found claiming responsibility for \"%##s\"!", newRR->resrec.name->c);
+               LogInfo("RecordRegistrationGotZoneData: No name server found claiming responsibility for \"%##s\"!", newRR->resrec.name->c);
                return;
                }
 
        // Store discovered zone data
-       AssignDomainName(&newRR->zone, &zoneData->ZoneName);
+       c1 = CountLabels(newRR->resrec.name);
+       c2 = CountLabels(&zoneData->ZoneName);
+       if (c2 > c1)
+               {
+               LogMsg("RecordRegistrationGotZoneData: Zone \"%##s\" is longer than \"%##s\"", zoneData->ZoneName.c, newRR->resrec.name->c);
+               return;
+               }
+       newRR->zone = SkipLeadingLabels(newRR->resrec.name, c1-c2);
+       if (!SameDomainName(newRR->zone, &zoneData->ZoneName))
+               {
+               LogMsg("RecordRegistrationGotZoneData: Zone \"%##s\" does not match \"%##s\" for \"%##s\"", newRR->zone->c, zoneData->ZoneName.c, newRR->resrec.name->c);
+               return;
+               }
        newRR->UpdateServer = zoneData->Addr;
        newRR->UpdatePort   = zoneData->Port;
        newRR->Private      = zoneData->ZonePrivate;
@@ -4166,7 +4466,7 @@ mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const
 
        if (mDNSIPPortIsZero(zoneData->Port) || mDNSAddressIsZero(&zoneData->Addr))
                {
-               LogOperation("RecordRegistrationGotZoneData: No _dns-update._udp service found for \"%##s\"!", newRR->resrec.name->c);
+               LogInfo("RecordRegistrationGotZoneData: No _dns-update._udp service found for \"%##s\"!", newRR->resrec.name->c);
                return;
                }
 
@@ -4190,9 +4490,9 @@ mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr)
                return;
                }
 
-       InitializeDNSMessage(&m->omsg.h, rr->id, UpdateReqFlags);
+       InitializeDNSMessage(&m->omsg.h, rr->updateid, UpdateReqFlags);
 
-       ptr = putZone(&m->omsg, ptr, end, &rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
+       ptr = putZone(&m->omsg, ptr, end, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
        if (ptr) ptr = putDeletionRecord(&m->omsg, ptr, &rr->resrec);
        if (!ptr)
                {
@@ -4204,8 +4504,8 @@ mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr)
                rr->expire = 0;         // Indicate that we have no active registration any more
                if (rr->Private)
                        {
-                       LogOperation("SendRecordDeregistration TCP %p %s", rr->tcp, ARDisplayString(m, rr));
-                       if (rr->tcp) LogOperation("SendRecordDeregistration: Disposing existing TCP connection for %s", ARDisplayString(m, rr));
+                       LogInfo("SendRecordDeregistration TCP %p %s", rr->tcp, ARDisplayString(m, rr));
+                       if (rr->tcp) LogInfo("SendRecordDeregistration: Disposing existing TCP connection for %s", ARDisplayString(m, rr));
                        if (rr->tcp) DisposeTCPConn(rr->tcp);
                        rr->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, mDNSNULL, rr);
                        if (!rr->tcp) rr->ThisAPInterval = mDNSPlatformOneSecond * 5; // If failed to make TCP connection, try again in ten seconds (5*2)
@@ -4215,7 +4515,7 @@ mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr)
                else
                        {
                        mStatus err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name));
-                       if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %ld", err);
+                       if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %d", err);
                        if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr);          // Don't touch rr after this
                        }
                }
@@ -4255,7 +4555,7 @@ mDNSexport mStatus uDNS_DeregisterService(mDNS *const m, ServiceRecordSet *srs)
        // don't re-register with a new target following deregistration
        srs->SRVChanged = srs->SRVUpdateDeferred = mDNSfalse;
 
-       if (srs->nta) { CancelGetZoneData(m, srs->nta); srs->nta = mDNSNULL; }
+       if (srs->srs_nta) { CancelGetZoneData(m, srs->srs_nta); srs->srs_nta = mDNSNULL; }
 
        if (srs->NATinfo.clientContext)
                {
@@ -4405,26 +4705,9 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
                if (q->unansweredQueries >= MAX_UCAST_UNANSWERED_QUERIES)
                        {
                        DNSServer *orig = q->qDNSServer;
-                       
-#if LogAllOperations || MDNS_DEBUGMSGS
-                       char buffer[1024];
-
-                       mDNS_snprintf(buffer, sizeof(buffer), orig ? "%#a:%d (%##s)" : "null", &orig->addr, mDNSVal16(orig->port), orig->domain.c);
-                       LogOperation("Sent %d unanswered queries for %##s (%s) to %s", q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype), buffer);
-#endif
+                       if (orig) LogInfo("Sent %d unanswered queries for %##s (%s) to %#a:%d (%##s)", q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype), &orig->addr, mDNSVal16(orig->port), orig->domain.c);
 
                        PushDNSServerToEnd(m, q);
-                       q->qDNSServer = GetServerForName(m, &q->qname);
-
-                       if (q->qDNSServer != orig)
-                               {
-#if LogAllOperations || MDNS_DEBUGMSGS
-                               mDNS_snprintf(buffer, sizeof(buffer), q->qDNSServer ? "%#a:%d (%##s)" : "null", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c);
-                               LogOperation("Server for %##s (%s) changed to %s", q->qname.c, DNSTypeName(q->qtype), buffer);
-#endif
-                               q->ThisQInterval = q->ThisQInterval / QuestionIntervalStep; // Decrease interval one step so we don't quickly bounce between servers for queries that will not be answered.
-                               }
-
                        q->unansweredQueries = 0;
                        }
 
@@ -4443,10 +4726,11 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
                                }
                        else if (m->timenow - q->qDNSServer->lasttest >= INIT_UCAST_POLL_INTERVAL)      // Make sure at least three seconds has elapsed since last test query
                                {
-                               LogOperation("Sending DNS test query to %#a:%d", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port));
+                               LogInfo("Sending DNS test query to %#a:%d", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port));
                                q->ThisQInterval = INIT_UCAST_POLL_INTERVAL / QuestionIntervalStep;
                                q->qDNSServer->lasttest = m->timenow;
                                end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, DNSRelayTestQuestion, kDNSType_PTR, kDNSClass_IN);
+                               q->qDNSServer->testid = m->omsg.h.id;
                                }
 
                        if (end > m->omsg.data && (q->qDNSServer->teststate != DNSServer_Failed || NoTestQuery(q)))
@@ -4460,19 +4744,21 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
                                        }
                                else
                                        {
-                                       err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL);
+                                       if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
+                                       if (!q->LocalSocket) err = mStatus_NoMemoryErr; // If failed to make socket (should be very rare), we'll try again next time
+                                       else err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL);
                                        m->SuppressStdPort53Queries = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+99)/100);
                                        }
                                }
 
-                       if (err) debugf("ERROR: uDNS_idle - mDNSSendDNSMessage - %ld", err); // surpress syslog messages if we have no network
+                       if (err) debugf("ERROR: uDNS_idle - mDNSSendDNSMessage - %d", err); // surpress syslog messages if we have no network
                        else
                                {
                                q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep;     // Only increase interval if send succeeded
                                q->unansweredQueries++;
                                if (q->ThisQInterval > MAX_UCAST_POLL_INTERVAL)
                                        q->ThisQInterval = MAX_UCAST_POLL_INTERVAL;
-                               LogOperation("Increased ThisQInterval to %d for %##s (%s)", q->ThisQInterval, q->qname.c, DNSTypeName(q->qtype));
+                               debugf("Increased ThisQInterval to %d for %##s (%s)", q->ThisQInterval, q->qname.c, DNSTypeName(q->qtype));
                                }
                        q->LastQTime = m->timenow;
                        SetNextQueryTime(m, q);
@@ -4495,10 +4781,10 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
                                for (rr = cg->members; rr; rr=rr->next)
                                        if (SameNameRecordAnswersQuestion(&rr->resrec, q)) mDNS_PurgeCacheResourceRecord(m, rr);
 
-                       if (!q->qDNSServer) LogOperation("uDNS_CheckCurrentQuestion no DNS server for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+                       if (!q->qDNSServer) debugf("uDNS_CheckCurrentQuestion no DNS server for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                        else LogMsg("uDNS_CheckCurrentQuestion DNS server %#a:%d for %##s is disabled", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qname.c);
 
-                       MakeNegativeCacheRecord(m, &q->qname, q->qnamehash, q->qtype, q->qclass, 60);
+                       MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any);
                        // Inactivate this question until the next change of DNS servers (do this before AnswerCurrentQuestionWithResourceRecord)
                        q->ThisQInterval = 0;
                        q->unansweredQueries = 0;
@@ -4522,17 +4808,25 @@ mDNSlocal void CheckNATMappings(mDNS *m)
                {
                if (m->NATMcastRecvskt == mDNSNULL)             // If we are behind a NAT and the socket hasn't been opened yet, open it
                        {
+                       // we need to log a message if we can't get our socket, but only the first time (after success)
+                       static mDNSBool needLog = mDNStrue;
                        m->NATMcastRecvskt = mDNSPlatformUDPSocket(m, NATPMPAnnouncementPort);
-                       m->NATMcastRecvsk2 = mDNSPlatformUDPSocket(m, NATPMPPort);      // For backwards compatibility with older base stations that announce on 5351
-                       if (!m->NATMcastRecvskt) LogMsg("CheckNATMappings: Failed to allocate port 5350 UDP multicast socket for NAT-PMP announcements");
-                       if (!m->NATMcastRecvsk2) LogOperation("CheckNATMappings: Failed to allocate port 5351 UDP multicast socket for NAT-PMP announcements");
+                       if (!m->NATMcastRecvskt)
+                               {
+                               if (needLog)
+                                       {
+                                       LogMsg("CheckNATMappings: Failed to allocate port 5350 UDP multicast socket for NAT-PMP announcements");
+                                       needLog = mDNSfalse;
+                                       }
+                               }
+                       else
+                               needLog = mDNStrue;                             
                        }
                }
        else                                                                            // else, we don't want to listen for announcements, so close them if they're open
                {
                if (m->NATMcastRecvskt) { mDNSPlatformUDPClose(m->NATMcastRecvskt); m->NATMcastRecvskt = mDNSNULL; }
-               if (m->NATMcastRecvsk2) { mDNSPlatformUDPClose(m->NATMcastRecvsk2); m->NATMcastRecvsk2 = mDNSNULL; }
-               if (m->SSDPSocket)      { LogOperation("CheckNATMappings destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
+               if (m->SSDPSocket)      { debugf("CheckNATMappings destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
                }
 
        if (m->NATTraversals)
@@ -4612,8 +4906,14 @@ mDNSlocal void CheckNATMappings(mDNS *m)
                                        {
                                        //LogMsg("NAT callback %d %d %d", cur->Protocol, cur->ExpiryTime, cur->retryInterval);
                                        if (cur->Protocol && mDNSIPPortIsZero(ExternalPort) && !mDNSIPv4AddressIsZero(m->Router.ip.v4))
-                                               LogMsg("Failed to obtain NAT port mapping %p from router %#a external address %.4a internal port %d error %d",
-                                                       cur, &m->Router, &m->ExternalAddress, mDNSVal16(cur->IntPort), EffectiveResult);
+                                               {
+                                               if (!EffectiveResult)
+                                                       LogInfo("Failed to obtain NAT port mapping %p from router %#a external address %.4a internal port %5d interval %d error %d",
+                                                               cur, &m->Router, &m->ExternalAddress, mDNSVal16(cur->IntPort), cur->retryInterval, EffectiveResult);
+                                               else
+                                                       LogMsg("Failed to obtain NAT port mapping %p from router %#a external address %.4a internal port %5d interval %d error %d",
+                                                               cur, &m->Router, &m->ExternalAddress, mDNSVal16(cur->IntPort), cur->retryInterval, EffectiveResult);
+                                               }
 
                                        cur->ExternalAddress = m->ExternalAddress;
                                        cur->ExternalPort    = ExternalPort;
@@ -4682,8 +4982,8 @@ mDNSlocal mDNSs32 CheckServiceRegistrations(mDNS *m)
                                if (srs->tcp) { DisposeTCPConn(srs->tcp); srs->tcp = mDNSNULL; }
                                if (srs->state == regState_FetchingZoneData)
                                        {
-                                       if (srs->nta) CancelGetZoneData(m, srs->nta);
-                                       srs->nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs);
+                                       if (srs->srs_nta) CancelGetZoneData(m, srs->srs_nta);
+                                       srs->srs_nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs);
                                        SetRecordRetry(m, &srs->RR_SRV, mStatus_NoError);
                                        }
                                else if (srs->state == regState_DeregPending) SendServiceDeregistration(m, srs);
@@ -4747,8 +5047,8 @@ mDNSexport void SleepServiceRegistrations(mDNS *m)
        ServiceRecordSet *srs = m->ServiceRegistrations;
        while (srs)
                {
-               LogOperation("SleepServiceRegistrations: state %d %s", srs->state, ARDisplayString(m, &srs->RR_SRV));
-               if (srs->nta) { CancelGetZoneData(m, srs->nta); srs->nta = mDNSNULL; }
+               LogInfo("SleepServiceRegistrations: state %d %s", srs->state, ARDisplayString(m, &srs->RR_SRV));
+               if (srs->srs_nta) { CancelGetZoneData(m, srs->srs_nta); srs->srs_nta = mDNSNULL; }
 
                if (srs->NATinfo.clientContext)
                        {
@@ -4790,7 +5090,7 @@ mDNSexport void mDNS_AddSearchDomain(const domainname *const domain)
                        {
                        // If domain is already in list, and marked for deletion, change it to "leave alone"
                        if ((*p)->flag == -1) (*p)->flag = 0;
-                       LogOperation("mDNS_AddSearchDomain already in list %##s", domain->c);
+                       LogInfo("mDNS_AddSearchDomain already in list %##s", domain->c);
                        return;
                        }
 
@@ -4801,7 +5101,7 @@ mDNSexport void mDNS_AddSearchDomain(const domainname *const domain)
        AssignDomainName(&(*p)->domain, domain);
        (*p)->flag = 1; // add
        (*p)->next = mDNSNULL;
-       LogOperation("mDNS_AddSearchDomain created new %##s", domain->c);
+       LogInfo("mDNS_AddSearchDomain created new %##s", domain->c);
        }
 
 mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
@@ -4814,26 +5114,30 @@ mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceR
        {
        SearchListElem *slElem = question->QuestionContext;
        mStatus err;
+       const char *name;
 
        if (answer->rrtype != kDNSType_PTR) return;
        if (answer->RecordType == kDNSRecordTypePacketNegative) return;
+       if (answer->InterfaceID == mDNSInterface_LocalOnly) return;
+
+       if      (question == &slElem->BrowseQ)          name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowse];
+       else if (question == &slElem->DefBrowseQ)       name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseDefault];
+       else if (question == &slElem->AutomaticBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseAutomatic];
+       else if (question == &slElem->RegisterQ)        name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistration];
+       else if (question == &slElem->DefRegisterQ)     name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistrationDefault];
+       else { LogMsg("FoundDomain - unknown question"); return; }
+
+       LogInfo("FoundDomain: %p %s %s Q %##s A %s", answer->InterfaceID, AddRecord ? "Add" : "Rmv", name, question->qname.c, RRDisplayString(m, answer));
 
        if (AddRecord)
                {
-               const char *name;
                ARListElem *arElem = mDNSPlatformMemAllocate(sizeof(ARListElem));
-               if (!arElem) { LogMsg("ERROR: malloc"); return; }
+               if (!arElem) { LogMsg("ERROR: FoundDomain out of memory"); return; }
                mDNS_SetupResourceRecord(&arElem->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, arElem);
-               if      (question == &slElem->BrowseQ)          name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowse];
-               else if (question == &slElem->DefBrowseQ)       name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseDefault];
-               else if (question == &slElem->AutomaticBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseAutomatic];
-               else if (question == &slElem->RegisterQ)        name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistration];
-               else if (question == &slElem->DefRegisterQ)     name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistrationDefault];
-               else { LogMsg("FoundDomain - unknown question"); mDNSPlatformMemFree(arElem); return; }
-
                MakeDomainNameFromDNSNameString(&arElem->ar.namestorage, name);
                AppendDNSNameString            (&arElem->ar.namestorage, "local");
                AssignDomainName(&arElem->ar.resrec.rdata->u.name, &answer->rdata->u.name);
+               LogInfo("FoundDomain: Registering %s", ARDisplayString(m, &arElem->ar));
                err = mDNS_Register(m, &arElem->ar);
                if (err) { LogMsg("ERROR: FoundDomain - mDNS_Register returned %d", err); mDNSPlatformMemFree(arElem); return; }
                arElem->next = slElem->AuthRecs;
@@ -4848,7 +5152,7 @@ mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceR
                                {
                                ARListElem *dereg = *ptr;
                                *ptr = (*ptr)->next;
-                               debugf("Deregistering PTR %##s -> %##s", dereg->ar.resrec.name->c, dereg->ar.resrec.rdata->u.name.c);
+                               LogInfo("FoundDomain: Deregistering %s", ARDisplayString(m, &dereg->ar));
                                err = mDNS_Deregister(m, &dereg->ar);
                                if (err) LogMsg("ERROR: FoundDomain - mDNS_Deregister returned %d", err);
                                // Memory will be freed in the FreeARElemCallback
@@ -4917,18 +5221,22 @@ mDNSexport mStatus uDNS_RegisterSearchDomains(mDNS *const m)
        while (*p)
                {
                ptr = *p;
-               debugf("RegisterSearchDomains %d %p %##s", ptr->flag, ptr->AuthRecs, ptr->domain.c);
+               LogInfo("RegisterSearchDomains %d %p %##s", ptr->flag, ptr->AuthRecs, ptr->domain.c);
                if (ptr->flag == -1)    // remove
                        {
                        ARListElem *arList = ptr->AuthRecs;
                        ptr->AuthRecs = mDNSNULL;
                        *p = ptr->next;
 
-                       mDNS_StopGetDomains(m, &ptr->BrowseQ);
-                       mDNS_StopGetDomains(m, &ptr->RegisterQ);
-                       mDNS_StopGetDomains(m, &ptr->DefBrowseQ);
-                       mDNS_StopGetDomains(m, &ptr->DefRegisterQ);
-                       mDNS_StopGetDomains(m, &ptr->AutomaticBrowseQ);
+                       // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries
+                       if (!SameDomainName(&ptr->domain, &localdomain))
+                               {
+                               mDNS_StopGetDomains(m, &ptr->BrowseQ);
+                               mDNS_StopGetDomains(m, &ptr->RegisterQ);
+                               mDNS_StopGetDomains(m, &ptr->DefBrowseQ);
+                               mDNS_StopGetDomains(m, &ptr->DefRegisterQ);
+                               mDNS_StopGetDomains(m, &ptr->AutomaticBrowseQ);
+                               }
                        mDNSPlatformMemFree(ptr);
 
                // deregister records generated from answers to the query
@@ -4946,20 +5254,24 @@ mDNSexport mStatus uDNS_RegisterSearchDomains(mDNS *const m)
 
                if (ptr->flag == 1)     // add
                        {
-                       mStatus err1, err2, err3, err4, err5;
-                       err1 = mDNS_GetDomains(m, &ptr->BrowseQ,          mDNS_DomainTypeBrowse,              &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
-                       err2 = mDNS_GetDomains(m, &ptr->DefBrowseQ,       mDNS_DomainTypeBrowseDefault,       &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
-                       err3 = mDNS_GetDomains(m, &ptr->RegisterQ,        mDNS_DomainTypeRegistration,        &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
-                       err4 = mDNS_GetDomains(m, &ptr->DefRegisterQ,     mDNS_DomainTypeRegistrationDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
-                       err5 = mDNS_GetDomains(m, &ptr->AutomaticBrowseQ, mDNS_DomainTypeBrowseAutomatic,     &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
-                       if (err1 || err2 || err3 || err4 || err5)
-                               LogMsg("GetDomains for domain %##s returned error(s):\n"
-                                          "%d (mDNS_DomainTypeBrowse)\n"
-                                          "%d (mDNS_DomainTypeBrowseDefault)\n"
-                                          "%d (mDNS_DomainTypeRegistration)\n"
-                                          "%d (mDNS_DomainTypeRegistrationDefault)"
-                                          "%d (mDNS_DomainTypeBrowseAutomatic)\n",
-                                          ptr->domain.c, err1, err2, err3, err4, err5);
+                       // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries
+                       if (!SameDomainName(&ptr->domain, &localdomain))
+                               {
+                               mStatus err1, err2, err3, err4, err5;
+                               err1 = mDNS_GetDomains(m, &ptr->BrowseQ,          mDNS_DomainTypeBrowse,              &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+                               err2 = mDNS_GetDomains(m, &ptr->DefBrowseQ,       mDNS_DomainTypeBrowseDefault,       &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+                               err3 = mDNS_GetDomains(m, &ptr->RegisterQ,        mDNS_DomainTypeRegistration,        &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+                               err4 = mDNS_GetDomains(m, &ptr->DefRegisterQ,     mDNS_DomainTypeRegistrationDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+                               err5 = mDNS_GetDomains(m, &ptr->AutomaticBrowseQ, mDNS_DomainTypeBrowseAutomatic,     &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+                               if (err1 || err2 || err3 || err4 || err5)
+                                       LogMsg("GetDomains for domain %##s returned error(s):\n"
+                                                  "%d (mDNS_DomainTypeBrowse)\n"
+                                                  "%d (mDNS_DomainTypeBrowseDefault)\n"
+                                                  "%d (mDNS_DomainTypeRegistration)\n"
+                                                  "%d (mDNS_DomainTypeRegistrationDefault)"
+                                                  "%d (mDNS_DomainTypeBrowseAutomatic)\n",
+                                                  ptr->domain.c, err1, err2, err3, err4, err5);
+                               }
                        ptr->flag = 0;
                        }
 
@@ -4987,5 +5299,5 @@ struct CompileTimeAssertionChecks_uDNS
        // other overly-large structures instead of having a pointer to them, can inadvertently
        // cause structure sizes (and therefore memory usage) to balloon unreasonably.
        char sizecheck_tcpInfo_t     [(sizeof(tcpInfo_t)      <=  9056) ? 1 : -1];
-       char sizecheck_SearchListElem[(sizeof(SearchListElem) <=  3880) ? 1 : -1];
+       char sizecheck_SearchListElem[(sizeof(SearchListElem) <=  3920) ? 1 : -1];
        };
index 3a66ab6edbbf0a3319c396860b375853ac79125f..71f40975b8c5090fdc02c10a48d13a1a93b2ac50 100755 (executable)
     Change History (most recent first):
 
 $Log: uDNS.h,v $
+Revision 1.93  2008/09/24 23:48:05  cheshire
+Don't need to pass whole ServiceRecordSet reference to GetServiceTarget;
+it only needs to access the embedded SRV member of the set
+
 Revision 1.92  2008/06/19 23:42:03  mcguire
 <rdar://problem/4206534> Use all configured DNS servers
 
@@ -274,7 +278,7 @@ extern void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const Zone
 extern mStatus uDNS_DeregisterRecord(mDNS *const m, AuthRecord *const rr);
 
 extern void ServiceRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *result);
-extern const domainname *GetServiceTarget(mDNS *m, ServiceRecordSet *srs);
+extern const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr);
 extern mStatus uDNS_DeregisterService(mDNS *const m, ServiceRecordSet *srs);
 
 extern void uDNS_CheckCurrentQuestion(mDNS *const m);
index cc141734cca480d4ac917a13bbb30a9870f93fa9..1cf014c471e5d1f33e0495ff907aad21844eee87 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: Mac\040OS\040Test\040Responder.c,v $
+Revision 1.26  2008/11/04 19:43:35  cheshire
+Updated comment about MAX_ESCAPED_DOMAIN_NAME size (should be 1009, not 1005)
+
 Revision 1.25  2006/08/14 23:24:29  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -45,7 +48,7 @@ Change to use mDNSOpaque16fromIntVal/mDNSVal16 instead of shifting and masking
 
 Revision 1.18  2003/11/14 21:27:08  cheshire
 <rdar://problem/3484766>: Security: Crashing bug in mDNSResponder
-Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers.
+Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1009) instead of 256-byte buffers.
 
 Revision 1.17  2003/08/14 02:19:54  cheshire
 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
index 4f282dcb93351e1733b18483a5c863bf97d83a72..ca370516c7a48305c283c39562778d2c0175a29b 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: Mac\040OS\040Test\040Searcher.c,v $
+Revision 1.24  2008/11/04 19:43:35  cheshire
+Updated comment about MAX_ESCAPED_DOMAIN_NAME size (should be 1009, not 1005)
+
 Revision 1.23  2007/07/27 19:30:40  cheshire
 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
 to properly reflect tri-state nature of the possible responses
@@ -53,7 +56,7 @@ Change to use mDNSOpaque16fromIntVal/mDNSVal16 instead of shifting and masking
 
 Revision 1.14  2003/11/14 21:27:09  cheshire
 <rdar://problem/3484766>: Security: Crashing bug in mDNSResponder
-Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers.
+Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1009) instead of 256-byte buffers.
 
 Revision 1.13  2003/08/14 02:19:54  cheshire
 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
index 1f701f5d49f2c983348800f3bb3b0aa28a0457fc..1dea7f9819f5dd7fc7804bc673b49c2f953ceea5 100644 (file)
@@ -635,13 +635,13 @@ kern_return_t internal_DNSServiceResolverReply_rpc
     if (interface) {
         int len = ((struct sockaddr *)interface)->sa_len;
         interface_storage = (struct sockaddr *)malloc(len);
-        bcopy(interface, interface_storage,len);
+        memcpy(interface_storage, interface, len);
     }
 
     if (address) {
         int len = ((struct sockaddr *)address)->sa_len;
         address_storage = (struct sockaddr *)malloc(len);
-        bcopy(address, address_storage, len);
+        memcpy(address_storage, address, len);
     }
 
     pthread_mutex_lock(&a_requests_lock);
index 37cb38d2ffcdc03c6839305b4a901038f1542d6a..e31b391f8f5f0a44c30d8ce2043536e1a66e64db 100644 (file)
@@ -13,7 +13,5 @@
                <string>/usr/sbin/dnsextd</string>
                <string>-launchd</string>
        </array>
-       <key>ServiceIPC</key>
-       <false/>
 </dict>
 </plist>
index cb01007a7efde28f3c4631080b94a662b91e5091..edf5d064d9798073c761c7aae42a539faab2ca9a 100644 (file)
@@ -6,8 +6,6 @@
   <string>com.apple.mDNSResponderHelper</string>
   <key>OnDemand</key>
   <true/>
-  <key>HopefullyExitsLast</key>
-  <true/>
   <key>ProgramArguments</key>
   <array>
     <string>/usr/sbin/mDNSResponderHelper</string>
@@ -17,7 +15,7 @@
     <key>com.apple.mDNSResponderHelper</key>
     <true/>
   </dict>
-  <key>ServiceIPC</key>
+  <key>EnableTransactions</key>
   <true/>
 </dict>
 </plist>
index a36f31db57e664fc621b886aa4dd6ece70ddeadd..c81682f9120070f4217199651c3ad08e4905d257 100644 (file)
@@ -6,8 +6,6 @@
        <string>com.apple.mDNSResponder</string>
        <key>OnDemand</key>
        <false/>
-       <key>HopefullyExitsFirst</key>
-       <true/>
        <key>UserName</key>
        <string>_mdnsresponder</string>
        <key>GroupName</key>
@@ -34,7 +32,7 @@
                        <integer>438</integer>
                </dict>
        </dict>
-       <key>ServiceIPC</key>
+       <key>EnableTransactions</key>
        <true/>
 </dict>
 </plist>
index d833ca93d282697d95d182d6353032027bb2ca9f..5cf1ae1347aabf5f376828b7304c1c363704dc16 100644 (file)
     Change History (most recent first):
 
 $Log: LegacyNATTraversal.c,v $
-Revision 1.48.2.1  2008/09/30 18:03:03  mcguire
+Revision 1.65  2009/07/03 03:16:07  jessic2
+<rdar://problem/7026146> BTMM: UPnP works in Leopard but doesn't work in SnowLeopard (URLBase is empty) Made changes to support the case where the URLBase tag exists but there isn't a valid URL
+
+Revision 1.64  2009/06/25 21:07:44  herscher
+<rdar://problem/4147784> B4W should support UPnP
+
+Revision 1.63  2009/03/26 03:59:00  jessic2
+Changes for <rdar://problem/6492552&6492593&6492609&6492613&6492628&6492640&6492699>
+
+Revision 1.62  2009/02/13 06:31:09  cheshire
+Converted LogOperation messages to LogInfo
+
+Revision 1.61  2009/01/23 19:25:43  mcguire
+<rdar://problem/6514439> UPnP: Should not use NATErr_Refused when too many conflict retries
+
+Revision 1.60  2009/01/23 00:38:36  mcguire
+<rdar://problem/5570906> BTMM: Doesn't work with Linksys WRT54GS firmware 4.71.1
+
+Revision 1.59  2009/01/22 20:32:17  mcguire
+<rdar://problem/6446934> BTMM: pref pane reports enabled but negotiation failed
+Make sure we push the pointer out past the LF if we read it.
+
+Revision 1.58  2009/01/22 01:15:58  mcguire
+<rdar://problem/6446934> BTMM: pref pane reports enabled but negotiation failed
+
+Revision 1.57  2008/12/19 21:09:22  mcguire
+<rdar://problem/6431147> UPnP: error messages when canceling seemingly unrelated browse
+
+Revision 1.56  2008/12/06 01:42:57  mcguire
+<rdar://problem/6418958> Need to exponentially back-off after failure to get public address
+
+Revision 1.55  2008/12/01 19:43:48  mcguire
+<rdar://problem/6404766> UPnP: Handle errorCode 718 as a conflict when requesting a port mapping
+
+Revision 1.54  2008/11/26 20:57:37  cheshire
+For consistency with other similar macros, renamed mdnsIsDigit/mdnsIsLetter/mdnsValidHostChar
+to mDNSIsDigit/mDNSIsLetter/mDNSValidHostChar
+
+Revision 1.53  2008/11/26 20:34:04  cheshire
+Changed "destroying SSDPSocket" LogOperation debugging messages to debugf
+
+Revision 1.52  2008/11/26 19:54:03  cheshire
+Changed some "LogOperation" debugging messages to "debugf"
+
+Revision 1.51  2008/11/20 02:23:38  mcguire
+<rdar://problem/6041208> need to handle URLBase
+
+Revision 1.50  2008/09/20 00:34:22  mcguire
 <rdar://problem/6129039> BTMM: Add support for WANPPPConnection
 
+Revision 1.49  2008/08/07 21:51:13  mcguire
+<rdar://problem/5904423> UPnP: Possible memory corruption bug
+<rdar://problem/5930173> UPnP: Combine URL parsing code
+
 Revision 1.48  2008/07/24 20:23:04  cheshire
 <rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
 
@@ -183,7 +234,34 @@ Revision 1.1  2004/08/18 17:35:41  ksekar
 
 #include "stdlib.h"                    // For strtol()
 #include "string.h"                    // For strlcpy(), For strncpy(), strncasecmp()
-#include <arpa/inet.h>         // For inet_pton()
+
+#if defined( WIN32 )
+#      include <winsock2.h>
+#      include <ws2tcpip.h>
+#      define strcasecmp       _stricmp
+#      define strncasecmp      _strnicmp
+#      define mDNSASLLog( UUID, SUBDOMAIN, RESULT, SIGNATURE, FORMAT, ... ) ;
+
+static int
+inet_pton( int family, const char * addr, void * dst )
+       {
+       struct sockaddr_storage ss;
+       int sslen = sizeof( ss );
+
+       ZeroMemory( &ss, sizeof( ss ) );
+       ss.ss_family = family;
+
+       if ( WSAStringToAddressA( addr, family, NULL, ( struct sockaddr* ) &ss, &sslen ) == 0 )
+               {
+               if ( family == AF_INET ) { memcpy( dst, &( ( struct sockaddr_in* ) &ss)->sin_addr, sizeof( IN_ADDR ) ); return 1; }
+               else if ( family == AF_INET6 ) { memcpy( dst, &( ( struct sockaddr_in6* ) &ss)->sin6_addr, sizeof( IN6_ADDR ) ); return 1; }
+               else return 0;
+               }
+       else return 0;
+       }
+#else
+#      include <arpa/inet.h>           // For inet_pton()
+#endif
 
 #include "mDNSEmbeddedAPI.h"
 #include "uDNS.h"                      // For natTraversalHandleAddressReply() etc.
@@ -214,6 +292,116 @@ mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n);
 
 #define RequestedPortNum(n) (mDNSVal16(mDNSIPPortIsZero((n)->RequestedPort) ? (n)->IntPort : (n)->RequestedPort) + (n)->tcpInfo.retries)
 
+// Note that this function assumes src is already NULL terminated
+mDNSlocal void AllocAndCopy(mDNSu8** dst, mDNSu8* src)
+       {
+       if (src == mDNSNULL) return;
+       if ((*dst = (mDNSu8 *) mDNSPlatformMemAllocate(strlen((char*)src) + 1)) == mDNSNULL) { LogMsg("AllocAndCopy: can't allocate string"); return; }
+       strcpy((char *)*dst, (char*)src);
+       }
+
+// This function does a simple parse of an HTTP URL that may include a hostname, port, and path
+// If found in the URL, addressAndPort and path out params will point to newly allocated space (and will leak if they were previously pointing at allocated space)
+mDNSlocal mStatus ParseHttpUrl(char* ptr, char* end, mDNSu8** addressAndPort, mDNSIPPort* port, mDNSu8** path)
+       {
+       // if the data begins with "http://", we assume there is a hostname and possibly a port number
+       if (end - ptr >= 7 && strncasecmp(ptr, "http://", 7) == 0)
+               {
+               int  i;
+               char* stop = end;
+               char* addrPtr = mDNSNULL;
+               
+               ptr += 7; //skip over "http://"
+               if (ptr >= end) { LogInfo("ParseHttpUrl: past end of buffer parsing host:port"); return mStatus_BadParamErr; }
+               
+               // find the end of the host:port
+               addrPtr = ptr;
+               for (i = 0; addrPtr && addrPtr != end; i++, addrPtr++) if (*addrPtr == '/') break;
+
+               // allocate the buffer (len i+1 so we have space to terminate the string)
+               if ((*addressAndPort = (mDNSu8 *) mDNSPlatformMemAllocate(i+1)) == mDNSNULL) { LogMsg("ParseHttpUrl: can't allocate address string"); return mStatus_NoMemoryErr; }
+               strncpy((char *)*addressAndPort, ptr, i);
+               (*addressAndPort)[i] = '\0';
+
+               // find the port number in the string, by looking backwards for the ':'
+               stop = ptr;    // can't go back farther than the original start
+               ptr = addrPtr; // move ptr to the path part
+               
+               for (addrPtr--;addrPtr>stop;addrPtr--)
+                       {
+                       if (*addrPtr == ':')
+                               {
+                               int tmpport;
+                               addrPtr++; // skip over ':'
+                               tmpport = (int)strtol(addrPtr, mDNSNULL, 10);
+                               *port = mDNSOpaque16fromIntVal(tmpport); // store it properly converted
+                               break;
+                               }
+                       }
+               }
+               
+       // ptr should now point to the first character we haven't yet processed
+       // everything that remains is the path
+       if (path && ptr < end)
+               {
+               if ((*path = (mDNSu8 *)mDNSPlatformMemAllocate(end - ptr + 1)) == mDNSNULL) { LogMsg("ParseHttpUrl: can't mDNSPlatformMemAllocate path"); return mStatus_NoMemoryErr; }
+               strncpy((char *)*path, ptr, end - ptr);
+               (*path)[end - ptr] = '\0';
+               }
+               
+       return mStatus_NoError;
+       }
+
+enum
+       {
+       HTTPCode_NeedMoreData = -1, // No code found in stream
+       HTTPCode_Other        = -2, // Valid code other than those below found in stream
+       HTTPCode_Bad          = -3,
+       HTTPCode_200          = 200,
+       HTTPCode_404          = 404,
+       HTTPCode_500          = 500,
+       };
+       
+mDNSlocal mDNSs16 ParseHTTPResponseCode(mDNSu8** data, mDNSu8* end)
+       {
+       mDNSu8* ptr = *data;
+       char * code;
+       
+       if (end - ptr < 5) return HTTPCode_NeedMoreData;
+       if (strncasecmp((char*)ptr, "HTTP/", 5) != 0) return HTTPCode_Bad;
+       ptr += 5;
+       // should we care about the HTTP protocol version?
+       
+       // look for first space, which must come before first LF
+       while (ptr && ptr != end)
+               {
+               if (*ptr == '\n') return HTTPCode_Bad;
+               if (*ptr == ' ') break;
+               ptr++;
+               }
+       if (ptr == end) return HTTPCode_NeedMoreData;
+       ptr++;
+       
+       if (end - ptr < 3) return HTTPCode_NeedMoreData;
+
+       code = (char*)ptr;
+       ptr += 3;
+       while (ptr && ptr != end)
+               {
+               if (*ptr == '\n') break;
+               ptr++;
+               }
+       if (ptr == end) return HTTPCode_NeedMoreData;
+       *data = ++ptr;
+       
+       if (memcmp(code, "200", 3) == 0) return HTTPCode_200;
+       if (memcmp(code, "404", 3) == 0) return HTTPCode_404;
+       if (memcmp(code, "500", 3) == 0) return HTTPCode_500;
+       
+       LogInfo("ParseHTTPResponseCode found unexpected result code: %c%c%c", code[0], code[1], code[2]);
+       return HTTPCode_Other;
+       }
+
 // This function parses the xml body of the device description response from the router. Basically, we look to make sure this is a response
 // referencing a service we care about (WANIPConnection or WANPPPConnection), look for the "controlURL" header immediately following, and copy the addressing and URL info we need
 mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo)
@@ -222,12 +410,23 @@ mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo)
        char    *ptr  = (char *)tcpInfo->Reply;
        char    *end  = (char *)tcpInfo->Reply + tcpInfo->nread;
        char    *stop = mDNSNULL;
+       mDNSs16 http_result;
+       
+       if (!mDNSIPPortIsZero(m->UPnPSOAPPort)) return; // already have the info we need
+
+       http_result = ParseHTTPResponseCode((mDNSu8**)&ptr, (mDNSu8*)end); // Note: modifies ptr
+       if (http_result == HTTPCode_404) LNT_ClearState(m);
+       if (http_result != HTTPCode_200) 
+               {
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "noop", "HTTP Result", "HTTP code: %d", http_result);
+               return;
+               }
 
        // Always reset our flag to use WANIPConnection.  We'll use WANPPPConnection if we find it and don't find WANIPConnection.
        m->UPnPWANPPPConnection = mDNSfalse;
 
        // find either service we care about
-       while (ptr && ptr != end)
+       while (ptr && ptr < end)
                {
                if (*ptr == 'W' && (strncasecmp(ptr, "WANIPConnection:1", 17) == 0)) break;
                ptr++;
@@ -235,7 +434,7 @@ mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo)
        if (ptr == end)
                {
                ptr = (char *)tcpInfo->Reply;
-               while (ptr && ptr != end)
+               while (ptr && ptr < end)
                        {
                        if (*ptr == 'W' && (strncasecmp(ptr, "WANPPPConnection:1", 18) == 0))
                                {
@@ -245,79 +444,69 @@ mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo)
                        ptr++;
                        }
                }
-       if (ptr == mDNSNULL || ptr == end) { LogOperation("handleLNTDeviceDescriptionResponse: didn't find WANIPConnection:1 or WANPPPConnection:1 string"); return; }
+       if (ptr == mDNSNULL || ptr == end) { LogInfo("handleLNTDeviceDescriptionResponse: didn't find WANIPConnection:1 or WANPPPConnection:1 string"); return; }
 
        // find "controlURL", starting from where we left off
-       while (ptr && ptr != end)
+       while (ptr && ptr < end)
                {
                if (*ptr == 'c' && (strncasecmp(ptr, "controlURL", 10) == 0)) break;                    // find the first 'c'; is this controlURL? if not, keep looking
                ptr++;
                }
-       if (ptr == mDNSNULL || ptr == end) { LogOperation("handleLNTDeviceDescriptionResponse: didn't find controlURL string"); return; }
+       if (ptr == mDNSNULL || ptr == end) { LogInfo("handleLNTDeviceDescriptionResponse: didn't find controlURL string"); return; }
        ptr += 11;                                                      // skip over "controlURL>"
-       if (ptr >= end) { LogOperation("handleLNTDeviceDescriptionResponse: past end of buffer and no body!"); return; } // check ptr again in case we skipped over the end of the buffer
+       if (ptr >= end) { LogInfo("handleLNTDeviceDescriptionResponse: past end of buffer and no body!"); return; } // check ptr again in case we skipped over the end of the buffer
 
        // find the end of the controlURL element
-       for (stop = ptr; stop != end; stop++) { if (*stop == '<') { end = stop; break; } }
+       for (stop = ptr; stop < end; stop++) { if (*stop == '<') { end = stop; break; } }
 
        // fill in default port
        m->UPnPSOAPPort = m->UPnPRouterPort;
 
-       // is there an address string "http://"?
-       if (strncasecmp(ptr, "http://", 7) == 0)
+       // free string pointers and set to NULL 
+       if (m->UPnPSOAPAddressString != mDNSNULL)
                {
-               int  i;
-               char *addrPtr = mDNSNULL;
-               
-               ptr += 7;                                               //skip over "http://"
-               if (ptr >= end) { LogOperation("handleLNTDeviceDescriptionResponse: past end of buffer and no URL!"); return; }
-               addrPtr = ptr;
-               for (i = 0; addrPtr && addrPtr != end; i++, addrPtr++) if (*addrPtr == '/') break; // first find the beginning of the URL and count the chars
-               if (addrPtr == mDNSNULL || addrPtr == end) { LogOperation("handleLNTDeviceDescriptionResponse: didn't find SOAP address string"); return; }
+               mDNSPlatformMemFree(m->UPnPSOAPAddressString);
+               m->UPnPSOAPAddressString = mDNSNULL;
+               }
+       if (m->UPnPSOAPURL != mDNSNULL)
+               {
+               mDNSPlatformMemFree(m->UPnPSOAPURL);
+               m->UPnPSOAPURL = mDNSNULL; 
+               }
+       
+       if (ParseHttpUrl(ptr, end, &m->UPnPSOAPAddressString, &m->UPnPSOAPPort, &m->UPnPSOAPURL) != mStatus_NoError) return;
+       // the SOAPURL should look something like "/uuid:0013-108c-4b3f0000f3dc"
 
-               // allocate the buffer (len i+1 so we have space to terminate the string)
-               if (m->UPnPSOAPAddressString != mDNSNULL)  mDNSPlatformMemFree(m->UPnPSOAPAddressString);
-               if ((m->UPnPSOAPAddressString = (mDNSu8 *) mDNSPlatformMemAllocate(i+1)) == mDNSNULL) { LogMsg("can't allocate SOAP address string"); return; }
-               
-               strncpy((char *)m->UPnPSOAPAddressString, ptr, i);                              // copy the address string
-               m->UPnPSOAPAddressString[i] = '\0';                                                             // terminate the string
-               
-               stop = ptr; // remember where to stop (just after "http://")
-               ptr = addrPtr; // move ptr past the rest of what we just processed
-               
-               // find the port number in the string
-               for (addrPtr--;addrPtr>stop;addrPtr--)
+       if (m->UPnPSOAPAddressString == mDNSNULL)
+               {
+               ptr = (char *)tcpInfo->Reply;
+               while (ptr && ptr < end)
                        {
-                       if (*addrPtr == ':')
+                       if (*ptr == 'U' && (strncasecmp(ptr, "URLBase", 7) == 0))               break;
+                       ptr++;
+                       }
+
+               if (ptr < end)          // found URLBase
+                       {
+                       LogInfo("handleLNTDeviceDescriptionResponse: found URLBase");                   
+                       ptr += 8; // skip over "URLBase>"
+                       // find the end of the URLBase element
+                       for (stop = ptr; stop < end; stop++) { if (*stop == '<') { end = stop; break; } }
+                       if (ParseHttpUrl(ptr, end, &m->UPnPSOAPAddressString, &m->UPnPSOAPPort, mDNSNULL) != mStatus_NoError)
                                {
-                               int port;
-                               addrPtr++; // skip over ':'
-                               port = (int)strtol(addrPtr, mDNSNULL, 10);
-                               m->UPnPSOAPPort = mDNSOpaque16fromIntVal(port);         // store it properly converted
-                               break;
+                               LogInfo("handleLNTDeviceDescriptionResponse: failed to parse URLBase");
                                }
                        }
-               }
-
-       if (m->UPnPSOAPAddressString == mDNSNULL) m->UPnPSOAPAddressString = m->UPnPRouterAddressString; // just copy the pointer, don't allocate more memory
-       LogOperation("handleLNTDeviceDescriptionResponse: SOAP address string [%s]", m->UPnPSOAPAddressString);
-
-       // ptr should now point to the first character we haven't yet processed
-       if (ptr != end)
-               {
-               // allocate the buffer
-               if (m->UPnPSOAPURL != mDNSNULL) mDNSPlatformMemFree(m->UPnPSOAPURL);
-               if ((m->UPnPSOAPURL = (mDNSu8 *)mDNSPlatformMemAllocate(end - ptr + 1)) == mDNSNULL) { LogMsg("can't mDNSPlatformMemAllocate SOAP URL"); return; }
                
-               // now copy
-               strncpy((char *)m->UPnPSOAPURL, ptr, end - ptr); // this URL looks something like "/uuid:0013-108c-4b3f0000f3dc"
-               m->UPnPSOAPURL[end - ptr] = '\0';                                // terminate the string
+               // if all else fails, use the router address string
+               if (m->UPnPSOAPAddressString == mDNSNULL)  AllocAndCopy(&m->UPnPSOAPAddressString, m->UPnPRouterAddressString);
                }
+       if (m->UPnPSOAPAddressString == mDNSNULL) LogMsg("handleLNTDeviceDescriptionResponse: UPnPSOAPAddressString is NULL");
+       else LogInfo("handleLNTDeviceDescriptionResponse: SOAP address string [%s]", m->UPnPSOAPAddressString);
 
-       // if we get to the end and haven't found the URL fill in the defaults
-       if (m->UPnPSOAPURL == mDNSNULL) m->UPnPSOAPURL = m->UPnPRouterURL;      // just copy the pointer, don't allocate more memory
-       
-       LogOperation("handleLNTDeviceDescriptionResponse: SOAP URL [%s] port %d", m->UPnPSOAPURL, mDNSVal16(m->UPnPSOAPPort));
+       if (m->UPnPSOAPURL == mDNSNULL) AllocAndCopy(&m->UPnPSOAPURL, m->UPnPRouterURL);
+       if (m->UPnPSOAPURL == mDNSNULL) LogMsg("handleLNTDeviceDescriptionResponse: UPnPSOAPURL is NULL");
+       else LogInfo("handleLNTDeviceDescriptionResponse: SOAP URL [%s]", m->UPnPSOAPURL);
        }
 
 mDNSlocal void handleLNTGetExternalAddressResponse(tcpLNTInfo *tcpInfo)
@@ -325,26 +514,40 @@ mDNSlocal void handleLNTGetExternalAddressResponse(tcpLNTInfo *tcpInfo)
        mDNS       *m = tcpInfo->m;
        mDNSu16     err = NATErr_None;
        mDNSv4Addr  ExtAddr;
-       char       *ptr = (char *)tcpInfo->Reply;
-       char       *end = (char *)tcpInfo->Reply + tcpInfo->nread;
-       char       *addrend;
+       mDNSu8     *ptr = (mDNSu8*)tcpInfo->Reply;
+       mDNSu8     *end = (mDNSu8*)tcpInfo->Reply + tcpInfo->nread;
+       mDNSu8     *addrend;
        static char tagname[20] = "NewExternalIPAddress";               // Array NOT including a terminating nul
 
-//     LogOperation("handleLNTGetExternalAddressResponse: %s", ptr);
+//     LogInfo("handleLNTGetExternalAddressResponse: %s", ptr);
 
-       while (ptr < end && strncasecmp(ptr, tagname, sizeof(tagname))) ptr++;
+       mDNSs16 http_result = ParseHTTPResponseCode(&ptr, end); // Note: modifies ptr
+       if (http_result == HTTPCode_404) LNT_ClearState(m);
+       if (http_result != HTTPCode_200)
+               {
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest", "noop", "HTTP Result", "HTTP code: %d", http_result);
+               return;
+               }
+
+       
+       while (ptr < end && strncasecmp((char*)ptr, tagname, sizeof(tagname))) ptr++;
        ptr += sizeof(tagname);                                         // Skip over "NewExternalIPAddress"
        while (ptr < end && *ptr != '>') ptr++;
        ptr += 1;                                                                       // Skip over ">"
        // Find the end of the address and terminate the string so inet_pton() can convert it
        addrend = ptr;
-       while (addrend < end && (mdnsIsDigit(*addrend) || *addrend == '.')) addrend++;
+       while (addrend < end && (mDNSIsDigit(*addrend) || *addrend == '.')) addrend++;
        if (addrend >= end) return;
        *addrend = 0;
 
-       if (inet_pton(AF_INET, ptr, &ExtAddr) <= 0)
-               { LogMsg("handleLNTGetExternalAddressResponse: Router returned bad address %s", ptr); err = NATErr_NetFail; }
-       if (!err) LogOperation("handleLNTGetExternalAddressResponse: External IP address is %.4a", &ExtAddr);
+       if (inet_pton(AF_INET, (char*)ptr, &ExtAddr) <= 0)
+               {
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest", "noop", "inet_pton", "");
+               LogMsg("handleLNTGetExternalAddressResponse: Router returned bad address %s", ptr);
+               err = NATErr_NetFail;
+               ExtAddr = zerov4Addr;
+               }
+       if (!err) LogInfo("handleLNTGetExternalAddressResponse: External IP address is %.4a", &ExtAddr);
 
        natTraversalHandleAddressReply(m, err, ExtAddr);
        }
@@ -353,56 +556,53 @@ mDNSlocal void handleLNTPortMappingResponse(tcpLNTInfo *tcpInfo)
        {
        mDNS             *m       = tcpInfo->m;
        mDNSIPPort        extport = zeroIPPort;
-       char             *ptr     = (char *)tcpInfo->Reply;
-       char             *end     = (char *)tcpInfo->Reply + tcpInfo->nread;
+       mDNSu8           *ptr     = (mDNSu8*)tcpInfo->Reply;
+       mDNSu8           *end     = (mDNSu8*)tcpInfo->Reply + tcpInfo->nread;
        NATTraversalInfo *natInfo;
+       mDNSs16 http_result;
 
        for (natInfo = m->NATTraversals; natInfo; natInfo=natInfo->next) { if (natInfo == tcpInfo->parentNATInfo) break; }
 
-       if (!natInfo) { LogOperation("handleLNTPortMappingResponse: can't find matching tcpInfo in NATTraversals!"); return; }
+       if (!natInfo) { LogInfo("handleLNTPortMappingResponse: can't find matching tcpInfo in NATTraversals!"); return; }
 
-       // start from the beginning of the HTTP header; find "200 OK" status message; if the first characters after the
-       // space are not "200" then this is an error message or invalid in some other way
-       // if the error is "500" this is an internal server error
-       while (ptr && ptr != end)
+       http_result = ParseHTTPResponseCode(&ptr, end); // Note: modifies ptr
+       if (http_result == HTTPCode_200)
+               {
+               LogInfo("handleLNTPortMappingResponse: got a valid response, sending reply to natTraversalHandlePortMapReply(internal %d external %d retries %d)",
+                       mDNSVal16(natInfo->IntPort), RequestedPortNum(natInfo), tcpInfo->retries);
+       
+               // Make sure to compute extport *before* we zero tcpInfo->retries
+               extport = mDNSOpaque16fromIntVal(RequestedPortNum(natInfo));
+               tcpInfo->retries = 0;
+               natTraversalHandlePortMapReply(m, natInfo, m->UPnPInterfaceID, mStatus_NoError, extport, NATMAP_DEFAULT_LEASE);
+               }
+       else if (http_result == HTTPCode_500)
                {
-               if (*ptr == ' ')
+               while (ptr && ptr != end)
                        {
-                       ptr++;
-                       if (ptr == end) { LogOperation("handleLNTPortMappingResponse: past end of buffer!"); return; }
-                       if      (strncasecmp(ptr, "200", 3) == 0) break;
-                       else if (strncasecmp(ptr, "500", 3) == 0)
+                       if (((*ptr == 'c' || *ptr == 'C') && end - ptr >= 8 && strncasecmp((char*)ptr, "Conflict", 8) == 0) || (*ptr == '>' && end - ptr >= 15 && strncasecmp((char*)ptr, ">718</errorCode", 15) == 0))
                                {
-                               // now check to see if this was a port mapping conflict
-                               while (ptr && ptr != end)
+                               if (tcpInfo->retries < 100)
+                                       { 
+                                       tcpInfo->retries++; SendPortMapRequest(tcpInfo->m, natInfo); 
+                                       mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", "noop", "Conflict", "Retry %d", tcpInfo->retries);
+                                       }
+                               else
                                        {
-                                       if ((*ptr == 'c' || *ptr == 'C') && strncasecmp(ptr, "Conflict", 8) == 0)
-                                               {
-                                               if (tcpInfo->retries < 100)
-                                                       { tcpInfo->retries++; SendPortMapRequest(tcpInfo->m, natInfo); }
-                                               else
-                                                       {
-                                                       LogMsg("handleLNTPortMappingResponse too many conflict retries %d %d", mDNSVal16(natInfo->IntPort), mDNSVal16(natInfo->RequestedPort));
-                                                       natTraversalHandlePortMapReply(m, natInfo, m->UPnPInterfaceID, NATErr_Refused, zeroIPPort, 0);
-                                                       }
-                                               return;
-                                               }
-                                       ptr++;
+                                       LogMsg("handleLNTPortMappingResponse too many conflict retries %d %d", mDNSVal16(natInfo->IntPort), mDNSVal16(natInfo->RequestedPort));
+                                       mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", "noop", "Conflict - too many retries", "Retries: %d", tcpInfo->retries);
+                                       natTraversalHandlePortMapReply(m, natInfo, m->UPnPInterfaceID, NATErr_Res, zeroIPPort, 0);
                                        }
-                               break;  // out of HTTP status search
+                               return;
                                }
+                       ptr++;
                        }
-               ptr++;
                }
-       if (ptr == mDNSNULL || ptr == end) return;
-       
-       LogOperation("handleLNTPortMappingResponse: got a valid response, sending reply to natTraversalHandlePortMapReply(internal %d external %d retries %d)",
-               mDNSVal16(natInfo->IntPort), RequestedPortNum(natInfo), tcpInfo->retries);
-
-       // Make sure to compute extport *before* we zero tcpInfo->retries
-       extport = mDNSOpaque16fromIntVal(RequestedPortNum(natInfo));
-       tcpInfo->retries = 0;
-       natTraversalHandlePortMapReply(m, natInfo, m->UPnPInterfaceID, mStatus_NoError, extport, NATMAP_DEFAULT_LEASE);
+       else if (http_result == HTTPCode_Bad) LogMsg("handleLNTPortMappingResponse got data that was not a valid HTTP response");
+       else if (http_result == HTTPCode_Other) LogMsg("handleLNTPortMappingResponse got unexpected response code");
+       else if (http_result == HTTPCode_404) LNT_ClearState(m);
+       if (http_result != HTTPCode_200 && http_result != HTTPCode_500)
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", "noop", "HTTP Result", "HTTP code: %d", http_result);
        }
 
 mDNSlocal void DisposeInfoFromUnmapList(mDNS *m, tcpLNTInfo *tcpInfo)
@@ -420,32 +620,32 @@ mDNSlocal void tcpConnectionCallback(TCPSocket *sock, void *context, mDNSBool Co
        long        n       = 0;
        long        nsent   = 0;
 
-       if (tcpInfo == mDNSNULL) { LogOperation("tcpConnectionCallback: no tcpInfo context"); status = mStatus_Invalid; goto exit; }
+       if (tcpInfo == mDNSNULL) { LogInfo("tcpConnectionCallback: no tcpInfo context"); status = mStatus_Invalid; goto exit; }
 
        // The handlers below expect to be called with the lock held
        mDNS_Lock(tcpInfo->m);
        
-       if (err) { LogOperation("tcpConnectionCallback: received error"); goto exit; }
+       if (err) { LogInfo("tcpConnectionCallback: received error"); goto exit; }
 
        if (ConnectionEstablished)              // connection is established - send the message
                {
-               LogOperation("tcpConnectionCallback: connection established, sending message");
+               LogInfo("tcpConnectionCallback: connection established, sending message");
                nsent = mDNSPlatformWriteTCP(sock, (char *)tcpInfo->Request, tcpInfo->requestLen);
                if (nsent != (long)tcpInfo->requestLen) { LogMsg("tcpConnectionCallback: error writing"); status = mStatus_UnknownErr; goto exit; }
                }
        else
                {
                n = mDNSPlatformReadTCP(sock, (char *)tcpInfo->Reply + tcpInfo->nread, tcpInfo->replyLen - tcpInfo->nread, &closed);
-               LogOperation("tcpConnectionCallback: mDNSPlatformReadTCP read %d bytes", n);
+               LogInfo("tcpConnectionCallback: mDNSPlatformReadTCP read %d bytes", n);
 
-               if      (n < 0)  { LogOperation("tcpConnectionCallback - read returned %d", n);                           status = mStatus_ConnFailed; goto exit; }
-               else if (closed) { LogOperation("tcpConnectionCallback: socket closed by remote end %d", tcpInfo->nread); status = mStatus_ConnFailed; goto exit; }
+               if      (n < 0)  { LogInfo("tcpConnectionCallback - read returned %d", n);                           status = mStatus_ConnFailed; goto exit; }
+               else if (closed) { LogInfo("tcpConnectionCallback: socket closed by remote end %d", tcpInfo->nread); status = mStatus_ConnFailed; goto exit; }
 
                tcpInfo->nread += n;
-               LogOperation("tcpConnectionCallback tcpInfo->nread %d", tcpInfo->nread);
+               LogInfo("tcpConnectionCallback tcpInfo->nread %d", tcpInfo->nread);
                if (tcpInfo->nread > LNT_MAXBUFSIZE)
                        {
-                       LogOperation("result truncated...");
+                       LogInfo("result truncated...");
                        tcpInfo->nread = LNT_MAXBUFSIZE;
                        }
 
@@ -461,6 +661,26 @@ mDNSlocal void tcpConnectionCallback(TCPSocket *sock, void *context, mDNSBool Co
 exit:
        if (err || status)
                {
+               mDNS   *m = tcpInfo->m;
+               switch (tcpInfo->op)
+                       {
+                       case LNTDiscoveryOp:     if (m->UPnPSOAPAddressString == mDNSNULL)
+                                                                               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "failure", "SOAP Address", "");
+                                                                        if (m->UPnPSOAPURL == mDNSNULL)
+                                                                               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "failure", "SOAP path", "");
+                                                                        if (m->UPnPSOAPAddressString && m->UPnPSOAPURL)
+                                                                               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "success", "success", "");
+                                                                        break;
+                       case LNTExternalAddrOp:  mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest", mDNSIPv4AddressIsZero(m->ExternalAddress) ? "failure" : "success", mDNSIPv4AddressIsZero(m->ExternalAddress) ? "failure" : "success", "");
+                                                                        break;
+                       case LNTPortMapOp:       if (tcpInfo->parentNATInfo)    
+                                                                               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", (tcpInfo->parentNATInfo->Result) ? "failure" : "success", 
+                                                                                       (tcpInfo->parentNATInfo->Result) ? "failure" : "success", "Result: %d", tcpInfo->parentNATInfo->Result);
+                                                                        break;
+                       case LNTPortMapDeleteOp: break;
+                       default:                                 break;
+                       }
+
                mDNSPlatformTCPCloseConnection(tcpInfo->sock);
                tcpInfo->sock = mDNSNULL;
                if (tcpInfo->Request) { mDNSPlatformMemFree(tcpInfo->Request); tcpInfo->Request = mDNSNULL; }
@@ -486,12 +706,12 @@ mDNSlocal mStatus MakeTCPConnection(mDNS *const m, tcpLNTInfo *info, const mDNSA
        info->nread     = 0;
        info->replyLen  = LNT_MAXBUFSIZE;
        if      (info->Reply != mDNSNULL)  mDNSPlatformMemZero(info->Reply, LNT_MAXBUFSIZE);   // reuse previously allocated buffer
-       else if ((info->Reply = (mDNSs8 *) mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL) { LogOperation("can't allocate reply buffer"); return (mStatus_NoMemoryErr); }
+       else if ((info->Reply = (mDNSs8 *) mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL) { LogInfo("can't allocate reply buffer"); return (mStatus_NoMemoryErr); }
 
-       if (info->sock) { LogOperation("MakeTCPConnection: closing previous open connection"); mDNSPlatformTCPCloseConnection(info->sock); info->sock = mDNSNULL; }
+       if (info->sock) { LogInfo("MakeTCPConnection: closing previous open connection"); mDNSPlatformTCPCloseConnection(info->sock); info->sock = mDNSNULL; }
        info->sock = mDNSPlatformTCPSocket(m, kTCPSocketFlags_Zero, &srcport);
        if (!info->sock) { LogMsg("LNT MakeTCPConnection: unable to create TCP socket"); mDNSPlatformMemFree(info->Reply); info->Reply = mDNSNULL; return(mStatus_NoMemoryErr); }
-       LogOperation("MakeTCPConnection: connecting to %#a:%d", &info->Address, mDNSVal16(info->Port));
+       LogInfo("MakeTCPConnection: connecting to %#a:%d", &info->Address, mDNSVal16(info->Port));
        err = mDNSPlatformTCPConnect(info->sock, Addr, Port, 0, tcpConnectionCallback, info);
 
        if      (err == mStatus_ConnPending) err = mStatus_NoError;
@@ -505,7 +725,7 @@ mDNSlocal mStatus MakeTCPConnection(mDNS *const m, tcpLNTInfo *info, const mDNSA
        else
                {
                // Don't need to log this in customer builds -- it happens quite often during sleep, wake, configuration changes, etc.
-               LogOperation("LNT MakeTCPConnection: connection failed");
+               LogInfo("LNT MakeTCPConnection: connection failed");
                mDNSPlatformTCPCloseConnection(info->sock);     // Dispose the socket we created with mDNSPlatformTCPSocket() above
                info->sock = mDNSNULL;
                mDNSPlatformMemFree(info->Reply);
@@ -564,8 +784,8 @@ mDNSlocal mStatus SendSOAPMsgControlAction(mDNS *m, tcpLNTInfo *info, char *Acti
        char   *body = (char *)&m->omsg;                        // Typically requires 1110-1122 bytes; m->omsg is 8952 bytes, which is plenty
        int     bodyLen;
 
-       if (m->UPnPSOAPURL == mDNSNULL || m->UPnPSOAPAddressString == mDNSNULL) // if no SOAP URL or address exists get out here
-               { LogOperation("SendSOAPMsgControlAction: no SOAP URL or address string"); return mStatus_Invalid; }
+       if (mDNSIPPortIsZero(m->UPnPSOAPPort) || m->UPnPSOAPURL == mDNSNULL || m->UPnPSOAPAddressString == mDNSNULL)    // if no SOAP URL or address exists get out here
+               { LogInfo("SendSOAPMsgControlAction: no SOAP port, URL or address string"); return mStatus_Invalid; }
 
        // Create body
        bodyLen  = mDNS_snprintf   (body,           sizeof(m->omsg),           body1,   Action,   m->UPnPWANPPPConnection ? "PPP" : "IP");
@@ -619,7 +839,7 @@ mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n)
                                }
                        else
                                {
-                               natTraversalHandlePortMapReply(m, n, m->UPnPInterfaceID, NATErr_Refused, zeroIPPort, 0);
+                               natTraversalHandlePortMapReply(m, n, m->UPnPInterfaceID, NATErr_Res, zeroIPPort, 0);
                                return mStatus_NoError;
                                }
                        }
@@ -659,13 +879,13 @@ mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n)
        propArgs[7].type  = "ui4";
        propArgs[7].value = "0";
 
-       LogOperation("SendPortMapRequest: internal %u external %u", mDNSVal16(n->IntPort), ReqPortNum);
+       LogInfo("SendPortMapRequest: internal %u external %u", mDNSVal16(n->IntPort), ReqPortNum);
        return SendSOAPMsgControlAction(m, &n->tcpInfo, "AddPortMapping", 8, propArgs, LNTPortMapOp);
        }
 
 mDNSexport mStatus LNT_MapPort(mDNS *m, NATTraversalInfo *n)
        {
-       LogOperation("LNT_MapPort");
+       LogInfo("LNT_MapPort");
        if (n->tcpInfo.sock) return(mStatus_NoError);   // If we already have a connection up don't make another request for the same thing
        n->tcpInfo.parentNATInfo = n;
        n->tcpInfo.retries       = 0;
@@ -681,7 +901,7 @@ mDNSexport mStatus LNT_UnmapPort(mDNS *m, NATTraversalInfo *n)
        mStatus     err;
 
        // If no NAT gateway to talk to, no need to do all this work for nothing
-       if (!m->UPnPSOAPURL || !m->UPnPSOAPAddressString) return mStatus_NoError;
+       if (mDNSIPPortIsZero(m->UPnPSOAPPort) || !m->UPnPSOAPURL || !m->UPnPSOAPAddressString) return mStatus_NoError;
 
        mDNS_snprintf(externalPort, sizeof(externalPort), "%u", mDNSVal16(mDNSIPPortIsZero(n->RequestedPort) ? n->IntPort : n->RequestedPort));
 
@@ -699,14 +919,14 @@ mDNSexport mStatus LNT_UnmapPort(mDNS *m, NATTraversalInfo *n)
        n->tcpInfo.parentNATInfo = n;
 
        // clean up previous port mapping requests and allocations
-       if (n->tcpInfo.sock) LogOperation("LNT_UnmapPort: closing previous open connection");
+       if (n->tcpInfo.sock) LogInfo("LNT_UnmapPort: closing previous open connection");
        if (n->tcpInfo.sock   ) { mDNSPlatformTCPCloseConnection(n->tcpInfo.sock); n->tcpInfo.sock    = mDNSNULL; }
        if (n->tcpInfo.Request) { mDNSPlatformMemFree(n->tcpInfo.Request);         n->tcpInfo.Request = mDNSNULL; }
        if (n->tcpInfo.Reply  ) { mDNSPlatformMemFree(n->tcpInfo.Reply);           n->tcpInfo.Reply   = mDNSNULL; }
        
        // make a copy of the tcpInfo that we can clean up later (the one passed in will be destroyed by the client as soon as this returns)
        if ((info = mDNSPlatformMemAllocate(sizeof(tcpLNTInfo))) == mDNSNULL)
-               { LogOperation("LNT_UnmapPort: can't allocate tcpInfo"); return(mStatus_NoMemoryErr); }
+               { LogInfo("LNT_UnmapPort: can't allocate tcpInfo"); return(mStatus_NoMemoryErr); }
        *info = n->tcpInfo;
        
        while (*infoPtr) infoPtr = &(*infoPtr)->next;   // find the end of the list
@@ -735,13 +955,15 @@ mDNSlocal mStatus GetDeviceDescription(mDNS *m, tcpLNTInfo *info)
                "Connection: close\r\n"
                "\r\n";
 
-       if (m->UPnPRouterURL == mDNSNULL || m->UPnPRouterAddressString == mDNSNULL)     { LogOperation("GetDeviceDescription: no router URL or address string!"); return (mStatus_Invalid); }
+       if (!mDNSIPPortIsZero(m->UPnPSOAPPort)) return mStatus_NoError; // already have the info we need
+       
+       if (m->UPnPRouterURL == mDNSNULL || m->UPnPRouterAddressString == mDNSNULL)     { LogInfo("GetDeviceDescription: no router URL or address string!"); return (mStatus_Invalid); }
 
        // build message
        if      (info->Request != mDNSNULL)  mDNSPlatformMemZero(info->Request, LNT_MAXBUFSIZE); // reuse previously allocated buffer
-       else if ((info->Request = (mDNSs8 *) mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL) { LogOperation("can't allocate send buffer for discovery"); return (mStatus_NoMemoryErr); }
+       else if ((info->Request = (mDNSs8 *) mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL) { LogInfo("can't allocate send buffer for discovery"); return (mStatus_NoMemoryErr); }
        info->requestLen = mDNS_snprintf((char *)info->Request, LNT_MAXBUFSIZE, szSSDPMsgDescribeDeviceFMT, m->UPnPRouterURL, m->UPnPRouterAddressString);
-       LogOperation("Describe Device: [%s]", info->Request);
+       LogInfo("Describe Device: [%s]", info->Request);
        return MakeTCPConnection(m, info, &m->Router, m->UPnPRouterPort, LNTDiscoveryOp);
        }
 
@@ -752,6 +974,9 @@ mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID Interface
        {
        char *ptr = (char *)data;
        char *end = (char *)data + len;
+       char *stop = ptr;
+       
+       if (!mDNSIPPortIsZero(m->UPnPRouterPort)) return; // already have the info we need
 
        // The formatting of the HTTP header is not always the same when it comes to the placement of
        // the service and location strings, so we just look for each of them from the beginning for every response
@@ -777,77 +1002,66 @@ mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID Interface
        ptr = (char *)data;
        while (ptr && ptr != end)
                {
-               if (*ptr == 'L' && (strncasecmp(ptr, "Location", 8) == 0)) break;                       // find the first 'L'; is this Location? if not, keep looking
+               if (*ptr == 'L' && (strncasecmp(ptr, "Location:", 9) == 0)) break;                      // find the first 'L'; is this Location? if not, keep looking
                ptr++;
                }
-       if (ptr == mDNSNULL || ptr == end) return;      // not a message we care about
+       if (ptr == mDNSNULL || ptr == end) 
+               {
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Location", "");
+               return; // not a message we care about
+               }
+       ptr += 9; //Skip over 'Location:'
+       while (*ptr == ' ' && ptr < end) ptr++; // skip over spaces
+       if (ptr >= end) return;
        
-       // find "http://", starting from where we left off
-       while (ptr && ptr != end)
+       // find the end of the line
+       for (stop = ptr; stop != end; stop++) { if (*stop == '\r') { end = stop; break; } }
+       
+       // fill in default port
+       m->UPnPRouterPort = mDNSOpaque16fromIntVal(80);
+
+       // free string pointers and set to NULL 
+       if (m->UPnPRouterAddressString != mDNSNULL)
                {
-               if (*ptr == 'h' && (strncasecmp(ptr, "http://", 7) == 0))                                       // find the first 'h'; is this a URL? if not, keep looking
-                       {
-                       int i;
-                       char *addrPtr = mDNSNULL;
-                       
-                       ptr += 7;                                                       //skip over "http://"
-                       if (ptr >= end) { LogOperation("LNT_ConfigureRouterInfo: past end of buffer and no URL!"); return; }
-                       addrPtr = ptr;
-                       for (i = 0; addrPtr && addrPtr != end; i++, addrPtr++) if (*addrPtr == '/') break;      // first find the beginning of the URL and count the chars
-                       if (addrPtr == mDNSNULL || addrPtr == end) return; // not a valid message
+               mDNSPlatformMemFree(m->UPnPRouterAddressString);
+               m->UPnPRouterAddressString = mDNSNULL;
+               }
+       if (m->UPnPRouterURL != mDNSNULL)
+               {
+               mDNSPlatformMemFree(m->UPnPRouterURL);
+               m->UPnPRouterURL = mDNSNULL; 
+               }
        
-                       // allocate the buffer (len i+1 so we have space to terminate the string)
-                       if (m->UPnPRouterAddressString != mDNSNULL)  mDNSPlatformMemFree(m->UPnPRouterAddressString);
-                       if ((m->UPnPRouterAddressString = (mDNSu8 *) mDNSPlatformMemAllocate(i+1)) == mDNSNULL) { LogMsg("can't mDNSPlatformMemAllocate router address string"); return; }
-                       
-                       strncpy((char *)m->UPnPRouterAddressString, ptr, i);    // copy the address string
-                       m->UPnPRouterAddressString[i] = '\0';                                   // terminate the string
-                       LogOperation("LNT_ConfigureRouterInfo: router address string [%s]", m->UPnPRouterAddressString);
-                       break;
-                       }
-               ptr++;  // continue
+       // the Router URL should look something like "/dyndev/uuid:0013-108c-4b3f0000f3dc"
+       if (ParseHttpUrl(ptr, end, &m->UPnPRouterAddressString, &m->UPnPRouterPort, &m->UPnPRouterURL) != mStatus_NoError)
+               {
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Parse URL", "");
+               return;
                }
 
-       // find port and router URL, starting after the "http://" if it was there
-       while (ptr && ptr != end)
+       m->UPnPInterfaceID = InterfaceID;
+
+       if (m->UPnPRouterAddressString == mDNSNULL) 
                {
-               if (*ptr == ':')                                                                                // found the port number
-                       {
-                       int port;
-                       ptr++;                                                                          // skip over ':'
-                       if (ptr == end) { LogOperation("LNT_ConfigureRouterInfo: reached end of buffer and no address!"); return; }
-                       port = (int)strtol(ptr, (char **)mDNSNULL, 10);                 // get the port
-                       m->UPnPRouterPort = mDNSOpaque16fromIntVal(port);       // store it properly converted
-                       }
-               else if (*ptr == '/')                                                                   // found router URL
-                       {
-                       int j;
-                       char *urlPtr;
-                       m->UPnPInterfaceID = InterfaceID;
-                       if (mDNSIPPortIsZero(m->UPnPRouterPort)) m->UPnPRouterPort = mDNSOpaque16fromIntVal(80);                // fill in default port if we didn't find one before
-                       
-                       urlPtr = ptr;
-                       for (j = 0; urlPtr && urlPtr != end; j++, urlPtr++) if (*urlPtr == '\r') break; // first find the end of the line and count the chars
-                       if (urlPtr == mDNSNULL || urlPtr == end) return; // not a valid message
-                       
-                       // allocate the buffer (len j+1 so we have space to terminate the string)
-                       if (m->UPnPRouterURL != mDNSNULL) mDNSPlatformMemFree(m->UPnPRouterURL);
-                       if ((m->UPnPRouterURL = (mDNSu8 *) mDNSPlatformMemAllocate(j+1)) == mDNSNULL) { LogMsg("can't allocate router URL"); return; }
-                       
-                       // now copy everything to the end of the line
-                       strncpy((char *)m->UPnPRouterURL, ptr, j);                      // this URL looks something like "/dyndev/uuid:0013-108c-4b3f0000f3dc"
-                       m->UPnPRouterURL[j] = '\0';                                     // terminate the string
-                       break;                                                                  // we've got everything we need, so get out here
-                       }
-               ptr++;  // continue
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Router address", "");
+               LogMsg("LNT_ConfigureRouterInfo: UPnPRouterAddressString is NULL");
                }
+       else LogInfo("LNT_ConfigureRouterInfo: Router address string [%s]", m->UPnPRouterAddressString);
+
+       if (m->UPnPRouterURL == mDNSNULL) 
+               {
+               mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Router path", "");
+               LogMsg("LNT_ConfigureRouterInfo: UPnPRouterURL is NULL");
+               }
+       else LogInfo("LNT_ConfigureRouterInfo: Router URL [%s]", m->UPnPRouterURL);
+
+       LogInfo("LNT_ConfigureRouterInfo: Router port %d", mDNSVal16(m->UPnPRouterPort));
+       LogInfo("LNT_ConfigureRouterInfo: Router interface %d", m->UPnPInterfaceID);
 
-       if (ptr == mDNSNULL || ptr == end) return;      // not a valid message
-       LogOperation("Router port %d, URL set to [%s]...", mDNSVal16(m->UPnPRouterPort), m->UPnPRouterURL);
-       
        // Don't need the SSDP socket anymore
-       if (m->SSDPSocket) { LogOperation("LNT_ConfigureRouterInfo destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
+       if (m->SSDPSocket) { debugf("LNT_ConfigureRouterInfo destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
 
+       mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "success", "success", "");
        // now send message to get the device description
        GetDeviceDescription(m, &m->tcpDeviceInfo);
        }
@@ -864,6 +1078,13 @@ mDNSexport void LNT_SendDiscoveryMsg(mDNS *m)
        
        mDNSu8* buf = (mDNSu8*)&m->omsg; //m->omsg is 8952 bytes, which is plenty
        unsigned int bufLen;
+       
+       if (!mDNSIPPortIsZero(m->UPnPRouterPort))
+               {
+               if (m->SSDPSocket) { debugf("LNT_SendDiscoveryMsg destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
+               if (mDNSIPPortIsZero(m->UPnPSOAPPort) && !m->tcpDeviceInfo.sock) GetDeviceDescription(m, &m->tcpDeviceInfo);
+               return;
+               }
 
        // Always query for WANIPConnection in the first SSDP packet
        if (m->retryIntervalGetAddr <= NATMAP_INIT_RETRY) m->SSDPWANPPPConnection = mDNSfalse;
@@ -871,11 +1092,11 @@ mDNSexport void LNT_SendDiscoveryMsg(mDNS *m)
        // Create message
        bufLen = mDNS_snprintf((char*)buf, sizeof(m->omsg), msg, m->SSDPWANPPPConnection ? "PPP" : "IP");
 
-       LogOperation("LNT_SendDiscoveryMsg Router %.4a Current External Address %.4a", &m->Router.ip.v4, &m->ExternalAddress);
+       debugf("LNT_SendDiscoveryMsg Router %.4a Current External Address %.4a", &m->Router.ip.v4, &m->ExternalAddress);
 
-       if (!mDNSIPv4AddressIsZero(m->Router.ip.v4) && mDNSIPv4AddressIsZero(m->ExternalAddress))
+       if (!mDNSIPv4AddressIsZero(m->Router.ip.v4))
                {
-               if (!m->SSDPSocket) { m->SSDPSocket = mDNSPlatformUDPSocket(m, zeroIPPort); LogOperation("LNT_SendDiscoveryMsg created SSDPSocket %p", &m->SSDPSocket); }
+               if (!m->SSDPSocket) { m->SSDPSocket = mDNSPlatformUDPSocket(m, zeroIPPort); debugf("LNT_SendDiscoveryMsg created SSDPSocket %p", &m->SSDPSocket); }
                mDNSPlatformSendUDP(m, buf, buf + bufLen, 0, m->SSDPSocket, &m->Router,     SSDPPort);
                mDNSPlatformSendUDP(m, buf, buf + bufLen, 0, m->SSDPSocket, &multicastDest, SSDPPort);
                }
@@ -883,4 +1104,11 @@ mDNSexport void LNT_SendDiscoveryMsg(mDNS *m)
        m->SSDPWANPPPConnection = !m->SSDPWANPPPConnection;
        }
 
+mDNSexport void LNT_ClearState(mDNS *const m)
+       {
+       if (m->tcpAddrInfo.sock)   { mDNSPlatformTCPCloseConnection(m->tcpAddrInfo.sock);   m->tcpAddrInfo.sock   = mDNSNULL; }
+       if (m->tcpDeviceInfo.sock) { mDNSPlatformTCPCloseConnection(m->tcpDeviceInfo.sock); m->tcpDeviceInfo.sock = mDNSNULL; }
+       m->UPnPSOAPPort = m->UPnPRouterPort = zeroIPPort;       // Reset UPnP ports
+       }
+
 #endif /* _LEGACY_NAT_TRAVERSAL_ */
index a42d9a50aaa6df11e583f7f69631fc76fb68f66d..af22edf3e1c9e878a419b3b71cc4704b4578beb6 100644 (file)
@@ -44,6 +44,9 @@
     Change History (most recent first):
 
 $Log: ConfigurationAuthority.c,v $
+Revision 1.3  2008/06/26 17:34:18  mkrochma
+<rdar://problem/6030630> Pref pane destroying shared "system.preferences" authorization right
+
 Revision 1.2  2005/08/07 22:48:05  mkrochma
 <rdar://problem/4204003> Bonjour Pref Pane returns -927 when "system.preferences" is not shared
 
@@ -170,7 +173,7 @@ OSStatus    AttemptAcquireAuthority( Boolean allowUI)
 OSStatus ReleaseAuthority(void)
 /* Discard authority to perform operations */
 {
-       (void) AuthorizationFree( gAuthRef, kAuthorizationFlagDestroyRights);
+       (void) AuthorizationFree( gAuthRef, kAuthorizationFlagDefaults);
        gAuthRef = 0;
        return AuthorizationCreate( (AuthorizationRights*) NULL, (AuthorizationEnvironment*) NULL,
                                                                (AuthorizationFlags) 0, &gAuthRef);
index 412da6d315bd84cb55ed944e0742478f78cdef5e..1c481dc57ccc6fb674d53b7f26f69996caee644c 100644 (file)
     Change History (most recent first):
 
 $Log: DNSServiceDiscoveryPref.m,v $
+Revision 1.16  2008/09/15 23:52:30  cheshire
+<rdar://problem/6218902> mDNSResponder-177 fails to compile on Linux with .desc pseudo-op
+Made __crashreporter_info__ symbol conditional, so we only use it for OS X build
+
+Revision 1.15  2008/08/18 17:57:04  mcguire
+<rdar://problem/6156209> build error
+
+Revision 1.14  2008/07/18 17:39:14  cheshire
+If NSInteger is not defined (indicated by lack of definition for NSINTEGER_DEFINED)
+then #define "NSInteger" to be "int" like it used to be
+
+Revision 1.13  2008/07/01 01:40:01  mcguire
+<rdar://problem/5823010> 64-bit fixes
+
+Revision 1.12  2008/05/08 00:46:38  cheshire
+<rdar://problem/5919272> GetNextLabel insufficiently defensive
+User shared copy of GetNextLabel in ClientCommon.c instead of having a local copy here
+
 Revision 1.11  2007/11/30 23:42:09  cheshire
 Fixed compile warning: declaration of 'index' shadows a global declaration
 
@@ -84,9 +102,15 @@ Add Preference Pane to facilitate testing of DDNS & wide-area features
 #import "PrivilegedOperations.h"
 #import <unistd.h>
 
+#include "../../Clients/ClientCommon.h"
+
+#ifndef NSINTEGER_DEFINED
+#define NSInteger int
+#endif
+
 @implementation DNSServiceDiscoveryPref
 
-static int
+static NSComparisonResult
 MyArrayCompareFunction(id val1, id val2, void *context)
 {
        (void)context; // Unused
@@ -94,7 +118,7 @@ MyArrayCompareFunction(id val1, id val2, void *context)
 }
 
 
-static int
+static NSComparisonResult
 MyDomainArrayCompareFunction(id val1, id val2, void *context)
 {
        (void)context; // Unused
@@ -104,34 +128,6 @@ MyDomainArrayCompareFunction(id val1, id val2, void *context)
 }
 
 
-static const char *
-GetNextLabel(const char *cstr, char label[64])
-{
-       char *ptr = label;
-       while (*cstr && *cstr != '.')                                                           // While we have characters in the label...
-               {
-               char c = *cstr++;
-               if (c == '\\')
-                       {
-                       c = *cstr++;
-                       if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
-                               {
-                               int v0 = cstr[-1] - '0';                                                // then interpret as three-digit decimal
-                               int v1 = cstr[ 0] - '0';
-                               int v2 = cstr[ 1] - '0';
-                               int val = v0 * 100 + v1 * 10 + v2;
-                               if (val <= 255) { c = (char)val; cstr += 2; }   // If valid three-digit decimal value, use it
-                               }
-                       }
-               *ptr++ = c;
-               if (ptr >= label+64) return(NULL);
-               }
-       if (*cstr) cstr++;                                                                                      // Skip over the trailing dot (if present)
-       *ptr++ = 0;
-       return(cstr);
-}
-
-
 static void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
 {
        (void)store; // Unused
@@ -459,7 +455,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
 
 
 
-- (int)numberOfRowsInTableView:(NSTableView *)tableView;
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView;
 {
        (void)tableView; // Unused
        int numberOfRows = 0;
@@ -480,7 +476,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
 }
  
 
-- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row;
+- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;
 {
        (void)tableView; // Unused
        NSDictionary *browseDomainDict;
@@ -594,12 +590,10 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
     [self startDomainBrowsing];
     [self watchForPreferenceChanges];
        
-       [tabView setDelegate:self];    
-    
     InitConfigAuthority();
     err = EnsureToolInstalled();
     if (err == noErr) toolInstalled = YES;
-    else fprintf(stderr, "EnsureToolInstalled returned %ld\n", err);
+    else { long int tmp = err; fprintf(stderr, "EnsureToolInstalled returned %ld\n", tmp); }
     
 }
 
@@ -1195,7 +1189,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
 }
 
 
-- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;
+- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row;
 {
        (void)row; // Unused
        (void)tableView; // Unused
@@ -1250,6 +1244,8 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
 // The "@(#) " pattern is a special prefix the "what" command looks for
 const char VersionString_SCCS[] = "@(#) Bonjour Preference Pane " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
 
+#if _BUILDING_XCODE_PROJECT_
 // If the process crashes, then this string will be magically included in the automatically-generated crash log
 const char *__crashreporter_info__ = VersionString_SCCS + 5;
 asm(".desc ___crashreporter_info__, 0x10");
+#endif
index 01f09c5f0a0868ec9aea39d3f06a86ca285d3d36..5be57927106477af2a26fac372aa980c4b161012 100644 (file)
@@ -43,6 +43,9 @@
     Change History (most recent first):
 
 $Log: PrivilegedOperations.c,v $
+Revision 1.9  2008/06/26 17:34:18  mkrochma
+<rdar://problem/6030630> Pref pane destroying shared "system.preferences" authorization right
+
 Revision 1.8  2007/11/30 23:42:33  cheshire
 Fixed compile warning: declaration of 'status' shadows a previous local
 
@@ -159,7 +162,7 @@ OSStatus EnsureToolInstalled(void)
                                        err = -1;
                                }
                        }
-                       (void) AuthorizationFree(authRef, kAuthorizationFlagDestroyRights);
+                       (void) AuthorizationFree(authRef, kAuthorizationFlagDefaults);
                }
        }
 
index f415180dbfc1e3e76357cadcf30b616d34444a67..441741893cf93ddf424097762dde168097f662a7 100644 (file)
     Change History (most recent first):
 
 $Log: ddnswriteconfig.m,v $
+Revision 1.13  2008/11/04 20:08:44  cheshire
+Use constant kDNSServiceMaxDomainName instead of literal value "1005"
+
+Revision 1.12  2008/09/15 23:52:30  cheshire
+<rdar://problem/6218902> mDNSResponder-177 fails to compile on Linux with .desc pseudo-op
+Made __crashreporter_info__ symbol conditional, so we only use it for OS X build
+
+Revision 1.11  2008/06/26 17:34:18  mkrochma
+<rdar://problem/6030630> Pref pane destroying shared "system.preferences" authorization right
+
 Revision 1.10  2007/11/30 23:43:04  cheshire
 Fixed compile warning: declaration of 'access' shadows a global declaration
 
@@ -93,6 +103,7 @@ Add Preference Pane to facilitate testing of DDNS & wide-area features
 #import <sys/stat.h>
 #import <sys/mman.h>
 #import <mach-o/dyld.h>
+#import <dns_sd.h>
 #import <AssertMacros.h>
 #import <Security/Security.h>
 #import <CoreServices/CoreServices.h>
@@ -202,7 +213,7 @@ SetAuthInfo( int fd)
        require( len == kAuthorizationExternalFormLength, ReadParamsFailed);
 
        if (gAuthRef != 0) {
-               (void) AuthorizationFree(gAuthRef, kAuthorizationFlagDestroyRights);
+               (void) AuthorizationFree(gAuthRef, kAuthorizationFlagDefaults);
                gAuthRef = 0;
        }
 
@@ -361,9 +372,9 @@ SetKeychainEntry(int fd)
        int                                     result = 0;
        u_int32_t                       tag, len;
        char                            *p;
-       char                keyname[1005];
-       char                domain[1005];
-       char                secret[1005];
+       char                keyname[kDNSServiceMaxDomainName];
+       char                domain[kDNSServiceMaxDomainName];
+       char                secret[kDNSServiceMaxDomainName];
 
        AuthorizationItem       kcAuth = { EDIT_SYS_KEYCHAIN_RIGHT, 0, NULL, 0 };
        AuthorizationRights     authSet = { 1, &kcAuth };
@@ -386,9 +397,9 @@ SetKeychainEntry(int fd)
        secretString  = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_SECRET_KEY);
        assert(secretString != NULL);
                        
-       CFStringGetCString(keyNameString, keyname, 1005, kCFStringEncodingUTF8);
-       CFStringGetCString(domainString,   domain, 1005, kCFStringEncodingUTF8);
-       CFStringGetCString(secretString,   secret, 1005, kCFStringEncodingUTF8);
+       CFStringGetCString(keyNameString, keyname, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
+       CFStringGetCString(domainString,   domain, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
+       CFStringGetCString(secretString,   secret, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
 
        result = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
        if (result == noErr) {
@@ -470,6 +481,8 @@ int main( int argc, char **argv)
 // The "@(#) " pattern is a special prefix the "what" command looks for
 const char VersionString_SCCS[] = "@(#) ddnswriteconfig " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
 
+#if _BUILDING_XCODE_PROJECT_
 // If the process crashes, then this string will be magically included in the automatically-generated crash log
 const char *__crashreporter_info__ = VersionString_SCCS + 5;
 asm(".desc ___crashreporter_info__, 0x10");
+#endif
index 6497498b307f0e0a72952259809ec86f9afff651..76ec65a6ef69377cadc1c8f3b66c231cc1c82dc5 100644 (file)
        Change History (most recent first):
 
 $Log: SamplemDNSClient.c,v $
+Revision 1.56  2008/10/22 02:59:58  mkrochma
+<rdar://problem/6309616> Fix errors compiling mDNS tool caused by BIND8 removal
+
+Revision 1.55  2008/09/15 23:52:30  cheshire
+<rdar://problem/6218902> mDNSResponder-177 fails to compile on Linux with .desc pseudo-op
+Made __crashreporter_info__ symbol conditional, so we only use it for OS X build
+
 Revision 1.54  2007/11/30 23:39:55  cheshire
 Fixed compile warning: declaration of 'client' shadows a global declaration
 
@@ -60,7 +67,6 @@ Revision 1.47  2006/01/10 02:29:22  cheshire
 */
 
 #include <libc.h>
-#define BIND_8_COMPAT
 #include <arpa/nameser.h>
 #include <arpa/inet.h>
 #include <net/if.h>
@@ -256,7 +262,7 @@ static void myCFRunLoopTimerCallBack(CFRunLoopTimerRef timer, void *info)
                        switch (addtest)
                                {
                                case 0: printf("Adding Test HINFO record\n");
-                                               record = DNSServiceRegistrationAddRecord(client, T_HINFO, sizeof(myhinfo9), &myhinfo9[0], 120);
+                                               record = DNSServiceRegistrationAddRecord(client, ns_t_hinfo, sizeof(myhinfo9), &myhinfo9[0], 120);
                                                addtest = 1;
                                                break;
                                case 1: printf("Updating Test HINFO record\n");
@@ -285,7 +291,7 @@ static void myCFRunLoopTimerCallBack(CFRunLoopTimerRef timer, void *info)
                case 'N':
                        {
                        printf("Adding big NULL record\n");
-                       DNSServiceRegistrationAddRecord(client, T_NULL, sizeof(bigNULL), &bigNULL[0], 120);
+                       DNSServiceRegistrationAddRecord(client, ns_t_null, sizeof(bigNULL), &bigNULL[0], 120);
                        CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
                        }
                        break;
@@ -411,7 +417,7 @@ int main(int argc, char **argv)
                                        printf("Registering Service Test._testdualtxt._tcp.local.\n");
                                        client = DNSServiceRegistrationCreate("", "_testdualtxt._tcp.", "", registerPort.NotAnInteger, TXT1, reg_reply, nil);
                                        // use "sizeof(TXT2)-1" because we don't wan't the C compiler's null byte on the end of the string
-                                       record = DNSServiceRegistrationAddRecord(client, T_TXT, sizeof(TXT2)-1, TXT2, 120);
+                                       record = DNSServiceRegistrationAddRecord(client, ns_t_txt, sizeof(TXT2)-1, TXT2, 120);
                                        break;
                                        }
 
@@ -466,6 +472,8 @@ Fail:
 // The "@(#) " pattern is a special prefix the "what" command looks for
 const char VersionString_SCCS[] = "@(#) mDNS " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
 
+#if _BUILDING_XCODE_PROJECT_
 // If the process crashes, then this string will be magically included in the automatically-generated crash log
 const char *__crashreporter_info__ = VersionString_SCCS + 5;
 asm(".desc ___crashreporter_info__, 0x10");
+#endif
index 25b2e439e9641e61950e2396a89d6b6deadd94f4..50abe9615c84888e183f12f8ddbc2e71d115f132 100644 (file)
     Change History (most recent first):
 
 $Log: daemon.c,v $
+Revision 1.434  2009/06/27 00:55:27  cheshire
+Added code for displaying the size of various structures like CacheRecord and CacheGroup
+
+Revision 1.433  2009/06/25 23:36:57  cheshire
+To facilitate testing, added command-line switch "-OfferSleepProxyService"
+to re-enable the previously-supported mode of operation where we offer
+sleep proxy service on desktop Macs that are set to never sleep.
+
+Revision 1.432  2009/05/13 17:25:33  mkrochma
+<rdar://problem/6879926> Should not schedule maintenance wake when machine has no advertised services
+Sleep proxy client should only look for services being advertised via Multicast
+
+Revision 1.431  2009/05/12 23:21:18  cheshire
+<rdar://problem/6879926> Should not schedule maintenance wake when machine has no advertised services
+Use mDNSCoreHaveAdvertisedServices routine to determine whether we should schedule a maintenance wake
+
+Revision 1.430  2009/05/01 19:17:36  cheshire
+<rdar://problem/6501561> Sleep Proxy: Reduce the frequency of maintenance wakes: ODD, fans, power
+
+Revision 1.429  2009/04/30 20:07:50  mcguire
+<rdar://problem/6822674> Support multiple UDSs from launchd
+
+Revision 1.428  2009/04/22 19:43:37  cheshire
+To facilitate debugging, added -DebugLogging and -UnicastPacketLogging switches
+as launch-time alternatives to sending SIGUSR1 and SIGUSR2 signals later
+
+Revision 1.427  2009/04/22 01:19:57  jessic2
+<rdar://problem/6814585> Daemon: mDNSResponder is logging garbage for error codes because it's using %ld for int 32
+
+Revision 1.426  2009/04/20 19:25:26  cheshire
+For readability, changed "nomulticastadvertisements" to "NoMulticastAdvertisements"
+
+Revision 1.425  2009/04/20 19:17:19  cheshire
+Added a comment explaining why we don't need our CatchABRT handler on 10.5 and later
+
+Revision 1.424  2009/04/17 19:10:27  mcguire
+<rdar://problem/6802833> May still ping-pong with kernel when a framework calls abort()
+
+Revision 1.423  2009/04/16 16:03:08  mcguire
+<rdar://problem/6792024> abort() causes high CPU usage instead of crash & restart
+
+Revision 1.422  2009/04/11 01:43:28  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.421  2009/04/11 00:20:06  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.420  2009/03/20 23:53:03  jessic2
+<rdar://problem/6646228> SIGHUP should restart all in-progress queries
+
+Revision 1.419  2009/03/20 21:30:04  cheshire
+<rdar://problem/6705866> Crash passing invalid parameters to DNSServiceBrowserCreate()
+Do not append a new question to the browser list until *after* we verify that mDNS_StartBrowse() succeeded
+
+Revision 1.418  2009/03/17 21:32:15  cheshire
+Improved "DHCPWakeTime: SCDynamicStoreCopyDHCPInfo failed" error message
+
+Revision 1.417  2009/03/17 01:25:39  cheshire
+<rdar://problem/6601427> Sleep Proxy: Retransmit and retry Sleep Proxy Server requests
+In SIGINFO output, show three best Sleep Proxies
+
+Revision 1.416  2009/02/21 01:47:36  cheshire
+<rdar://problem/6600825> Race condition when sleep initiated and then immediately canceled
+
+Revision 1.415  2009/02/21 01:45:33  cheshire
+Move declaration of "mDNSs32 interval"
+
+Revision 1.414  2009/02/14 00:05:32  cheshire
+Left-justify interface names
+
+Revision 1.413  2009/02/13 18:16:05  cheshire
+Fixed some compile warnings
+
+Revision 1.412  2009/02/13 06:34:41  cheshire
+Converted LogOperation messages to LogInfo or LogSPS
+
+Revision 1.411  2009/02/12 20:57:26  cheshire
+Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
+
+Revision 1.410  2009/02/11 02:32:18  cheshire
+m->p->SystemWakeForNetworkAccessEnabled renamed to m->SystemWakeOnLANEnabled
+
+Revision 1.409  2009/02/09 21:16:14  cheshire
+Improved debugging messages
+
+Revision 1.408  2009/02/07 06:08:44  cheshire
+Commented out testing code
+
+Revision 1.407  2009/02/07 02:57:31  cheshire
+<rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
+
+Revision 1.406  2009/02/06 03:06:49  mcguire
+<rdar://problem/5858533> Adopt vproc_transaction API in mDNSResponder
+
+Revision 1.405  2009/02/04 23:00:28  cheshire
+Move logic for deciding when to next wake up into a subroutine called AllowSleepNow
+
+Revision 1.404  2009/02/02 22:18:32  cheshire
+If we wake up and find no wireless network, don't just give up and go back to sleep and never try again
+
+Revision 1.403  2009/01/15 21:58:18  cheshire
+Stop using ifa_name field of NetworkInterfaceInfoOSX structure, because it will be going away
+
+Revision 1.402  2009/01/07 23:08:18  cheshire
+Updated debugging messages and comments
+
+Revision 1.401  2008/12/17 05:05:26  cheshire
+Fixed alignment of NAT mapping syslog messages
+
+Revision 1.400  2008/12/10 19:30:57  cheshire
+Use symbolic name OSXVers_10_3_Panther in version check instead of literal integer "7"
+
+Revision 1.399  2008/12/10 02:13:04  cheshire
+Fix alignment of SIGINFO output for longer interface names like "bridge0"
+
+Revision 1.398  2008/12/04 21:08:51  mcguire
+<rdar://problem/6116863> mDNS: Provide mechanism to disable Multicast advertisements
+
+Revision 1.397  2008/12/04 02:18:50  cheshire
+Improved sleep/wake debugging messages
+
+Revision 1.396  2008/11/26 23:37:44  cheshire
+Use SCDynamicStoreCopyDHCPInfo to compute desired wakeup time for our next DHCP lease renewal
+
+Revision 1.395  2008/11/14 21:56:31  cheshire
+Moved debugging routine ShowTaskSchedulingError() from daemon.c into DNSCommon.c
+
+Revision 1.394  2008/11/14 02:20:03  cheshire
+Include m->NextScheduledSPS in task scheduling calculations
+
+Revision 1.393  2008/11/14 01:22:38  cheshire
+Include SPS-registered records when computing the next required wakeup time
+
+Revision 1.392  2008/11/11 01:55:16  cheshire
+Improved comments; minium requested sleep is 60 seconds
+
+Revision 1.391  2008/11/04 02:29:55  cheshire
+Clear interface list before sleeping
+
+Revision 1.390  2008/11/02 21:22:05  cheshire
+Changed mallocL size parameter back to "unsigned int"
+
+Revision 1.389  2008/11/02 21:14:58  cheshire
+Fixes to make mallocL/freeL debugging checks work on 64-bit
+
+Revision 1.388  2008/10/31 23:05:30  cheshire
+Move logic to decide when to at as Sleep Proxy Server from daemon.c to mDNSMacOSX.c
+
+Revision 1.387  2008/10/30 01:08:18  cheshire
+After waking for network maintenance operations go back to sleep again
+
+Revision 1.386  2008/10/29 22:03:39  cheshire
+Compute correct required wakeup time for NAT traversals and uDNS-registered records
+
+Revision 1.385  2008/10/28 20:40:13  cheshire
+Now that the BPF code in mDNSMacOSX.c makes its own CFSocketCreateWithNative directly, the
+udsSupportAddFDToEventLoop/udsSupportRemoveFDFromEventLoop routines can go back to using kqueue
+
+Revision 1.384  2008/10/27 22:22:59  cheshire
+Extra sanity checking in udsSupportAddFDToEventLoop/udsSupportRemoveFDFromEventLoop
+
+Revision 1.383  2008/10/27 07:24:53  cheshire
+Need a "usleep(1000)" (workaround for <rdar://problem/3585273>) to avoid crashes
+
+Revision 1.382  2008/10/24 01:51:48  cheshire
+Before going to sleep, request a future wakeup to renew NAT-PMP mappings, SPS registrations, etc.
+
+Revision 1.381  2008/10/23 22:25:58  cheshire
+Renamed field "id" to more descriptive "updateid"
+
+Revision 1.380  2008/10/23 02:25:08  cheshire
+Added locking in InternetSharingChanged()
+
+Revision 1.379  2008/10/22 23:23:59  cheshire
+Moved definition of OSXVers from daemon.c into mDNSMacOSX.c
+
+Revision 1.378  2008/10/22 19:55:35  cheshire
+Miscellaneous fixes; renamed FindFirstAnswerInCache to FindSPSInCache
+
+Revision 1.377  2008/10/22 17:17:22  cheshire
+Need to open and close BPF fds when turning Sleep Proxy Server on and off
+
+Revision 1.376  2008/10/22 01:42:39  cheshire
+Before allowing sleep, delay until NetWakeResolve queries have completed
+
+Revision 1.375  2008/10/20 22:31:31  cheshire
+Instead of requesting a single BPF descriptor via mDNSRequestBPF(), call mDNSMacOSXNetworkChanged()
+to signal that UDS is now available to handle BPF requests, and let it work out what it needs
+
+Revision 1.374  2008/10/16 22:40:48  cheshire
+Removed "usleep(100000);" from CFSCallBack()
+
+Revision 1.373  2008/10/16 20:49:30  cheshire
+When kevent/kqueue fails, fall back to using old CFSocket RunLoopSource instead
+
+Revision 1.372  2008/10/15 00:03:21  cheshire
+When finally going to sleep, update m->SleepState from SleepState_Transferring to SleepState_Sleeping
+
+Revision 1.371  2008/10/14 19:09:53  cheshire
+When going to sleep, delay sleep until we've got our acknowledgment from the SPS
+
+Revision 1.370  2008/10/09 22:32:27  cheshire
+Include MAC address in interface listing in SIGINFO output
+
+Revision 1.369  2008/10/09 19:32:39  cheshire
+Updated SIGINFO output to indicate whether we've found a sleep proxy server on a given interface
+Hollow sun with rays "☼" indicates we're still looking; solid sun with rays "☀" indicates we found one
+
+Revision 1.368  2008/10/03 21:23:17  mkrochma
+Fix crash by not passing NULL to CFGetTypeID
+
+Revision 1.367  2008/10/03 18:25:17  cheshire
+Instead of calling "m->MainCallback" function pointer directly, call mDNSCore routine "mDNS_ConfigChanged(m);"
+
+Revision 1.366  2008/10/03 00:34:55  cheshire
+<rdar://problem/6134215> Mac with Internet Sharing should also offer Sleep Proxy service
+Start and stop Sleep Proxy service when user starts and stops Internet Sharing
+
+Revision 1.365  2008/10/02 22:23:13  cheshire
+Additional debugging message giving explanation if shutdown is delayed
+
+Revision 1.364  2008/10/01 21:23:40  cheshire
+In SIGINFO interface listing, indicate whether NetWake is set
+
+Revision 1.363  2008/09/27 01:29:15  cheshire
+Call mDNSRequestBPF() to request the helper to send us the BPF fd
+
+Revision 1.362  2008/09/26 19:47:42  cheshire
+Fixed locking error: lock is supposed to be held when calling mDNS_PurgeCacheResourceRecord
+
+Revision 1.361  2008/09/15 23:52:30  cheshire
+<rdar://problem/6218902> mDNSResponder-177 fails to compile on Linux with .desc pseudo-op
+Made __crashreporter_info__ symbol conditional, so we only use it for OS X build
+
 Revision 1.360  2008/03/13 20:55:16  mcguire
 <rdar://problem/5769316> fix deprecated warnings/errors
 Additional cleanup: use a conditional macro instead of lots of #if
@@ -102,7 +336,7 @@ Revision 1.340  2007/09/07 22:44:03  mcguire
 <rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
 
 Revision 1.339  2007/09/06 19:08:29  cheshire
-LogAllOperations check needs to be "#if LogAllOperations || MDNS_DEBUGMSGS"
+LogClientOperations check needs to be "#if LogClientOperations || MDNS_DEBUGMSGS"
 
 Revision 1.338  2007/09/05 23:34:27  mcguire
 Revert logging change
@@ -378,6 +612,7 @@ Revision 1.261  2006/01/06 01:22:28  cheshire
 #include <pthread.h>
 #include <sandbox.h>
 #include <SystemConfiguration/SCPreferencesSetSpecific.h>
+#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
 
 #if TARGET_OS_EMBEDDED
 #include <bootstrap_priv.h>
@@ -396,9 +631,12 @@ Revision 1.261  2006/01/06 01:22:28  cheshire
 
 #include <DNSServiceDiscovery/DNSServiceDiscovery.h>
 #include "helper.h"
+#include "safe_vproc.h"
 
 //*************************************************************************************************************
-// Globals
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark - Globals
+#endif
 
 static mDNS_PlatformSupport PlatformStorage;
 
@@ -415,7 +653,8 @@ static mach_port_t client_death_port = MACH_PORT_NULL;
 static mach_port_t signal_port       = MACH_PORT_NULL;
 static mach_port_t server_priv_port  = MACH_PORT_NULL;
 
-static dnssd_sock_t launchd_fd = dnssd_InvalidSocket;
+static dnssd_sock_t *launchd_fds = mDNSNULL;
+static mDNSu32 launchd_fds_count = 0;
 
 // mDNS Mach Message Timeout, in milliseconds.
 // We need this to be short enough that we don't deadlock the mDNSResponder if a client
@@ -427,13 +666,13 @@ static dnssd_sock_t launchd_fd = dnssd_InvalidSocket;
 
 static int restarting_via_mach_init = 0;       // Used on Jaguar/Panther when daemon is started via mach_init mechanism
 static int started_via_launchdaemon = 0;       // Indicates we're running on Tiger or later, where daemon is managed by launchd
-
-static int OSXVers;
-
-static CFRunLoopRef CFRunLoop;
+static mDNSBool advertise = mDNS_Init_AdvertiseLocalAddresses; // By default, advertise addresses (& other records) via multicast
 
 //*************************************************************************************************************
-// Active client list structures
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Active client list structures
+#endif
 
 typedef struct DNSServiceDomainEnumeration_struct DNSServiceDomainEnumeration;
 struct DNSServiceDomainEnumeration_struct
@@ -469,7 +708,7 @@ struct DNSServiceBrowser_struct
        DNSServiceBrowserResult *results;
        mDNSs32 lastsuccess;
     mDNSBool DefaultDomain;                // was the browse started on an explicit domain?
-    domainname type;                       //  registration type 
+    domainname type;                       // registration type
        };
 
 typedef struct DNSServiceResolver_struct DNSServiceResolver;
@@ -509,7 +748,7 @@ typedef struct DNSServiceRegistration
     size_t rdsize;
     int NumSubTypes;
     char regtype[MAX_ESCAPED_DOMAIN_NAME]; // for use in AllocateSubtypes
-    domainlabel name;  // used only if autoname is false 
+    domainlabel name;  // used only if autoname is false
     domainname type;
     mDNSIPPort port;
     unsigned char txtinfo[1024];
@@ -534,7 +773,10 @@ typedef struct KQSocketEventSource
 static KQSocketEventSource *gEventSources;
 
 //*************************************************************************************************************
-// General Utility Functions
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - General Utility Functions
+#endif
 
 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
 
@@ -636,8 +878,8 @@ mDNSlocal void validatelists(mDNS *const m)
        // Check platform-layer lists
        NetworkInterfaceInfoOSX     *i;
        for (i = m->p->InterfaceList; i; i = i->next)
-               if (i->next == (NetworkInterfaceInfoOSX *)~0 || !i->ifa_name || i->ifa_name == (char *)~0)
-                       LogMemCorruption("m->p->InterfaceList: %p is garbage (%p)", i, i->ifa_name);
+               if (i->next == (NetworkInterfaceInfoOSX *)~0 || !i->m || i->m == (mDNS *)~0)
+                       LogMemCorruption("m->p->InterfaceList: %p is garbage (%p)", i, i->ifinfo.ifname);
 
        ClientTunnel *t;
        for (t = m->TunnelClients; t; t=t->next)
@@ -645,14 +887,12 @@ mDNSlocal void validatelists(mDNS *const m)
                        LogMemCorruption("m->TunnelClients: %p is garbage (%d)", t, t->dstname.c[0]);
        }
 
-void *mallocL(char *msg, unsigned int size)
+mDNSexport void *mallocL(char *msg, unsigned int size)
        {
-       unsigned long *mem = malloc(size+8);
+       // Allocate space for two words of sanity checking data before the requested block
+       mDNSu32 *mem = malloc(sizeof(mDNSu32) * 2 + size);
        if (!mem)
-               {
-               LogMsg("malloc( %s : %d ) failed", msg, size);
-               return(NULL);
-               }
+               { LogMsg("malloc( %s : %d ) failed", msg, size); return(NULL); }
        else
                {
                if      (size > 24000)                      LogMsg("malloc( %s : %lu ) = %p suspiciously large", msg, size, &mem[2]);
@@ -666,18 +906,18 @@ void *mallocL(char *msg, unsigned int size)
                }
        }
 
-void freeL(char *msg, void *x)
+mDNSexport void freeL(char *msg, void *x)
        {
        if (!x)
                LogMsg("free( %s @ NULL )!", msg);
        else
                {
-               unsigned long *mem = ((unsigned long *)x) - 2;
-               if (mem[0] != 0xDEAD1234) { LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg, &mem[2]); return; }
+               mDNSu32 *mem = ((mDNSu32 *)x) - 2;
+               if      (mem[0] != 0xDEAD1234)            { LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg, &mem[2]); return; }
                if      (mem[1] > 24000)                    LogMsg("free( %s : %ld @ %p) suspiciously large", msg, mem[1], &mem[2]);
                else if (MACOSX_MDNS_MALLOC_DEBUGGING >= 2) LogMsg("free( %s : %ld @ %p)",                    msg, mem[1], &mem[2]);
-               //mDNSPlatformMemZero(mem, mem[1]+8);
-               memset(mem, 0xFF, mem[1]+8);
+               //mDNSPlatformMemZero(mem, sizeof(mDNSu32) * 2 + mem[1]);
+               memset(mem, 0xFF, sizeof(mDNSu32) * 2 + mem[1]);
                validatelists(&mDNSStorage);
                free(mem);
                }
@@ -685,6 +925,12 @@ void freeL(char *msg, void *x)
 
 #endif
 
+//*************************************************************************************************************
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Mach client request handlers
+#endif
+
 //*************************************************************************************************************
 // Client Death Detection
 
@@ -784,7 +1030,7 @@ mDNSlocal void AbortClient(mach_port_t ClientMachPort, void *m)
                while (si)
                        {
                        ServiceInstance *instance = si;
-                       si = si->next;                 
+                       si = si->next;
                        instance->renameonmemfree = mDNSfalse;
                        if (m && m != x) LogMsg("%5d: DNSServiceRegistration(%##s, %u) STOP; WARNING m %p != x %p", ClientMachPort, instance->srs.RR_SRV.resrec.name->c, SRS_PORT(&instance->srs), m, x);
                        else LogOperation("%5d: DNSServiceRegistration(%##s, %u) STOP", ClientMachPort, instance->srs.RR_SRV.resrec.name->c, SRS_PORT(&instance->srs));
@@ -959,7 +1205,7 @@ mDNSexport kern_return_t provide_DNSServiceDomainEnumerationCreate_rpc(mach_port
        return(mStatus_NoError);
 
 fail:
-       LogMsg("%5d: DNSServiceDomainEnumeration(%d) failed: %s (%ld)", client, regDom, errormsg, err);
+       LogMsg("%5d: DNSServiceDomainEnumeration(%d) failed: %s (%d)", client, regDom, errormsg, err);
        return(err);
        }
 
@@ -1016,10 +1262,15 @@ mDNSlocal mStatus AddDomainToBrowser(DNSServiceBrowser *browser, const domainnam
        if (!question) { LogMsg("Error: malloc"); return mStatus_NoMemoryErr; }
        AssignDomainName(&question->domain, d);
        question->next = browser->qlist;
-       browser->qlist = question;
        LogOperation("%5d: DNSServiceBrowse(%##s%##s) START", browser->ClientMachPort, browser->type.c, d->c);
        err = mDNS_StartBrowse(&mDNSStorage, &question->q, &browser->type, d, mDNSInterface_Any, mDNSfalse, FoundInstance, browser);
-       if (err) LogMsg("Error: AddDomainToBrowser: mDNS_StartBrowse %d", err);
+       if (!err)
+               browser->qlist = question;
+       else
+               {
+               LogMsg("Error: AddDomainToBrowser: mDNS_StartBrowse %d", err);
+               freeL("DNSServiceBrowserQuestion", question);
+               }
        return err;
        }
 
@@ -1126,7 +1377,7 @@ mDNSexport kern_return_t provide_DNSServiceBrowserCreate_rpc(mach_port_t unuseds
        badparam:
        err = mStatus_BadParamErr;
 fail:
-       LogMsg("%5d: DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", client, regtype, domain, errormsg, err);
+       LogMsg("%5d: DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%d)", client, regtype, domain, errormsg, err);
        return(err);
        }
 
@@ -1257,7 +1508,7 @@ mDNSexport kern_return_t provide_DNSServiceResolverResolve_rpc(mach_port_t unuse
 badparam:
        err = mStatus_BadParamErr;
 fail:
-       LogMsg("%5d: DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", client, name, regtype, domain, errormsg, err);
+       LogMsg("%5d: DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%d)", client, name, regtype, domain, errormsg, err);
        return(err);
        }
 
@@ -1293,7 +1544,7 @@ mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus r
                        {
                        // On conflict for an autoname service, rename and reregister *all* autoname services
                        IncrementLabelSuffix(&m->nicelabel, mDNStrue);
-                       m->MainCallback(m, mStatus_ConfigChanged);
+                       mDNS_ConfigChanged(m);
                        }
                else if (si->autoname)
                        {
@@ -1339,7 +1590,7 @@ mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus r
                }
 
        else if (result != mStatus_NATTraversal)
-               LogMsg("%5d: DNSServiceRegistration(%##s, %u) Unknown Result %ld", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs), result);
+               LogMsg("%5d: DNSServiceRegistration(%##s, %u) Unknown Result %d", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs), result);
        }
 
 mDNSlocal mStatus AddServiceInstance(DNSServiceRegistration *x, const domainname *domain)
@@ -1531,7 +1782,7 @@ badtxt:
 badparam:
        err = mStatus_BadParamErr;
 fail:
-       LogMsg("%5d: DNSServiceRegister(\"%s\", \"%s\", \"%s\", %d) failed: %s (%ld)",
+       LogMsg("%5d: DNSServiceRegister(\"%s\", \"%s\", \"%s\", %d) failed: %s (%d)",
                   client, name, regtype, domain, mDNSVal16(port), errormsg, err);
        return(err);
        }
@@ -1542,13 +1793,13 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
        if (result == mStatus_NoError)
                {
                if (!SameDomainLabelCS(m->p->userhostlabel.c, m->hostlabel.c))
-                       LogOperation("Local Hostname changed from \"%#s.local\" to \"%#s.local\"", m->p->userhostlabel.c, m->hostlabel.c);
+                       LogInfo("Local Hostname changed from \"%#s.local\" to \"%#s.local\"", m->p->userhostlabel.c, m->hostlabel.c);
                // One second pause in case we get a Computer Name update too -- don't want to alert the user twice
                RecordUpdatedNiceLabel(m, mDNSPlatformOneSecond);
                }
        else if (result == mStatus_NameConflict)
                {
-               LogOperation("Local Hostname conflict for \"%#s.local\"", m->hostlabel.c);
+               LogInfo("Local Hostname conflict for \"%#s.local\"", m->hostlabel.c);
                if (!m->p->HostNameConflict) m->p->HostNameConflict = NonZeroTime(m->timenow);
                else if (m->timenow - m->p->HostNameConflict > 60 * mDNSPlatformOneSecond)
                        {
@@ -1560,7 +1811,7 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
                {
                // Allocate another chunk of cache storage
                CacheEntity *storage = mallocL("mStatus_GrowCache", sizeof(CacheEntity) * RR_CACHE_SIZE);
-               //LogOperation("GrowCache %d * %d = %d", sizeof(CacheEntity), RR_CACHE_SIZE, sizeof(CacheEntity) * RR_CACHE_SIZE);
+               //LogInfo("GrowCache %d * %d = %d", sizeof(CacheEntity), RR_CACHE_SIZE, sizeof(CacheEntity) * RR_CACHE_SIZE);
                if (storage) mDNS_GrowCache(m, storage, RR_CACHE_SIZE);
                }
        else if (result == mStatus_ConfigChanged)
@@ -1647,7 +1898,7 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationAddRecord_rpc(mach_port_t
        return mStatus_NoError;
 
 fail:
-       LogMsg("%5d: DNSServiceRegistrationAddRecord(%##s, type %d, length %d) failed: %s (%ld)", client, x ? x->name.c : (mDNSu8*)"\x8""«NULL»", type, data_len, errormsg, err);
+       LogMsg("%5d: DNSServiceRegistrationAddRecord(%##s, type %d, length %d) failed: %s (%d)", client, x ? x->name.c : (mDNSu8*)"\x8""«NULL»", type, data_len, errormsg, err);
        return mStatus_UnknownErr;
        }
 
@@ -1698,7 +1949,7 @@ mDNSlocal mStatus UpdateRecord(ServiceRecordSet *srs, mach_port_t client, AuthRe
        return(mStatus_NoError);
 
 fail:
-       LogMsg("%5d: DNSServiceRegistrationUpdateRecord(%##s, %d) failed: %s (%ld)", client, name->c, data_len, errormsg, err);
+       LogMsg("%5d: DNSServiceRegistrationUpdateRecord(%##s, %d) failed: %s (%d)", client, name->c, data_len, errormsg, err);
        return(err);
        }
 
@@ -1743,7 +1994,7 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationUpdateRecord_rpc(mach_por
        return mStatus_NoError;
 
 fail:
-       LogMsg("%5d: DNSServiceRegistrationUpdateRecord(%##s, %X, %d) failed: %s (%ld)", client, name->c, reference, data_len, errormsg, err);
+       LogMsg("%5d: DNSServiceRegistrationUpdateRecord(%##s, %X, %d) failed: %s (%d)", client, name->c, reference, data_len, errormsg, err);
        return(err);
        }
 
@@ -1792,12 +2043,15 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationRemoveRecord_rpc(mach_por
        return mStatus_NoError;
 
 fail:
-       LogMsg("%5d: DNSServiceRegistrationRemoveRecord(%X) failed: %s (%ld)", client, reference, errormsg, err);
+       LogMsg("%5d: DNSServiceRegistrationRemoveRecord(%X) failed: %s (%d)", client, reference, errormsg, err);
        return(err);
        }
 
 //*************************************************************************************************************
-// Support Code
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Startup, shutdown, and supporting code
+#endif
 
 mDNSlocal void DNSserverCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
        {
@@ -1955,7 +2209,7 @@ mDNSlocal kern_return_t destroyBootstrapService()
 mDNSlocal void ExitCallback(int sig)
        {
        (void)sig; // Unused
-       LogMsgIdent(mDNSResponderVersionString, "stopping");
+       LogMsg("%s stopping", mDNSResponderVersionString);
 
        debugf("ExitCallback");
        if (!mDNS_DebugMode && !started_via_launchdaemon)
@@ -1971,7 +2225,7 @@ mDNSlocal void ExitCallback(int sig)
        while (DNSServiceRegistrationList)
                AbortClient(DNSServiceRegistrationList     ->ClientMachPort, DNSServiceRegistrationList);
 
-       if (udsserver_exit(launchd_fd) < 0) LogMsg("ExitCallback: udsserver_exit failed");
+       if (udsserver_exit() < 0) LogMsg("ExitCallback: udsserver_exit failed");
 
        debugf("ExitCallback: mDNS_StartExit");
        mDNS_StartExit(&mDNSStorage);
@@ -1980,8 +2234,7 @@ mDNSlocal void ExitCallback(int sig)
 // Send a mach_msg to ourselves (since that is signal safe) telling us to cleanup and exit
 mDNSlocal void HandleSIG(int sig)
        {
-       debugf(" ");
-       debugf("HandleSIG %d", sig);
+       // WARNING: can't call syslog or fprintf from signal handler
        mach_msg_header_t header;
        header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
        header.msgh_remote_port = signal_port;
@@ -1989,17 +2242,19 @@ mDNSlocal void HandleSIG(int sig)
        header.msgh_size = sizeof(header);
        header.msgh_id = sig;
        if (mach_msg_send(&header) != MACH_MSG_SUCCESS)
-               {
-               LogMsg("HandleSIG %d: mach_msg_send failed", sig);
                if (sig == SIGTERM || sig == SIGINT) exit(-1);
-               }
        }
 
 mDNSlocal void CatchABRT(int sig)
        {
-       LogMsg("Received SIGABRT %d", sig);
-       sleep(1);                                       // Pause to make sure syslog gets the message
-       while(1) *(long*)0 = 0;         // Generate a CrashReporter stack trace so we can find out what library called abort();
+       // WARNING: can't call syslog or fprintf from signal handler
+       // We want a CrashReporter stack trace so we can find out what library called abort()
+       // So that we will crash, unblock all signals (that abort() may have blocked)
+       sigset_t mask;
+       sigfillset(&mask);
+       sigprocmask(SIG_UNBLOCK, &mask, NULL);
+       (void)sig;
+       while(1) *(long*)0 = 0;
        }
 
 mDNSlocal void INFOCallback(void)
@@ -2012,7 +2267,7 @@ mDNSlocal void INFOCallback(void)
        NetworkInterfaceInfoOSX     *i;
        DNSServer *s;
 
-       LogMsgIdent(mDNSResponderVersionString, "---- BEGIN STATE LOG ----");
+       LogMsg("---- BEGIN STATE LOG ----");
        
        udsserver_info(&mDNSStorage);
 
@@ -2056,21 +2311,32 @@ mDNSlocal void INFOCallback(void)
                {
                for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
                        {
+                       // Allow six characters for interface name, for names like "vmnet8"
                        if (!i->Exists)
-                               LogMsgNoIdent("Interface: %s %5s(%lu) %.6a %#a dormant for %d seconds",
-                                       i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifa_name, i->scope_id, &i->BSSID,
+                               LogMsgNoIdent("%p %s %-6s(%lu) %.6a %.6a %#-14a dormant for %d seconds",
+                                       i->ifinfo.InterfaceID,
+                                       i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, i->scope_id, &i->ifinfo.MAC, &i->BSSID,
                                        &i->ifinfo.ip, utc - i->LastSeen);
                        else
-                               LogMsgNoIdent("Interface: %s %5s(%lu) %.6a %s %s %-15.4a %s InterfaceID %p %s %s %#a",
-                                       i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifa_name, i->scope_id, &i->BSSID,
+                               {
+                               const CacheRecord *sps[3];
+                               FindSPSInCache(&mDNSStorage, &i->ifinfo.NetWakeBrowse, sps);
+                               LogMsgNoIdent("%p %s %-6s(%lu) %.6a %.6a %s %s %-15.4a %s %s %s %s %#a",
+                                       i->ifinfo.InterfaceID,
+                                       i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, i->scope_id, &i->ifinfo.MAC, &i->BSSID,
                                        i->ifinfo.InterfaceActive ? "Active" : "      ",
                                        i->ifinfo.IPv4Available ? "v4" : "  ",
                                        i->ifinfo.IPv4Available ? (mDNSv4Addr*)&i->ifa_v4addr : &zerov4Addr,
                                        i->ifinfo.IPv6Available ? "v6" : "  ",
-                                       i->ifinfo.InterfaceID,
-                                       i->ifinfo.Advertise ? "Adv"  : "   ",
-                                       i->ifinfo.McastTxRx ? "TxRx" : "    ",
+                                       i->ifinfo.Advertise ? "⊙" : " ",
+                                       i->ifinfo.McastTxRx ? "⇆" : " ",
+                                       !(i->ifinfo.InterfaceActive && i->ifinfo.NetWake) ? " " : !sps[0] ? "☼" : "☀",
                                        &i->ifinfo.ip);
+
+                               if (sps[0]) LogMsgNoIdent("  %13d %#s", SPSMetric(sps[0]->resrec.rdata->u.name.c), sps[0]->resrec.rdata->u.name.c);
+                               if (sps[1]) LogMsgNoIdent("  %13d %#s", SPSMetric(sps[1]->resrec.rdata->u.name.c), sps[1]->resrec.rdata->u.name.c);
+                               if (sps[2]) LogMsgNoIdent("  %13d %#s", SPSMetric(sps[2]->resrec.rdata->u.name.c), sps[2]->resrec.rdata->u.name.c);
+                               }
                        }
                }
 
@@ -2082,7 +2348,7 @@ mDNSlocal void INFOCallback(void)
                        {
                        NetworkInterfaceInfoOSX *ifx = (NetworkInterfaceInfoOSX *)s->interface;
                        LogMsgNoIdent("DNS Server %##s %s%s%#a:%d %s",
-                               s->domain.c, ifx ? ifx->ifa_name : "", ifx ? " " : "", &s->addr, mDNSVal16(s->port),
+                               s->domain.c, ifx ? ifx->ifinfo.ifname : "", ifx ? " " : "", &s->addr, mDNSVal16(s->port),
                                s->teststate == DNSServer_Untested ? "(Untested)" :
                                s->teststate == DNSServer_Passed   ? ""           :
                                s->teststate == DNSServer_Failed   ? "(Failed)"   :
@@ -2091,9 +2357,9 @@ mDNSlocal void INFOCallback(void)
                }
 
        mDNSs32 now = mDNS_TimeNow(&mDNSStorage);
-       LogMsgNoIdent("Timenow 0x%08lX (%ld)", (mDNSu32)now, now);
+       LogMsgNoIdent("Timenow 0x%08lX (%d)", (mDNSu32)now, now);
 
-       LogMsgIdent(mDNSResponderVersionString, "----  END STATE LOG  ----");
+       LogMsg("----  END STATE LOG  ----");
        }
 
 mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
@@ -2113,22 +2379,22 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void
                                                CacheGroup *cg;
                                                CacheRecord *rr;
                                                LogMsg("SIGHUP: Purge cache");
+                                               mDNS_Lock(m);
                                                FORALL_CACHERECORDS(slot, cg, rr) mDNS_PurgeCacheResourceRecord(m, rr);
+                                               // Restart unicast and multicast queries
+                                               mDNSCoreRestartQueries(m);
+                                               mDNS_Unlock(m);
                                                } break;
                case SIGINT:
                case SIGTERM:   ExitCallback(msg_header->msgh_id); break;
                case SIGINFO:   INFOCallback(); break;
-               case SIGUSR1:   // mDNSCoreMachineSleep(m, !m->SleepState); break;
-                                               LogMsg("SIGUSR1: Simulate Network Configuration Change Event");
-                                               mDNSMacOSXNetworkChanged(m);
-
-                                               // Simulate KeychainChanged
-                                               mDNS_Lock(m);
-                                               SetDomainSecrets(m);
-                                               mDNS_Unlock(m);
-
+               case SIGUSR1:   mDNS_LoggingEnabled = mDNS_LoggingEnabled ? 0 : 1;
+                                               LogMsg("SIGUSR1: Logging %s", mDNS_LoggingEnabled ? "Enabled" : "Disabled");
+                                               WatchDogReportingThreshold = mDNS_LoggingEnabled ? 50 : 250;
+                                               break;
+               case SIGUSR2:   mDNS_PacketLoggingEnabled = mDNS_PacketLoggingEnabled ? 0 : 1;
+                                               LogMsg("SIGUSR2: Packet Logging %s", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
                                                break;
-               case SIGUSR2:   SigLogLevel(); break;
                default: LogMsg("SignalCallback: Unknown signal %d", msg_header->msgh_id); break;
                }
        KQueueUnlock(m, "Unix Signal");
@@ -2149,7 +2415,7 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void)
                {
                s_port = CFMachPortCreate(NULL, DNSserverCallback, NULL, NULL);
                m_port = CFMachPortGetPort(s_port);
-               char *MachServerName = OSXVers < 7 ? "DNSServiceDiscoveryServer" : "com.apple.mDNSResponder";
+               char *MachServerName = OSXVers < OSXVers_10_3_Panther ? "DNSServiceDiscoveryServer" : "com.apple.mDNSResponder";
                kern_return_t status = bootstrap_register(bootstrap_port, MachServerName, m_port);
        
                if (status)
@@ -2170,18 +2436,17 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void)
 
        err = mDNS_Init(&mDNSStorage, &PlatformStorage,
                rrcachestorage, RR_CACHE_SIZE,
-               mDNS_Init_AdvertiseLocalAddresses,
+               advertise,
                mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
 
-       if (err) { LogMsg("Daemon start: mDNS_Init failed %ld", err); return(err); }
+       if (err) { LogMsg("Daemon start: mDNS_Init failed %d", err); return(err); }
 
        client_death_port = CFMachPortGetPort(d_port);
        signal_port       = CFMachPortGetPort(i_port);
 
-       CFRunLoop = CFRunLoopGetCurrent();
-       CFRunLoopAddSource(CFRunLoop, d_rls, kCFRunLoopDefaultMode);
-       CFRunLoopAddSource(CFRunLoop, s_rls, kCFRunLoopDefaultMode);
-       CFRunLoopAddSource(CFRunLoop, i_rls, kCFRunLoopDefaultMode);
+       CFRunLoopAddSource(PlatformStorage.CFRunLoop, d_rls, kCFRunLoopDefaultMode);
+       CFRunLoopAddSource(PlatformStorage.CFRunLoop, s_rls, kCFRunLoopDefaultMode);
+       CFRunLoopAddSource(PlatformStorage.CFRunLoop, i_rls, kCFRunLoopDefaultMode);
        CFRelease(d_rls);
        CFRelease(s_rls);
        CFRelease(i_rls);
@@ -2201,6 +2466,8 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
        // we then systematically lose our own looped-back packets.
        if (m->p->NetworkChanged && now - m->p->NetworkChanged >= 0) mDNSMacOSXNetworkChanged(m);
 
+       if (m->p->RequestReSleep && now - m->p->RequestReSleep >= 0) { m->p->RequestReSleep = 0; mDNSPowerRequest(0, 0); }
+
        // KeyChain frequently fails to notify clients of change events. To work around this
        // we set a timer and periodically poll to detect if any changes have occurred.
        // Without this Back To My Mac just does't work for a large number of users.
@@ -2226,12 +2493,16 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
                if (nextevent - m->p->KeyChainBugTimer > 0)
                        nextevent = m->p->KeyChainBugTimer;
 
+       if (m->p->RequestReSleep)
+               if (nextevent - m->p->RequestReSleep > 0)
+                       nextevent = m->p->RequestReSleep;
+
        // 3. Deliver any waiting browse messages to clients
        DNSServiceBrowser *b = DNSServiceBrowserList;
 
        while (b)
                {
-               // NOTE: Need to advance b to the next element BEFORE we call DeliverInstance(), because in the
+               // Note: Need to advance b to the next element BEFORE we call DeliverInstance(), because in the
                // event that the client Mach queue overflows, DeliverInstance() will call AbortBlockedClient()
                // and that will cause the DNSServiceBrowser object's memory to be freed before it returns
                DNSServiceBrowser *x = b;
@@ -2308,61 +2579,202 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
        return(nextevent);
        }
 
-mDNSlocal void ShowTaskSchedulingError(mDNS *const m)
+// Right now we consider *ALL* of our DHCP leases
+// It might make sense to be a bit more selective and only consider the leases on interfaces
+// (a) that are capable and enabled for wake-on-LAN, and
+// (b) where we have found (and successfully registered with) a Sleep Proxy
+// If we can't be woken for traffic on a given interface, then why keep waking to renew its lease?
+mDNSlocal mDNSu32 DHCPWakeTime(void)
        {
-       mDNS_Lock(m);
-
-       LogMsg("Task Scheduling Error: Continuously busy for more than a second");
-       
-       // NOTE: To accurately diagnose *why* we're busy, the debugging code here needs to mirror the logic in GetNextScheduledEvent
-
-       if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0))
-               LogMsg("Task Scheduling Error: NewQuestion %##s (%s)",
-                       m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
-       if (m->NewLocalOnlyQuestions)
-               LogMsg("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)",
-                       m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
-       if (m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords))
-               LogMsg("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, m->NewLocalRecords));
-       if (m->SuppressSending && m->timenow - m->SuppressSending >= 0)
-               LogMsg("Task Scheduling Error: m->SuppressSending %d",       m->timenow - m->SuppressSending);
-#ifndef UNICAST_DISABLED
-       if (m->timenow - m->NextuDNSEvent         >= 0)
-               LogMsg("Task Scheduling Error: NextuDNSEvent %d",            m->timenow - m->NextuDNSEvent);
-#endif
-       if (m->timenow - m->NextCacheCheck        >= 0)
-               LogMsg("Task Scheduling Error: m->NextCacheCheck %d",        m->timenow - m->NextCacheCheck);
-       if (m->timenow - m->NextScheduledQuery    >= 0)
-               LogMsg("Task Scheduling Error: m->NextScheduledQuery %d",    m->timenow - m->NextScheduledQuery);
-       if (m->timenow - m->NextScheduledProbe    >= 0)
-               LogMsg("Task Scheduling Error: m->NextScheduledProbe %d",    m->timenow - m->NextScheduledProbe);
-       if (m->timenow - m->NextScheduledResponse >= 0)
-               LogMsg("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse);
-       if (m->timenow - m->NextScheduledNATOp >= 0)
-               LogMsg("Task Scheduling Error: m->NextScheduledNATOp %d",    m->timenow - m->NextScheduledNATOp);
-
-       mDNS_Unlock(&mDNSStorage);
+       mDNSu32 e = 24 * 3600;          // Maximum maintenance wake interval is 24 hours
+       const CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
+       if (!now) LogMsg("DHCPWakeTime: CFAbsoluteTimeGetCurrent failed");
+       else
+               {
+               const SCPreferencesRef prefs = SCPreferencesCreate(NULL, CFSTR("mDNSResponder:DHCPWakeTime"), NULL);
+               if (!prefs) LogMsg("DHCPWakeTime: SCPreferencesCreate failed");
+               else
+                       {
+                       const SCNetworkSetRef currentset = SCNetworkSetCopyCurrent(prefs);
+                       if (!currentset) LogMsg("DHCPWakeTime: SCNetworkSetCopyCurrent failed");
+                       else
+                               {
+                               const CFArrayRef services = SCNetworkSetCopyServices(currentset);
+                               if (!services) LogMsg("DHCPWakeTime: SCNetworkSetCopyServices failed");
+                               else
+                                       {
+                                       int i;
+                                       for (i = 0; i < CFArrayGetCount(services); i++)
+                                               {
+                                               const SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, i);
+                                               if (!service) LogMsg("DHCPWakeTime: CFArrayGetValueAtIndex %d failed", i);
+                                               else
+                                                       {
+                                                       const CFStringRef serviceid = SCNetworkServiceGetServiceID(service);
+                                                       if (!serviceid) LogMsg("DHCPWakeTime: SCNetworkServiceGetServiceID %d failed", i);
+                                                       else
+                                                               {
+                                                               // Note: It's normal for this call to return NULL, for interfaces not using DHCP
+                                                               const CFDictionaryRef dhcp = SCDynamicStoreCopyDHCPInfo(NULL, serviceid);
+                                                               if (dhcp)
+                                                                       {
+                                                                       const CFDateRef start = DHCPInfoGetLeaseStartTime(dhcp);
+                                                                       const CFDataRef lease = DHCPInfoGetOptionData(dhcp, 51);        // Option 51 = IP Address Lease Time
+                                                                       if (!start || !lease || CFDataGetLength(lease) < 4)
+                                                                               LogMsg("DHCPWakeTime: SCDynamicStoreCopyDHCPInfo index %d failed "
+                                                                                       "CFDateRef start %p CFDataRef lease %p CFDataGetLength(lease) %d",
+                                                                                       i, start, lease, lease ? CFDataGetLength(lease) : 0);
+                                                                       else
+                                                                               {
+                                                                               const UInt8 *d = CFDataGetBytePtr(lease);
+                                                                               if (!d) LogMsg("DHCPWakeTime: CFDataGetBytePtr %d failed", i);
+                                                                               else
+                                                                                       {
+                                                                                       const mDNSu32 elapsed   = now - CFDateGetAbsoluteTime(start);
+                                                                                       const mDNSu32 lifetime  = (mDNSs32) ((mDNSs32)d[0] << 24 | (mDNSs32)d[1] << 16 | (mDNSs32)d[2] << 8 | d[3]);
+                                                                                       const mDNSu32 remaining = lifetime - elapsed;
+                                                                                       const mDNSu32 wake      = remaining > 60 ? remaining - remaining/10 : 54;       // Wake at 90% of the lease time
+                                                                                       LogSPS("DHCP Address Lease Elapsed %6u Lifetime %6u Remaining %6u Wake %6u", elapsed, lifetime, remaining, wake);
+                                                                                       if (e > wake) e = wake;
+                                                                                       }
+                                                                               }
+                                                                       CFRelease(dhcp);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       CFRelease(services);
+                                       }
+                               CFRelease(currentset);
+                               }
+                       CFRelease(prefs);
+                       }
+               }
+       return(e);
        }
 
-mDNSlocal mDNSBool ReadyForSleep(mDNS *m)
+// We deliberately schedule our wakeup for halfway between when we'd *like* it and when we *need* it.
+// For example, if our DHCP lease expires in two hours, we'll typically renew it at the halfway point, after one hour.
+// If we scheduled our wakeup for the one-hour renewal time, that might be just seconds from now, and sleeping
+// for a few seconds and then waking again is silly and annoying.
+// If we scheduled our wakeup for the two-hour expiry time, and we were slow to wake, we might lose our lease.
+// Scheduling our wakeup for halfway in between -- 90 minutes -- avoids short wakeups while still
+// allowing us an adequate safety margin to renew our lease before we lose it.
+
+mDNSlocal mDNSBool AllowSleepNow(mDNS *const m, mDNSs32 now)
        {
-       (void)m;
+       mDNSBool ready = mDNSCoreReadyForSleep(m);
+       if (m->SleepState && !ready && now - m->SleepLimit < 0) return(mDNSfalse);
 
-       // 1. Scan list of private LLQs, and make sure they've all completed their handshake with the server
-       DNSQuestion *q;
-       for (q = m->Questions; q; q = q->next)
-               if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->ReqLease == 0 && q->tcp) return(mDNSfalse);
+       m->p->WakeAtUTC = 0;
+       int result = kIOReturnSuccess;
+       CFDictionaryRef opts = NULL;
 
-       // 2. Scan list of registered records
-       AuthRecord *rr;
-       for (rr = m->ResourceRecords; rr; rr = rr->next)
-               if (rr->state == regState_Refresh && rr->tcp) return(mDNSfalse);
+       // If the sleep request was cancelled, and we're no longer planning to sleep, don't need to
+       // do the stuff below, but we *DO* still need to acknowledge the sleep message we received.
+       if (!m->SleepState)
+               LogMsg("AllowSleepNow: Sleep request was canceled with %d ticks remaining", m->SleepLimit - now);
+       else
+               {
+               if (!m->SystemWakeOnLANEnabled || !mDNSCoreHaveAdvertisedMulticastServices(m))
+                       LogSPS("AllowSleepNow: Not scheduling wakeup: SystemWakeOnLAN %s enabled; %s advertised services",
+                               m->SystemWakeOnLANEnabled                  ? "is" : "not",
+                               mDNSCoreHaveAdvertisedMulticastServices(m) ? "have" : "no");
+               else
+                       {
+                       mDNSs32 dhcp = DHCPWakeTime();
+                       LogSPS("ComputeWakeTime: DHCP Wake %d", dhcp);
+                       mDNSs32 interval = mDNSCoreIntervalToNextWake(m, now) / mDNSPlatformOneSecond;
+                       if (interval > dhcp) interval = dhcp;
+       
+                       // If we're not ready to sleep (failed to register with Sleep Proxy, maybe because of
+                       // transient network problem) then schedule a wakeup in one hour to try again. Otherwise,
+                       // a single SPS failure could result in a remote machine falling permanently asleep, requiring
+                       // someone to go to the machine in person to wake it up again, which would be unacceptable.
+                       if (!ready && interval > 3600) interval = 3600;
+       
+                       //interval = 48; // For testing
+       
+#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+                       if (m->p->IOPMConnection)       // If lightweight-wake capability is available, use that
+                               {
+                               const CFDateRef WakeDate = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent() + interval);
+                               if (!WakeDate) LogMsg("ScheduleNextWake: CFDateCreate failed");
+                               else
+                                       {
+                                       const mDNSs32     reqs         = kIOPMSystemPowerStateCapabilityNetwork;
+                                       const CFNumberRef Requirements = CFNumberCreate(NULL, kCFNumberSInt32Type, &reqs);
+                                       if (!Requirements) LogMsg("ScheduleNextWake: CFNumberCreate failed");
+                                       else
+                                               {
+                                               const void *OptionKeys[2] = { CFSTR("WakeDate"), CFSTR("Requirements") };
+                                               const void *OptionVals[2] = {        WakeDate,          Requirements   };
+                                               opts = CFDictionaryCreate(NULL, (void*)OptionKeys, (void*)OptionVals, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+                                               if (!opts) LogMsg("ScheduleNextWake: CFDictionaryCreate failed");
+                                               CFRelease(Requirements);
+                                               }
+                                       CFRelease(WakeDate);
+                                       }
+                               LogSPS("AllowSleepNow: Will request lightweight wakeup in %d seconds", interval);
+                               }
+                       else                                            // else schedule the wakeup using the old API instead to
+#endif
+                               {
+                               // If we wake within +/- 30 seconds of our requested time we'll assume the system woke for us,
+                               // so we should put it back to sleep. To avoid frustrating the user, we always request at least
+                               // 60 seconds sleep, so if they immediately re-wake the system within seconds of it going to sleep,
+                               // we then shouldn't hit our 30-second window, and we won't attempt to re-sleep the machine.
+                               if (interval < 60) interval = 60;
+       
+                               result = mDNSPowerRequest(1, interval);
+       
+                               if (result == kIOReturnNotReady)
+                                       {
+                                       LogMsg("Requested wakeup in %d seconds unsuccessful; retrying with longer intervals", interval);
+                                       // IOPMSchedulePowerEvent fails with kIOReturnNotReady (-536870184/0xe00002d8) if the
+                                       // requested wake time is "too soon", but there's no API to find out what constitutes
+                                       // "too soon" on any given OS/hardware combination, so if we get kIOReturnNotReady
+                                       // we just have to iterate with successively longer intervals until it doesn't fail.
+                                       // Additionally, if our power request is deemed "too soon" for the machine to get to
+                                       // sleep and wake back up again, we attempt to cancel the sleep request, since the
+                                       // implication is that the system won't manage to be awake again at the time we need it.
+                                       do
+                                               {
+                                               interval += (interval < 20) ? 1 : ((interval+3) / 4);
+                                               result = mDNSPowerRequest(1, interval);
+                                               }
+                                       while (result == kIOReturnNotReady);
+                                       }
+       
+                               if (result) LogMsg("AllowSleepNow: Requested wakeup in %d seconds unsuccessful: %d %X", interval, result, result);
+                               else LogSPS("AllowSleepNow: Requested wakeup in %d seconds", interval);
+                               m->p->WakeAtUTC = mDNSPlatformUTC() + interval;
+                               }
+                       }
+       
+               // Clear our interface list to empty state, ready to go to sleep
+               // As a side effect of doing this, we'll also cancel any outstanding SPS Resolve calls that didn't complete
+               m->SleepState = SleepState_Sleeping;
+               mDNSMacOSXNetworkChanged(m);
+               }
+
+       LogSPS("AllowSleepNow: %s(%lX) %s at %ld (%d ticks remaining)",
+#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+               (m->p->IOPMConnection) ? "IOPMConnectionAcknowledgeEventWithOptions" :
+#endif
+               (result == kIOReturnSuccess) ? "IOAllowPowerChange" : "IOCancelPowerChange",
+               m->p->SleepCookie, ready ? "ready for sleep" : "giving up", now, m->SleepLimit - now);
 
-       // 2. Scan list of registered services
-       ServiceRecordSet *srs;
-       for (srs = m->ServiceRegistrations; srs; srs = srs->uDNS_next)
-               if (srs->state == regState_NoTarget && srs->tcp) return(mDNSfalse);
+       m->SleepLimit = 0;      // Don't clear m->SleepLimit until after we've logged it above
 
+#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+       if (m->p->IOPMConnection) IOPMConnectionAcknowledgeEventWithOptions(m->p->IOPMConnection, m->p->SleepCookie, opts);
+       else
+#endif
+       if (result == kIOReturnSuccess) IOAllowPowerChange (m->p->PowerConnection, m->p->SleepCookie);
+       else                            IOCancelPowerChange(m->p->PowerConnection, m->p->SleepCookie);
+
+       if (opts) CFRelease(opts);
        return(mDNStrue);
        }
 
@@ -2387,7 +2799,7 @@ mDNSlocal void * KQueueLoop(void *m_param)
 #endif
        
        pthread_mutex_lock(&PlatformStorage.BigMutex);
-       LogOperation("Starting time value 0x%08lX (%ld)", (mDNSu32)mDNSStorage.timenow_last, mDNSStorage.timenow_last);
+       LogInfo("Starting time value 0x%08lX (%ld)", (mDNSu32)mDNSStorage.timenow_last, mDNSStorage.timenow_last);
        
        // This is the main work loop:
        // (1) First we give mDNSCore a chance to finish off any of its deferred work and calculate the next sleep time
@@ -2405,15 +2817,24 @@ mDNSlocal void * KQueueLoop(void *m_param)
                mDNSs32 nextTimerEvent = udsserver_idle(mDNSDaemonIdle(m));
                mDNSs32 end            = mDNSPlatformRawTime();
                if (end - start >= WatchDogReportingThreshold)
-                       LogOperation("WARNING: Idle task took %dms to complete", end - start);
+                       LogInfo("WARNING: Idle task took %dms to complete", end - start);
 
                mDNSs32 now = mDNS_TimeNow(m);
 
                if (m->ShutdownTime)
                        {
+                       if (mDNSStorage.ResourceRecords)
+                               {
+                               LogInfo("Cannot exit yet; Resource Record still exists: %s", ARDisplayString(m, mDNSStorage.ResourceRecords));
+                               if (mDNS_LoggingEnabled) usleep(10000);         // Sleep 10ms so that we don't flood syslog with too many messages
+                               }
+                       if (mDNSStorage.ServiceRegistrations)
+                               LogInfo("Cannot exit yet; ServiceRegistrations still exists: %s", ARDisplayString(m, &mDNSStorage.ServiceRegistrations->RR_SRV));
                        if (mDNS_ExitNow(m, now))
                                {
-                               LogOperation("mDNS_FinalExit");
+                               if (!mDNSStorage.ResourceRecords && !mDNSStorage.ServiceRegistrations)
+                                       safe_vproc_transaction_end();
+                               LogInfo("mDNS_FinalExit");
                                mDNS_FinalExit(&mDNSStorage);
                                usleep(1000);           // Little 1ms pause before exiting, so we don't lose our final syslog messages
                                exit(0);
@@ -2422,20 +2843,10 @@ mDNSlocal void * KQueueLoop(void *m_param)
                                nextTimerEvent = m->ShutdownTime;
                        }
 
-               if (m->p->SleepLimit)
-                       {
-                       mDNSBool ready = ReadyForSleep(m);
-                       if (ready || now - m->p->SleepLimit >= 0)
-                               {
-                               LogOperation("IOAllowPowerChange(%lX) %s at %ld (%d ticks remaining)", m->p->SleepCookie,
-                                       ready ? "ready for sleep" : "giving up", now, m->p->SleepLimit - now);
-                               m->p->SleepLimit = 0;
-                               IOAllowPowerChange(m->p->PowerConnection, m->p->SleepCookie);
-                               }
-                       else
-                               if (nextTimerEvent - m->p->SleepLimit >= 0)
-                                       nextTimerEvent = m->p->SleepLimit;
-                       }
+               if (m->SleepLimit)
+                       if (!AllowSleepNow(m, now))
+                               if (nextTimerEvent - m->SleepLimit >= 0)
+                                       nextTimerEvent = m->SleepLimit;
 
                // Convert absolute wakeup time to a relative time from now
                mDNSs32 ticks = nextTimerEvent - now;
@@ -2504,13 +2915,11 @@ mDNSlocal void * KQueueLoop(void *m_param)
                                {
                                const KQueueEntry *const kqentry = new_events[i].udata;
                                mDNSs32 stime = mDNSPlatformRawTime();
-#if LogAllOperations || MDNS_DEBUGMSGS
                                const char *const KQtask = kqentry->KQtask;     // Grab a copy in case KQcallback deletes the task
-#endif
                                kqentry->KQcallback(new_events[i].ident, new_events[i].filter, kqentry->KQcontext);
                                mDNSs32 etime = mDNSPlatformRawTime();
                                if (etime - stime >= WatchDogReportingThreshold)
-                                       LogOperation("WARNING: %s took %dms to complete", KQtask, etime - stime);
+                                       LogInfo("WARNING: %s took %dms to complete", KQtask, etime - stime);
                                }
                        }
                }
@@ -2530,7 +2939,7 @@ mDNSlocal void LaunchdCheckin(void)
                int err = launch_data_get_errno(resp);
                // When running on Tiger with "ServiceIPC = false", we get "err == EACCES" to tell us there's no launchdata to fetch
                if (err != EACCES) LogMsg("launch_msg returned %d", err);
-               else LogOperation("Launchd provided no launchdata; will open Mach port and Unix Domain Socket explicitly...", err);
+               else LogInfo("Launchd provided no launchdata; will open Mach port and Unix Domain Socket explicitly...", err);
                }
        else
                {
@@ -2542,12 +2951,30 @@ mDNSlocal void LaunchdCheckin(void)
                        if (!skt) LogMsg("launch_data_dict_lookup Listeners returned NULL");
                        else
                                {
-                               launch_data_t s = launch_data_array_get_index(skt, 0);
-                               if (!s) LogMsg("launch_data_array_get_index(skt, 0) returned NULL");
+                               launchd_fds_count = launch_data_array_get_count(skt);
+                               if (launchd_fds_count == 0) LogMsg("launch_data_array_get_count(skt) returned 0");
                                else
                                        {
-                                       launchd_fd = launch_data_get_fd(s);
-                                       LogOperation("Launchd Unix Domain Socket: %d", launchd_fd);
+                                       launchd_fds = mallocL("LaunchdCheckin", sizeof(dnssd_sock_t) * launchd_fds_count);
+                                       if (!launchd_fds) LogMsg("LaunchdCheckin: malloc failed");
+                                       else
+                                               {
+                                               size_t i;
+                                               for(i = 0; i < launchd_fds_count; i++)
+                                                       {                                               
+                                                       launch_data_t s = launch_data_array_get_index(skt, i);
+                                                       if (!s)
+                                                               {
+                                                               launchd_fds[i] = dnssd_InvalidSocket;
+                                                               LogMsg("launch_data_array_get_index(skt, %d) returned NULL", i);
+                                                               }
+                                                       else
+                                                               {
+                                                               launchd_fds[i] = launch_data_get_fd(s);
+                                                               LogInfo("Launchd Unix Domain Socket [%d]: %d", i, launchd_fds[i]);
+                                                               }
+                                                       }
+                                               }
                                        // In some early versions of 10.4.x, the permissions on the UDS were not set correctly, so we fix them here
                                        chmod(MDNS_UDS_SERVERPATH, S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | S_IROTH|S_IWOTH);
                                        }
@@ -2559,11 +2986,11 @@ mDNSlocal void LaunchdCheckin(void)
                else
                        {
                        launch_data_t p = launch_data_dict_lookup(ports, "com.apple.mDNSResponder");
-                       if (!p) LogOperation("launch_data_array_get_index(ports, 0) returned NULL");
+                       if (!p) LogInfo("launch_data_dict_lookup(ports, \"com.apple.mDNSResponder\") returned NULL");
                        else
                                {
                                m_port = launch_data_get_fd(p);
-                               LogOperation("Launchd Mach Port: %d", m_port);
+                               LogInfo("Launchd Mach Port: %d", m_port);
                                if (m_port == ~0U) m_port = MACH_PORT_NULL;
                                }
                        }
@@ -2597,7 +3024,7 @@ mDNSlocal void DropPrivileges(void)
                                *p = '/';
                                if (unlink(path) < 0 && errno != ENOENT) LogMsg("DropPrivileges: Could not unlink \"%s\": (%d) %s", path, errno, strerror(errno));
                                else if (symlink(path, MDNS_UDS_SERVERPATH) < 0) LogMsg("DropPrivileges: Could not symlink \"%s\" -> \"%s\": (%d) %s", MDNS_UDS_SERVERPATH, path, errno, strerror(errno));
-                               else LogOperation("DropPrivileges: Created subdirectory and symlink");
+                               else LogInfo("DropPrivileges: Created subdirectory and symlink");
                                }
                        }
 
@@ -2615,25 +3042,54 @@ mDNSexport int main(int argc, char **argv)
        kern_return_t status;
        pthread_t KQueueThread;
 
-       LogMsgIdent(mDNSResponderVersionString, "starting");
+       LogMsg("%s starting", mDNSResponderVersionString);
+       
+#if 0
+       LogMsg("CacheRecord %d", sizeof(CacheRecord));
+       LogMsg("CacheGroup  %d", sizeof(CacheGroup));
+       LogMsg("ResourceRecord  %d", sizeof(ResourceRecord));
+       LogMsg("RData_small     %d", sizeof(RData_small));
+
+       LogMsg("sizeof(CacheEntity) %d", sizeof(CacheEntity));
+       LogMsg("RR_CACHE_SIZE       %d", RR_CACHE_SIZE);
+       LogMsg("block usage         %d", sizeof(CacheEntity) * RR_CACHE_SIZE);
+       LogMsg("block wastage       %d", 16*1024 - sizeof(CacheEntity) * RR_CACHE_SIZE);
+#endif
+
+       safe_vproc_transaction_begin();
 
        if (0 == geteuid()) DropPrivileges();
 
        for (i=1; i<argc; i++)
                {
-               if (!strcasecmp(argv[i], "-d"           )) mDNS_DebugMode = mDNStrue;
-               if (!strcasecmp(argv[i], "-launchd"     )) started_via_launchdaemon = mDNStrue;
-               if (!strcasecmp(argv[i], "-launchdaemon")) started_via_launchdaemon = mDNStrue;
+               if (!strcasecmp(argv[i], "-d"                        )) mDNS_DebugMode            = mDNStrue;
+               if (!strcasecmp(argv[i], "-launchd"                  )) started_via_launchdaemon  = mDNStrue;
+               if (!strcasecmp(argv[i], "-launchdaemon"             )) started_via_launchdaemon  = mDNStrue;
+               if (!strcasecmp(argv[i], "-NoMulticastAdvertisements")) advertise                 = mDNS_Init_DontAdvertiseLocalAddresses;
+               if (!strcasecmp(argv[i], "-DebugLogging"             )) mDNS_LoggingEnabled       = mDNStrue;
+               if (!strcasecmp(argv[i], "-UnicastPacketLogging"     )) mDNS_PacketLoggingEnabled = mDNStrue;
+               if (!strcasecmp(argv[i], "-OfferSleepProxyService"   ))
+                       OfferSleepProxyService = (i+1<argc && mDNSIsDigit(argv[i+1][0]) && mDNSIsDigit(argv[i+1][1]) && argv[i+1][2]==0) ? atoi(argv[++i]) : 80;
                }
+       
+       // Note that mDNSPlatformInit will set DivertMulticastAdvertisements in the mDNS structure
+       if (!advertise) LogMsg("Administratively prohibiting multicast advertisements");
+
+       OSXVers = mDNSMacOSXSystemBuildNumber(NULL);
 
        signal(SIGHUP,  HandleSIG);             // (Debugging) Purge the cache to check for cache handling bugs
        signal(SIGINT,  HandleSIG);             // Ctrl-C: Detach from Mach BootstrapService and exit cleanly
-       signal(SIGABRT, CatchABRT);             // For debugging -- SIGABRT should never happen
+       // On 10.5 and later, the default action for SIGABRT is to generate a crash report, so we only need our CatchABRT handler on 10.4
+       if (OSXVers <= OSXVers_10_4_Tiger)
+               {
+               LogInfo("Adding SIGABRT handler");
+               signal(SIGABRT, CatchABRT); // For debugging -- SIGABRT should never happen
+               }
        signal(SIGPIPE, SIG_IGN  );             // Don't want SIGPIPE signals -- we'll handle EPIPE errors directly
        signal(SIGTERM, HandleSIG);             // Machine shutting down: Detach from and exit cleanly like Ctrl-C
        signal(SIGINFO, HandleSIG);             // (Debugging) Write state snapshot to syslog
-       signal(SIGUSR1, HandleSIG);             // (Debugging) Simulate network change notification from System Configuration Framework
-       signal(SIGUSR2, HandleSIG);             // (Debugging) Change log level
+       signal(SIGUSR1, HandleSIG);             // (Debugging) Enable Logging
+       signal(SIGUSR2, HandleSIG);             // (Debugging) Enable Packet Logging
 
        mDNSStorage.p = &PlatformStorage;       // Make sure mDNSStorage.p is set up, because validatelists uses it
        LaunchdCheckin();
@@ -2684,16 +3140,18 @@ mDNSexport int main(int argc, char **argv)
                char *sandbox_msg;
                int sandbox_err = sandbox_init("mDNSResponder", SANDBOX_NAMED, &sandbox_msg);
                if (sandbox_err) { LogMsg("WARNING: sandbox_init error %s", sandbox_msg); sandbox_free_error(sandbox_msg); }
-               else LogOperation("Now running under Apple Sandbox restrictions");
+               else LogInfo("Now running under Apple Sandbox restrictions");
                }
 #endif
 
-       OSXVers = mDNSMacOSXSystemBuildNumber(NULL);
        status = mDNSDaemonInitialize();
        if (status) { LogMsg("Daemon start: mDNSDaemonInitialize failed"); goto exit; }
-       status = udsserver_init(launchd_fd);
+
+       status = udsserver_init(launchd_fds, launchd_fds_count);
        if (status) { LogMsg("Daemon start: udsserver_init failed"); goto exit; }
-       
+
+       mDNSMacOSXNetworkChanged(&mDNSStorage);
+
        // Start the kqueue thread
        i = pthread_create(&KQueueThread, NULL, KQueueLoop, &mDNSStorage);
        if (i == -1) { LogMsg("pthread_create() failed errno %d (%s)", errno, strerror(errno)); status = errno; goto exit; }
@@ -2705,7 +3163,7 @@ mDNSexport int main(int argc, char **argv)
                mDNS_Close(&mDNSStorage);
                }
 
-       LogMsgIdent(mDNSResponderVersionString, "exiting");
+       LogMsg("%s exiting", mDNSResponderVersionString);
 
 exit:
        if (!mDNS_DebugMode && !started_via_launchdaemon) destroyBootstrapService();
@@ -2714,38 +3172,38 @@ exit:
 
 // uds_daemon.c support routines /////////////////////////////////////////////
 
-// Arrange things so that callback is called with context when data appears on fd
-mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context)
+// Arrange things so that when data appears on fd, callback is called with context
+mDNSexport mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context)
        {
+       KQSocketEventSource **p = &gEventSources;
+       while (*p && (*p)->fd != fd) p = &(*p)->next;
+       if (*p) { LogMsg("udsSupportAddFDToEventLoop: ERROR fd %d already has EventLoop source entry", fd); return mStatus_AlreadyRegistered; }
+
        KQSocketEventSource *newSource = (KQSocketEventSource*) mallocL("KQSocketEventSource", sizeof *newSource);
        if (!newSource) return mStatus_NoMemoryErr;
 
-       mDNSPlatformMemZero(newSource, sizeof(*newSource));
-       newSource->fd = fd;
+       newSource->next           = mDNSNULL;
+       newSource->fd             = fd;
        newSource->kqs.KQcallback = callback;
        newSource->kqs.KQcontext  = context;
        newSource->kqs.KQtask     = "UDS client";
 
        if (KQueueSet(fd, EV_ADD, EVFILT_READ, &newSource->kqs) == 0)
                {
-               KQSocketEventSource **p = &gEventSources;
-               while (*p) p = &(*p)->next;
                *p = newSource;
                return mStatus_NoError;
                }
-       else
-               {
-               close(fd);
-               free(newSource);
-               return mStatus_NoMemoryErr;
-               }
+
+       LogMsg("KQueueSet failed for fd %d errno %d (%s)", fd, errno, strerror(errno));
+       freeL("KQSocketEventSource", newSource);
+       return mStatus_BadParamErr;
        }
 
-mStatus udsSupportRemoveFDFromEventLoop(int fd)                // Note: This also CLOSES the file descriptor
+mDNSexport mStatus udsSupportRemoveFDFromEventLoop(int fd)             // Note: This also CLOSES the file descriptor
        {
        KQSocketEventSource **p = &gEventSources;
        while (*p && (*p)->fd != fd) p = &(*p)->next;
-       if (*p) 
+       if (*p)
                {
                KQSocketEventSource *s = *p;
                *p = (*p)->next;
@@ -2755,12 +3213,15 @@ mStatus udsSupportRemoveFDFromEventLoop(int fd)         // Note: This also CLOSES the f
                freeL("KQSocketEventSource", s);
                return mStatus_NoError;
                }
+       LogMsg("udsSupportRemoveFDFromEventLoop: ERROR fd %d not found in EventLoop source list", fd);
        return mStatus_NoSuchNameErr;
        }
 
+#if _BUILDING_XCODE_PROJECT_
 // If mDNSResponder crashes, then this string will be magically included in the automatically-generated crash log
 const char *__crashreporter_info__ = mDNSResponderVersionString;
 asm(".desc ___crashreporter_info__, 0x10");
+#endif
 
 // For convenience when using the "strings" command, this is the last thing in the file
 // The "@(#) " pattern is a special prefix the "what" command looks for
index af019b3b2786b94e6ee3c713cfafa4e6f3aae239..3bf71f2abe5ddd24ef44fd6a8bc1f14b8c04b992 100644 (file)
     Change History (most recent first):
 
 $Log: helper-main.c,v $
+Revision 1.28  2009/04/11 00:20:08  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.27  2009/03/09 19:00:26  mcguire
+<rdar://problem/6660098> temporarily don't use getpwnam
+
+Revision 1.26  2009/03/05 23:08:12  cheshire
+<rdar://problem/6648751> mDNSResponderHelper deadlocked — Can't use syslog from within a signal handler
+
+Revision 1.25  2009/02/06 03:06:49  mcguire
+<rdar://problem/5858533> Adopt vproc_transaction API in mDNSResponder
+
+Revision 1.24  2009/01/28 17:20:46  mcguire
+changed incorrect notice level log to debug
+
+Revision 1.23  2009/01/28 03:17:19  mcguire
+<rdar://problem/5858535> helper: Adopt vproc_transaction API
+
+Revision 1.22  2008/12/19 01:56:47  mcguire
+<rdar://problem/6181947> crashes in mDNSResponderHelper
+
+Revision 1.21  2008/09/15 23:52:30  cheshire
+<rdar://problem/6218902> mDNSResponder-177 fails to compile on Linux with .desc pseudo-op
+Made __crashreporter_info__ symbol conditional, so we only use it for OS X build
+
+Revision 1.20  2008/08/13 23:11:35  mcguire
+<rdar://problem/5858535> handle SIGTERM in mDNSResponderHelper
+
+Revision 1.19  2008/08/13 23:04:06  mcguire
+<rdar://problem/5858535> handle SIGTERM in mDNSResponderHelper
+Preparation: rename message function, as it will no longer be called only on idle exit
+
+Revision 1.18  2008/08/13 22:56:32  mcguire
+<rdar://problem/5858535> handle SIGTERM in mDNSResponderHelper
+Preparation: store mach port in global variable so we can write to it from a signal handler
+
+Revision 1.17  2008/07/24 01:04:04  mcguire
+<rdar://problem/6003721> helper spawned every 10s
+
+Revision 1.16  2008/07/01 01:40:01  mcguire
+<rdar://problem/5823010> 64-bit fixes
+
 Revision 1.15  2008/03/13 20:55:16  mcguire
 <rdar://problem/5769316> fix deprecated warnings/errors
 Additional cleanup: use a conditional macro instead of lots of #if
@@ -89,6 +131,7 @@ Revision 1.1  2007/08/08 22:34:58  mcguire
 #include "helper-server.h"
 #include "helpermsg.h"
 #include "helpermsgServer.h"
+#include "safe_vproc.h"
 
 #if TARGET_OS_EMBEDDED
 #include <bootstrap_priv.h>
@@ -109,17 +152,29 @@ union max_msg_size
        union __ReplyUnion__proxy_helper_subsystem rep;
        };
 
+#ifdef VPROC_HAS_TRANSACTIONS
+typedef struct __transaction_s
+       {
+       struct __transaction_s* next;
+       vproc_transaction_t vt;
+       } transaction_t;
+       
+static transaction_t* transactions = NULL;
+#endif
+
 static const mach_msg_size_t MAX_MSG_SIZE = sizeof(union max_msg_size) + MAX_TRAILER_SIZE;
 static aslclient logclient = NULL;
 static int opt_debug;
 static pthread_t idletimer_thread;
 
-unsigned long maxidle = 10;
+unsigned long maxidle = 15;
 unsigned long actualidle = 3600;
 
 CFRunLoopRef gRunLoop = NULL;
 CFRunLoopTimerRef gTimer = NULL;
 
+mach_port_t gPort = MACH_PORT_NULL;
+
 static void helplogv(int level, const char *fmt, va_list ap)
        {
        if (NULL == logclient) { vfprintf(stderr, fmt, ap); fflush(stderr); }
@@ -133,6 +188,24 @@ void helplog(int level, const char *fmt, ...)
        helplogv(level, fmt, ap);
        va_end(ap);
        }
+       
+// for safe_vproc
+void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *fmt, ...)
+       {
+       (void)logLevel;
+       va_list ap;
+       va_start(ap, fmt);
+       // safe_vproc only calls LogMsg, so assume logLevel maps to ASL_LEVEL_ERR
+       helplog(ASL_LEVEL_ERR, fmt, ap);
+       va_end(ap);
+       }       
+
+static void handle_sigterm(int sig)
+       {
+       // debug("entry sig=%d", sig);  Can't use syslog from within a signal handler
+       assert(sig == SIGTERM);
+       (void)proxy_mDNSExit(gPort);
+       }
 
 static void initialize_logging(void)
        {
@@ -144,7 +217,10 @@ static void initialize_logging(void)
 static void initialize_id(void)
        {
        static char login[] = "_mdnsresponder";
-       struct passwd *pwd = getpwnam(login);
+       struct passwd hardcode;
+       struct passwd *pwd = &hardcode; // getpwnam(login);
+       hardcode.pw_uid = 65;
+       hardcode.pw_gid = 65;
 
        if (!pwd) { helplog(ASL_LEVEL_ERR, "Could not find account name `%s'.  I will only help root.", login); return; }
        mDNSResponderUID = pwd->pw_uid;
@@ -153,10 +229,10 @@ static void initialize_id(void)
 
 static void diediedie(CFRunLoopTimerRef timer, void *context)
        {
-       debug("entry");
+       debug("entry %p %p %d", timer, context, maxidle);
        assert(gTimer == timer);
        if (maxidle)
-         (void)proxy_mDNSIdleExit((mach_port_t)context);
+               (void)proxy_mDNSExit(gPort);
        }
 
 void pause_idle_timer(void)
@@ -199,15 +275,16 @@ static void *idletimer(void *context)
        return NULL;
        }
 
-static void initialize_timer(mach_port_t port)
+static int initialize_timer()
        {
-       CFRunLoopTimerContext cxt = {0, (void *)port, NULL, NULL, NULL};
-       gTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + actualidle, actualidle, 0, 0, diediedie, &cxt);
+       gTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + actualidle, actualidle, 0, 0, diediedie, NULL);
        int err = 0;
 
-       debug("entry port=%p", port);
-       if (0 != (err = pthread_create(&idletimer_thread, NULL, idletimer, (void *)port)))
+       debug("entry");
+       if (0 != (err = pthread_create(&idletimer_thread, NULL, idletimer, NULL)))
                helplog(ASL_LEVEL_ERR, "Could not start idletimer thread: %s", strerror(err));
+
+       return err;
        }
 
 static mach_port_t checkin(char *service_name)
@@ -272,9 +349,9 @@ int main(int ac, char *av[])
        {
        char *p = NULL;
        kern_return_t kr = KERN_FAILURE;
-       mach_port_t port = MACH_PORT_NULL;
        long n;
        int ch;
+       mach_msg_header_t hdr;
 
        while ((ch = getopt(ac, av, "dt:")) != -1)
                switch (ch)
@@ -303,20 +380,44 @@ int main(int ac, char *av[])
        // Explicitly ensure that our Keychain operations utilize the system domain.
        SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
 #endif
-       port = checkin(kmDNSHelperServiceName);
-       if (!port)
+       gPort = checkin(kmDNSHelperServiceName);
+       if (!gPort)
                {
                helplog(ASL_LEVEL_ERR, "Launchd provided no launchdata; will open Mach port explicitly");
-               port = register_service(kmDNSHelperServiceName);
+               gPort = register_service(kmDNSHelperServiceName);
                }
 
        if (maxidle) actualidle = maxidle;
-       initialize_timer(port);
 
-       kr = mach_msg_server(helper_server, MAX_MSG_SIZE, port,
-               MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0));
-       if (KERN_SUCCESS != kr)
-               { helplog(ASL_LEVEL_ERR, "mach_msg_server: %s\n", mach_error_string(kr)); exit(EXIT_FAILURE); }
+       signal(SIGTERM, handle_sigterm);
+
+       if (initialize_timer()) exit(EXIT_FAILURE);
+       for (n=0; n<100000; n++) if (!gRunLoop) usleep(100);
+       if (!gRunLoop)
+               {
+               helplog(ASL_LEVEL_ERR, "gRunLoop not set after waiting");
+               exit(EXIT_FAILURE);
+               }
+
+       for(;;)
+               {
+               hdr.msgh_bits = 0;
+               hdr.msgh_local_port = gPort;
+               hdr.msgh_remote_port = MACH_PORT_NULL;
+               hdr.msgh_size = sizeof(hdr);
+               hdr.msgh_id = 0;
+               kr = mach_msg(&hdr, MACH_RCV_LARGE | MACH_RCV_MSG, 0, hdr.msgh_size, gPort, 0, 0);
+               if (MACH_RCV_TOO_LARGE != kr) helplog(ASL_LEVEL_ERR, "kr: %d: %s", kr, mach_error_string(kr));
+               
+               safe_vproc_transaction_begin();
+               
+               kr = mach_msg_server_once(helper_server, MAX_MSG_SIZE, gPort,
+                       MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0));
+               if (KERN_SUCCESS != kr)
+                       { helplog(ASL_LEVEL_ERR, "mach_msg_server: %s\n", mach_error_string(kr)); exit(EXIT_FAILURE); }
+               
+               safe_vproc_transaction_end();
+               }
        exit(EXIT_SUCCESS);
        }
 
@@ -330,6 +431,8 @@ int main(int ac, char *av[])
 // The "@(#) " pattern is a special prefix the "what" command looks for
 const char VersionString_SCCS[] = "@(#) mDNSResponderHelper " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
 
+#if _BUILDING_XCODE_PROJECT_
 // If the process crashes, then this string will be magically included in the automatically-generated crash log
 const char *__crashreporter_info__ = VersionString_SCCS + 5;
 asm(".desc ___crashreporter_info__, 0x10");
+#endif
index defebe18038111faf13f06aee0bba4d7353404d6..1efaa415af9ea16c6a769ab16dbf28b92f710698 100644 (file)
     Change History (most recent first):
 
 $Log: helper-server.h,v $
+Revision 1.5  2009/02/06 03:06:49  mcguire
+<rdar://problem/5858533> Adopt vproc_transaction API in mDNSResponder
+
+Revision 1.4  2009/01/28 03:17:19  mcguire
+<rdar://problem/5858535> helper: Adopt vproc_transaction API
+
 Revision 1.3  2007/09/07 22:44:03  mcguire
 <rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
 
index e2084e08e30a23d524a8fb26d85a78b9386cee20..09b262c7380bde28fc6f32f2f8841cdee440d213 100644 (file)
     Change History (most recent first):
 
 $Log: helper-stubs.c,v $
+Revision 1.19  2009/04/20 20:40:14  cheshire
+<rdar://problem/6786150> uDNS: Running location cycling caused configd and mDNSResponder to deadlock
+Changed mDNSPreferencesSetName (and similar) routines from MIG "routine" to MIG "simpleroutine"
+so we don't deadlock waiting for a result that we're just going to ignore anyway
+
+Revision 1.18  2009/03/20 22:12:27  mcguire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+Make the call to the helper a simpleroutine: don't wait for an unused return value
+
+Revision 1.17  2009/03/20 20:52:22  cheshire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+
+Revision 1.16  2009/03/14 01:42:56  mcguire
+<rdar://problem/5457116> BTMM: Fix issues with multiple .Mac accounts on the same machine
+
+Revision 1.15  2009/01/22 02:14:27  cheshire
+<rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
+
+Revision 1.14  2009/01/14 01:38:42  mcguire
+<rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
+
+Revision 1.13  2009/01/14 01:28:17  mcguire
+removed unused variable
+
+Revision 1.12  2008/11/11 00:46:37  cheshire
+Don't just show "<unknown error>"; show the actual numeric error code too, so we can see what the unknown error was
+
+Revision 1.11  2008/11/04 23:54:09  cheshire
+Added routine mDNSSetARP(), used to replace an SPS client's entry in our ARP cache with
+a dummy one, so that IP traffic to the SPS client initiated by the SPS machine can be
+captured by our BPF filters, and used as a trigger to wake the sleeping machine.
+
+Revision 1.10  2008/10/29 21:25:35  cheshire
+Don't report kIOReturnNotReady errors
+
+Revision 1.9  2008/10/24 01:42:36  cheshire
+Added mDNSPowerRequest helper routine to request a scheduled wakeup some time in the future
+
+Revision 1.8  2008/10/20 22:01:28  cheshire
+Made new Mach simpleroutine "mDNSRequestBPF"
+
+Revision 1.7  2008/09/27 00:58:32  cheshire
+Added mDNSRequestBPF definition
+
 Revision 1.6  2007/12/10 23:23:48  cheshire
 Removed unnecessary log message ("mDNSKeychainGetSecrets failed 0 00000000" because mDNSKeychainGetSecrets was failing to return a valid array)
 
@@ -39,6 +83,7 @@ Revision 1.1  2007/08/08 22:34:58  mcguire
 #include <mach/mach_error.h>
 #include <mach/vm_map.h>
 #include <servers/bootstrap.h>
+#include <IOKit/IOReturn.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include "mDNSDebug.h"
 #include "helper.h"
@@ -52,46 +97,44 @@ static const char *errorstring[] =
        };
 #undef ERROR
 
-static mach_port_t
-getHelperPort(int retry)
+static mach_port_t getHelperPort(int retry)
        {
        static mach_port_t port = MACH_PORT_NULL;
-
-       if (retry)
-               port = MACH_PORT_NULL;
-       if (port == MACH_PORT_NULL &&
-           BOOTSTRAP_SUCCESS != bootstrap_look_up(bootstrap_port,
-           kmDNSHelperServiceName, &port))
+       if (retry) port = MACH_PORT_NULL;
+       if (port == MACH_PORT_NULL && BOOTSTRAP_SUCCESS != bootstrap_look_up(bootstrap_port, kmDNSHelperServiceName, &port))
                LogMsg("%s: cannot contact helper", __func__);
        return port;
        }
 
-const char *
-mDNSHelperError(int err)
+const char *mDNSHelperError(int err)
        {
-       const char *p = "<unknown error>";
+       static const char *p = "<unknown error>";
        if (mDNSHelperErrorBase < err && mDNSHelperErrorEnd > err)
                p = errorstring[err - mDNSHelperErrorBase - 1];
        return p;
        }
 
 /* Ugly but handy. */
-#define MACHRETRYLOOP_BEGIN(kr, retry, err, fin) for (;;) {
-
-#define MACHRETRYLOOP_END(kr, retry, err, fin)                         \
-               if (KERN_SUCCESS == (kr)) break;                                        \
-               else if (MACH_SEND_INVALID_DEST == (kr) && 0 == (retry)++) continue;    \
-               else \
-                       {                                                               \
-                       (err) = kmDNSHelperCommunicationFailed;                 \
-                       LogMsg("%s: Mach communication failed: %s", __func__, mach_error_string(kr));                           \
-                       goto fin;                                               \
-                       }                                                               \
-               }                                                               \
-       if (0 != (err)) { LogMsg("%s: %s", __func__, mDNSHelperError((err))); goto fin; }
-
-int
-mDNSPreferencesSetName(int key, domainlabel* old, domainlabel* new)
+// We don't bother reporting kIOReturnNotReady because that error code occurs in "normal" operation
+// and doesn't indicate anything unexpected that needs to be investigated
+
+#define MACHRETRYLOOP_BEGIN(kr, retry, err, fin)                                            \
+       for (;;)                                                                                \
+               {
+#define MACHRETRYLOOP_END(kr, retry, err, fin)                                                                                         \
+               if (KERN_SUCCESS == (kr)) break;                                                                                                        \
+               else if (MACH_SEND_INVALID_DEST == (kr) && 0 == (retry)++) continue;                            \
+               else                                                                                                                                                            \
+                       {                                                                                                                                                               \
+                       (err) = kmDNSHelperCommunicationFailed;                                                                                 \
+                       LogMsg("%s: Mach communication failed: %s", __func__, mach_error_string(kr));   \
+                       goto fin;                                                                                                                                               \
+                       }                                                                                                                                                               \
+               }                                                                                                                                                                       \
+       if (0 != (err) && kIOReturnNotReady != (err))                                                                                   \
+               { LogMsg("%s: %d 0x%X (%s)", __func__, (err), (err), mDNSHelperError(err)); goto fin; }
+
+void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new)
        {
        kern_return_t kr = KERN_FAILURE;
        int retry = 0;
@@ -102,15 +145,14 @@ mDNSPreferencesSetName(int key, domainlabel* old, domainlabel* new)
        if (new) ConvertDomainLabelToCString_unescaped(new, newname);
 
        MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
-       kr = proxy_mDNSPreferencesSetName(getHelperPort(retry), key, oldname, newname, &err);
+       kr = proxy_mDNSPreferencesSetName(getHelperPort(retry), key, oldname, newname);
        MACHRETRYLOOP_END(kr, retry, err, fin);
 
 fin:
-       return err;
+       (void)err;
        }
 
-int
-mDNSDynamicStoreSetConfig(int key, CFPropertyListRef value)
+void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value)
        {
        CFWriteStreamRef stream = NULL;
        CFDataRef bytes = NULL;
@@ -118,24 +160,20 @@ mDNSDynamicStoreSetConfig(int key, CFPropertyListRef value)
        int retry = 0;
        int err = 0;
 
-       if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL,
-           NULL)))
+       if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL)))
                {
                err = kmDNSHelperCreationFailed;
-               LogMsg("%s: CFWriteStreamCreateWithAllocatedBuffers failed",
-                       __func__);
+               LogMsg("%s: CFWriteStreamCreateWithAllocatedBuffers failed", __func__);
                goto fin;
                }
        CFWriteStreamOpen(stream);
-       if (0 == CFPropertyListWriteToStream(value, stream,
-           kCFPropertyListBinaryFormat_v1_0, NULL))
+       if (0 == CFPropertyListWriteToStream(value, stream, kCFPropertyListBinaryFormat_v1_0, NULL))
                {
                err = kmDNSHelperPListWriteFailed;
                LogMsg("%s: CFPropertyListWriteToStream failed", __func__);
                goto fin;
                }
-       if (NULL == (bytes = CFWriteStreamCopyProperty(stream,
-           kCFStreamPropertyDataWritten)))
+       if (NULL == (bytes = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten)))
                {
                err = kmDNSHelperCreationFailed;
                LogMsg("%s: CFWriteStreamCopyProperty failed", __func__);
@@ -145,24 +183,60 @@ mDNSDynamicStoreSetConfig(int key, CFPropertyListRef value)
        CFRelease(stream);
        stream = NULL;
        MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
-       kr = proxy_mDNSDynamicStoreSetConfig(getHelperPort(retry), key,
-           (vm_offset_t)CFDataGetBytePtr(bytes),
-           CFDataGetLength(bytes), &err);
+       kr = proxy_mDNSDynamicStoreSetConfig(getHelperPort(retry), key, subkey ? subkey : "", (vm_offset_t)CFDataGetBytePtr(bytes), CFDataGetLength(bytes));
        MACHRETRYLOOP_END(kr, retry, err, fin);
 
 fin:
-       if (NULL != stream)
-               {
-               CFWriteStreamClose(stream);
-               CFRelease(stream);
-               }
-       if (NULL != bytes)
-               CFRelease(bytes);
+       if (NULL != stream) { CFWriteStreamClose(stream); CFRelease(stream); }
+       if (NULL != bytes) CFRelease(bytes);
+       (void)err;
+       }
+
+void mDNSRequestBPF(void)
+       {
+       kern_return_t kr = KERN_FAILURE;
+       int retry = 0, err = 0;
+       MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
+       kr = proxy_mDNSRequestBPF(getHelperPort(retry));
+       MACHRETRYLOOP_END(kr, retry, err, fin);
+fin:
+       (void)err;
+       }
+
+int mDNSPowerRequest(int key, int interval)
+       {
+       kern_return_t kr = KERN_FAILURE;
+       int retry = 0, err = 0;
+       MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
+       kr = proxy_mDNSPowerRequest(getHelperPort(retry), key, interval, &err);
+       MACHRETRYLOOP_END(kr, retry, err, fin);
+fin:
+       return err;
+       }
+
+int mDNSSetARP(int ifindex, const v4addr_t ip, const ethaddr_t eth)
+       {
+       kern_return_t kr = KERN_FAILURE;
+       int retry = 0, err = 0;
+       MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
+       kr = proxy_mDNSSetARP(getHelperPort(retry), ifindex, (uint8_t*)ip, (uint8_t*)eth, &err);
+       MACHRETRYLOOP_END(kr, retry, err, fin);
+fin:
        return err;
        }
 
-int
-mDNSKeychainGetSecrets(CFArrayRef *result)
+void mDNSNotify(const char *title, const char *msg)    // Both strings are UTF-8 text
+       {
+       kern_return_t kr = KERN_FAILURE;
+       int retry = 0, err = 0;
+       MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
+       kr = proxy_mDNSNotify(getHelperPort(retry), title, msg);
+       MACHRETRYLOOP_END(kr, retry, err, fin);
+fin:
+       (void)err;
+       }
+
+int mDNSKeychainGetSecrets(CFArrayRef *result)
        {
        CFPropertyListRef plist = NULL;
        CFDataRef bytes = NULL;
@@ -170,23 +244,19 @@ mDNSKeychainGetSecrets(CFArrayRef *result)
        unsigned int numsecrets = 0;
        void *secrets = NULL;
        mach_msg_type_number_t secretsCnt = 0;
-       int retry = 0;
-       int err = 0;
+       int retry = 0, err = 0;
 
        MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
-       kr = proxy_mDNSKeychainGetSecrets(getHelperPort(retry),
-           &numsecrets, (vm_offset_t *)&secrets, &secretsCnt, &err);
+       kr = proxy_mDNSKeychainGetSecrets(getHelperPort(retry), &numsecrets, (vm_offset_t *)&secrets, &secretsCnt, &err);
        MACHRETRYLOOP_END(kr, retry, err, fin);
 
-       if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
-           secrets, secretsCnt, kCFAllocatorNull)))
+       if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, secrets, secretsCnt, kCFAllocatorNull)))
                {
                err = kmDNSHelperCreationFailed;
                LogMsg("%s: CFDataCreateWithBytesNoCopy failed", __func__);
                goto fin;
                }
-       if (NULL == (plist = CFPropertyListCreateFromXMLData(
-           kCFAllocatorDefault, bytes, kCFPropertyListImmutable, NULL)))
+       if (NULL == (plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, bytes, kCFPropertyListImmutable, NULL)))
                {
                err = kmDNSHelperInvalidPList;
                LogMsg("%s: CFPropertyListCreateFromXMLData failed", __func__);
@@ -203,65 +273,56 @@ mDNSKeychainGetSecrets(CFArrayRef *result)
        *result = (CFArrayRef)plist;
 
 fin:
-       if (NULL != bytes)
-               CFRelease(bytes);
-       if (NULL != secrets)
-               vm_deallocate(mach_task_self(), (vm_offset_t)secrets,
-                   secretsCnt);
+       if (NULL != bytes) CFRelease(bytes);
+       if (NULL != secrets) vm_deallocate(mach_task_self(), (vm_offset_t)secrets, secretsCnt);
        return err;
        }
 
-int
-mDNSAutoTunnelInterfaceUpDown(int updown, v6addr_t address)
+void mDNSAutoTunnelInterfaceUpDown(int updown, v6addr_t address)
        {
        kern_return_t kr = KERN_SUCCESS;
-       int retry = 0;
-       int err = 0;
-
+       int retry = 0, err = 0;
        MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
-       kr = proxy_mDNSAutoTunnelInterfaceUpDown(getHelperPort(retry),
-           updown, address, &err);
+       kr = proxy_mDNSAutoTunnelInterfaceUpDown(getHelperPort(retry), updown, address);
        MACHRETRYLOOP_END(kr, retry, err, fin);
-
 fin:
-       return err;
+       (void)err;
        }
 
-int
-mDNSConfigureServer(int updown, const char *keydata)
+void mDNSConfigureServer(int updown, const domainname *const fqdn)
        {
        kern_return_t kr = KERN_SUCCESS;
-       int retry = 0;
-       int err = 0;
-
+       int retry = 0, err = 0;
+       char fqdnStr[MAX_ESCAPED_DOMAIN_NAME] = { 0 };
+       if (fqdn && ConvertDomainNameToCString(fqdn, fqdnStr))
+               {
+               // remove the trailing dot, as that is not used in the keychain entry racoon will lookup
+               mDNSu32 fqdnEnd = mDNSPlatformStrLen(fqdnStr);
+               if (fqdnEnd) fqdnStr[fqdnEnd - 1] = 0;
+               }
        MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
-       kr = proxy_mDNSConfigureServer(getHelperPort(retry), updown, keydata, &err);
+       kr = proxy_mDNSConfigureServer(getHelperPort(retry), updown, fqdnStr);
        MACHRETRYLOOP_END(kr, retry, err, fin);
-
 fin:
-       return err;
+       (void)err;
        }
 
-int
-mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
+int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
     v4addr_t local_outer, short local_port, v6addr_t remote_inner,
-    v4addr_t remote_outer, short remote_port, const char *keydata)
+    v4addr_t remote_outer, short remote_port, const domainname *const fqdn)
        {
        kern_return_t kr = KERN_SUCCESS;
-       const char *p = NULL;
-       int retry = 0;
-       int err = 0;
-
-       if (kmDNSAutoTunnelSetKeysReplace == replacedelete)
-               p = keydata;
-       else
-               p = "";
+       int retry = 0, err = 0;
+       char fqdnStr[MAX_ESCAPED_DOMAIN_NAME] = { 0 };
+       if (fqdn && ConvertDomainNameToCString(fqdn, fqdnStr))
+               {
+               // remove the trailing dot, as that is not used in the keychain entry racoon will lookup
+               mDNSu32 fqdnEnd = mDNSPlatformStrLen(fqdnStr);
+               if (fqdnEnd) fqdnStr[fqdnEnd - 1] = 0;
+               }
        MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
-       kr = proxy_mDNSAutoTunnelSetKeys(getHelperPort(retry), replacedelete,
-           local_inner, local_outer, local_port, remote_inner, remote_outer,
-           remote_port, keydata, &err);
+       kr = proxy_mDNSAutoTunnelSetKeys(getHelperPort(retry), replacedelete, local_inner, local_outer, local_port, remote_inner, remote_outer, remote_port, fqdnStr, &err);
        MACHRETRYLOOP_END(kr, retry, err, fin);
-
 fin:
        return err;
        }
index d3ad6b1859f20bbea571f0dc79b31ad867e3fe93..720d18dbc9321724a73aab39c81d27ca60c73194 100644 (file)
     Change History (most recent first):
 
 $Log: helper.c,v $
+Revision 1.66  2009/04/20 20:40:14  cheshire
+<rdar://problem/6786150> uDNS: Running location cycling caused configd and mDNSResponder to deadlock
+Changed mDNSPreferencesSetName (and similar) routines from MIG "routine" to MIG "simpleroutine"
+so we don't deadlock waiting for a result that we're just going to ignore anyway
+
+Revision 1.65  2009/03/20 22:12:28  mcguire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+Make the call to the helper a simpleroutine: don't wait for an unused return value
+
+Revision 1.64  2009/03/20 21:52:39  cheshire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+Need to CFRelease strings in do_mDNSNotify
+
+Revision 1.63  2009/03/20 21:21:15  cheshire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+Need to set error code correctly in do_mDNSNotify
+
+Revision 1.62  2009/03/20 20:52:22  cheshire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+
+Revision 1.61  2009/03/14 01:42:56  mcguire
+<rdar://problem/5457116> BTMM: Fix issues with multiple .Mac accounts on the same machine
+
+Revision 1.60  2009/02/18 02:09:10  cheshire
+<rdar://problem/6514947> Sleep Proxy: PF_ROUTE command to set ARP entry returns errno 17 (EEXIST)
+Also need to set rtmsg.hdr.rtm_index
+
+Revision 1.59  2009/02/17 23:33:45  cheshire
+<rdar://problem/6514947> Sleep Proxy: PF_ROUTE command to set ARP entry returns errno 17 (EEXIST)
+
+Revision 1.58  2009/02/04 22:23:04  cheshire
+Simplified do_mDNSPowerRequest --
+code was checking for CFAbsoluteTimeGetCurrent() returning NULL, which makes no sense
+
+Revision 1.57  2009/01/22 02:14:27  cheshire
+<rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
+
+Revision 1.56  2009/01/20 21:03:22  cheshire
+Improved debugging messages
+
+Revision 1.55  2009/01/20 02:37:26  mcguire
+revert previous erroneous commit
+
+Revision 1.54  2009/01/20 02:35:15  mcguire
+mDNSMacOSX/mDNSMacOSX.c
+
+Revision 1.53  2009/01/14 01:38:42  mcguire
+<rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
+
+Revision 1.52  2009/01/13 05:31:34  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.51  2009/01/12 22:26:12  mkrochma
+Change DynamicStore location from BonjourSleepProxy/DiscoveredServers to SleepProxyServers
+
+Revision 1.50  2008/12/15 18:40:41  mcguire
+<rdar://problem/6444440> Socket leak in helper's doTunnelPolicy
+
+Revision 1.49  2008/12/12 00:37:42  mcguire
+<rdar://problem/6417648> BTMM outbound fails if /var/run/racoon doesn't exist
+
+Revision 1.48  2008/12/05 02:35:24  mcguire
+<rdar://problem/6107390> Write to the DynamicStore when a Sleep Proxy server is available on the network
+
+Revision 1.47  2008/11/21 02:28:55  mcguire
+<rdar://problem/6354979> send racoon a SIGUSR1 instead of SIGHUP
+
+Revision 1.46  2008/11/11 02:09:42  cheshire
+Removed some unnecessary log messages
+
+Revision 1.45  2008/11/06 23:35:38  cheshire
+Refinements to the do_mDNSSetARP() routine
+
+Revision 1.44  2008/11/05 18:41:14  cheshire
+Log errors from read() call in do_mDNSSetARP()
+
+Revision 1.43  2008/11/04 23:54:09  cheshire
+Added routine mDNSSetARP(), used to replace an SPS client's entry in our ARP cache with
+a dummy one, so that IP traffic to the SPS client initiated by the SPS machine can be
+captured by our BPF filters, and used as a trigger to wake the sleeping machine.
+
+Revision 1.42  2008/10/31 23:35:31  cheshire
+When scheduling new power event make sure all old events are deleted;
+mDNSPowerRequest(-1,-1); just clears old events without scheduling a new one
+
+Revision 1.41  2008/10/31 18:41:55  cheshire
+Do update_idle_timer() before returning from do_mDNSRequestBPF()
+
+Revision 1.40  2008/10/30 01:05:27  cheshire
+mDNSPowerRequest(0, 0) means "sleep now"
+
+Revision 1.39  2008/10/29 21:26:50  cheshire
+Only log IOPMSchedulePowerEvent calls when there's an error
+
+Revision 1.38  2008/10/24 01:42:36  cheshire
+Added mDNSPowerRequest helper routine to request a scheduled wakeup some time in the future
+
+Revision 1.37  2008/10/24 00:17:22  mcguire
+Add compatibility for older racoon behavior
+
+Revision 1.36  2008/10/22 17:22:31  cheshire
+Remove SO_NOSIGPIPE bug workaround
+
+Revision 1.35  2008/10/20 22:01:28  cheshire
+Made new Mach simpleroutine "mDNSRequestBPF"
+
+Revision 1.34  2008/10/02 23:50:07  mcguire
+<rdar://problem/6136442> shutdown time issues
+improve log messages when SCDynamicStoreCreate() fails
+
+Revision 1.33  2008/09/30 01:00:45  cheshire
+Added workaround to avoid SO_NOSIGPIPE bug
+
+Revision 1.32  2008/09/27 01:11:46  cheshire
+Added handler to respond to kmDNSSendBPF message
+
+Revision 1.31  2008/09/08 17:42:40  mcguire
+<rdar://problem/5536811> change location of racoon files
+cleanup, handle stat failure cases, reduce log messages
+
+Revision 1.30  2008/09/05 21:51:26  mcguire
+<rdar://problem/6077707> BTMM: Need to launch racoon by opening VPN control socket
+
+Revision 1.29  2008/09/05 18:26:53  mcguire
+<rdar://problem/6077707> BTMM: Need to launch racoon by opening VPN control socket
+
+Revision 1.28  2008/09/04 22:49:28  mcguire
+<rdar://problem/5536811> change location of racoon files
+
+Revision 1.27  2008/08/28 23:11:12  mcguire
+<rdar://problem/5858535> handle SIGTERM in mDNSResponderHelper
+
+Revision 1.26  2008/08/19 00:35:02  mcguire
+<rdar://problem/5858535> handle SIGTERM in mDNSResponderHelper
+
+Revision 1.25  2008/08/13 23:04:06  mcguire
+<rdar://problem/5858535> handle SIGTERM in mDNSResponderHelper
+Preparation: rename message function, as it will no longer be called only on idle exit
+
 Revision 1.24  2008/01/30 19:01:51  mcguire
 <rdar://problem/5703989> Crash in mDNSResponderHelper
 
@@ -97,7 +236,10 @@ Revision 1.1  2007/08/08 22:34:58  mcguire
 #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>
@@ -113,10 +255,13 @@ Revision 1.1  2007/08/08 22:34:58  mcguire
 #include <string.h>
 #include <unistd.h>
 #include <Security/Security.h>
+#include <SystemConfiguration/SystemConfiguration.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 #include <SystemConfiguration/SCPreferencesSetSpecific.h>
 #include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
 #include <TargetConditionals.h>
+#include <IOKit/pwr_mgt/IOPMLib.h>
+
 #include "mDNSEmbeddedAPI.h"
 #include "dns_sd.h"
 #include "dnssd_ipc.h"
@@ -126,11 +271,19 @@ Revision 1.1  2007/08/08 22:34:58  mcguire
 #include "helper-server.h"
 #include "ipsec_options.h"
 
+#ifndef RTF_IFSCOPE
+#define RTF_IFSCOPE 0x1000000
+#endif
+
 #if TARGET_OS_EMBEDDED
 #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;
 
 uid_t mDNSResponderUID;
@@ -166,93 +319,235 @@ authorized(audit_token_t *token)
        return ok;
        }
 
-#ifndef MDNS_NO_IPSEC
-static void
-closefds(int from)
+kern_return_t
+do_mDNSExit(__unused mach_port_t port, audit_token_t token)
        {
-       int fd = 0;
-       struct dirent entry, *entryp = NULL;
-       DIR *dirp = opendir("/dev/fd");
+       debug("entry");
+       if (!authorized(&token))
+               goto fin;
+       helplog(ASL_LEVEL_INFO, "exit");
+       exit(0);
 
-       if (dirp == NULL)
+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)
                {
-               /* fall back to the erroneous getdtablesize method */
-               for (fd = from; fd < getdtablesize(); ++fd)
-                       close(fd);
-               return;
+               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);
                }
-       while (0 == readdir_r(dirp, &entry, &entryp) && NULL != entryp)
+
+       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"
                {
-               fd = atoi(entryp->d_name);
-               if (fd >= from && fd != dirfd(dirp))
-                       close(fd);
+               IOReturn r = IOPMSleepSystem(IOPMFindPowerManagement(MACH_PORT_NULL));
+               if (r) { usleep(100000); helplog(ASL_LEVEL_ERR, "IOPMSleepSystem %d", r); }
+               *err = r;
                }
-       closedir(dirp);
+       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;
        }
-#endif
 
-kern_return_t
-do_mDNSIdleExit(__unused mach_port_t port, audit_token_t token)
+kern_return_t do_mDNSSetARP(__unused mach_port_t port, int ifindex, v4addr_t v4, ethaddr_t eth, int *err, audit_token_t token)
        {
-       debug("entry");
-       if (!authorized(&token))
-               goto fin;
-       helplog(ASL_LEVEL_INFO, "Idle exit");
-       exit(0);
+       //helplog(ASL_LEVEL_ERR, "do_mDNSSetARP %d %d.%d.%d.%d %02X:%02X:%02X:%02X:%02X:%02X",
+       //      ifindex, v4[0], v4[1], v4[2], v4[3], eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+
+       *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_mDNSSetARP: socket(PF_ROUTE, SOCK_RAW, 0) failed %d (%s)", errno, strerror(errno));
+               }
+
+       if (s >= 0)
+               {
+               struct timeval tv;
+               gettimeofday(&tv, 0);
+
+               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(struct sockaddr_inarp);
+               rtmsg.dst.sin_family         = AF_INET;
+               rtmsg.dst.sin_port           = 0;
+               rtmsg.dst.sin_addr.s_addr    = *(in_addr_t*)v4;
+               rtmsg.dst.sin_srcaddr.s_addr = 0;
+               rtmsg.dst.sin_tos            = 0;
+               rtmsg.dst.sin_other          = 0;
+
+               rtmsg.sdl.sdl_len            = sizeof(struct sockaddr_dl);
+               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_mDNSSetARP: write(%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s)",
+                               sizeof(rtmsg), ifindex, v4[0], v4[1], v4[2], v4[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
+               len = read(s, (char *)&rtmsg, sizeof(rtmsg));
+               if (len < 0)
+                       helplog(ASL_LEVEL_ERR, "do_mDNSSetARP: read (%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s)",
+                               sizeof(rtmsg), ifindex, v4[0], v4[1], v4[2], v4[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
+
+               *err = 0;
+               }
 
 fin:
-       debug("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);
+#endif /* NO_CFUSERNOTIFICATION */
+
+       update_idle_timer();
        return KERN_SUCCESS;
        }
 
 kern_return_t
 do_mDNSDynamicStoreSetConfig(__unused mach_port_t port, int key,
-    vm_offset_t value, mach_msg_type_number_t valueCnt, int *err,
+    const char* subkey, vm_offset_t value, mach_msg_type_number_t valueCnt,
     audit_token_t token)
        {
        CFStringRef sckey = NULL;
+       Boolean release_sckey = FALSE;
        CFDataRef bytes = NULL;
        CFPropertyListRef plist = NULL;
        SCDynamicStoreRef store = NULL;
 
        debug("entry");
-       *err = 0;
-       if (!authorized(&token))
-               {
-               *err = kmDNSHelperNotAuthorized;
-               goto fin;
-               }
+       if (!authorized(&token)) goto fin;
+
        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;
-       default:
-               debug("unrecognized key %d", key);
-               *err = kmDNSHelperInvalidConfigKey;
-               goto fin;
+               {
+               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;
+                       }
+               default:
+                       debug("unrecognized key %d", key);
+                       goto fin;
                }
        if (NULL == (bytes = CFDataCreateWithBytesNoCopy(NULL, (void *)value,
            valueCnt, kCFAllocatorNull)))
                {
                debug("CFDataCreateWithBytesNoCopy of value failed");
-               *err = kmDNSHelperCreationFailed;
                goto fin;
                }
        if (NULL == (plist = CFPropertyListCreateFromXMLData(NULL, bytes,
            kCFPropertyListImmutable, NULL)))
                {
                debug("CFPropertyListCreateFromXMLData of bytes failed");
-               *err = kmDNSHelperInvalidPList;
                goto fin;
                }
        CFRelease(bytes);
@@ -260,23 +555,21 @@ do_mDNSDynamicStoreSetConfig(__unused mach_port_t port, int key,
        if (NULL == (store = SCDynamicStoreCreate(NULL,
            CFSTR(kmDNSHelperServiceName), NULL, NULL)))
                {
-               debug("SCDynamicStoreCreate failed");
-               *err = kmDNSHelperDynamicStoreFailed;
+               debug("SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
                goto fin;
                }
        SCDynamicStoreSetValue(store, sckey, plist);
-       *err = 0;
        debug("succeeded");
 
 fin:
-       if (0 != *err)
-               debug("failed err=%d", *err);
        if (NULL != bytes)
                CFRelease(bytes);
        if (NULL != plist)
                CFRelease(plist);
        if (NULL != store)
                CFRelease(store);
+       if (release_sckey && sckey)
+               CFRelease(sckey);
        vm_deallocate(mach_task_self(), value, valueCnt);
        update_idle_timer();
        return KERN_SUCCESS;
@@ -475,7 +768,7 @@ static void update_notification(void)
        }
 
 kern_return_t
-do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, const char* new, int *err, audit_token_t token)
+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;
@@ -486,12 +779,8 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c
        Boolean needUpdate = FALSE;
 
        debug("entry %s old=%s new=%s", key==kmDNSComputerName ? "ComputerName" : (key==kmDNSLocalHostName ? "LocalHostName" : "UNKNOWN"), old, new);
-       *err = 0;
-       if (!authorized(&token))
-               {
-               *err = kmDNSHelperNotAuthorized;
-               goto fin;
-               }
+       if (!authorized(&token)) goto fin;
+
        switch ((enum mDNSPreferencesSetNameKey)key)
                {
                case kmDNSComputerName:
@@ -504,7 +793,6 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c
                        break;
                default:
                        debug("unrecognized key: %d", key);
-                       *err = kmDNSHelperInvalidNameKey;
                        goto fin;
                }
 
@@ -556,13 +844,11 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c
        if (cfstr == NULL || session == NULL)
                {
                debug("SCPreferencesCreate failed");
-               *err = kmDNSHelperPreferencesFailed;
                goto fin;
                }
        if (!SCPreferencesLock(session, 0))
                {
                debug("lock failed");
-               *err = kmDNSHelperPreferencesLockFailed;
                goto fin;
                }
        locked = TRUE;
@@ -594,15 +880,11 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c
            !SCPreferencesApplyChanges(session))
                {
                debug("SCPreferences update failed");
-               *err = kmDNSHelperPreferencesSetFailed;
                goto fin;
                }
-       *err = 0;
        debug("succeeded");
 
 fin:
-       if (0 != *err)
-               debug("failed err=%d", *err);
        if (NULL != cfstr)
                CFRelease(cfstr);
        if (NULL != session)
@@ -925,7 +1207,7 @@ aliasTunnelAddress(v6addr_t address)
                err = kmDNSHelperDatagramSocketCreationFailed;
                goto fin;
                }
-       bzero(&ifra_in6, sizeof(ifra_in6));
+       memset(&ifra_in6, 0, sizeof(ifra_in6));
        strlcpy(ifra_in6.ifra_name, kTunnelAddressInterface,
            sizeof(ifra_in6.ifra_name));
        ifra_in6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
@@ -975,7 +1257,7 @@ unaliasTunnelAddress(v6addr_t address)
                err = kmDNSHelperDatagramSocketCreationFailed;
                goto fin;
                }
-       bzero(&ifr, sizeof(ifr));
+       memset(&ifr, 0, sizeof(ifr));
        strlcpy(ifr.ifr_name, kTunnelAddressInterface, sizeof(ifr.ifr_name));
        ifr.ifr_ifru.ifru_addr.sin6_family = AF_INET6;
        ifr.ifr_ifru.ifru_addr.sin6_len = sizeof(struct sockaddr_in6);
@@ -1005,27 +1287,22 @@ fin:
 
 int
 do_mDNSAutoTunnelInterfaceUpDown(__unused mach_port_t port, int updown,
-    v6addr_t address, int *err, audit_token_t token)
+    v6addr_t address, audit_token_t token)
        {
 #ifndef MDNS_NO_IPSEC
        debug("entry");
-       *err = 0;
-       if (!authorized(&token))
-               {
-               *err = kmDNSHelperNotAuthorized;
-               goto fin;
-               }
+       if (!authorized(&token)) goto fin;
+
        switch ((enum mDNSUpDown)updown)
-       {
-       case kmDNSUp:
-               *err = aliasTunnelAddress(address);
-               break;
-       case kmDNSDown:
-               *err = unaliasTunnelAddress(address);
-               break;
-       default:
-               *err = kmDNSHelperInvalidInterfaceState;
-               goto fin;
+               {
+               case kmDNSUp:
+                       aliasTunnelAddress(address);
+                       break;
+               case kmDNSDown:
+                       unaliasTunnelAddress(address);
+                       break;
+               default:
+                       goto fin;
                }
        debug("succeeded");
 
@@ -1039,15 +1316,85 @@ fin:
        }
 
 #ifndef MDNS_NO_IPSEC
-static const char racoon_config_path[] = "/etc/racoon/remote/anonymous.conf";
-static const char racoon_config_path_orig[] = "/etc/racoon/remote/anonymous.conf.orig";
+
+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 g_oldRacoon = -1;
+static int g_racoonSignal = SIGUSR1;
+
+static void DetermineRacoonVersion()
+       {
+       if (g_oldRacoon == -1)
+               {
+               char letter = 0;
+               int minor = 0;
+               g_oldRacoon = (MacOSXSystemBuildNumber(&letter, &minor) < 10);
+               if (g_oldRacoon || (letter == 'A' && minor < 218)) g_racoonSignal = SIGHUP;
+               debug("%s, signal=%d", g_oldRacoon?"old":"new", g_racoonSignal);
+               }
+       }
+
+static int UseOldRacoon()
+       {
+       DetermineRacoonVersion();
+       return g_oldRacoon;
+       }
+       
+static int RacoonSignal()
+       {
+       DetermineRacoonVersion();
+       return g_racoonSignal;
+       }
+       
+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()
+static int IsFamiliarRacoonConfiguration(const char* racoon_config_path)
        {
        int fd = open(racoon_config_path, O_RDONLY);
-       debug("entry");
+       debug("entry %s", racoon_config_path);
        if (0 > fd)
                {
                helplog(ASL_LEVEL_NOTICE, "open \"%s\" failed: %s", racoon_config_path, strerror(errno));
@@ -1064,25 +1411,134 @@ static int IsFamiliarRacoonConfiguration()
        }
 
 static void
-revertAnonymousRacoonConfiguration()
+revertAnonymousRacoonConfiguration(const char* dir)
        {
-       debug("entry");
-       if (!IsFamiliarRacoonConfiguration())
+       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)
                {
-               helplog(ASL_LEVEL_NOTICE, "\"%s\" does not look familiar, leaving in place", racoon_config_path);
+               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;
                }
 
-       if (0 > rename(racoon_config_path_orig, racoon_config_path))
+       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)
                {
-               helplog(ASL_LEVEL_NOTICE, "rename \"%s\" \"%s\" failed: %s", racoon_config_path_orig, racoon_config_path, strerror(errno));
-               helplog(ASL_LEVEL_NOTICE, "\"%s\" looks familiar, unlinking", racoon_config_path);
-               unlink(racoon_config_path);
+               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
-createAnonymousRacoonConfiguration(const char *keydata)
+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"
@@ -1091,7 +1547,7 @@ createAnonymousRacoonConfiguration(const char *keydata)
          "  situation identity_only;\n"
          "  verify_identifier off;\n"
          "  generate_policy on;\n"
-         "  shared_secret use \"";
+         "  shared_secret keychain_by_id \"dns:";
        static const char config2[] =
          "\";\n"
          "  nonce_size 16;\n"
@@ -1115,11 +1571,21 @@ createAnonymousRacoonConfiguration(const char *keydata)
          "  authentication_algorithm hmac_sha1;\n"
          "  compression_algorithm deflate;\n"
          "}\n";
-       char tmp_config_path[] =
-           "/etc/racoon/remote/tmp.XXXXXX";
-       int fd = mkstemp(tmp_config_path);
-
+       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)
                {
@@ -1129,23 +1595,23 @@ createAnonymousRacoonConfiguration(const char *keydata)
                }
        write(fd, configHeader, sizeof(configHeader)-1);
        write(fd, config1, sizeof(config1)-1);
-       write(fd, keydata, strlen(keydata));
+       write(fd, fqdn, strlen(fqdn));
        write(fd, config2, sizeof(config2)-1);
        close(fd);
 
-       if (IsFamiliarRacoonConfiguration())
-               helplog(ASL_LEVEL_NOTICE, "\"%s\" looks familiar, will overwrite", racoon_config_path);
-       else 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\" \"%s\" failed: %s", racoon_config_path, racoon_config_path_orig, strerror(errno));
-       else
-               debug("successfully renamed \"%s\" \"%s\"", racoon_config_path, racoon_config_path_orig);
+       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();
+               revertAnonymousRacoonConfiguration(racoon_config_dir_old);
+               revertAnonymousRacoonConfiguration(racoon_config_dir);
                return -1;
                }
 
@@ -1190,17 +1656,40 @@ notifyRacoon(void)
                debug("refusing to kill PID %lu", m);
                return kmDNSHelperRacoonNotificationFailed;
                }
-       if (0 != kill(m, SIGHUP))
+       if (0 != kill(m, RacoonSignal()))
                {
                debug("Could not signal racoon (%lu): %s", m, strerror(errno));
                return kmDNSHelperRacoonNotificationFailed;
                }
-       debug("Sent SIGHUP to racoon (%lu)", m);
+       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
-startRacoon(void)
+startRacoonOld(void)
        {
        debug("entry");
        char * const racoon_args[] = { "/usr/sbin/racoon", "-e", NULL   };
@@ -1256,53 +1745,147 @@ startRacoon(void)
        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 = { 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;
+       
+       while (counter < 100)
+               {
+               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 startRacoon();
+       return UseOldRacoon() ? startRacoonOld() : startRacoon();
        }
 
 #endif /* ndef MDNS_NO_IPSEC */
 
 int
-do_mDNSConfigureServer(__unused mach_port_t port, int updown, const char *keydata, int *err, audit_token_t token)
+do_mDNSConfigureServer(__unused mach_port_t port, int updown, const char *fqdn, audit_token_t token)
        {
 #ifndef MDNS_NO_IPSEC
        debug("entry");
-       *err = 0;
-
-       if (!authorized(&token))
-               {
-               *err = kmDNSHelperNotAuthorized;
-               goto fin;
-               }
+       if (!authorized(&token)) goto fin;
 
        switch ((enum mDNSUpDown)updown)
                {
                case kmDNSUp:
-                       if (0 != createAnonymousRacoonConfiguration(keydata))
-                               {
-                               *err = kmDNSHelperRacoonConfigCreationFailed;
-                               goto fin;
-                               }
+                       if (0 != createAnonymousRacoonConfiguration(fqdn)) goto fin;
                        break;
                case kmDNSDown:
-                       revertAnonymousRacoonConfiguration();
+                       revertAnonymousRacoonConfiguration(GetOldRacoonConfigDir());
+                       revertAnonymousRacoonConfiguration(GetRacoonConfigDir());
                        break;
                default:
-                       *err = kmDNSHelperInvalidServerState;
                        goto fin;
                }
 
-       if (0 != (*err = kickRacoon()))
+       if (0 != kickRacoon())
                goto fin;
        debug("succeeded");
 
 fin:
 #else
-       (void)port; (void)updown; (void)keydata; (void)token;
+       (void)port; (void)updown; (void)fqdn; (void)token;
        *err = kmDNSHelperIPsecDisabled;
 #endif
        update_idle_timer();
@@ -1649,8 +2232,8 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which,
        debug("succeeded");
 
 fin:
-       if (0 >= s)
-               close(s);
+       if (s >= 0)
+               pfkey_close(s);
        if (NULL != policy)
                free(policy);
        return err;
@@ -1662,7 +2245,7 @@ int
 do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
     v6addr_t loc_inner, v4addr_t loc_outer, uint16_t loc_port,
     v6addr_t rmt_inner, v4addr_t rmt_outer, uint16_t rmt_port,
-    const char *keydata, int *err, audit_token_t token)
+    const char *fqdn, int *err, audit_token_t token)
        {
 #ifndef MDNS_NO_IPSEC
        static const char config[] =
@@ -1673,7 +2256,8 @@ do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
          "  situation identity_only;\n"
          "  verify_identifier off;\n"
          "  generate_policy on;\n"
-         "  shared_secret use \"%s\";\n"
+         "  my_identifier user_fqdn \"dns:%s\";\n"
+         "  shared_secret keychain \"dns:%s\";\n"
          "  nonce_size 16;\n"
          "  lifetime time 5 min;\n"
          "  initial_contact on;\n"
@@ -1738,7 +2322,7 @@ do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
            lo, loc_port, ro, rmt_port);
 
        if ((int)sizeof(path) <= snprintf(path, sizeof(path),
-           "/etc/racoon/remote/%s.%u.conf", ro,
+           "%s%s.%u.conf", GetRacoonConfigDir(), ro,
            rmt_port))
                {
                *err = kmDNSHelperResultTooLarge;
@@ -1746,6 +2330,11 @@ do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
                }
        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))
                        {
@@ -1754,7 +2343,7 @@ do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
                        }       
                if (0 > (fd = mkstemp(tmp_path)))
                        {
-                       helplog(ASL_LEVEL_ERR, "mktemp \"%s\" failed: %s",
+                       helplog(ASL_LEVEL_ERR, "mkstemp \"%s\" failed: %s",
                            tmp_path, strerror(errno));
                        *err = kmDNSHelperRacoonConfigCreationFailed;
                        goto fin;
@@ -1767,7 +2356,7 @@ do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
                        goto fin;
                        }
                fd = -1;
-               fprintf(fp, config, configHeader, ro, rmt_port, keydata, ri, li, li, ri);
+               fprintf(fp, config, configHeader, ro, rmt_port, fqdn, fqdn, ri, li, li, ri);
                fclose(fp);
                fp = NULL;
                if (0 > rename(tmp_path, path))
index 00d5289786436e2482647df1da81e64bc0b3a956..ac974a5345d17cf7ad3f709abd4f232a6bc83fa9 100644 (file)
     Change History (most recent first):
 
 $Log: helper.h,v $
+Revision 1.18  2009/04/20 20:40:14  cheshire
+<rdar://problem/6786150> uDNS: Running location cycling caused configd and mDNSResponder to deadlock
+Changed mDNSPreferencesSetName (and similar) routines from MIG "routine" to MIG "simpleroutine"
+so we don't deadlock waiting for a result that we're just going to ignore anyway
+
+Revision 1.17  2009/03/20 22:12:28  mcguire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+Make the call to the helper a simpleroutine: don't wait for an unused return value
+
+Revision 1.16  2009/03/20 20:52:22  cheshire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+
+Revision 1.15  2009/03/14 01:42:56  mcguire
+<rdar://problem/5457116> BTMM: Fix issues with multiple .Mac accounts on the same machine
+
+Revision 1.14  2009/01/22 02:14:27  cheshire
+<rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
+
+Revision 1.13  2009/01/14 01:38:43  mcguire
+<rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
+
+Revision 1.12  2009/01/12 22:26:13  mkrochma
+Change DynamicStore location from BonjourSleepProxy/DiscoveredServers to SleepProxyServers
+
+Revision 1.11  2008/12/05 02:35:24  mcguire
+<rdar://problem/6107390> Write to the DynamicStore when a Sleep Proxy server is available on the network
+
+Revision 1.10  2008/11/04 23:54:09  cheshire
+Added routine mDNSSetARP(), used to replace an SPS client's entry in our ARP cache with
+a dummy one, so that IP traffic to the SPS client initiated by the SPS machine can be
+captured by our BPF filters, and used as a trigger to wake the sleeping machine.
+
+Revision 1.9  2008/10/24 01:42:36  cheshire
+Added mDNSPowerRequest helper routine to request a scheduled wakeup some time in the future
+
+Revision 1.8  2008/10/20 22:01:28  cheshire
+Made new Mach simpleroutine "mDNSRequestBPF"
+
+Revision 1.7  2008/09/27 00:58:11  cheshire
+Added mDNSRequestBPF declaration
+
 Revision 1.6  2007/09/20 22:33:17  cheshire
 Tidied up inconsistent and error-prone naming -- used to be mDNSResponderHelper in
 some places and mDNSResponder.helper in others; now mDNSResponderHelper everywhere
@@ -44,7 +85,8 @@ enum mDNSDynamicStoreSetConfigKey
        kmDNSMulticastConfig = 1,
        kmDNSDynamicConfig,
        kmDNSPrivateConfig,
-       kmDNSBackToMyMacConfig
+       kmDNSBackToMyMacConfig,
+       kmDNSSleepProxyServersState
        };
 
 enum mDNSPreferencesSetNameKey
@@ -78,13 +120,18 @@ enum mDNSHelperErrors
 #include "helpermsg-types.h"
 
 extern const char *mDNSHelperError(int errornum);
-extern int mDNSPreferencesSetName(int key, domainlabel* old, domainlabel* new);
-extern int mDNSDynamicStoreSetConfig(int key, CFPropertyListRef value);
-extern int mDNSKeychainGetSecrets(CFArrayRef *secrets);
-extern int mDNSAutoTunnelInterfaceUpDown(int updown, v6addr_t addr);
-extern int mDNSConfigureServer(int updown, const char *keydata);
-extern int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
-    v4addr_t local_outer, short local_port, v6addr_t remote_inner,
-    v4addr_t remote_outer, short remote_port, const char *keydata);
+
+extern void mDNSRequestBPF(void);
+extern int  mDNSPowerRequest(int key, int interval);
+extern int  mDNSSetARP(int ifindex, const v4addr_t ip, const ethaddr_t eth);
+extern void mDNSNotify(const char *title, const char *msg);            // Both strings are UTF-8 text
+extern void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value);
+extern void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new);
+extern int  mDNSKeychainGetSecrets(CFArrayRef *secrets);
+extern void mDNSAutoTunnelInterfaceUpDown(int updown, v6addr_t addr);
+extern void mDNSConfigureServer(int updown, const domainname *const fqdn);
+extern int  mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
+                               v4addr_t local_outer, short local_port, v6addr_t remote_inner,
+                               v4addr_t remote_outer, short remote_port, const domainname *const fqdn);
 
 #endif /* H_HELPER_H */
index 132169235b69e2d288e301bb8ceec0e4dfee3edd..07539d2848c5f851afa612bc1a69dea821a1f990 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: helpermsg-types.h,v $
+Revision 1.3  2009/01/22 02:14:27  cheshire
+<rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
+
 Revision 1.2  2007/08/23 21:52:19  cheshire
 Added License header
 
@@ -28,8 +31,9 @@ Revision 1.1  2007/08/08 22:34:58  mcguire
 #define H_HELPERMSG_TYPES_H
 
 #include <stdint.h>
-typedef uint8_t v6addr_t[16];
-typedef uint8_t v4addr_t[4];
+typedef uint8_t v4addr_t [ 4];
+typedef uint8_t ethaddr_t[ 6];
+typedef uint8_t v6addr_t [16];
 typedef const char *string_t;
 
 #endif /* H_HELPERMSG_TYPES_H */
index 03ae2da714c0d3a9d95fe67511f5e919e54c9a82..0c2d1724621234f3d58a13c0976219d535662255 100644 (file)
     Change History (most recent first):
 
 $Log: helpermsg.defs,v $
+Revision 1.17  2009/04/20 20:40:14  cheshire
+<rdar://problem/6786150> uDNS: Running location cycling caused configd and mDNSResponder to deadlock
+Changed mDNSPreferencesSetName (and similar) routines from MIG "routine" to MIG "simpleroutine"
+so we don't deadlock waiting for a result that we're just going to ignore anyway
+
+Revision 1.16  2009/03/20 22:12:28  mcguire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+Make the call to the helper a simpleroutine: don't wait for an unused return value
+
+Revision 1.15  2009/03/20 20:52:22  cheshire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+
+Revision 1.14  2009/03/14 01:42:56  mcguire
+<rdar://problem/5457116> BTMM: Fix issues with multiple .Mac accounts on the same machine
+
+Revision 1.13  2009/01/22 02:14:26  cheshire
+<rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
+
+Revision 1.12  2009/01/14 01:38:43  mcguire
+<rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
+
+Revision 1.11  2008/11/04 23:54:09  cheshire
+Added routine mDNSSetARP(), used to replace an SPS client's entry in our ARP cache with
+a dummy one, so that IP traffic to the SPS client initiated by the SPS machine can be
+captured by our BPF filters, and used as a trigger to wake the sleeping machine.
+
+Revision 1.10  2008/10/24 01:42:36  cheshire
+Added mDNSPowerRequest helper routine to request a scheduled wakeup some time in the future
+
+Revision 1.9  2008/10/20 22:01:28  cheshire
+Made new Mach simpleroutine "mDNSRequestBPF"
+
+Revision 1.8  2008/09/26 21:18:13  cheshire
+Tidy up code layout
+
+Revision 1.7  2008/08/13 23:04:06  mcguire
+<rdar://problem/5858535> handle SIGTERM in mDNSResponderHelper
+Preparation: rename message function, as it will no longer be called only on idle exit
+
 Revision 1.6  2007/09/07 22:44:03  mcguire
 <rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
 
@@ -41,63 +80,77 @@ Revision 1.1  2007/08/08 22:34:58  mcguire
 
 import "helpermsg-types.h";
 
-type v6addr_t = array [16] of uint8_t;
-type v4addr_t = array [4] of uint8_t;
+type v4addr_t  = array [ 4] of uint8_t;
+type ethaddr_t = array [ 6] of uint8_t;
+type v6addr_t  = array [16] of uint8_t;
 type string_t = c_string[*:1024];
 
 subsystem helper 1833193043;
 serverprefix do_;
 userprefix proxy_;
 
-simpleroutine mDNSIdleExit(
-                               port            : mach_port_t;
-       ServerAuditToken        token           : audit_token_t);
-
-routine mDNSDynamicStoreSetConfig(
-                               port            : mach_port_t;
-                               key             : int;
-                               value           : pointer_t;
-       out                     err             : int;
-       ServerAuditToken        token           : audit_token_t);
-
-routine mDNSPreferencesSetName(
-                                               port    : mach_port_t;
-                                               key             : int;
-                                               old             : string_t;
-                                               new             : string_t;
-       out                                     err             : int;
-       ServerAuditToken        token   : audit_token_t);
-
-routine mDNSKeychainGetSecrets(
-                               port            : mach_port_t;
-       out                     numsecrets      : unsigned;
-       out                     secrets         : pointer_t;
-       out                     err             : int;
-       ServerAuditToken        token           : audit_token_t);
-
-routine mDNSAutoTunnelInterfaceUpDown(
-                               port            : mach_port_t;
-                               updown          : int;
-                               address         : v6addr_t;
-       out                     err             : int;
-       ServerAuditToken        token           : audit_token_t);
-
-routine mDNSConfigureServer(
-                               port            : mach_port_t;
-                               updown          : int;
-                               keydata         : string_t;
-       out                     err             : int;
-       ServerAuditToken        token           : audit_token_t);
-
-routine mDNSAutoTunnelSetKeys(
-                               port            : mach_port_t;
-                               replacedelete   : int;
-                               local_inner     : v6addr_t;
-                               local_outer     : v4addr_t;
-                               local_port      : uint16_t;
-                               remote_inner    : v6addr_t;
-                               remote_outer    : v4addr_t;
-                               remote_port     : uint16_t;
-                               keydata         : string_t;
-       out                     err             : int;
-       ServerAuditToken        token           : audit_token_t);
+simpleroutine mDNSExit(                        port                    : mach_port_t;
+               ServerAuditToken                token                   : audit_token_t);
+
+simpleroutine mDNSRequestBPF(  port                    : mach_port_t;
+               ServerAuditToken                token                   : audit_token_t);
+
+routine mDNSPowerRequest(              port                    : mach_port_t;
+                                                               key                             : int;
+                                                               interval                : int;
+               out                                             err                             : int;
+               ServerAuditToken                token                   : audit_token_t);
+
+routine mDNSSetARP(                            port                    : mach_port_t;
+                                                               ifindex                 : int;
+                                                               ip                              : v4addr_t;
+                                                               eth                             : ethaddr_t;
+               out                                             err                             : int;
+               ServerAuditToken                token                   : audit_token_t);
+
+simpleroutine mDNSNotify(              port                    : mach_port_t;
+                                                               title                   : string_t;
+                                                               msg                             : string_t;
+               ServerAuditToken                token                   : audit_token_t);
+
+simpleroutine mDNSDynamicStoreSetConfig(
+                                                               port                    : mach_port_t;
+                                                               key                             : int;
+                                                               subkey                  : string_t;
+                                                               value                   : pointer_t;
+               ServerAuditToken                token                   : audit_token_t);
+
+simpleroutine mDNSPreferencesSetName( port                     : mach_port_t;
+                                                               key                             : int;
+                                                               old                             : string_t;
+                                                               new                             : string_t;
+               ServerAuditToken                token                   : audit_token_t);
+
+routine mDNSKeychainGetSecrets( port                   : mach_port_t;
+               out                                             numsecrets              : unsigned;
+               out                                             secrets                 : pointer_t;
+               out                                             err                             : int;
+               ServerAuditToken                token                   : audit_token_t);
+
+simpleroutine mDNSAutoTunnelInterfaceUpDown(
+                                                               port                    : mach_port_t;
+                                                               updown                  : int;
+                                                               address                 : v6addr_t;
+               ServerAuditToken                token                   : audit_token_t);
+
+simpleroutine mDNSConfigureServer(     port                    : mach_port_t;
+                                                               updown                  : int;
+                                                               fqdn                    : string_t;
+               ServerAuditToken                token                   : audit_token_t);
+
+routine mDNSAutoTunnelSetKeys( port                    : mach_port_t;
+                                                               replacedelete   : int;
+                                                               local_inner             : v6addr_t;
+                                                               local_outer             : v4addr_t;
+                                                               local_port              : uint16_t;
+                                                               remote_inner    : v6addr_t;
+                                                               remote_outer    : v4addr_t;
+                                                               remote_port             : uint16_t;
+                                                               fqdn                    : string_t;
+               out                                             err                             : int;
+               ServerAuditToken                token                   : audit_token_t);
index cc139802cf235fe2988e6a62fffad811be687c88..7f66dd4d62da9fc3d97ee5319310b6664c6859d5 100644 (file)
     Change History (most recent first):
 
 $Log: mDNSMacOSX.c,v $
-Revision 1.536.2.2  2008/07/30 01:08:17  mcguire
-<rdar://problem/6090007> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
-merge r1.540 from <rdar://problem/3988320>
+Revision 1.687  2009/06/30 21:16:09  cheshire
+<rdar://problem/7020041> Plugging and unplugging the power cable shouldn't cause a network change event
+Additional fix: Only start and stop NetWake browses for active interfaces that are currently registered with mDNSCore
 
-Revision 1.536.2.1  2008/07/29 20:48:10  mcguire
-<rdar://problem/6090007> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
-merge r1.539 from <rdar://problem/3988320>
+Revision 1.686  2009/06/25 23:36:56  cheshire
+To facilitate testing, added command-line switch "-OfferSleepProxyService"
+to re-enable the previously-supported mode of operation where we offer
+sleep proxy service on desktop Macs that are set to never sleep.
+
+Revision 1.685  2009/06/25 23:15:12  cheshire
+Don't try to use private header file "IOPowerSourcesPrivate.h"
+(it prevents external developers from being able to compile the code)
+
+Revision 1.684  2009/06/24 22:14:22  cheshire
+<rdar://problem/6911445> Plugging and unplugging the power cable shouldn't cause a network change event
+
+Revision 1.683  2009/06/08 22:31:03  cheshire
+Fixed typo in comment: Portability > 35 means nominal weight < 3kg
+
+Revision 1.682  2009/05/19 23:30:31  cheshire
+Suppressed some unnecessary debugging messages; added AppleTV to list of recognized hardware
+
+Revision 1.681  2009/05/12 23:23:15  cheshire
+Removed unnecessary "mDNSPlatformTCPConnect - connect failed ... Error 50 (Network is down)" debugging message
+
+Revision 1.680  2009/05/05 01:32:50  jessic2
+<rdar://problem/6830541> regservice_callback: instance->request is NULL 0 -- Clean up spurious logs resulting from fixing this bug.
+
+Revision 1.679  2009/05/01 23:48:46  jessic2
+<rdar://problem/6830541> regservice_callback: instance->request is NULL 0
+
+Revision 1.678  2009/04/24 23:32:28  cheshire
+To facilitate testing, put back code to be a sleep proxy when set to never sleep, compiled out by compile-time switch
+
+Revision 1.677  2009/04/24 20:50:16  mcguire
+<rdar://problem/6791775> 4 second delay in DNS response
+
+Revision 1.676  2009/04/24 02:17:58  mcguire
+<rdar://problem/5264124> uDNS: Not always respecting preference order of DNS servers
+
+Revision 1.675  2009/04/23 18:51:28  mcguire
+<rdar://problem/6729406> uDNS: PPP doesn't automatically reconnect on wake from sleep (no name resolver)
+
+Revision 1.674  2009/04/23 00:58:01  jessic2
+<rdar://problem/6802117> uDNS: DNS stops working after configd crashes
+
+Revision 1.673  2009/04/22 01:19:57  jessic2
+<rdar://problem/6814585> Daemon: mDNSResponder is logging garbage for error codes because it's using %ld for int 32
+
+Revision 1.672  2009/04/21 16:34:47  mcguire
+<rdar://problem/6810663> null deref in mDNSPlatformSetDNSConfig
+
+Revision 1.671  2009/04/15 01:14:07  mcguire
+<rdar://problem/6791775> 4 second delay in DNS response
+
+Revision 1.670  2009/04/15 01:10:39  jessic2
+<rdar://problem/6466541> BTMM: Add support for setting kDNSServiceErr_NoSuchRecord in DynamicStore
+
+Revision 1.669  2009/04/11 02:02:34  mcguire
+<rdar://problem/6780046> crash in doSSLHandshake
+
+Revision 1.668  2009/04/11 00:20:08  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.667  2009/04/09 20:01:00  cheshire
+<rdar://problem/6767122> IOPMCopyActivePMPreferences not available on Apple TV
+At Rory's suggestion, removed unnecessary "Could not get Wake On LAN value" log message
+
+Revision 1.666  2009/04/07 21:57:53  cheshire
+<rdar://problem/6767122> IOPMCopyActivePMPreferences not available on Apple TV
+Put previous code back
+
+Revision 1.665  2009/04/03 21:48:44  mcguire
+Back out checkin 1.664 (<rdar://problem/6755199> MessageTracer: prepend domain to make signature field unique)
+
+Revision 1.663  2009/04/02 22:21:16  mcguire
+<rdar://problem/6577409> Adopt IOPM APIs
+
+Revision 1.662  2009/04/02 01:08:15  mcguire
+<rdar://problem/6735635> Don't be a sleep proxy when set to sleep never
+
+Revision 1.661  2009/04/01 17:50:14  mcguire
+cleanup mDNSRandom
+
+Revision 1.660  2009/04/01 01:13:10  mcguire
+<rdar://problem/6744276> Sleep Proxy: Detect lid closed
+
+Revision 1.659  2009/03/30 21:11:07  jessic2
+<rdar://problem/6728725> Need to do some polish work on MessageTracer logging
+
+Revision 1.658  2009/03/30 20:07:28  mcguire
+<rdar://problem/6736133> BTMM: SSLHandshake threads are leaking Mach ports
+
+Revision 1.657  2009/03/27 17:27:13  cheshire
+<rdar://problem/6724859> Need to support querying IPv6 DNS servers
+
+Revision 1.656  2009/03/26 05:02:48  mcguire
+fix build error in dnsextd
+
+Revision 1.655  2009/03/26 03:59:00  jessic2
+Changes for <rdar://problem/6492552&6492593&6492609&6492613&6492628&6492640&6492699>
+
+Revision 1.654  2009/03/20 20:53:26  cheshire
+Added test code for testing with MacBook Air, using a USB dongle that doesn't actually support Wake-On-LAN
+
+Revision 1.653  2009/03/20 20:52:22  cheshire
+<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+
+Revision 1.652  2009/03/19 23:44:47  mcguire
+<rdar://problem/6699216> Properly handle EADDRINUSE
+
+Revision 1.651  2009/03/17 19:15:24  mcguire
+<rdar://problem/6655415> SSLHandshake deadlock issues
+
+Revision 1.650  2009/03/17 01:24:22  cheshire
+Updated to new Sleep Proxy metric ranges: 100000-999999; 1000000 means "do not use"
+
+Revision 1.649  2009/03/15 01:30:29  mcguire
+fix log message
+
+Revision 1.648  2009/03/15 01:16:08  mcguire
+<rdar://problem/6655415> SSLHandshake deadlock issues
+
+Revision 1.647  2009/03/14 01:42:56  mcguire
+<rdar://problem/5457116> BTMM: Fix issues with multiple .Mac accounts on the same machine
+
+Revision 1.646  2009/03/13 01:36:24  mcguire
+<rdar://problem/6657640> Reachability fixes on DNS config change
+
+Revision 1.645  2009/03/10 23:48:33  cheshire
+<rdar://problem/6665739> Task scheduling failure when Sleep Proxy Server is active
+
+Revision 1.644  2009/03/10 04:17:09  cheshire
+Check for NULL answer in UpdateSPSStatus()
+
+Revision 1.643  2009/03/10 01:15:55  cheshire
+Sleep Proxies with invalid names (score 10000) need to be ignored
+
+Revision 1.642  2009/03/08 04:46:51  mkrochma
+Change Keychain LogMsg to LogInfo
+
+Revision 1.641  2009/03/05 23:53:34  cheshire
+Removed spurious "SnowLeopardPowerChanged: wake ERROR" syslog message
+
+Revision 1.640  2009/03/05 21:57:13  cheshire
+Don't close BPF fd until we have no more records we're proxying for on that interface
+
+Revision 1.639  2009/03/04 01:45:01  cheshire
+HW_MODEL information should be LogSPS, not LogMsg
+
+Revision 1.638  2009/03/03 22:51:54  cheshire
+<rdar://problem/6504236> Sleep Proxy: Waking on same network but different interface will cause conflicts
+
+Revision 1.637  2009/02/26 22:58:47  cheshire
+<rdar://problem/6616335> Crash in mDNSResponder at mDNSResponder • CloseBPF + 75
+Fixed race condition between the kqueue thread and the CFRunLoop thread.
+
+Revision 1.636  2009/02/21 01:38:39  cheshire
+Added comment: mDNSCoreMachineSleep(m, false); // Will set m->SleepState = SleepState_Awake;
+
+Revision 1.635  2009/02/17 23:29:03  cheshire
+Throttle logging to a slower rate when running on SnowLeopard
+
+Revision 1.634  2009/02/14 00:29:17  mcguire
+fixed typo
+
+Revision 1.633  2009/02/14 00:07:11  cheshire
+Need to set up m->SystemWakeOnLANEnabled before calling UpdateInterfaceList(m, utc);
+
+Revision 1.632  2009/02/13 19:40:07  cheshire
+Improved alignment of LogSPS messages
+
+Revision 1.631  2009/02/13 18:16:05  cheshire
+Fixed some compile warnings
+
+Revision 1.630  2009/02/13 06:32:43  cheshire
+Converted LogOperation messages to LogInfo or LogSPS
+
+Revision 1.629  2009/02/12 20:57:26  cheshire
+Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
+
+Revision 1.628  2009/02/11 02:34:45  cheshire
+m->p->SystemWakeForNetworkAccessEnabled renamed to m->SystemWakeOnLANEnabled
+
+Revision 1.627  2009/02/10 00:19:17  cheshire
+<rdar://problem/6107426> Sleep Proxy: Adopt SIOCGIFWAKEFLAGS ioctl to determine interface WOMP-ability
+
+Revision 1.626  2009/02/10 00:15:38  cheshire
+<rdar://problem/6551529> Sleep Proxy: "Unknown DNS packet type 8849" logs
+
+Revision 1.625  2009/02/09 21:24:25  cheshire
+Set correct bit in ifr.ifr_wake_flags (was coincidentally working because IF_WAKE_ON_MAGIC_PACKET happens to have the value 1)
+
+Revision 1.624  2009/02/09 21:11:43  cheshire
+Need to acknowledge kIOPMSystemPowerStateCapabilityCPU message
+
+Revision 1.623  2009/02/09 06:20:42  cheshire
+Upon receiving system power change notification, make sure our m->p->SystemWakeForNetworkAccessEnabled value
+correctly reflects the current system setting
+
+Revision 1.622  2009/02/07 02:57:32  cheshire
+<rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
+
+Revision 1.621  2009/02/06 03:18:12  mcguire
+<rdar://problem/6534643> BTMM: State not cleaned up on SIGTERM w/o reboot
+
+Revision 1.620  2009/02/02 22:14:11  cheshire
+Instead of repeatedly checking the Dynamic Store, use m->p->SystemWakeForNetworkAccessEnabled variable
+
+Revision 1.619  2009/01/24 02:11:58  cheshire
+Handle case where config->resolver[0]->nameserver[0] is NULL
+
+Revision 1.618  2009/01/24 01:55:51  cheshire
+Handle case where config->resolver[0]->domain is NULL
+
+Revision 1.617  2009/01/24 01:48:42  cheshire
+<rdar://problem/4786302> Implement logic to determine when to send dot-local lookups via Unicast
+
+Revision 1.616  2009/01/24 00:28:43  cheshire
+Updated comments
+
+Revision 1.615  2009/01/22 02:14:26  cheshire
+<rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
+
+Revision 1.614  2009/01/21 03:43:57  mcguire
+<rdar://problem/6511765> BTMM: Add support for setting kDNSServiceErr_NATPortMappingDisabled in DynamicStore
+
+Revision 1.613  2009/01/20 02:38:41  mcguire
+fix previous checkin comment
+
+Revision 1.612  2009/01/20 02:35:15  mcguire
+<rdar://problem/6508974> don't update BTMM & SleepProxyServers status at shutdown time
+
+Revision 1.611  2009/01/17 04:15:40  cheshire
+Updated "did sleep(5)" debugging message
+
+Revision 1.610  2009/01/16 20:37:30  cheshire
+Fixed incorrect value of EOPNOTSUPP
+
+Revision 1.609  2009/01/16 03:08:13  cheshire
+Use kernel event notifications to track KEV_DL_WAKEFLAGS_CHANGED
+(indicates when SIOCGIFWAKEFLAGS changes for an interface, e.g. when AirPort
+switches from a base-station that's WakeOnLAN-capable to one that isn't)
+
+Revision 1.608  2009/01/16 01:27:03  cheshire
+Initial work to adopt SIOCGIFWAKEFLAGS ioctl to determine whether an interface is WakeOnLAN-capable
+
+Revision 1.607  2009/01/15 22:24:01  cheshire
+Get rid of unnecessary ifa_name field in NetworkInterfaceInfoOSX (it just duplicates the content of ifinfo.ifname)
+This also eliminates an unnecessary malloc, memory copy, and free
+
+Revision 1.606  2009/01/15 00:22:49  mcguire
+<rdar://problem/6437092> NAT-PMP: mDNSResponder needs to listen on 224.0.0.1:5350/UDP with REUSEPORT
+
+Revision 1.605  2009/01/14 01:38:43  mcguire
+<rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
+
+Revision 1.604  2009/01/13 05:31:34  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.603  2009/01/12 22:26:13  mkrochma
+Change DynamicStore location from BonjourSleepProxy/DiscoveredServers to SleepProxyServers
+
+Revision 1.602  2008/12/19 20:23:34  mcguire
+<rdar://problem/6459269> Lots of duplicate log messages about failure to bind to NAT-PMP Announcement port
+
+Revision 1.601  2008/12/15 19:51:56  mcguire
+<rdar://problem/6443067> Retry UDP socket creation only when randomizing ports
+
+Revision 1.600  2008/12/12 21:30:14  cheshire
+Additional defensive coding -- make sure InterfaceID is found in our list before using it
+
+Revision 1.599  2008/12/12 04:36:26  cheshire
+Make sure we don't overflow our BPF filter buffer
+Only add addresses for records where the InterfaceID matches
+
+Revision 1.598  2008/12/12 00:57:51  cheshire
+Updated BPF filter generation to explicitly match addresses we're proxying for,
+rather than just matching any unknown IP address
+
+Revision 1.597  2008/12/10 20:37:05  cheshire
+Don't mark interfaces like PPP as being WakeonLAN-capable
+
+Revision 1.596  2008/12/10 19:34:30  cheshire
+Use symbolic OS version names instead of literal integers
+
+Revision 1.595  2008/12/10 02:25:31  cheshire
+Minor fixes to use of LogClientOperations symbol
+
+Revision 1.594  2008/12/10 02:11:45  cheshire
+ARMv5 compiler doesn't like uncommented stuff after #endif
+
+Revision 1.593  2008/12/09 23:08:55  mcguire
+<rdar://problem/6430877> should use IP_BOUND_IF
+additional cleanup
+
+Revision 1.592  2008/12/09 19:58:44  mcguire
+<rdar://problem/6430877> should use IP_BOUND_IF
+
+Revision 1.591  2008/12/09 15:39:05  cheshire
+Workaround for bug on Leopard and earlier where Ethernet drivers report wrong link state immediately after wake from sleep
+
+Revision 1.590  2008/12/09 05:21:54  cheshire
+Should key sleep/wake handling off kIOMessageSystemWillPowerOn message -- the kIOMessageSystemHasPoweredOn
+message is delayed by some seemingly-random amount in the range 0-15 seconds.
+
+Revision 1.589  2008/12/05 02:35:25  mcguire
+<rdar://problem/6107390> Write to the DynamicStore when a Sleep Proxy server is available on the network
+
+Revision 1.588  2008/12/04 21:08:52  mcguire
+<rdar://problem/6116863> mDNS: Provide mechanism to disable Multicast advertisements
+
+Revision 1.587  2008/12/04 02:17:47  cheshire
+Additional sleep/wake debugging messages
+
+Revision 1.586  2008/11/26 20:34:55  cheshire
+Changed some "LogOperation" debugging messages to "debugf"
+
+Revision 1.585  2008/11/25 20:53:35  cheshire
+Updated portability metrics; added Xserve and PowerBook to list
+
+Revision 1.584  2008/11/25 05:07:16  cheshire
+<rdar://problem/6374328> Advertise Sleep Proxy metrics in service name
+
+Revision 1.583  2008/11/20 01:42:31  cheshire
+For consistency with other parts of the code, changed code to only check
+that the first 4 bytes of MAC address are zero, not the whole 6 bytes.
+
+Revision 1.582  2008/11/14 22:59:09  cheshire
+When on a network with more than one subnet overlayed on a single physical link, don't make local ARP
+entries for hosts that are on our physical link but not on our logical subnet -- it confuses the kernel
+
+Revision 1.581  2008/11/14 21:01:26  cheshire
+Log a warning if we fail to get a MAC address for an interface
+
+Revision 1.580  2008/11/14 02:16:15  cheshire
+Clean up NetworkChanged handling
+
+Revision 1.579  2008/11/12 23:15:37  cheshire
+Updated log messages
+
+Revision 1.578  2008/11/06 23:41:57  cheshire
+Refinement: Only need to create local ARP entry when sending ARP packet to broadcast address or to ourselves
+
+Revision 1.577  2008/11/06 01:15:47  mcguire
+Fix compile error that occurs when LogOperation is disabled
+
+Revision 1.576  2008/11/05 21:55:21  cheshire
+Fixed mistake in BPF filter generation
+
+Revision 1.575  2008/11/04 23:54:09  cheshire
+Added routine mDNSSetARP(), used to replace an SPS client's entry in our ARP cache with
+a dummy one, so that IP traffic to the SPS client initiated by the SPS machine can be
+captured by our BPF filters, and used as a trigger to wake the sleeping machine.
+
+Revision 1.574  2008/11/04 00:27:58  cheshire
+Corrected some timing anomalies in sleep/wake causing spurious name self-conflicts
+
+Revision 1.573  2008/11/03 01:12:42  mkrochma
+Fix compile error that occurs when LogOperation is disabled
+
+Revision 1.572  2008/10/31 23:36:13  cheshire
+One wakeup clear any previous power requests
+
+Revision 1.571  2008/10/31 23:05:30  cheshire
+Move logic to decide when to at as Sleep Proxy Server from daemon.c to mDNSMacOSX.c
+
+Revision 1.570  2008/10/30 01:08:19  cheshire
+After waking for network maintenance operations go back to sleep again
+
+Revision 1.569  2008/10/29 21:39:43  cheshire
+Updated syslog messages; close BPF socket on read error
+
+Revision 1.568  2008/10/28 20:37:28  cheshire
+Changed code to create its own CFSocketCreateWithNative directly, instead of
+relying on udsSupportAddFDToEventLoop/udsSupportRemoveFDFromEventLoop
+
+Revision 1.567  2008/10/27 22:31:37  cheshire
+Can't just close BPF_fd using "close(i->BPF_fd);" -- need to call
+"udsSupportRemoveFDFromEventLoop(i->BPF_fd);" to remove it from our event source list
+
+Revision 1.566  2008/10/23 22:33:23  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
+Revision 1.565  2008/10/22 23:23:55  cheshire
+Moved definition of OSXVers from daemon.c into mDNSMacOSX.c
+
+Revision 1.564  2008/10/22 22:08:46  cheshire
+Take IP header length into account when determining how many bytes to return from BPF filter
+
+Revision 1.563  2008/10/22 20:59:28  cheshire
+BPF filter needs to capture a few more bytes so that we can examine TCP header fields
+
+Revision 1.562  2008/10/22 19:48:29  cheshire
+Improved syslog messages
+
+Revision 1.561  2008/10/22 17:18:57  cheshire
+Need to open and close BPF fds when turning Sleep Proxy Server on and off
+
+Revision 1.560  2008/10/22 01:09:36  cheshire
+Fixed build warning when not using LogClientOperations
+
+Revision 1.559  2008/10/21 01:05:30  cheshire
+Added code to receive raw packets using Berkeley Packet Filter (BPF)
+
+Revision 1.558  2008/10/16 22:42:06  cheshire
+Removed debugging messages
+
+Revision 1.557  2008/10/09 22:33:14  cheshire
+Fill in ifinfo.MAC field when fetching interface list
+
+Revision 1.556  2008/10/09 21:15:23  cheshire
+In mDNSPlatformUDPSocket(), need to create an IPv6 socket as well as IPv4
+
+Revision 1.555  2008/10/09 19:05:57  cheshire
+No longer want to inhibit all networking when going to sleep
+
+Revision 1.554  2008/10/08 18:36:51  mkrochma
+<rdar://problem/4371323> Supress Couldn't read user-specified Computer Name logs
+
+Revision 1.553  2008/10/04 00:47:12  cheshire
+If NetWake setting changes for an interface, treat it as a whole new interface (like BSSID changing)
+
+Revision 1.552  2008/10/03 23:32:15  cheshire
+Added definition of mDNSPlatformSendRawPacket
+
+Revision 1.551  2008/10/03 18:25:16  cheshire
+Instead of calling "m->MainCallback" function pointer directly, call mDNSCore routine "mDNS_ConfigChanged(m);"
+
+Revision 1.550  2008/10/03 00:51:58  cheshire
+Removed spurious "else" case that got left in by mistake
+
+Revision 1.549  2008/10/03 00:50:13  cheshire
+Minor code rearrangement; don't set up interface list until *after* we've started watching for network changes
+
+Revision 1.548  2008/10/03 00:26:25  cheshire
+Export DictionaryIsEnabled() so it's callable from other files
+
+Revision 1.547  2008/10/02 23:50:07  mcguire
+<rdar://problem/6136442> shutdown time issues
+improve log messages when SCDynamicStoreCreate() fails
+
+Revision 1.546  2008/10/02 22:26:21  cheshire
+Moved declaration of BPF_fd from uds_daemon.c to mDNSMacOSX.c, where it really belongs
+
+Revision 1.545  2008/10/01 22:01:40  cheshire
+On Allan Nathanson's advice, add "State:/IOKit/PowerManagement/CurrentSettings"
+to keys array instead of patterns array, for efficiency
+
+Revision 1.544  2008/10/01 21:35:35  cheshire
+Monitor "State:/IOKit/PowerManagement/CurrentSettings" to track state of "Wake for network access" setting
+
+Revision 1.543  2008/09/26 23:05:56  mkrochma
+Improve log messages by using good old UTF-8
+
+Revision 1.542  2008/09/26 19:49:51  cheshire
+Improved "failed to send packet" debugging message
+
+Revision 1.541  2008/09/25 21:02:05  cheshire
+<rdar://problem/6245044> Stop using separate m->ServiceRegistrations list
+In TunnelServers(), need to check main m->ResourceRecords list to see
+if we have a non-zero number of advertised AutoTunnel services
+
+Revision 1.540  2008/07/30 00:55:56  mcguire
+<rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+Additional fixes so that we know when a socket has been closed while in a loop reading from it
+
+Revision 1.539  2008/07/24 20:23:04  cheshire
+<rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+
+Revision 1.538  2008/06/02 05:39:39  mkrochma
+<rdar://problem/5932760> Don't set TOS bits anymore
+
+Revision 1.537  2008/05/01 18:30:54  mkrochma
+<rdar://problem/5895642> Make mDNSResponder and mDNSResponderHelper shutdown at regular time
 
 Revision 1.536  2008/03/25 01:27:30  mcguire
 <rdar://problem/5810718> Status sometimes wrong when link goes down
@@ -773,18 +1241,20 @@ Add (commented out) trigger value for testing "mach_absolute_time went backwards
 
 #define USE_V6_ONLY_WHEN_NO_ROUTABLE_V4 0
 
-#include "mDNSEmbeddedAPI.h"          // Defines the interface provided to the client layer above
+#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 "../mDNSShared/uds_daemon.h" // Defines communication interface from platform layer up to UDS daemon
+#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 <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>
@@ -831,11 +1301,19 @@ Add (commented out) trigger value for testing "mach_absolute_time went backwards
 
 #include <IOKit/IOKitLib.h>
 #include <IOKit/IOMessage.h>
+
+#if USE_IOPMCOPYACTIVEPMPREFERENCES
+#include <IOKit/ps/IOPowerSources.h>
+#include <IOKit/ps/IOPowerSourcesPrivate.h>
+#endif
+
 #include <mach/mach_error.h>
 #include <mach/mach_port.h>
 #include <mach/mach_time.h>
 #include "helper.h"
 
+#include <asl.h>
+
 #define kInterfaceSpecificOption "interface="
 
 // ***************************************************************************
@@ -845,21 +1323,41 @@ Add (commented out) trigger value for testing "mach_absolute_time went backwards
 #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 OSXVers;
 mDNSexport int KQueueFD;
 
 #ifndef NO_SECURITYFRAMEWORK
 static CFArrayRef ServerCerts;
 #endif /* NO_SECURITYFRAMEWORK */
 
-#define DYNDNS_KEYCHAIN_SERVICE "DynDNS Shared Secret"
+static CFStringRef NetworkChangedKey_IPv4;
+static CFStringRef NetworkChangedKey_IPv6;
+static CFStringRef NetworkChangedKey_Hostnames;
+static CFStringRef NetworkChangedKey_Computername;
+static CFStringRef NetworkChangedKey_DNS;
+static CFStringRef NetworkChangedKey_DynamicDNS  = CFSTR("Setup:/Network/DynamicDNS");
+static CFStringRef NetworkChangedKey_BackToMyMac = CFSTR("Setup:/Network/BackToMyMac");
+
+static char  HINFO_HWstring_buffer[32];
+static char *HINFO_HWstring = "Device";
+static int   HINFO_HWstring_prefixlen = 6;
+
+mDNSexport int WatchDogReportingThreshold = 250;
 
-CFStringRef NetworkChangedKey_IPv4;
-CFStringRef NetworkChangedKey_IPv6;
-CFStringRef NetworkChangedKey_Hostnames;
-CFStringRef NetworkChangedKey_Computername;
-CFStringRef NetworkChangedKey_DNS;
-CFStringRef NetworkChangedKey_DynamicDNS  = CFSTR("Setup:/Network/DynamicDNS");
-CFStringRef NetworkChangedKey_BackToMyMac = CFSTR("Setup:/Network/BackToMyMac");
+#if APPLE_OSX_mDNSResponder
+static mDNSu8 SPMetricPortability   = 99;
+static mDNSu8 SPMetricMarginalPower = 99;
+static mDNSu8 SPMetricTotalPower    = 99;
+mDNSexport domainname ActiveDirectoryPrimaryDomain;
+mDNSexport int        ActiveDirectoryPrimaryDomainLabelCount;
+mDNSexport mDNSAddr   ActiveDirectoryPrimaryDomainServer;
+#endif // APPLE_OSX_mDNSResponder
 
 // ***************************************************************************
 // Functions
@@ -875,7 +1373,7 @@ CFStringRef NetworkChangedKey_BackToMyMac = CFSTR("Setup:/Network/BackToMyMac");
 // 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))
+#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
        {
@@ -905,12 +1403,7 @@ mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg)    // Both s
        notifyCount++;
 
 #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);
-       CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, NULL);
+       mDNSNotify(title, msg);
 #endif /* NO_CFUSERNOTIFICATION */
        }
 
@@ -934,7 +1427,7 @@ mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const
        {
        NetworkInterfaceInfoOSX *i;
        for (i = m->p->InterfaceList; i; i = i->next)
-               if (i->Exists && !strcmp(i->ifa_name, ifname) &&
+               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);
@@ -962,7 +1455,7 @@ mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const
                if (i->ifinfo.InterfaceID && i->scope_id == ifindex) return(i->ifinfo.InterfaceID);
 
        // Not found. Make sure our interface list is up to date, then try again.
-       LogOperation("InterfaceID for interface index %d not found; Updating interface list", ifindex);
+       LogInfo("InterfaceID for interface index %d not found; Updating interface list", ifindex);
        mDNSMacOSXNetworkChanged(m);
        for (i = m->p->InterfaceList; i; i = i->next)
                if (i->ifinfo.InterfaceID && i->scope_id == ifindex) return(i->ifinfo.InterfaceID);
@@ -981,7 +1474,7 @@ mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNS
                if ((mDNSInterfaceID)i == id) return(i->scope_id);
 
        // Not found. Make sure our interface list is up to date, then try again.
-       LogOperation("Interface index for InterfaceID %p not found; Updating interface list", id);
+       LogInfo("Interface index for InterfaceID %p not found; Updating interface list", id);
        mDNSMacOSXNetworkChanged(m);
        for (i = m->p->InterfaceList; i; i = i->next)
                if ((mDNSInterfaceID)i == id) return(i->scope_id);
@@ -989,6 +1482,41 @@ mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNS
        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 (OSXVers < OSXVers_10_6_SnowLeopard)         return;
+
+       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[36];
+               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);
+       }
+#endif
+
 #if COMPILER_LIKES_PRAGMA_MARK
 #pragma mark -
 #pragma mark - UDP & TCP send & receive
@@ -1010,8 +1538,8 @@ mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr)
        return result;
        }
 
-// 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"
+// 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,
@@ -1021,7 +1549,7 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
        // to the NetworkInterfaceInfoOSX structure that holds the active sockets. The mDNSCore code
        // doesn't know that and doesn't need to know that -- it just treats InterfaceIDs as opaque identifiers.
        NetworkInterfaceInfoOSX *info = (NetworkInterfaceInfoOSX *)InterfaceID;
-       char *ifa_name = info ? info->ifa_name : "unicast";
+       char *ifa_name = info ? info->ifinfo.ifname : "unicast";
        struct sockaddr_storage to;
        int s = -1, err;
        mStatus result = mStatus_NoError;
@@ -1033,23 +1561,24 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
                sin_to->sin_family         = AF_INET;
                sin_to->sin_port           = dstPort.NotAnInteger;
                sin_to->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
-               s = m->p->permanentsockets.sktv4;
-
-               if (src) { s = src->ss.sktv4; debugf("mDNSPlatformSendUDP using port %d %d %d", mDNSVal16(src->ss.port), m->p->permanentsockets.sktv4, s); }
+               s = (src ? src->ss : m->p->permanentsockets).sktv4;
 
                if (info)       // Specify outgoing interface
                        {
                        if (!mDNSAddrIsDNSMulticast(dst))
                                {
-                               #ifdef IP_FORCE_OUT_IFP
-                                       setsockopt(s, IPPROTO_IP, IP_FORCE_OUT_IFP, ifa_name, strlen(ifa_name) + 1);
+                               #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++;
-                                               LogOperation("IP_FORCE_OUT_IFP Socket option not defined -- cannot specify interface for unicast packets");
+                                               LogInfo("IP_BOUND_IF socket option not defined -- cannot specify interface for unicast packets");
                                                }
                                        }
                                #endif
@@ -1057,7 +1586,8 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
                        else
                                {
                                err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
-                               if (err < 0) LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %ld errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
+                               if (err < 0 && !m->p->NetworkChanged)
+                                       LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
                                }
                        }
                }
@@ -1070,11 +1600,11 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
                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 = m->p->permanentsockets.sktv6;
+               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) LogMsg("setsockopt - IPV6_MULTICAST_IF error %ld errno %d (%s)", err, errno, strerror(errno));
+                       if (err < 0) LogMsg("setsockopt - IPV6_MULTICAST_IF error %d errno %d (%s)", err, errno, strerror(errno));
                        }
                }
        else
@@ -1086,15 +1616,6 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
                return mStatus_BadParamErr;
                }
 
-       // Don't send if it would cause dial-on-demand connection initiation.
-       // As an optimization, don't bother consulting reachability API / routing
-       // table when sending Multicast DNS since we ignore PPP interfaces for mDNS traffic.
-       if (!info && !mDNSAddrIsDNSMulticast(dst) && AddrRequiresPPPConnection((struct sockaddr *)&to))
-               {
-               debugf("mDNSPlatformSendUDP: Surpressing sending to avoid dial-on-demand connection");
-               return mStatus_NoError;
-               }
-
        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);
@@ -1122,15 +1643,22 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
                if (MessageCount < 1000)
                        {
                        MessageCount++;
-                       LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %5s/%ld to %#a:%d skt %d error %d errno %d (%s) %lu",
-                               InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
+                       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
+                               LogMsg("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));
                        }
                result = mStatus_UnknownErr;
                }
 
-#ifdef IP_FORCE_OUT_IFP
+#ifdef IP_BOUND_IF
        if (dst->type == mDNSAddrType_IPv4 && info && !mDNSAddrIsDNSMulticast(dst))
-               setsockopt(s, IPPROTO_IP, IP_FORCE_OUT_IFP, "", 1);
+               {
+               static const mDNSu32 ifindex = 0;
+               setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
+               }
 #endif
 
        return(result);
@@ -1248,7 +1776,7 @@ mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
                        senderAddr.type = mDNSAddrType_IPv4;
                        senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
                        senderPort.NotAnInteger = s->sin_port;
-                       //LogOperation("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
+                       //LogInfo("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
                        }
                else if (from.ss_family == AF_INET6)
                        {
@@ -1256,7 +1784,7 @@ mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
                        senderAddr.type = mDNSAddrType_IPv6;
                        senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
                        senderPort.NotAnInteger = sin6->sin6_port;
-                       //LogOperation("myKQSocketCallBack received IPv6 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
+                       //LogInfo("myKQSocketCallBack received IPv6 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
                        }
                else
                        {
@@ -1264,7 +1792,7 @@ mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
                        return;
                        }
 
-               // NOTE: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
+               // Note: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
                mDNSInterfaceID InterfaceID = mDNSNULL;
                NetworkInterfaceInfo *intf = m->HostInterfaces;
                while (intf && strcmp(intf->ifname, packetifname)) intf = intf->next;
@@ -1277,7 +1805,7 @@ mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
                else if (mDNSAddrIsDNSMulticast(&destAddr)) continue;
 
 //             LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s",
-//                     &senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifa_name);
+//                     &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
@@ -1335,6 +1863,14 @@ mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
 
 // TCP socket support
 
+typedef enum
+       {
+       handshake_required,
+       handshake_in_progress,
+       handshake_completed,
+       handshake_to_be_closed
+       } handshakeStatus;
+       
 struct TCPSocket_struct
        {
        TCPSocketFlags flags;           // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with TCPSocketFlags flags
@@ -1343,13 +1879,24 @@ struct TCPSocket_struct
        KQueueEntry kqEntry;
 #ifndef NO_SECURITYFRAMEWORK
        SSLContextRef tlsContext;
+       pthread_t handshake_thread;
 #endif /* NO_SECURITYFRAMEWORK */
        void *context;
        mDNSBool setup;
-       mDNSBool handshakecomplete;
        mDNSBool connected;
+       handshakeStatus handshake;
+       mDNS *m; // So we can call KQueueLock from the SSLHandshake thread
+       mStatus err;
        };
 
+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)
@@ -1361,7 +1908,7 @@ mDNSlocal OSStatus tlsWriteSock(SSLConnectionRef connection, const void *data, s
        if (errno == EAGAIN                      ) return(errSSLWouldBlock);
        if (errno == ENOENT                      ) return(errSSLClosedGraceful);
        if (errno == EPIPE || errno == ECONNRESET) return(errSSLClosedAbort);
-       LogMsg("ERROR: tlsWriteSock: error %d %s\n", errno, strerror(errno));
+       LogMsg("ERROR: tlsWriteSock: %d error %d (%s)\n", ((TCPSocket *)connection)->fd, errno, strerror(errno));
        return(errSSLClosedAbort);
        }
 
@@ -1374,7 +1921,7 @@ mDNSlocal OSStatus tlsReadSock(SSLConnectionRef connection, void *data, size_t *
        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));
+       LogMsg("ERROR: tlsSockRead: error %d (%s)\n", errno, strerror(errno));
        return(errSSLClosedAbort);
        }
 
@@ -1392,6 +1939,73 @@ mDNSlocal OSStatus tlsSetupSock(TCPSocket *sock, mDNSBool server)
        return(err);
        }
 
+mDNSlocal void *doSSLHandshake(void *ctx)
+       {
+       // Warning: Touching sock without the kqueue lock!
+       // We're protected because sock->handshake == handshake_in_progress
+       TCPSocket *sock = (TCPSocket*)ctx;
+       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);
+       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", err);
+                               SSLDisposeContext(sock->tlsContext);
+                               sock->tlsContext = NULL;
+                               }
+                       
+                       sock->err = err;
+                       sock->handshake = handshake_completed;
+                       
+                       LogInfo("doSSLHandshake: %p calling doTcpSocketCallback", sock);
+                       doTcpSocketCallback(sock);
+                       }
+               }
+       
+       LogInfo("SSLHandshake %p: dropping lock", sock);
+       KQueueUnlock(m, "doSSLHandshake");
+       return NULL;
+       }
+
+mDNSlocal mStatus spawnSSLHandshake(TCPSocket* sock)
+       {
+       LogInfo("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);
+       pthread_attr_t attr;
+       pthread_attr_init(&attr);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+       mStatus err = pthread_create(&sock->handshake_thread, &attr, doSSLHandshake, sock);
+       pthread_attr_destroy(&attr);
+       if (err)
+               {
+               LogMsg("Could not start SSLHandshake thread: (%d) %s", err, strerror(err));
+               sock->handshake = handshake_completed;
+               sock->err = err;
+               KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry);
+               }
+       LogInfo("spawnSSLHandshake %p: done", sock);
+       return err;
+       }
+
 mDNSlocal mDNSBool IsTunnelModeDomain(const domainname *d)
        {
        static const domainname *mmc = (const domainname*) "\x7" "members" "\x3" "mac" "\x3" "com";
@@ -1407,7 +2021,7 @@ mDNSlocal mDNSBool IsTunnelModeDomain(const domainname *d)
 mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context)
        {
        TCPSocket *sock = context;
-       mStatus err = mStatus_NoError;
+       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);
@@ -1418,24 +2032,20 @@ mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context)
                {
 #ifndef NO_SECURITYFRAMEWORK
                if (!sock->setup) { sock->setup = mDNStrue; tlsSetupSock(sock, mDNSfalse); }
-               if (!sock->handshakecomplete)
+               
+               if (sock->handshake == handshake_required) { if (spawnSSLHandshake(sock) == 0) return; }
+               else if (sock->handshake == handshake_in_progress || sock->handshake == handshake_to_be_closed) return;
+               else if (sock->handshake != handshake_completed)
                        {
-                       //LogMsg("tcpKQSocketCallback Starting SSLHandshake");
-                       err = SSLHandshake(sock->tlsContext);
-                       //if (!err) LogMsg("tcpKQSocketCallback SSLHandshake complete");
-                       if (!err) sock->handshakecomplete = mDNStrue;
-                       else if (err == errSSLWouldBlock) return;
-                       else { LogMsg("KQ SSLHandshake failed: %d", err); SSLDisposeContext(sock->tlsContext); sock->tlsContext = NULL; }
+                       if (!sock->err) sock->err = mStatus_UnknownErr;
+                       LogMsg("tcpKQSocketCallback called with unexpected SSLHandshake status: %d", sock->handshake);
                        }
 #else
-               err = mStatus_UnsupportedErr;
+               sock->err = mStatus_UnsupportedErr;
 #endif /* NO_SECURITYFRAMEWORK */
                }
-
-       mDNSBool c = !sock->connected;
-       sock->connected = mDNStrue;
-       sock->callback(sock, sock->context, c, err);
-       // NOTE: the callback may call CloseConnection here, which frees the context structure!
+       
+       doTcpSocketCallback(sock);
        }
 
 mDNSexport int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *const entryRef)
@@ -1456,13 +2066,13 @@ mDNSexport void KQueueUnlock(mDNS *const m, const char const *task)
        mDNSs32 end = mDNSPlatformRawTime();
        (void)task;
        if (end - m->p->BigMutexStartTime >= WatchDogReportingThreshold)
-               LogOperation("WARNING: %s took %dms to complete", task, end - m->p->BigMutexStartTime);
+               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));
+               LogMsg("ERROR: KQueueWake: send failed with error code: %d (%s)", errno, strerror(errno));
        }
 
 mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port)
@@ -1481,8 +2091,10 @@ mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags,
        sock->flags             = flags;
        sock->context           = mDNSNULL;
        sock->setup             = mDNSfalse;
-       sock->handshakecomplete = mDNSfalse;
        sock->connected         = mDNSfalse;
+       sock->handshake         = handshake_required;
+       sock->m                 = m;
+       sock->err               = mStatus_NoError;
        
        if (sock->fd == -1)
                {
@@ -1493,7 +2105,7 @@ mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags,
 
        // Bind it
        struct sockaddr_in addr;
-       memset(&addr, 0, sizeof(addr));
+       mDNSPlatformMemZero(&addr, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        addr.sin_port = port->NotAnInteger;
@@ -1505,7 +2117,7 @@ mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags,
        if (setsockopt(sock->fd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0)
                { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); goto error; }
 
-       memset(&addr, 0, sizeof(addr));
+       mDNSPlatformMemZero(&addr, sizeof(addr));
        socklen_t len = sizeof(addr);
        if (getsockname(sock->fd, (struct sockaddr*) &addr, &len) < 0)
                { LogMsg("getsockname - %s", strerror(errno)); goto error; }
@@ -1528,8 +2140,9 @@ mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst,
        sock->callback          = callback;
        sock->context           = context;
        sock->setup             = mDNSfalse;
-       sock->handshakecomplete = mDNSfalse;
        sock->connected         = mDNSfalse;
+       sock->handshake         = handshake_required;
+       sock->err               = mStatus_NoError;
 
        (void) InterfaceID;     //!!!KRS use this if non-zero!!!
 
@@ -1545,13 +2158,6 @@ mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst,
        saddr.sin_len         = sizeof(saddr);
        saddr.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
 
-       // Don't send if it would cause dial-on-demand connection initiation.
-       if (AddrRequiresPPPConnection((struct sockaddr *)&saddr))
-               {
-               debugf("mDNSPlatformTCPConnect: Surpressing sending to avoid dial-on-demand connection");
-               return mStatus_UnknownErr;
-               }
-
        sock->kqEntry.KQcallback = tcpKQSocketCallback;
        sock->kqEntry.KQcontext  = sock;
        sock->kqEntry.KQtask     = "Outgoing TCP";
@@ -1583,7 +2189,10 @@ mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst,
        if (connect(sock->fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
                {
                if (errno == EINPROGRESS) return mStatus_ConnPending;
-               LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d %s", sock->fd, errno, strerror(errno));
+               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)", sock->fd, errno, strerror(errno));
                close(sock->fd);
                return mStatus_ConnFailed;
                }
@@ -1601,7 +2210,7 @@ mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int fd)
        TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPAccept", sizeof(TCPSocket));
        if (!sock) return(mDNSNULL);
 
-       memset(sock, 0, sizeof(*sock));
+       mDNSPlatformMemZero(sock, sizeof(*sock));
        sock->fd = fd;
        sock->flags = flags;
 
@@ -1630,10 +2239,18 @@ exit:
 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");
+                               sock->handshake = handshake_to_be_closed;
+                               }
+                       if (sock->handshake == handshake_to_be_closed)
+                               return;
+
                        SSLClose(sock->tlsContext);
                        SSLDisposeContext(sock->tlsContext);
                        sock->tlsContext = NULL;
@@ -1658,15 +2275,9 @@ mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long bu
        if (sock->flags & kTCPSocketFlags_UseTLS)
                {
 #ifndef NO_SECURITYFRAMEWORK
-               if (!sock->handshakecomplete)
-                       {
-                       //LogMsg("mDNSPlatformReadTCP Starting SSLHandshake");
-                       mStatus err = SSLHandshake(sock->tlsContext);
-                       //if (!err) LogMsg("mDNSPlatformReadTCP SSLHandshake complete");
-                       if (!err) sock->handshakecomplete = mDNStrue;
-                       else if (err == errSSLWouldBlock) return(0);
-                       else { LogMsg("Read SSLHandshake failed: %d", err); SSLDisposeContext(sock->tlsContext); sock->tlsContext = NULL; }
-                       }
+               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);
@@ -1693,7 +2304,7 @@ mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long bu
                        }
                // 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 if (errno != EAGAIN) { LogMsg("ERROR: mDNSPlatformReadTCP - recv: %d (%s)", errno, strerror(errno)); nread = -1; }
                else // errno is EAGAIN (EWOULDBLOCK) -- no data available
                        {
                        nread = 0;
@@ -1712,6 +2323,10 @@ mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned
                {
 #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;
@@ -1743,7 +2358,6 @@ mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
 // 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)
        {
-       const int ip_tosbits = IPTOS_LOWDELAY | IPTOS_THROUGHPUT;
        int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
        KQueueEntry     *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
        const int on = 1;
@@ -1757,7 +2371,7 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
        if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); }
 
        // ... with a shared UDP port, if it's for multicast receiving
-       if (mDNSSameIPPort(port, MulticastDNSPort)) err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
+       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)
@@ -1782,21 +2396,20 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
                err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
                if (err < 0) { errstr = "setsockopt - IP_MULTICAST_TTL"; goto fail; }
 
-               // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
-               err = setsockopt(skt, IPPROTO_IP, IP_TOS, &ip_tosbits, sizeof(ip_tosbits));
-               if (err < 0) { errstr = "setsockopt - IP_TOS"; 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 = 0; // Want to receive multicasts AND unicasts on this socket
+               listening_sockaddr.sin_addr.s_addr = mDNSSameIPPort(port, NATPMPAnnouncementPort) ? AllSystemsMcast.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, 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_PKTINFO, &on, sizeof(on));
                if (err < 0) { errstr = "setsockopt - IPV6_PKTINFO"; goto fail; }
@@ -1818,14 +2431,6 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
                err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
                if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_HOPS"; goto fail; }
 
-               // Note: IPV6_TCLASS appears not to be implemented on OS X right now (or indeed on ANY version of Unix?)
-               #ifdef IPV6_TCLASS
-               // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
-               int tclass = IPTOS_LOWDELAY | IPTOS_THROUGHPUT; // This may not be right (since tclass is not implemented on OS X, I can't test it)
-               err = setsockopt(skt, IPPROTO_IPV6, IPV6_TCLASS, &tclass, sizeof(tclass));
-               if (err < 0) { errstr = "setsockopt - IPV6_TCLASS"; goto fail; }
-               #endif
-
                // 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; }
@@ -1857,15 +2462,19 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
        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 %ld errno %d (%s)", errstr, skt, mDNSVal16(port), err, errno, strerror(errno));
+               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 with an EADDRINUSE error for our shared mDNS port, display error alert
-       if (!strcmp(errstr, "bind") && mDNSSameIPPort(port, MulticastDNSPort) && errno == EADDRINUSE)
-               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@group.apple.com. (Note number is different.)\r"
-                       "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
+       // 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@group.apple.com. (Note number is different.)\r"
+                               "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
+               }
 
        close(skt);
        return(err);
@@ -1873,31 +2482,40 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
 
 mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
        {
-       int i;
        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); }
-       memset(p, 0, sizeof(UDPSocket));
+       mDNSPlatformMemZero(p, sizeof(UDPSocket));
        p->ss.port  = zeroIPPort;
        p->ss.m     = m;
        p->ss.sktv4 = -1;
        p->ss.sktv6 = -1;
 
-       for (i=0; i<10000; i++) // Try at most 10000 times to get a unique random port
+       do
                {
                // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here
-               if (mDNSIPPortIsZero(requestedport)) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
+               if (randomizePort) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
                err = SetupSocket(&p->ss, port, AF_INET, &p->ss.port);
-               if (!err) break;
-               }
+               if (!err)
+                       {
+                       err = SetupSocket(&p->ss, port, AF_INET6, &p->ss.port);
+                       if (err) { close(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
-               if (mDNSSameIPPort(requestedport, NATPMPPort))
-                       LogOperation("mDNSPlatformUDPSocket: SetupSocket %d failed error %ld errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
-               else LogMsg     ("mDNSPlatformUDPSocket: SetupSocket %d failed error %ld errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
+               // 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);
                }
@@ -1927,20 +2545,328 @@ mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
 
 #if COMPILER_LIKES_PRAGMA_MARK
 #pragma mark -
-#pragma mark - Key Management
+#pragma mark - BPF Raw packet sending/receiving
 #endif
 
-#ifndef NO_SECURITYFRAMEWORK
-mDNSlocal CFArrayRef GetCertChain(SecIdentityRef identity)
+#if APPLE_OSX_mDNSResponder
+
+mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
        {
-       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);
+       if (!InterfaceID) { LogMsg("mDNSPlatformSendRawPacket: No InterfaceID specified"); return; }
+       NetworkInterfaceInfoOSX *info = (NetworkInterfaceInfoOSX *)InterfaceID;
+       if (info->BPF_fd < 0)
+               LogMsg("mDNSPlatformSendRawPacket: %s BPF_fd %d not ready", info->ifinfo.ifname, info->BPF_fd);
        else
                {
-               SecPolicySearchRef searchRef;
+               //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 mDNSPlatformSetLocalARP(const mDNSv4Addr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
+       {
+       if (!InterfaceID) { LogMsg("mDNSPlatformSetLocalARP: No InterfaceID specified"); return; }
+       NetworkInterfaceInfoOSX *info = (NetworkInterfaceInfoOSX *)InterfaceID;
+       // 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.)
+       mDNSBool makearp = mDNSv4AddressIsLinkLocal(tpa);
+       if (!makearp)
+               {
+               NetworkInterfaceInfoOSX *i;
+               for (i = info->m->p->InterfaceList; i; i = i->next)
+                       if (i->Exists && i->ifinfo.InterfaceID == InterfaceID && i->ifinfo.ip.type == mDNSAddrType_IPv4)
+                               if (((i->ifinfo.ip.ip.v4.NotAnInteger ^ tpa->NotAnInteger) & i->ifinfo.mask.ip.v4.NotAnInteger) == 0)
+                                       makearp = mDNStrue;
+               }
+       if (!makearp)
+               LogInfo("Don't need ARP entry for %s %.4a %.6a",            info->ifinfo.ifname, tpa, tha);
+       else
+               {
+               int result = mDNSSetARP(info->scope_id, tpa->b, tha->b);
+               if (result) LogMsg("Set local ARP entry for %s %.4a %.6a failed: %d", info->ifinfo.ifname, tpa, tha, result);
+               else debugf       ("Set local ARP entry for %s %.4a %.6a",            info->ifinfo.ifname, tpa, tha);
+               }
+       }
+
+mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i)
+       {
+       LogSPS("%s closing BPF fd %d", i->ifinfo.ifname, i->BPF_fd);
+
+       // 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);
+       i->BPF_fd = -1;
+       }
+
+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;
+
+       NetworkInterfaceInfoOSX *const info = (NetworkInterfaceInfoOSX *)context;
+       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)
+               {
+               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 *bh = (const struct bpf_hdr *)ptr;
+               debugf("%3d: bpf_callback bh_caplen %4d bh_datalen %4d remaining %4d", info->BPF_fd, bh->bh_caplen, bh->bh_datalen, end - (ptr + BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen)));
+               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");
+       }
+
+#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 == (mDNSInterfaceID)x && rr->AddressProxy.type == mDNSAddrType_IPv4)
+                       {
+                       if (p4) LogSPS("mDNSPlatformUpdateProxyList: 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 == (mDNSInterfaceID)x && rr->AddressProxy.type == mDNSAddrType_IPv6)
+                       {
+                       if (p6) LogSPS("mDNSPlatformUpdateProxyList: 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;
+       for (x = m->p->InterfaceList; x; x = x->next) if (x == (NetworkInterfaceInfoOSX *)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,             78),                              // 7 Return 78-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,           34);   // A = 34 (14-byte Ethernet plus 20-byte TCP)
+       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
+
+       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.
+
+       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
+
+       for (rr = m->ResourceRecords; rr; rr=rr->next)
+               if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
+                       {
+                       mDNSv6Addr 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[12] << 24 | (bpf_u_int32)a.b[13] << 16 | (bpf_u_int32)a.b[14] << 8 | (bpf_u_int32)a.b[15];
+                       pc++;
+                       }
+
+       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 (ioctl(x->BPF_fd, BIOCSETF, &prog) < 0) LogMsg("mDNSPlatformUpdateProxyList: BIOCSETF(%d) failed %d (%s)", prog.bf_len, errno, strerror(errno));
+       else LogSPS("mDNSPlatformUpdateProxyList: BIOCSETF(%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", i->BPF_len);
+                       }
+       
+               static const u_int opt_immediate = 1;
+               if (ioctl(fd, BIOCIMMEDIATE, &opt_immediate) < 0)
+                       LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCIMMEDIATE 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
+                       {
+                       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);
+                       mDNSPlatformUpdateProxyList(m, (mDNSInterfaceID)i);
+                       }
+               }
+
+       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
@@ -2058,12 +2984,13 @@ mDNSlocal void GetUserSpecifiedLocalHostName(domainlabel *const namelabel)
                }
        }
 
-mDNSlocal mDNSBool DDNSSettingEnabled(CFDictionaryRef dict)
+mDNSexport mDNSBool DictionaryIsEnabled(CFDictionaryRef dict)
        {
        mDNSs32 val;
        CFNumberRef state = CFDictionaryGetValue(dict, CFSTR("Enabled"));
        if (!state) return mDNSfalse;
-       if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val)) { LogMsg("ERROR: DDNSSettingEnabled - CFNumberGetValue"); return mDNSfalse; }
+       if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val))
+               { LogMsg("ERROR: DictionaryIsEnabled - CFNumberGetValue"); return mDNSfalse; }
        return val ? mDNStrue : mDNSfalse;
        }
 
@@ -2101,7 +3028,9 @@ mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
        {
        mDNSEthAddr eth = zeroEthAddr;
        SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetBSSID"), NULL, NULL);
-       if (store)
+       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)
@@ -2121,6 +3050,73 @@ mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
        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 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
+
+       int s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0) { LogMsg("NetWakeInterface %s socket failed %s errno %d (%s)", i->ifinfo.ifname, 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;
+               }
+#if ASSUME_SNOWLEOPARD_INCORRECTLY_REPORTS_AIRPORT_INCAPABLE_OF_WAKE_ON_LAN
+       else
+               {
+               // Call succeeded.
+               // However, on SnowLeopard, it currently indicates incorrectly that AirPort is incapable of Wake-on-LAN.
+               // Therefore, for AirPort interfaces, we just track the system-wide Wake-on-LAN setting.
+               if ((i)->BSSID.l[0]) ifr.ifr_wake_flags = i->m->SystemWakeOnLANEnabled ? IF_WAKE_ON_MAGIC_PACKET : 0;
+               }
+#endif
+
+       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);
+       }
+
 // 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
@@ -2136,12 +3132,34 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad
 
        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))
+               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", scope_id, &bssid, &ip, *p);
                        (*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)->ifinfo.InterfaceID)
+                                       {
+                                       mDNS_Lock(m);
+                                       if (NetWake) mDNS_ActivateNetWake_internal  (m, &(*p)->ifinfo);
+                                       else         mDNS_DeactivateNetWake_internal(m, &(*p)->ifinfo);
+                                       mDNS_Unlock(m);
+                                       }
+                               }
+
                        return(*p);
                        }
 
@@ -2149,28 +3167,35 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad
        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->ifa_name        = (char *)mallocL("NetworkInterfaceInfoOSX name", strlen(ifa->ifa_name) + 1);
-       if (!i->ifa_name) { freeL("NetworkInterfaceInfoOSX", i); return(mDNSNULL); }
-       strcpy(i->ifa_name, ifa->ifa_name);             // This is safe because we know we allocated i->ifa_name with sufficient space
-
        i->ifinfo.InterfaceID = mDNSNULL;
        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;
-       i->ifinfo.Advertise   = m->AdvertiseLocalAddresses;
+       // 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->next            = mDNSNULL;
+       i->m               = m;
        i->Exists          = mDNStrue;
-       i->AppearanceTime  = utc;               // Brand new interface; AppearanceTime is now
-       i->LastSeen        = utc;
        i->Flashing        = mDNSfalse;
        i->Occulting       = mDNSfalse;
+       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->ifa_flags       = ifa->ifa_flags;
+       i->BPF_fd          = -1;
+       i->BPF_len         = 0;
+
+       // 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);
@@ -2197,19 +3222,19 @@ mDNSlocal NetworkInterfaceInfoOSX *FindRoutableIPv4(mDNS *const m, mDNSu32 scope
 
 #define kRacoonPort 4500
 
-static mDNSBool AnonymousRacoonConfig = mDNSfalse;
+static DomainAuthInfo* AnonymousRacoonConfig = mDNSNULL;
 
 #ifndef NO_SECURITYFRAMEWORK
 
 static CFMutableDictionaryRef domainStatusDict = NULL;
 
 // MUST be called with lock held
-mDNSlocal void RemoveAutoTunnelDomainStatus(const DomainAuthInfo *const info)
+mDNSlocal void RemoveAutoTunnelDomainStatus(const mDNS *const m, const DomainAuthInfo *const info)
        {
        char buffer[1024];
        CFStringRef domain;
 
-       LogOperation("RemoveAutoTunnelDomainStatus: %##s", info->domain.c);
+       LogInfo("RemoveAutoTunnelDomainStatus: %##s", info->domain.c);
 
        if (!domainStatusDict) { LogMsg("RemoveAutoTunnelDomainStatus: No domainStatusDict"); return; }
        
@@ -2220,13 +3245,28 @@ mDNSlocal void RemoveAutoTunnelDomainStatus(const DomainAuthInfo *const info)
        if (CFDictionaryContainsKey(domainStatusDict, domain))
                {
                CFDictionaryRemoveValue(domainStatusDict, domain);
-               mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, domainStatusDict);
+               if (!m->ShutdownTime) mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
                }
        CFRelease(domain);
        }
 
 #endif // ndef NO_SECURITYFRAMEWORK
 
+mDNSlocal mStatus CheckQuestionForStatus(const DNSQuestion *const q)
+       {
+       if (q->LongLived)
+               {
+               if (q->nta || (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;
+}
+
 // MUST be called with lock held
 mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAuthInfo *const info)
        {
@@ -2326,17 +3366,36 @@ mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAut
                                }
                        }
                }
+       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);
+                       }
+               }
        
        if (!llq && !tun)
                {
                status = mStatus_NotInitializedErr;
                mDNS_snprintf(buffer, sizeof(buffer), "Neither LLQ nor AutoTunnel NAT port mapping is currently active");
-               }       
+               }
        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 an external 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), "NAT-PMP is disabled on the router");
+               }
        else if ((llq && llq->Result) || (tun && tun->Result))
                {
                status = mStatus_NATTraversal;
@@ -2359,23 +3418,20 @@ mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAut
                }
        else
                {
-               DNSQuestion* q;
+               DNSQuestion* q, *worst_q = mDNSNULL;
                for (q = m->Questions; q; q=q->next)
-                       if (q->LongLived && q->AuthInfo == info && q->state == LLQ_Poll)
+                       if (q->AuthInfo == info)
                                {
-                               status = mStatus_PollingMode;
-                               mDNS_snprintf(buffer, sizeof(buffer), "Query polling %##s", q->qname.c);
-                               break;
+                               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)
-                       for (q = m->Questions; q; q=q->next)
-                               if (q->LongLived && q->AuthInfo == info && q->state != LLQ_Established && !q->DuplicateOf)
-                                       {
-                                       status = mStatus_TransientErr;
-                                       mDNS_snprintf(buffer, sizeof(buffer), "Query not yet established %##s", q->qname.c);
-                                       break;
-                                       }
-               if (status == mStatus_NoError) mDNS_snprintf(buffer, sizeof(buffer), "Success");
+               
+               if      (status == mStatus_NoError)      mDNS_snprintf(buffer, sizeof(buffer), "Success");
+               else if (status == mStatus_NoSuchRecord) mDNS_snprintf(buffer, sizeof(buffer), "GetZoneData %s: %##s", worst_q->nta ? "not yet complete" : "failed", worst_q->qname.c);
+               else if (status == mStatus_PollingMode)  mDNS_snprintf(buffer, sizeof(buffer), "Query polling %##s", worst_q->qname.c);
+               else if (status == mStatus_TransientErr) mDNS_snprintf(buffer, sizeof(buffer), "Query not yet established %##s", worst_q->qname.c);
                }
        
        num = CFNumberCreate(NULL, kCFNumberSInt32Type, &status);
@@ -2400,13 +3456,19 @@ mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAut
            !CFEqual(dict, (CFMutableDictionaryRef)CFDictionaryGetValue(domainStatusDict, domain)))
            {
                CFDictionarySetValue(domainStatusDict, domain, dict);
-               mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, domainStatusDict);
+               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);
 
-       LogOperation("UpdateAutoTunnelDomainStatus: %s", buffer);
+       debugf("UpdateAutoTunnelDomainStatus: %s", buffer);
 #endif // def NO_SECURITYFRAMEWORK
        }
 
@@ -2432,6 +3494,15 @@ mDNSlocal mDNSBool TunnelServers(mDNS *const m)
                DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, p->RR_SRV.resrec.name);
                if (AuthInfo && AuthInfo->AutoTunnel && !AuthInfo->deltime) return(mDNStrue);
                }
+
+       AuthRecord *r;
+       for (r = m->ResourceRecords; r; r = r->next)
+               if (r->resrec.rrtype == kDNSType_SRV)
+                       {
+                       DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, r->resrec.name);
+                       if (AuthInfo && AuthInfo->AutoTunnel && !AuthInfo->deltime) return(mDNStrue);
+                       }
+
        return(mDNSfalse);
        }
 
@@ -2450,7 +3521,7 @@ mDNSlocal void RegisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
        if (info->AutoTunnelNAT.clientContext && !info->AutoTunnelNAT.Result && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) && AutoTunnelUnregistered(info))
                {
                mStatus err;
-               LogOperation("RegisterAutoTunnelRecords %##s (%#s)", info->domain.c, m->hostlabel.c);
+               LogInfo("RegisterAutoTunnelRecords %##s (%#s)", info->domain.c, m->hostlabel.c);
 
                // 1. Set up our address record for the internal tunnel address
                // (User-visible user-friendly host name, used as target in AutoTunnel SRV records)
@@ -2460,7 +3531,7 @@ mDNSlocal void RegisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
                info->AutoTunnelHostRecord.resrec.rdata->u.ipv6 = m->AutoTunnelHostAddr;
                info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeKnownUnique;
                err = mDNS_Register(m, &info->AutoTunnelHostRecord);
-               if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelHostRecord %##s", err, info->AutoTunnelHostRecord.namestorage.c);     
+               if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelHostRecord %##s", err, info->AutoTunnelHostRecord.namestorage.c);
 
                // 2. Set up device info record
                ConstructServiceName(&info->AutoTunnelDeviceInfo.namestorage, &m->nicelabel, &DeviceInfoName, &info->domain);
@@ -2496,7 +3567,7 @@ mDNSlocal void RegisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
                err = mDNS_Register(m, &info->AutoTunnelService);
                if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
 
-               LogOperation("AutoTunnel server listening for connections on %##s[%.4a]:%d:%##s[%.16a]",
+               LogInfo("AutoTunnel server listening for connections on %##s[%.4a]:%d:%##s[%.16a]",
                        info->AutoTunnelTarget.namestorage.c,     &m->AdvertisedV4.ip.v4, mDNSVal16(info->AutoTunnelNAT.IntPort),
                        info->AutoTunnelHostRecord.namestorage.c, &m->AutoTunnelHostAddr);
                }
@@ -2504,7 +3575,7 @@ mDNSlocal void RegisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
 
 mDNSlocal void DeregisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
        {
-       LogOperation("DeregisterAutoTunnelRecords %##s", info->domain.c);
+       LogInfo("DeregisterAutoTunnelRecords %##s", info->domain.c);
        if (info->AutoTunnelService.resrec.RecordType > kDNSRecordTypeDeregistering)
                {
                mStatus err = mDNS_Deregister(m, &info->AutoTunnelService);
@@ -2545,7 +3616,7 @@ mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mSt
        DomainAuthInfo *info = (DomainAuthInfo *)rr->RecordContext;
        if (result == mStatus_MemFree)
                {
-               LogOperation("AutoTunnelRecordCallback MemFree %s", ARDisplayString(m, rr));
+               LogInfo("AutoTunnelRecordCallback MemFree %s", ARDisplayString(m, rr));
                // Reset the host record namestorage to force high-level PTR/SRV/TXT to deregister
                if (rr == &info->AutoTunnelHostRecord)
                        {
@@ -2556,28 +3627,35 @@ mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mSt
                }
        }
 
+// Determine whether we need racoon to accept incoming connections
+mDNSlocal void UpdateConfigureServer(mDNS *m)
+       {
+       DomainAuthInfo *info;
+       
+       for (info = m->AuthInfoList; info; info = info->next)
+               if (info->AutoTunnel && !info->deltime && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort))
+                       break;
+       
+       if (info != AnonymousRacoonConfig)
+               {
+               AnonymousRacoonConfig = info;
+               // Create or revert configuration file, and start (or SIGHUP) Racoon
+               (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, AnonymousRacoonConfig ? &AnonymousRacoonConfig->domain : mDNSNULL);
+               }
+       }
+               
 mDNSlocal void AutoTunnelNATCallback(mDNS *m, NATTraversalInfo *n)
        {
        DomainAuthInfo *info = (DomainAuthInfo *)n->clientContext;
-       LogOperation("AutoTunnelNATCallback Result %d %.4a Internal %d External %d %#s.%##s",
+       LogInfo("AutoTunnelNATCallback Result %d %.4a Internal %d External %d %#s.%##s",
                n->Result, &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), m->hostlabel.c, info->domain.c);
 
        m->NextSRVUpdate = NonZeroTime(m->timenow);
        DeregisterAutoTunnelRecords(m,info);
        RegisterAutoTunnelRecords(m,info);
+       
+       UpdateConfigureServer(m);
 
-       // Determine whether we need racoon to accept incoming connections
-       for (info = m->AuthInfoList; info; info = info->next)
-               if (info->AutoTunnel && !info->deltime && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort))
-                       break;
-       mDNSBool needRacoonConfig = info != mDNSNULL;
-       if (needRacoonConfig != AnonymousRacoonConfig)
-               {
-               AnonymousRacoonConfig = needRacoonConfig;
-               // Create or revert configuration file, and start (or SIGHUP) Racoon
-               (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, info ? info->b64keydata : "");
-               }
-               
        UpdateAutoTunnelDomainStatus(m, (DomainAuthInfo *)n->clientContext);
        }
 
@@ -2585,7 +3663,7 @@ mDNSlocal void AbortDeregistration(mDNS *const m, AuthRecord *rr)
        {
        if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
                {
-               LogOperation("Aborting deregistration of %s", ARDisplayString(m, rr));
+               LogInfo("Aborting deregistration of %s", ARDisplayString(m, rr));
                CompleteDeregistration(m, rr);
                }
        else if (rr->resrec.RecordType != kDNSRecordTypeUnregistered)
@@ -2597,13 +3675,13 @@ mDNSlocal void AbortDeregistration(mDNS *const m, AuthRecord *rr)
 // Must be called with the lock held
 mDNSexport void SetupLocalAutoTunnelInterface_internal(mDNS *const m)
        {
-       LogOperation("SetupLocalAutoTunnelInterface");
+       LogInfo("SetupLocalAutoTunnelInterface");
 
        // 1. Configure the local IPv6 address
        if (!m->AutoTunnelHostAddrActive)
                {
                m->AutoTunnelHostAddrActive = mDNStrue;
-               LogOperation("Setting up AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
+               LogInfo("Setting up AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
                (void)mDNSAutoTunnelInterfaceUpDown(kmDNSUp, m->AutoTunnelHostAddr.b);
                }
 
@@ -2641,7 +3719,7 @@ mDNSexport void SetupLocalAutoTunnelInterface_internal(mDNS *const m)
 
 mDNSlocal mStatus AutoTunnelSetKeys(ClientTunnel *tun, mDNSBool AddNew)
        {
-       return(mDNSAutoTunnelSetKeys(AddNew ? kmDNSAutoTunnelSetKeysReplace : kmDNSAutoTunnelSetKeysDelete, tun->loc_inner.b, tun->loc_outer.b, kRacoonPort, tun->rmt_inner.b, tun->rmt_outer.b, mDNSVal16(tun->rmt_outer_port), tun->b64keydata));
+       return(mDNSAutoTunnelSetKeys(AddNew ? kmDNSAutoTunnelSetKeysReplace : kmDNSAutoTunnelSetKeysDelete, tun->loc_inner.b, tun->loc_outer.b, kRacoonPort, tun->rmt_inner.b, tun->rmt_outer.b, mDNSVal16(tun->rmt_outer_port), 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
@@ -2654,14 +3732,14 @@ mDNSlocal void ReissueBlockedQuestionWithType(mDNS *const m, domainname *d, mDNS
                {
                if (q->NoAnswer == NoAnswer_Suspended && q->qtype == qtype && q->AuthInfo && q->AuthInfo->AutoTunnel && SameDomainName(&q->qname, d))
                        {
-                       LogOperation("Restart %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+                       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 subbordinate questions like the GetZoneData query to be cancelled too.
+                       // 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.
@@ -2691,21 +3769,24 @@ mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun
        while (*p != tun && *p) p = &(*p)->next;
        if (*p) *p = tun->next;
        ReissueBlockedQuestions(m, &tun->dstname, success);
-       LogOperation("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
+       LogInfo("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
        freeL("ClientTunnel", tun);
        }
 
 mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
        {
        ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
-       LogOperation("AutoTunnelCallback tun %p AddRecord %d rdlength %d qtype %d", tun, AddRecord, answer->rdlength, question->qtype);
+       LogInfo("AutoTunnelCallback tun %p AddRecord %d rdlength %d qtype %d", tun, AddRecord, answer->rdlength, question->qtype);
 
        if (!AddRecord) return;
        mDNS_StopQuery(m, question);
 
        if (!answer->rdlength)
                {
-               LogOperation("AutoTunnelCallback NXDOMAIN %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
+               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;
                }
@@ -2714,13 +3795,13 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
                {
                if (mDNSSameIPv6Address(answer->rdata->u.ipv6, m->AutoTunnelHostAddr))
                        {
-                       LogOperation("AutoTunnelCallback: suppressing tunnel to self %.16a", &answer->rdata->u.ipv6);
+                       LogInfo("AutoTunnelCallback: suppressing tunnel to self %.16a", &answer->rdata->u.ipv6);
                        UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
                        return;
                        }
 
                tun->rmt_inner = answer->rdata->u.ipv6;
-               LogOperation("AutoTunnelCallback: dst host %.16a", &tun->rmt_inner);
+               LogInfo("AutoTunnelCallback: dst host %.16a", &tun->rmt_inner);
                AssignDomainName(&question->qname, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
                AppendDomainName(&question->qname, &tun->dstname);
                question->qtype = kDNSType_SRV;
@@ -2728,7 +3809,7 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
                }
        else if (question->qtype == kDNSType_SRV)
                {
-               LogOperation("AutoTunnelCallback: SRV target name %##s", answer->rdata->u.srv.target.c);
+               LogInfo("AutoTunnelCallback: SRV target name %##s", answer->rdata->u.srv.target.c);
                AssignDomainName(&tun->q.qname, &answer->rdata->u.srv.target);
                tun->rmt_outer_port = answer->rdata->u.srv.port;
                question->qtype = kDNSType_A;
@@ -2737,7 +3818,7 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
        else if (question->qtype == kDNSType_A)
                {
                ClientTunnel *old = mDNSNULL;
-               LogOperation("AutoTunnelCallback: SRV target addr %.4a", &answer->rdata->u.ipv4);
+               LogInfo("AutoTunnelCallback: SRV target addr %.4a", &answer->rdata->u.ipv4);
                question->ThisQInterval = -1;           // So we know this tunnel setup has completed
                tun->rmt_outer = answer->rdata->u.ipv4;
                tun->loc_inner = m->AutoTunnelHostAddr;
@@ -2755,7 +3836,7 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
                        if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
                        else
                                {
-                               LogOperation("Found existing AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
+                               LogInfo("Found existing AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
                                old = *p;
                                *p = old->next;
                                if (old->q.ThisQInterval >= 0) mDNS_StopQuery(m, &old->q);
@@ -2765,21 +3846,24 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
                                                 !mDNSSameIPv4Address(old->rmt_outer, tun->rmt_outer) ||
                                                 !mDNSSameIPPort(old->rmt_outer_port, tun->rmt_outer_port))
                                        {
-                                       LogOperation("Deleting existing AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
+                                       LogInfo("Deleting existing AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
                                        AutoTunnelSetKeys(old, mDNSfalse);
                                        }
                                else needSetKeys = mDNSfalse;
 
-                               LogOperation("AutoTunnelCallback: Disposing ClientTunnel %p", tun);
+                               LogInfo("AutoTunnelCallback: Disposing ClientTunnel %p", tun);
                                freeL("ClientTunnel", old);
                                }
                        }
 
-               if (needSetKeys) LogOperation("New AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
+               if (needSetKeys) LogInfo("New AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
 
                if (m->AutoTunnelHostAddr.b[0]) { mDNS_Lock(m); SetupLocalAutoTunnelInterface_internal(m); mDNS_Unlock(m); };
 
                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);
                }
@@ -2799,7 +3883,6 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
        p->rmt_inner      = zerov6Addr;
        p->rmt_outer      = zerov4Addr;
        p->rmt_outer_port = zeroIPPort;
-       mDNS_snprintf(p->b64keydata, sizeof(p->b64keydata), "%s", q->AuthInfo->b64keydata);
        p->next = m->TunnelClients;
        m->TunnelClients = p;           // We intentionally build list in reverse order
 
@@ -2815,7 +3898,7 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
        p->q.QuestionCallback = AutoTunnelCallback;
        p->q.QuestionContext  = p;
 
-       LogOperation("AddNewClientTunnel start tun %p %##s (%s)%s", p, &q->qname.c, DNSTypeName(q->qtype), q->LongLived ? " LongLived" : "");
+       LogInfo("AddNewClientTunnel start tun %p %##s (%s)%s", p, &q->qname.c, DNSTypeName(q->qtype), q->LongLived ? " LongLived" : "");
        mDNS_StartQuery_internal(m, &p->q);
        }
 
@@ -2826,32 +3909,6 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
 #pragma mark - Power State & Configuration Change Management
 #endif
 
-mDNSlocal void GenerateDefaultName(const mDNSEthAddr PrimaryMAC, char *buffer, mDNSu32 length)
-{
-       char    hwName[32];
-       size_t  hwNameLen = sizeof(hwName);
-       
-       hwName[0] = 0;
-       if (sysctlbyname("hw.model", &hwName, &hwNameLen, NULL, 0) == 0)
-               {
-               // hw.model contains a number like iMac6,1. We want the "iMac" part.
-               hwName[sizeof(hwName) - 1] = 0;
-               char    *ptr;
-               for (ptr = hwName; *ptr != 0; ptr++)
-                       {
-                       if (*ptr >= '0' && *ptr <= '9') *ptr = 0;
-                       if (*ptr == ',') break;
-                       }
-               // Prototype model names do not contain commas, do not use prototype names
-               if (*ptr != ',') hwName[0] = 0;
-               }
-       
-       if (hwName[0] == 0) strlcpy(hwName, "Device", sizeof(hwName));
-       
-       mDNS_snprintf(buffer, length, "%s-%02X%02X%02X%02X%02X%02X", hwName,
-               PrimaryMAC.b[0], PrimaryMAC.b[1], PrimaryMAC.b[2], PrimaryMAC.b[3], PrimaryMAC.b[4], PrimaryMAC.b[5]);
-}
-
 mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
        {
        mDNSBool foundav4           = mDNSfalse;
@@ -2859,13 +3916,12 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
        struct ifaddrs *ifa         = myGetIfAddrs(1);
        struct ifaddrs *v4Loopback  = NULL;
        struct ifaddrs *v6Loopback  = NULL;
-       mDNSEthAddr PrimaryMAC      = zeroEthAddr;
        char defaultname[64];
 #ifndef NO_IPV6
        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));
 #endif
-       if (m->SleepState) ifa = NULL;
+       if (m->SleepState == SleepState_Sleeping) ifa = NULL;
 
        while (ifa)
                {
@@ -2896,8 +3952,8 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
                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(PrimaryMAC) && mDNSSameEthAddress(&PrimaryMAC, &zeroEthAddr))
-                               mDNSPlatformMemCopy(PrimaryMAC.b, sdl->sdl_data + sdl->sdl_nlen, 6);
+                       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)
@@ -2950,7 +4006,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
                                                else
                                                        {
                                                        NetworkInterfaceInfoOSX *i = AddInterfaceToList(m, ifa, utc);
-                                                       if (i && MulticastInterface(i))
+                                                       if (i && MulticastInterface(i) && i->ifinfo.Advertise)
                                                                {
                                                                if (ifa->ifa_addr->sa_family == AF_INET) foundav4 = mDNStrue;
                                                                else                                     foundav6 = mDNStrue;
@@ -2962,7 +4018,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
                ifa = ifa->ifa_next;
                }
 
-       // For efficiency, we don't register a loopback interface when other interfaces of that family are available
+       // 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);
 
@@ -2987,7 +4043,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
 #endif
 
        // If we haven't set up AutoTunnelHostAddr yet, do it now
-       if (!mDNSSameEthAddress(&PrimaryMAC, &zeroEthAddr) && m->AutoTunnelHostAddr.b[0] == 0)
+       if (!mDNSSameEthAddress(&m->PrimaryMAC, &zeroEthAddr) && m->AutoTunnelHostAddr.b[0] == 0)
                {
                m->AutoTunnelHostAddr.b[0x0] = 0xFD;            // Required prefix for "locally assigned" ULA (See RFC 4193)
                m->AutoTunnelHostAddr.b[0x1] = mDNSRandom(255);
@@ -2997,21 +4053,22 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
                m->AutoTunnelHostAddr.b[0x5] = mDNSRandom(255);
                m->AutoTunnelHostAddr.b[0x6] = mDNSRandom(255);
                m->AutoTunnelHostAddr.b[0x7] = mDNSRandom(255);
-               m->AutoTunnelHostAddr.b[0x8] = PrimaryMAC.b[0] ^ 0x02;  // See RFC 3513, Appendix A for explanation
-               m->AutoTunnelHostAddr.b[0x9] = PrimaryMAC.b[1];
-               m->AutoTunnelHostAddr.b[0xA] = PrimaryMAC.b[2];
+               m->AutoTunnelHostAddr.b[0x8] = m->PrimaryMAC.b[0] ^ 0x02;       // See RFC 3513, Appendix A for explanation
+               m->AutoTunnelHostAddr.b[0x9] = m->PrimaryMAC.b[1];
+               m->AutoTunnelHostAddr.b[0xA] = m->PrimaryMAC.b[2];
                m->AutoTunnelHostAddr.b[0xB] = 0xFF;
                m->AutoTunnelHostAddr.b[0xC] = 0xFE;
-               m->AutoTunnelHostAddr.b[0xD] = PrimaryMAC.b[3];
-               m->AutoTunnelHostAddr.b[0xE] = PrimaryMAC.b[4];
-               m->AutoTunnelHostAddr.b[0xF] = PrimaryMAC.b[5];
+               m->AutoTunnelHostAddr.b[0xD] = m->PrimaryMAC.b[3];
+               m->AutoTunnelHostAddr.b[0xE] = m->PrimaryMAC.b[4];
+               m->AutoTunnelHostAddr.b[0xF] = m->PrimaryMAC.b[5];
                m->AutoTunnelLabel.c[0] = mDNS_snprintf((char*)m->AutoTunnelLabel.c+1, 254, "AutoTunnel-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
                        m->AutoTunnelHostAddr.b[0x8], m->AutoTunnelHostAddr.b[0x9], m->AutoTunnelHostAddr.b[0xA], m->AutoTunnelHostAddr.b[0xB],
                        m->AutoTunnelHostAddr.b[0xC], m->AutoTunnelHostAddr.b[0xD], m->AutoTunnelHostAddr.b[0xE], m->AutoTunnelHostAddr.b[0xF]);
-               LogOperation("m->AutoTunnelLabel %#s", m->AutoTunnelLabel.c);
+               LogInfo("m->AutoTunnelLabel %#s", m->AutoTunnelLabel.c);
                }
        
-       GenerateDefaultName(PrimaryMAC, defaultname, sizeof(defaultname));
+       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;
@@ -3019,7 +4076,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
        GetUserSpecifiedFriendlyComputerName(&nicelabel);
        if (nicelabel.c[0] == 0)
                {
-               LogMsg("Couldn't read user-specified Computer Name; using default “%s” instead", defaultname);
+               debugf("Couldn’t read user-specified Computer Name; using default “%s” instead", defaultname);
                MakeDomainLabelFromLiteralString(&nicelabel, defaultname);
                }
 
@@ -3029,7 +4086,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
        GetUserSpecifiedLocalHostName(&hostlabel);
        if (hostlabel.c[0] == 0)
                {
-               LogMsg("Couldn't read user-specified local hostname; using default “%s.local” instead", defaultname);
+               debugf("Couldn’t read user-specified Local Hostname; using default “%s.local” instead", defaultname);
                MakeDomainLabelFromLiteralString(&hostlabel, defaultname);
                }
 
@@ -3042,7 +4099,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
        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);
+                       LogMsg("User updated Computer Name from “%#s” to “%#s”", m->p->usernicelabel.c, nicelabel.c);
                m->p->usernicelabel = m->nicelabel = nicelabel;
                namechange = mDNStrue;
                }
@@ -3052,7 +4109,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
        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);
+                       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;
@@ -3066,12 +4123,11 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
                        if (info->AutoTunnelNAT.clientContext && !mDNSIPv4AddressIsOnes(info->AutoTunnelNAT.ExternalAddress))
                                AutoTunnelNATCallback(m, &info->AutoTunnelNAT);
                }
-#endif
+#endif // APPLE_OSX_mDNSResponder
 
        return(mStatus_NoError);
        }
 
-#if LogAllOperations || MDNS_DEBUGMSGS
 // 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)
@@ -3087,7 +4143,6 @@ mDNSlocal int CountMaskBits(mDNSAddr *mask)
        while (i < bytes) if (mask->ip.v6.b[i++]) return(-1);
        return(bits);
        }
-#endif
 
 // returns count of non-link local V4 addresses registered
 mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
@@ -3098,8 +4153,8 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
                if (i->Exists)
                        {
                        NetworkInterfaceInfo *const n = &i->ifinfo;
-                       NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifa_name, AAAA_OVER_V4 ? AF_UNSPEC : i->sa_family);
-                       if (!primary) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i->ifa_name);
+                       NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifinfo.ifname, AAAA_OVER_V4 ? AF_UNSPEC : i->sa_family);
+                       if (!primary) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i->ifinfo.ifname);
 
                        if (n->InterfaceID && n->InterfaceID != (mDNSInterfaceID)primary)       // Sanity check
                                {
@@ -3109,7 +4164,7 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
 
                        if (!n->InterfaceID)
                                {
-                               // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
+                               // Note: If n->InterfaceID 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 n->InterfaceID is NOT set, then we haven't registered it and we should not try to deregister it
                                n->InterfaceID = (mDNSInterfaceID)primary;
@@ -3120,21 +4175,21 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
                                i->Occulting = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->LastSeen > 0 && utc - i->LastSeen < 60);
 
                                mDNS_RegisterInterface(m, n, i->Flashing && i->Occulting);
-                               if (!mDNSAddressIsLinkLocal(&i->ifinfo.ip)) count++;
-                               LogOperation("SetupActiveInterfaces:   Registered    %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
-                                       i->ifa_name, i->scope_id, &i->BSSID, primary, &n->ip, CountMaskBits(&n->mask),
+                               if (!mDNSAddressIsLinkLocal(&n->ip)) count++;
+                               LogInfo("SetupActiveInterfaces:   Registered    %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
+                                       i->ifinfo.ifname, i->scope_id, &i->BSSID, 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->ifa_name, i->scope_id, &i->BSSID, primary, &n->ip);
+                                       debugf("SetupActiveInterfaces:   No Tx/Rx on   %5s(%lu) %.6a InterfaceID %p %#a", i->ifinfo.ifname, i->scope_id, &i->BSSID, primary, &n->ip);
                                else
                                        {
                                        if (i->sa_family == AF_INET)
                                                {
                                                struct ip_mreq imr;
-                                               primary->ifa_v4addr.s_addr = i->ifinfo.ip.ip.v4.NotAnInteger;
+                                               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;
        
@@ -3148,19 +4203,19 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
                                                // because by the time we get the configuration change notification, the interface is already gone,
                                                // so attempts to unsubscribe fail with EADDRNOTAVAIL (errno 49 "Can't assign requested address").
                                                // <rdar://problem/5585972> IP_ADD_MEMBERSHIP fails for previously-connected removable interfaces
-                                               if (SearchForInterfaceByName(m, i->ifa_name, AF_INET) == i)
+                                               if (SearchForInterfaceByName(m, i->ifinfo.ifname, AF_INET) == i)
                                                        {
-                                                       LogOperation("SetupActiveInterfaces: %5s(%lu) Doing precautionary IP_DROP_MEMBERSHIP for %.4a on %.4a", i->ifa_name, i->scope_id, &imr.imr_multiaddr, &imr.imr_interface);
+                                                       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 || LogAllOperations))
-                                                               LogMsg("setsockopt - IP_DROP_MEMBERSHIP error %ld errno %d (%s)", err, errno, strerror(errno));
+                                                       if (err < 0 && (errno != EADDRNOTAVAIL))
+                                                               LogMsg("setsockopt - IP_DROP_MEMBERSHIP error %d errno %d (%s)", err, errno, strerror(errno));
                                                        }
        
-                                               LogOperation("SetupActiveInterfaces: %5s(%lu) joining IPv4 mcast group %.4a on %.4a", i->ifa_name, i->scope_id, &imr.imr_multiaddr, &imr.imr_interface);
+                                               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 || LogAllOperations))
-                                                       LogMsg("setsockopt - IP_ADD_MEMBERSHIP error %ld errno %d (%s) group %.4a on %.4a", err, errno, strerror(errno), &imr.imr_multiaddr, &imr.imr_interface);
+                                               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);
                                                }
 #ifndef NO_IPV6
                                        if (i->sa_family == AF_INET6)
@@ -3169,24 +4224,25 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
                                                i6mr.ipv6mr_interface = primary->scope_id;
                                                i6mr.ipv6mr_multiaddr = *(struct in6_addr*)&AllDNSLinkGroup_v6.ip.v6;
        
-                                               if (SearchForInterfaceByName(m, i->ifa_name, AF_INET6) == i)
+                                               if (SearchForInterfaceByName(m, i->ifinfo.ifname, AF_INET6) == i)
                                                        {
-                                                       LogOperation("SetupActiveInterfaces: %5s(%lu) Doing precautionary IPV6_LEAVE_GROUP for %.16a on %u", i->ifa_name, i->scope_id, &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+                                                       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 || LogAllOperations))
-                                                               LogMsg("setsockopt - IPV6_LEAVE_GROUP error %ld errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+                                                       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);
                                                        }
        
-                                               LogOperation("SetupActiveInterfaces: %5s(%lu) joining IPv6 mcast group %.16a on %u", i->ifa_name, i->scope_id, &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 || LogAllOperations))
-                                                       LogMsg("setsockopt - IPV6_JOIN_GROUP error %ld errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+                                               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);
                                                }
 #endif
                                        }
                                }
                        }
+
        return count;
        }
 
@@ -3213,13 +4269,13 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
        for (i = m->p->InterfaceList; i; i = i->next)
                {
                // If this interface is no longer active, or its InterfaceID is changing, deregister it
-               NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifa_name, AAAA_OVER_V4 ? AF_UNSPEC : i->sa_family);
+               NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifinfo.ifname, AAAA_OVER_V4 ? AF_UNSPEC : i->sa_family);
                if (i->ifinfo.InterfaceID)
                        if (i->Exists == 0 || i->Exists == 2 || i->ifinfo.InterfaceID != (mDNSInterfaceID)primary)
                                {
                                i->Flashing = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->AppearanceTime < 60);
-                               LogOperation("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
-                                       i->ifa_name, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID,
+                               LogInfo("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
+                                       i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID,
                                        &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask),
                                        i->Flashing               ? " (Flashing)"  : "",
                                        i->Occulting              ? " (Occulting)" : "",
@@ -3227,7 +4283,7 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
                                mDNS_DeregisterInterface(m, &i->ifinfo, i->Flashing && i->Occulting);
                                if (!mDNSAddressIsLinkLocal(&i->ifinfo.ip)) count++;
                                i->ifinfo.InterfaceID = mDNSNULL;
-                               // NOTE: If i->ifinfo.InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
+                               // Note: If i->ifinfo.InterfaceID 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->ifinfo.InterfaceID is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
 
@@ -3247,14 +4303,16 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
                        {
                        if (i->LastSeen == utc) i->LastSeen = utc - 1;
                        mDNSBool delete = (NumCacheRecordsForInterfaceID(m, (mDNSInterfaceID)i) == 0) && (utc - i->LastSeen >= 60);
-                       LogOperation("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
-                               i->ifa_name, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID,
+                       LogInfo("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
+                               i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID,
                                &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;
-                               if (i->ifa_name) freeL("NetworkInterfaceInfoOSX name", i->ifa_name);
                                freeL("NetworkInterfaceInfoOSX", i);
                                continue;       // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
                                }
@@ -3278,6 +4336,14 @@ mDNSlocal void AppendDNameListElem(DNameListElem ***List, mDNSu32 uid, domainnam
                }
        }
 
+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;
+       }
+
 mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains)
        {
        int i;
@@ -3289,18 +4355,28 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
        if (RegDomains   ) *RegDomains     = NULL;
        if (BrowseDomains) *BrowseDomains  = NULL;
 
-       LogOperation("mDNSPlatformSetDNSConfig%s%s%s%s%s",
-               setservers    ? " setservers"    : "",
-               setsearch     ? " setsearch"     : "",
-               fqdn          ? " fqdn"          : "",
-               RegDomains    ? " RegDomains"    : "",
-               BrowseDomains ? " BrowseDomains" : "");
+       LogInfo("mDNSPlatformSetDNSConfig:%s%s%s%s%s",
+               setservers    ? " setservers"    : "",
+               setsearch     ? " setsearch"     : "",
+               fqdn          ? " fqdn"          : "",
+               RegDomains    ? " RegDomains"    : "",
+               BrowseDomains ? " BrowseDomains" : "");
 
        // Add the inferred address-based configuration discovery domains
        // (should really be in core code I think, not platform-specific)
        if (setsearch)
                {
-               struct ifaddrs *ifa = myGetIfAddrs(1);
+               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;
@@ -3336,101 +4412,119 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                        // 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 (mDNSMacOSXSystemBuildNumber(NULL) > 7 && (mDNSu32)mDNSPlatformRawTime() > (mDNSu32)(mDNSPlatformOneSecond * 180))
-                               LogMsg("GetDNSConfig: Error: dns_configuration_copy returned NULL");
+                       if (OSXVers > OSXVers_10_3_Panther && (mDNSu32)mDNSPlatformRawTime() > (mDNSu32)(mDNSPlatformOneSecond * 180))
+                               LogMsg("mDNSPlatformSetDNSConfig: Error: dns_configuration_copy returned NULL");
                        }
                else
                        {
-                       LogOperation("mDNSPlatformSetDNSConfig: config->n_resolver = %d", config->n_resolver);
+                       LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d", config->n_resolver);
+                       if (setsearch && config->n_resolver)
+                               {
+                               // Due to the vagaries of Apple's SystemConfiguration and dnsinfo.h APIs, if there are no search domains
+                               // listed, then you're supposed to interpret the "domain" field as also being the search domain, but if
+                               // there *are* search domains listed, then you're supposed to ignore the "domain" field completely and
+                               // instead use the search domain list as the sole authority for what domains to search and in what order
+                               // (and the domain from the "domain" field will also appear somewhere in that list).
+                               // Also, all search domains get added to the search list for resolver[0], so the domains and/or
+                               // search lists for other resolvers in the list need to be ignored.
+                               if (config->resolver[0]->n_search == 0) mDNS_AddSearchDomain_CString(config->resolver[0]->domain);
+                               else for (i = 0; i < config->resolver[0]->n_search; i++) mDNS_AddSearchDomain_CString(config->resolver[0]->search[i]);
+                               }
+
+#if APPLE_OSX_mDNSResponder
+                               // 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
+
                        if (setservers)
                                {
+                               // For the "default" resolver ("resolver #1") the "domain" value is bogus and we need to ignore it.
+                               // e.g. the default resolver's "domain" value might say "apple.com", which indicates that this resolver
+                               // is only for names that fall under "apple.com", but that's not correct. Actually the default resolver is
+                               // for all names not covered by a more specific resolver (i.e. its domain should be ".", the root domain).
+                               if (config->n_resolver && config->resolver[0]->domain)
+                                       config->resolver[0]->domain[0] = 0; // don't stop pointing at the memory, just change the first byte
+                               
+                               qsort(config->resolver, config->n_resolver, sizeof(dns_resolver_t*), compare_dns_configs);
+                               
                                for (i = 0; i < config->n_resolver; i++)
                                        {
-                                       int j, n;
+                                       int n;
                                        dns_resolver_t *r = config->resolver[i];
-                                       // Ignore dnsinfo entries for mDNS domains (indicated by the fact that the resolver port is 5353, the mDNS port)
+                                       mDNSInterfaceID interface = mDNSInterface_Any;
+                                       int disabled = 0;
+                                       
+                                       // On Tiger, dnsinfo entries for mDNS domains have port 5353, the mDNS port.  Ignore them.
                                        // Note: Unlike the BSD Sockets APIs (where TCP and UDP port numbers are universally in network byte order)
                                        // in Apple's "dnsinfo.h" API the port number is declared to be a "uint16_t in host byte order"
-                                       if (r->port == 5353) continue;
-                                       if (r->search_order == DEFAULT_SEARCH_ORDER || !r->domain || !*r->domain) d.c[0] = 0; // we ignore domain for "default" resolver
-                                       else if (!MakeDomainNameFromDNSNameString(&d, r->domain)) { LogMsg("RegisterSplitDNS: bad domain %s", r->domain); continue; }
-
-                                       for (j = 0; j < config->n_resolver; j++)  // check if this is the lowest-weighted server for the domain
+                                       // We also don't need to do any more work if there are no nameserver addresses
+                                       if (r->port == 5353 || r->n_nameserver == 0) continue;
+                                       
+                                       if (!r->domain || !*r->domain) d.c[0] = 0;
+                                       else if (!MakeDomainNameFromDNSNameString(&d, r->domain)) { LogMsg("mDNSPlatformSetDNSConfig: bad domain %s", r->domain); continue; }
+
+                                       // DNS server option parsing
+                                       if (r->options != NULL)
                                                {
-                                               dns_resolver_t *p = config->resolver[j];
-                                               if (p->port == 5353) continue; // Note: dns_resolver_t port is defined to be "uint16_t in host byte order"
-                                               if (p->search_order <= r->search_order)
+                                               char *nextOption = r->options;
+                                               char *currentOption = NULL;
+                                               while ((currentOption = strsep(&nextOption, " ")) != NULL && currentOption[0] != 0)
                                                        {
-                                                       domainname tmp;
-                                                       if (p->search_order == DEFAULT_SEARCH_ORDER || !p->domain || !*p->domain) tmp.c[0] = '\0';
-                                                       else if (!MakeDomainNameFromDNSNameString(&tmp, p->domain)) { LogMsg("RegisterSplitDNS: bad domain %s", p->domain); continue; }
-                                                       if (SameDomainName(&d, &tmp))
-                                                               if (p->search_order < r->search_order || j < i) break;  // if equal weights, pick first in list, otherwise pick lower-weight (p)
+                                                       // The option may be in the form of interface=xxx where xxx is an interface name.
+                                                       if (strncmp(currentOption, kInterfaceSpecificOption, sizeof(kInterfaceSpecificOption) - 1) == 0)
+                                                               {
+                                                               NetworkInterfaceInfoOSX *ni;
+                                                               char    ifname[IF_NAMESIZE+1];
+                                                               mDNSu32 ifindex = 0;
+                                                               // If something goes wrong finding the interface, create the server entry anyhow but mark it as disabled.
+                                                               // This allows us to block these special queries from going out on the wire.
+                                                               strlcpy(ifname, currentOption + sizeof(kInterfaceSpecificOption)-1, sizeof(ifname));
+                                                               ifindex = if_nametoindex(ifname);
+                                                               if (ifindex == 0) { disabled = 1; LogMsg("RegisterSplitDNS: interfaceSpecific - interface %s not found", ifname); continue; }
+                                                               LogInfo("%s: Interface-specific entry: %s on %s (%d)", __FUNCTION__, r->domain, ifname, ifindex);
+                                                               // Find the interface, can't use mDNSPlatformInterfaceIDFromInterfaceIndex
+                                                               // because that will call mDNSMacOSXNetworkChanged if the interface doesn't exist
+                                                               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;
+                                                               if (interface == mDNSNULL) { disabled = 1; LogMsg("RegisterSplitDNS: interfaceSpecific - index %d (%s) not found", ifindex, ifname); continue; }
+                                                               }
                                                        }
                                                }
-                                       if (j < config->n_resolver) // found a lower-weighted resolver for this domain
-                                               debugf("Rejecting DNS server in slot %d domain %##s (slot %d outranks)", i, d.c, j);
-                                       else
-                                               {
-                                               mDNSInterfaceID interface = mDNSInterface_Any;
-                                               int disabled  = 0;
-                                               
-                                               // DNS server option parsing
-                                               if (r->options != NULL)
+
+                                       for (n = 0; n < r->n_nameserver; n++)
+                                               if (r->nameserver[n]->sa_family == AF_INET || r->nameserver[n]->sa_family == AF_INET6)
                                                        {
-                                                       char *nextOption = r->options;
-                                                       char *currentOption = NULL;
-                                                       while ((currentOption = strsep(&nextOption, " ")) != NULL && currentOption[0] != 0)
+                                                       mDNSAddr saddr;
+                                                       // mDNSAddr saddr = { mDNSAddrType_IPv4, { { { 192, 168, 1, 1 } } } }; // for testing
+                                                       if (SetupAddr(&saddr, r->nameserver[n])) LogMsg("RegisterSplitDNS: bad IP address");
+                                                       else
                                                                {
-                                                               // The option may be in the form of interface=xxx where xxx is an interface name.
-                                                               if (strncmp(currentOption, kInterfaceSpecificOption, sizeof(kInterfaceSpecificOption) - 1) == 0)
+                                                               DNSServer *s = mDNS_AddDNSServer(m, &d, interface, &saddr, r->port ? mDNSOpaque16fromIntVal(r->port) : UnicastDNSPort);
+                                                               if (s)
                                                                        {
-                                                                       NetworkInterfaceInfoOSX *ni;
-                                                                       char    ifname[IF_NAMESIZE+1];
-                                                                       mDNSu32 ifindex = 0;
-                                                                       // If something goes wrong finding the interface, create the server entry anyhow but mark it as disabled.
-                                                                       // This allows us to block these special queries from going out on the wire.
-                                                                       strlcpy(ifname, currentOption + sizeof(kInterfaceSpecificOption)-1, sizeof(ifname));
-                                                                       ifindex = if_nametoindex(ifname);
-                                                                       if (ifindex == 0) { disabled = 1; LogMsg("RegisterSplitDNS: interfaceSpecific - interface %s not found", ifname); continue; }
-                                                                       LogOperation("%s: Interface-specific entry: %s on %s (%d)", __FUNCTION__, r->domain, ifname, ifindex);
-                                                                       // Find the interface, can't use mDNSPlatformInterfaceIDFromInterfaceIndex
-                                                                       // because that will call mDNSMacOSXNetworkChanged if the interface doesn't exist
-                                                                       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;
-                                                                       if (interface == mDNSNULL) { disabled = 1; LogMsg("RegisterSplitDNS: interfaceSpecific - index %d (%s) not found", ifindex, ifname); continue; }
+                                                                       if (disabled) s->teststate = DNSServer_Disabled;
+                                                                       LogInfo("Added dns server %#a:%d for domain %##s from slot %d,%d", &s->addr, mDNSVal16(s->port), d.c, i, n);
                                                                        }
                                                                }
                                                        }
-                                               for (n = 0; n < r->n_nameserver; n++)
-                                                       if (r->nameserver[n]->sa_family == AF_INET && (interface || disabled || !AddrRequiresPPPConnection(r->nameserver[n])))
-                                                               {
-                                                               mDNSAddr saddr;
-                                                               // mDNSAddr saddr = { mDNSAddrType_IPv4, { { { 192, 168, 1, 1 } } } }; // for testing
-                                                               debugf("Adding dns server from slot %d %#a for domain %##s", i, &saddr, d.c);
-                                                               if (SetupAddr(&saddr, r->nameserver[n])) LogMsg("RegisterSplitDNS: bad IP address");
-                                                               else
-                                                                       {
-                                                                       DNSServer *s = mDNS_AddDNSServer(m, &d, interface, &saddr, r->port ? mDNSOpaque16fromIntVal(r->port) : UnicastDNSPort);
-                                                                       if (s && disabled) s->teststate = DNSServer_Disabled;
-                                                                       }
-                                                               }
-                                               }
+                                               
                                        }
                                }
-                       if (setsearch)
-                               {
-                               // Due to the vagaries of Apple's SystemConfiguration and dnsinfo.h APIs, if there are no search domains
-                               // listed, then you're supposed to interpret the "domain" field as also being the search domain, but if
-                               // there *are* search domains listed, then you're supposed to ignore the "domain" field completely and
-                               // instead use the search domain list as the sole authority for what domains to search and in what order
-                               // (and the domain from the "domain" field will also appear somewhere in that list).
-                               // Also, all search domains get added to the search list for resolver[0], so the domains and/or
-                               // search lists for other resolvers in the list need to be ignored.
-                               if (config->resolver[0]->n_search == 0) mDNS_AddSearchDomain_CString(config->resolver[0]->domain);
-                               else for (i = 0; i < config->resolver[0]->n_search; i++) mDNS_AddSearchDomain_CString(config->resolver[0]->search[i]);
-                               }
+
                        dns_configuration_free(config);
                        setservers = mDNSfalse;  // Done these now -- no need to fetch the same data from SCDynamicStore
                        setsearch  = mDNSfalse;
@@ -3439,7 +4533,9 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
 #endif // MDNS_NO_DNSINFO
 
        SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformSetDNSConfig"), NULL, NULL);
-       if (store)
+       if (!store)
+               LogMsg("mDNSPlatformSetDNSConfig: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+       else
                {
                CFDictionaryRef ddnsdict = SCDynamicStoreCopyValue(store, NetworkChangedKey_DynamicDNS);
                if (ddnsdict)
@@ -3451,7 +4547,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                        {
                                        // 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 && DDNSSettingEnabled(fqdnDict))
+                                       if (fqdnDict && DictionaryIsEnabled(fqdnDict))
                                                {
                                                CFStringRef name = CFDictionaryGetValue(fqdnDict, CFSTR("Domain"));
                                                if (name)
@@ -3471,7 +4567,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                if (regArray && CFArrayGetCount(regArray) > 0)
                                        {
                                        CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
-                                       if (regDict && DDNSSettingEnabled(regDict))
+                                       if (regDict && DictionaryIsEnabled(regDict))
                                                {
                                                CFStringRef name = CFDictionaryGetValue(regDict, CFSTR("Domain"));
                                                if (name)
@@ -3497,7 +4593,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                        for (i = 0; i < CFArrayGetCount(browseArray); i++)
                                                {
                                                CFDictionaryRef browseDict = CFArrayGetValueAtIndex(browseArray, i);
-                                               if (browseDict && DDNSSettingEnabled(browseDict))
+                                               if (browseDict && DictionaryIsEnabled(browseDict))
                                                        {
                                                        CFStringRef name = CFDictionaryGetValue(browseDict, CFSTR("Domain"));
                                                        if (name)
@@ -3529,7 +4625,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                CFDictionaryGetKeysAndValues(btmm, key, val);
                                for (i = 0; i < size; i++)
                                        {
-                                       LogOperation("BackToMyMac %d", i);
+                                       LogInfo("BackToMyMac %d", i);
                                        if (!CFStringGetCString(key[i], buf, sizeof(buf), kCFStringEncodingUTF8))
                                                LogMsg("Can't read BackToMyMac %d key %s", i, buf);
                                        else
@@ -3539,7 +4635,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                                        LogMsg("Can't read BackToMyMac %d val %s", i, buf);
                                                else if (MakeDomainNameFromDNSNameString(&d, buf) && d.c[0])
                                                        {
-                                                       LogOperation("BackToMyMac %d %d %##s", i, uid, d.c);
+                                                       LogInfo("BackToMyMac %d %d %##s", i, uid, d.c);
                                                        AppendDNameListElem(&RegDomains, uid, &d);
                                                        }
                                                }
@@ -3558,15 +4654,20 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                        CFArrayRef values = CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses);
                                        if (values)
                                                {
+                                               LogInfo("DNS Server Address values: %d", CFArrayGetCount(values));
                                                for (i = 0; i < CFArrayGetCount(values); i++)
                                                        {
                                                        CFStringRef s = CFArrayGetValueAtIndex(values, i);
                                                        mDNSAddr addr = { mDNSAddrType_IPv4, { { { 0 } } } };
                                                        if (s && CFStringGetCString(s, buf, 256, kCFStringEncodingUTF8) &&
                                                                inet_aton(buf, (struct in_addr *) &addr.ip.v4))
+                                                               {
+                                                               LogInfo("Adding DNS server from dict: %s", buf);
                                                                mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, &addr, UnicastDNSPort);
+                                                               }
                                                        }
                                                }
+                                       else LogInfo("No DNS Server Address values");
                                        }
                                if (setsearch)
                                        {
@@ -3607,7 +4708,8 @@ mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4,
        (void)m; // Unused
 
        SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformGetPrimaryInterface"), NULL, NULL);
-       if (!store) LogMsg("mDNSPlatformGetPrimaryInterface: SCDynamicStoreCreate failed");
+       if (!store)
+               LogMsg("mDNSPlatformGetPrimaryInterface: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
        else
                {
                CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_IPv4);
@@ -3628,8 +4730,7 @@ mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4,
                                        saddr.sin_port = 0;
                                        inet_aton(buf, &saddr.sin_addr);
                
-                                       if (AddrRequiresPPPConnection((struct sockaddr *)&saddr)) debugf("Ignoring router %s (requires PPP connection)", buf);
-                                       else *(in_addr_t *)&r->ip.v4 = saddr.sin_addr.s_addr;
+                                       *(in_addr_t *)&r->ip.v4 = saddr.sin_addr.s_addr;
                                        }
                                }
                
@@ -3686,7 +4787,7 @@ mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4,
 
 mDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
        {
-       LogOperation("mDNSPlatformDynDNSHostNameStatusChanged %d %##s", status, dname->c);
+       LogInfo("mDNSPlatformDynDNSHostNameStatusChanged %d %##s", status, dname->c);
        char uname[MAX_ESCAPED_DOMAIN_NAME];    // Max legal C-string name, including terminating NUL
        ConvertDomainNameToCString(dname, uname);
 
@@ -3713,19 +4814,19 @@ mDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const
        else
                {
                const CFNumberRef StatusVals[1] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &status) };
-               if (!StatusVals[0]) LogMsg("SetDDNSNameStatus: CFNumberCreate(%ld) failed", status);
+               if (!StatusVals[0]) LogMsg("SetDDNSNameStatus: CFNumberCreate(%d) failed", status);
                else
                        {
-                       const CFDictionaryRef HostVals[1] = { CFDictionaryCreate(NULL, (void*)StatusKeys, (void*)StatusVals, 1, NULL, NULL) };
+                       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, NULL, NULL) };
+                               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, NULL, NULL);
+                                       CFDictionaryRef StateDict = CFDictionaryCreate(NULL, (void*)StateKeys, (void*)StateVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
                                        if (StateDict)
                                                {
-                                               mDNSDynamicStoreSetConfig(kmDNSDynamicConfig, StateDict);
+                                               mDNSDynamicStoreSetConfig(kmDNSDynamicConfig, mDNSNULL, StateDict);
                                                CFRelease(StateDict);
                                                }
                                        CFRelease(StateVals[0]);
@@ -3747,7 +4848,7 @@ mDNSexport void SetDomainSecrets(mDNS *m)
 #else
        mDNSBool        haveAutoTunnels = mDNSfalse;
 
-       LogOperation("SetDomainSecrets");
+       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
@@ -3764,11 +4865,11 @@ mDNSexport void SetDomainSecrets(mDNS *m)
        ClientTunnel *client;
        for (client = m->TunnelClients; client; client = client->next)
                {
-               LogOperation("SetDomainSecrets: tunnel to %##s marked for deletion", client->dstname.c);
+               LogInfo("SetDomainSecrets: tunnel to %##s marked for deletion", client->dstname.c);
                client->MarkedForDeletion = mDNStrue;
                }
        }
-#endif APPLE_OSX_mDNSResponder
+#endif // APPLE_OSX_mDNSResponder
 
        // String Array used to write list of private domains to Dynamic Store
        CFMutableArrayRef sa = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
@@ -3836,27 +4937,16 @@ mDNSexport void SetDomainSecrets(mDNS *m)
                                for (client = m->TunnelClients; client; client = client->next)
                                        if (FoundInList == GetAuthInfoForName_internal(m, &client->dstname))
                                        {
-                                       LogOperation("SetDomainSecrets: tunnel to %##s no longer marked for deletion", client->dstname.c);
+                                       LogInfo("SetDomainSecrets: tunnel to %##s no longer marked for deletion", client->dstname.c);
                                        client->MarkedForDeletion = mDNSfalse;
-                                       // If the key has changed, reconfigure the tunnel
-                                       if (strncmp(stringbuf, client->b64keydata, sizeof(client->b64keydata)))
-                                               {
-                                               mDNSBool queryNotInProgress = client->q.ThisQInterval < 0;
-                                               LogOperation("SetDomainSecrets: secret changed for tunnel %##s %s", client->dstname.c, queryNotInProgress ? "reconfiguring" : "query in progress");
-                                               if (queryNotInProgress) AutoTunnelSetKeys(client, mDNSfalse);
-                                               mDNS_snprintf(client->b64keydata, sizeof(client->b64keydata), "%s", stringbuf);
-                                               if (queryNotInProgress) AutoTunnelSetKeys(client, mDNStrue);
-                                               }
                                        }
                                }
 
-                       mDNSBool keyChanged = FoundInList && FoundInList->AutoTunnel ? strncmp(stringbuf, FoundInList->b64keydata, sizeof(FoundInList->b64keydata)) : mDNSfalse;
-
-#endif APPLE_OSX_mDNSResponder
+#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!
-                       //LogOperation("SetDomainSecrets: %##s %##s %s", &domain.c, &keyname.c, stringbuf);
+                       //LogInfo("SetDomainSecrets: %##s %##s %s", &domain.c, &keyname.c, stringbuf);
 
                        // If didn't find desired domain in the list, make a new entry
                        ptr = FoundInList;
@@ -3867,7 +4957,7 @@ mDNSexport void SetDomainSecrets(mDNS *m)
                                if (!ptr) { LogMsg("SetDomainSecrets: No memory"); continue; }
                                }
 
-                       LogOperation("SetDomainSecrets: %d of %d %##s", i, ArrayCount, &domain);
+                       LogInfo("SetDomainSecrets: %d of %d %##s", i, ArrayCount, &domain);
                        if (mDNS_SetSecretForDomain(m, ptr, &domain, &keyname, stringbuf, IsTunnelModeDomain(&domain)) == mStatus_BadParamErr)
                                {
                                if (!FoundInList) mDNSPlatformMemFree(ptr);             // If we made a new DomainAuthInfo here, and it turned out bad, dispose it immediately
@@ -3875,14 +4965,8 @@ mDNSexport void SetDomainSecrets(mDNS *m)
                                }
 
 #if APPLE_OSX_mDNSResponder
-                       if (keyChanged && AnonymousRacoonConfig)
-                               {
-                               LogOperation("SetDomainSecrets: secret changed for %##s", &domain);
-                               (void)mDNSConfigureServer(kmDNSUp, stringbuf);
-                               }
-                               
                        if (ptr->AutoTunnel) UpdateAutoTunnelDomainStatus(m, ptr);
-#endif APPLE_OSX_mDNSResponder
+#endif // APPLE_OSX_mDNSResponder
 
                        ConvertDomainNameToCString(&domain, stringbuf);
                        CFStringRef cfs = CFStringCreateWithCString(NULL, stringbuf, kCFStringEncodingUTF8);
@@ -3890,10 +4974,10 @@ mDNSexport void SetDomainSecrets(mDNS *m)
                        }
                CFRelease(secrets);
                }
-       mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, sa);
+       mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, mDNSNULL, sa);
        CFRelease(sa);
 
-       #if APPLE_OSX_mDNSResponder
+#if APPLE_OSX_mDNSResponder
                {
                // clean up ClientTunnels
                ClientTunnel **pp = &m->TunnelClients;
@@ -3902,13 +4986,13 @@ mDNSexport void SetDomainSecrets(mDNS *m)
                        if ((*pp)->MarkedForDeletion)
                                {
                                ClientTunnel *cur = *pp;
-                               LogOperation("SetDomainSecrets: removing client %p %##s from list", cur, cur->dstname.c);
+                               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 
+                       else
                                pp = &(*pp)->next;
                        }
 
@@ -3934,7 +5018,7 @@ mDNSexport void SetDomainSecrets(mDNS *m)
                                                }
                                        info->AutoTunnelNAT.clientContext = mDNSNULL;
                                        }
-                               RemoveAutoTunnelDomainStatus(info);
+                               RemoveAutoTunnelDomainStatus(m, info);
                                }
                        info = info->next;
                        }
@@ -3942,24 +5026,19 @@ mDNSexport void SetDomainSecrets(mDNS *m)
                if (!haveAutoTunnels && !m->TunnelClients && m->AutoTunnelHostAddrActive)
                        {
                        // remove interface if no autotunnel servers and no more client tunnels
-                       LogOperation("SetDomainSecrets: Bringing tunnel interface DOWN");
+                       LogInfo("SetDomainSecrets: Bringing tunnel interface DOWN");
                        m->AutoTunnelHostAddrActive = mDNSfalse;
                        (void)mDNSAutoTunnelInterfaceUpDown(kmDNSDown, m->AutoTunnelHostAddr.b);
-                       memset(m->AutoTunnelHostAddr.b, 0, sizeof(m->AutoTunnelHostAddr.b));
-                       }
-
-               if (!haveAutoTunnels && AnonymousRacoonConfig)
-                       {
-                       LogMsg("SetDomainSecrets: Resetting AnonymousRacoonConfig to false");
-                       AnonymousRacoonConfig = mDNSfalse;
-                       (void)mDNSConfigureServer(kmDNSDown, "");
+                       mDNSPlatformMemZero(m->AutoTunnelHostAddr.b, sizeof(m->AutoTunnelHostAddr.b));
                        }
 
+               UpdateConfigureServer(m);
+               
                if (m->AutoTunnelHostAddr.b[0])
                        if (TunnelClients(m) || TunnelServers(m))
                                SetupLocalAutoTunnelInterface_internal(m);
                }
-       #endif APPLE_OSX_mDNSResponder
+#endif // APPLE_OSX_mDNSResponder
 
 #endif /* NO_SECURITYFRAMEWORK */
        }
@@ -3976,116 +5055,436 @@ mDNSlocal void SetLocalDomains(void)
        CFArrayAppendValue(sa, CFSTR("a.e.f.ip6.arpa"));
        CFArrayAppendValue(sa, CFSTR("b.e.f.ip6.arpa"));
 
-       mDNSDynamicStoreSetConfig(kmDNSMulticastConfig, sa);
+       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, CFSTR("State:/IOKit/PowerManagement/CurrentSettings"));
+               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)
+       {
+       (void)m;
+       NetworkInterfaceInfo* info = (NetworkInterfaceInfo*)question->QuestionContext;
+       debugf("UpdateSPSStatus: %s %##s %s %s", info->ifname, question->qname.c, AddRecord ? "Add" : "Rmv", answer ? RRDisplayString(m, answer) : "<null>");
+
+       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, CFSTR("State:/IOKit/PowerManagement/CurrentSettings"));
+               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)
+       {
+       SCPreferencesSynchronize(m->p->SCPrefs);
+       CFDictionaryRef dict = SCPreferencesGetValue(m->p->SCPrefs, CFSTR("NAT"));
+       mDNSBool natenabled = (dict && (CFGetTypeID(dict) == CFDictionaryGetTypeID()) && DictionaryIsEnabled(dict));
+       mDNSu8 sps = natenabled ? 50 : (OfferSleepProxyService && GetSystemSleepTimerSetting() == 0) ? OfferSleepProxyService : 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 > 50 && 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 (e.g. the current Apple TV hardware)
+       // 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 == 10 && (!sps || sps > 70)) sps = 70;
+
+       mDNSCoreBeSleepProxyServer(m, sps, SPMetricPortability, SPMetricMarginalPower, SPMetricTotalPower);
+       }
+
+mDNSlocal void InternetSharingChanged(SCPreferencesRef prefs, SCPreferencesNotification notificationType, void *context)
+       {
+       (void)prefs;             // Parameter not used
+       (void)notificationType;  // Parameter not used
+       mDNS *const m = (mDNS *const)context;
+       KQueueLock(m);
+       mDNS_Lock(m);
+
+       // Tell platform layer to open or close its BPF fds
+       if (!m->p->NetworkChanged ||
+               m->p->NetworkChanged - NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2) < 0)
+               {
+               m->p->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
+               LogInfo("InternetSharingChanged: Set NetworkChanged to %d (%d)", m->p->NetworkChanged - m->timenow, m->p->NetworkChanged);
+               }
+
+       mDNS_Unlock(m);
+       KQueueUnlock(m, "InternetSharingChanged");
+       }
+
+mDNSlocal mStatus WatchForInternetSharingChanges(mDNS *const m)
+       {
+       SCPreferencesRef SCPrefs = SCPreferencesCreate(NULL, CFSTR("mDNSResponder:WatchForInternetSharingChanges"), CFSTR("com.apple.nat.plist"));
+       if (!SCPrefs) { LogMsg("SCPreferencesCreate failed: %s", SCErrorString(SCError())); return(mStatus_NoMemoryErr); }
+
+       SCPreferencesContext context = { 0, m, NULL, NULL, NULL };
+       if (!SCPreferencesSetCallback(SCPrefs, InternetSharingChanged, &context))
+               { LogMsg("SCPreferencesSetCallback failed: %s", SCErrorString(SCError())); CFRelease(SCPrefs); return(mStatus_NoMemoryErr); }
+
+       if (!SCPreferencesScheduleWithRunLoop(SCPrefs, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
+               { LogMsg("SCPreferencesScheduleWithRunLoop failed: %s", SCErrorString(SCError())); CFRelease(SCPrefs); return(mStatus_NoMemoryErr); }
+
+       m->p->SCPrefs = SCPrefs;
+       return(mStatus_NoError);
+       }
+
+#endif // APPLE_OSX_mDNSResponder
+
+static io_service_t g_rootdomain = MACH_PORT_NULL;
+
+mDNSlocal mDNSBool SystemWakeForNetworkAccess(void)
+       {
+       mDNSs32 val = 0;
+       CFBooleanRef clamshellStop = NULL;
+       mDNSBool retnow = mDNSfalse;
+
+       GetCurrentPMSetting(CFSTR("Wake On LAN"), &val);
+       LogSPS("SystemWakeForNetworkAccess: Wake On LAN: %d", val);
+       if (!val) return mDNSfalse;
+       
+       if (!g_rootdomain) g_rootdomain = IORegistryEntryFromPath(MACH_PORT_NULL, kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain");
+       if (!g_rootdomain) { LogMsg("SystemWakeForNetworkAccess: IORegistryEntryFromPath failed; assuming no clamshell so can WOMP"); return mDNStrue; }
+       
+       clamshellStop = (CFBooleanRef)IORegistryEntryCreateCFProperty(g_rootdomain, CFSTR(kAppleClamshellStateKey), kCFAllocatorDefault, 0);
+       if (!clamshellStop) { LogSPS("SystemWakeForNetworkAccess: kAppleClamshellStateKey does not exist; assuming no clamshell so can WOMP"); return mDNStrue; }
+       retnow = clamshellStop == kCFBooleanFalse;
+       CFRelease(clamshellStop);
+       if (retnow) { LogSPS("SystemWakeForNetworkAccess: kAppleClamshellStateKey is false; clamshell is open so can WOMP"); return mDNStrue; }
+       
+       clamshellStop = (CFBooleanRef)IORegistryEntryCreateCFProperty(g_rootdomain, CFSTR(kAppleClamshellCausesSleepKey), kCFAllocatorDefault, 0);
+       if (!clamshellStop) { LogSPS("SystemWakeForNetworkAccess: kAppleClamshellCausesSleepKey does not exist; assuming no clamshell so can WOMP"); return mDNStrue; }
+       retnow = clamshellStop == kCFBooleanFalse;
+       CFRelease(clamshellStop);       
+       if (retnow) { LogSPS("SystemWakeForNetworkAccess: kAppleClamshellCausesSleepKey is false; clamshell is closed but can WOMP"); return mDNStrue; }
+       
+       LogSPS("SystemWakeForNetworkAccess: clamshell is closed and can't WOMP");
+       return mDNSfalse;
+       }
+
 mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
        {
-       LogOperation("***   Network Configuration Change   ***  (%d)%s",
+       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();
        MarkAllInterfacesInactive(m, utc);
        UpdateInterfaceList(m, utc);
        ClearInactiveInterfaces(m, utc);
        SetupActiveInterfaces(m, utc);
 
-       #if APPLE_OSX_mDNSResponder
+#if APPLE_OSX_mDNSResponder
+
+       if (m->AutoTunnelHostAddr.b[0])
                {
-               if (m->AutoTunnelHostAddr.b[0])
+               mDNS_Lock(m);
+               if (TunnelClients(m) || TunnelServers(m))
+                       SetupLocalAutoTunnelInterface_internal(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)
                        {
-                       mDNS_Lock(m);
-                       if (TunnelClients(m) || TunnelServers(m))
-                               SetupLocalAutoTunnelInterface_internal(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)
+                       mDNSAddr tmpSrc = zeroAddr;
+                       mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
+                       tmpDst.ip.v4 = p->rmt_outer;
+                       mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
+                       if (!mDNSSameIPv6Address(p->loc_inner, m->AutoTunnelHostAddr) ||
+                               !mDNSSameIPv4Address(p->loc_outer, tmpSrc.ip.v4))
                                {
-                               mDNSAddr tmpSrc = zeroAddr;
-                               mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
-                               tmpDst.ip.v4 = p->rmt_outer;
-                               mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
-                               if (!mDNSSameIPv6Address(p->loc_inner, m->AutoTunnelHostAddr) ||
-                                       !mDNSSameIPv4Address(p->loc_outer, tmpSrc.ip.v4))
-                                       {
-                                       AutoTunnelSetKeys(p, mDNSfalse);
-                                       p->loc_inner = m->AutoTunnelHostAddr;
-                                       p->loc_outer = tmpSrc.ip.v4;
-                                       AutoTunnelSetKeys(p, mDNStrue);
-                                       }
+                               AutoTunnelSetKeys(p, mDNSfalse);
+                               p->loc_inner = m->AutoTunnelHostAddr;
+                               p->loc_outer = tmpSrc.ip.v4;
+                               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->ifinfo.InterfaceID == (mDNSInterfaceID)i && !(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
+
+#endif // APPLE_OSX_mDNSResponder
 
        uDNS_SetupDNSConfig(m);
+       mDNS_ConfigChanged(m);
+       }
 
-       if (m->MainCallback)
-               m->MainCallback(m, mStatus_ConfigChanged);
+// 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: setting network changed to %d (%d)", delay, m->p->NetworkChanged);
+               }
        }
 
+
 mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
        {
        (void)store;        // Parameter not used
-       (void)changedKeys;  // Parameter not used
        mDNS *const m = (mDNS *const)context;
        KQueueLock(m);
        mDNS_Lock(m);
 
-       mDNSs32 delay = mDNSPlatformOneSecond;                                  // Start off assuming a one-second delay
+       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);
-       if (c && c - c1 - c2 - c3 == 0) delay = mDNSPlatformOneSecond/20;       // If these were the only changes, shorten delay
+       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
        
-#if LogAllOperations
-       int i;
-       for (i=0; i<c; i++)
+       if (mDNS_LoggingEnabled)
                {
-               char buf[256];
-               if (!CFStringGetCString(CFArrayGetValueAtIndex(changedKeys, i), buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-               LogOperation("***   NetworkChanged SC key: %s", buf);
-               }
-       LogOperation("***   NetworkChanged   *** %d change%s %s%s%sdelay %d",
-               c, c>1?"s":"",
-               c1 ? "(Local Hostname) " : "",
-               c2 ? "(Computer Name) "  : "",
-               c3 ? "(DynamicDNS) "     : "",
-               delay);
-#endif
-
-       if (!m->p->NetworkChanged ||
-               m->p->NetworkChanged - NonZeroTime(m->timenow + delay) < 0)
-               m->p->NetworkChanged = NonZeroTime(m->timenow + delay);
-
-       // If we have a global DNS change, then disregard delay and reconfigure immediately
-       if (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DNS) != 0) m->p->NetworkChanged = NonZeroTime(m->timenow);
+               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) "            : "",
+                       delay);
+               }
 
+       SetNetworkChanged(m, delay);
+       
        // KeyChain frequently fails to notify clients of change events. To work around this
        // we set a timer and periodically poll to detect if any changes have occurred.
        // Without this Back To My Mac just does't work for a large number of users.
        // See <rdar://problem/5124399> Not getting Keychain Changed events when enabling BTMM
        if (c3 || CFArrayContainsValue(changedKeys, range, NetworkChangedKey_BackToMyMac))
                {
-               LogOperation("***   NetworkChanged   *** starting KeyChainBugTimer");
+               LogInfo("***   NetworkChanged   *** starting KeyChainBugTimer");
                m->p->KeyChainBugTimer    = NonZeroTime(m->timenow + delay);
                m->p->KeyChainBugInterval = mDNSPlatformOneSecond;
                }
 
-       if (!m->SuppressSending ||
-               m->SuppressSending - m->p->NetworkChanged < 0)
-               m->SuppressSending = m->p->NetworkChanged;
-
        mDNS_Unlock(m);
+
+       // If DNS settings changed, immediately force a reconfig (esp. cache flush)
+       if (c4) mDNSMacOSXNetworkChanged(m);
+
        KQueueUnlock(m, "NetworkChanged");
        }
 
@@ -4109,6 +5508,7 @@ mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
        CFArrayAppendValue(keys, NetworkChangedKey_DNS);
        CFArrayAppendValue(keys, NetworkChangedKey_DynamicDNS);
        CFArrayAppendValue(keys, NetworkChangedKey_BackToMyMac);
+       CFArrayAppendValue(keys, CFSTR("State:/IOKit/PowerManagement/CurrentSettings")); // should remove as part of <rdar://problem/6751656>
        CFArrayAppendValue(patterns, pattern1);
        CFArrayAppendValue(patterns, pattern2);
        CFArrayAppendValue(patterns, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
@@ -4135,10 +5535,107 @@ mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
        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
+
+#ifndef KEV_DL_WAKEFLAGS_CHANGED
+#define KEV_DL_WAKEFLAGS_CHANGED 17
+#endif
+
+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"    : "?");
+
+               if (msg.k.event_code == KEV_DL_WAKEFLAGS_CHANGED) SetNetworkChanged(m, mDNSPlatformOneSecond * 2);
+               }
+
+       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("WatchForNetworkChanges: socket failed %s errno %d (%s)", 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("WatchForNetworkChanges: SIOCSKEVFILT failed %s errno %d (%s)", 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)
        {
-       LogOperation("***   Keychain Changed   ***");
+       LogInfo("***   Keychain Changed   ***");
        mDNS *const m = (mDNS *const)context;
        SecKeychainRef skc;
        OSStatus err = SecKeychainCopyDefault(&skc);
@@ -4163,11 +5660,11 @@ mDNSlocal OSStatus KeychainChanged(SecKeychainEvent keychainEvent, SecKeychainCa
                                }
                        if (relevant)
                                {
-                               LogMsg("***   Keychain Changed   *** KeychainEvent=%d %s",
+                               LogInfo("***   Keychain Changed   *** KeychainEvent=%d %s",
                                        keychainEvent,
-                                       keychainEvent == kSecAddEvent    ? "kSecAddEvent" 
-                                       keychainEvent == kSecDeleteEvent ? "kSecDeleteEvent" : 
-                                       keychainEvent == kSecUpdateEvent ? "kSecUpdateEvent" :  "<Unknown>");
+                                       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);
@@ -4184,46 +5681,137 @@ mDNSlocal OSStatus KeychainChanged(SecKeychainEvent keychainEvent, SecKeychainCa
 #endif
 
 #ifndef NO_IOPOWER
+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) LogInfo("PowerChanged PowerOn %d seconds early, assuming not maintenance wake", m->p->WakeAtUTC - utc);
+               else if (utc - m->p->WakeAtUTC > 30) LogInfo("PowerChanged PowerOn %d seconds late, assuming not maintenance wake", utc - m->p->WakeAtUTC);
+               else
+                       {
+                       mDNSs32 i = 20;
+                       //int result = mDNSPowerRequest(0, i);
+                       //if (result == kIOReturnNotReady) do i += (i<20) ? 1 : ((i+3)/4); while (mDNSPowerRequest(0, i) == kIOReturnNotReady);
+                       LogMsg("PowerChanged: Waking for network maintenance operations %d seconds early; re-sleeping in %d seconds", m->p->WakeAtUTC - utc, i);
+                       m->p->RequestReSleep = mDNS_TimeNow(m) + i * 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
-       LogOperation("PowerChanged %X %lX", messageType, messageArgument);
+       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:               debugf      ("PowerChanged kIOMessageCanSystemPowerOff (no action)");                           break; // E0000240
-               case kIOMessageSystemWillPowerOff:              LogOperation("PowerChanged kIOMessageSystemWillPowerOff");
-                                                                                               mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m);                                                     break; // E0000250
-               case kIOMessageSystemWillNotPowerOff:   debugf      ("PowerChanged kIOMessageSystemWillNotPowerOff (no action)");                       break; // E0000260
-               case kIOMessageCanSystemSleep:                  debugf      ("PowerChanged kIOMessageCanSystemSleep (no action)");                                      break; // E0000270
-               case kIOMessageSystemWillSleep:                 LogOperation("PowerChanged kIOMessageSystemWillSleep");
-                                                                                               mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m);                                                     break; // E0000280
-               case kIOMessageSystemWillNotSleep:              debugf      ("PowerChanged kIOMessageSystemWillNotSleep (no action)");                          break; // E0000290
-               case kIOMessageSystemHasPoweredOn:              LogOperation("PowerChanged kIOMessageSystemHasPoweredOn");
+               case kIOMessageCanSystemPowerOff:               LogInfo("PowerChanged kIOMessageCanSystemPowerOff     (no action)");    break;  // E0000240
+               case kIOMessageSystemWillPowerOff:              LogInfo("PowerChanged kIOMessageSystemWillPowerOff");                                                   // E0000250
+                                                                                               mDNSCoreMachineSleep(m, true);
+                                                                                               if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged(m);
+                                                                                               break;
+               case kIOMessageSystemWillNotPowerOff:   LogInfo("PowerChanged kIOMessageSystemWillNotPowerOff (no action)");    break;  // E0000260
+               case kIOMessageCanSystemSleep:                  LogInfo("PowerChanged kIOMessageCanSystemSleep        (no action)");    break;  // E0000270
+               case kIOMessageSystemWillSleep:                 LogInfo("PowerChanged kIOMessageSystemWillSleep");                                                              // E0000280
+                                                                                               mDNSCoreMachineSleep(m, true);
+                                                                                               break;
+               case kIOMessageSystemWillNotSleep:              LogInfo("PowerChanged kIOMessageSystemWillNotSleep    (no action)");    break;  // E0000290
+               case kIOMessageSystemHasPoweredOn:              LogInfo("PowerChanged kIOMessageSystemHasPoweredOn");                                                   // E0000300
                                                                                                // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
-                                                                                               if (m->SleepState) mDNSCoreMachineSleep(m, false);
-                                                                                               // Just to be safe, also make sure our interface list is fully up to date, in case we
-                                                                                               // haven't yet received the System Configuration Framework "network changed" event that
-                                                                                               // we expect to receive some time shortly after the kIOMessageSystemWillPowerOn message
-                                                                                               mDNSMacOSXNetworkChanged(m);                                                                                                            break; // E0000300
-               case kIOMessageSystemWillRestart:               debugf      ("PowerChanged kIOMessageSystemWillRestart (no action)");                           break; // E0000310
-               case kIOMessageSystemWillPowerOn:               LogOperation("PowerChanged kIOMessageSystemWillPowerOn");
+                                                                                               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:               LogInfo("PowerChanged kIOMessageSystemWillRestart     (no action)");    break;  // E0000310
+               case kIOMessageSystemWillPowerOn:               LogInfo("PowerChanged kIOMessageSystemWillPowerOn");                                                    // E0000320
+
+                                                                                               // On Leopard and earlier, on wake from sleep, instead of reporting link state down, Apple
+                                                                                               // Ethernet drivers report "hardware incapable of detecting link state", which the kernel
+                                                                                               // interprets as "should assume we have networking", which results in the first 4-5 seconds
+                                                                                               // of packets vanishing into a black hole. To work around this, on wake from sleep,
+                                                                                               // we block for five seconds to let Ethernet come up, and then resume normal operation.
+                                                                                               if (OSXVers < OSXVers_10_6_SnowLeopard)
+                                                                                                       {
+                                                                                                       sleep(5);
+                                                                                                       LogMsg("Running on Mac OS X version 10.%d earlier than 10.6; "
+                                                                                                               "PowerChanged did sleep(5) to wait for Ethernet hardware", OSXVers - OSXVers_Base);
+                                                                                                       }
+
                                                                                                // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
-                                                                                               mDNSMacOSXNetworkChanged(m); mDNSCoreMachineSleep(m, false);                                            break; // E0000320
-               default:                                                                LogOperation("PowerChanged unknown message %X", messageType);                                           break;
+                                                                                               if (m->SleepState != SleepState_Sleeping)
+                                                                                                       {
+                                                                                                       LogMsg("kIOMessageSystemWillPowerOn: ERROR m->SleepState %d", m->SleepState);
+                                                                                                       m->SleepState = SleepState_Sleeping;
+                                                                                                       mDNSMacOSXNetworkChanged(m);
+                                                                                                       }
+                                                                                               PowerOn(m);
+                                                                                               break;
+               default:                                                                LogInfo("PowerChanged unknown message %X", messageType);                                break;
                }
 
-       if (!m->p->SleepLimit && messageType == kIOMessageSystemWillSleep)
+       if (messageType == kIOMessageSystemWillSleep) m->p->SleepCookie = (long)messageArgument;
+       else IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
+
+       KQueueUnlock(m, "PowerChanged Sleep/Wake");
+       }
+
+#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+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)
                {
-               m->p->SleepLimit  = NonZeroTime(mDNS_TimeNow(m) + mDNSPlatformOneSecond * 5);
-               m->p->SleepCookie = (long)messageArgument;
+               // CPU Waking. Note: Can get this message repeatedly, as other subsystems power up or down.
+               if (m->SleepState == SleepState_Sleeping) PowerOn(m);
+               IOPMConnectionAcknowledgeEvent(connection, token);
                }
        else
-               IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
+               {
+               // 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, "Sleep/Wake");
+       KQueueUnlock(m, "SnowLeopardPowerChanged Sleep/Wake");
        }
+#endif
+
 #endif /* NO_IOPOWER */
 
 #if COMPILER_LIKES_PRAGMA_MARK
@@ -4236,9 +5824,11 @@ CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey;
 CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey;
 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  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)
 mDNSexport int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring)
        {
        int major = 0, minor = 0;
@@ -4251,8 +5841,8 @@ mDNSexport int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring)
                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);
+               if (cfbuildver && CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8))
+                       sscanf(buildver, "%d%c%d", &major, &letter, &minor);
                CFRelease(vers);
                }
        if (!major) { major=8; LogMsg("Note: No Major Build Version number found; assuming 8"); }
@@ -4297,6 +5887,10 @@ mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
 mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
        {
        mStatus err;
+       m->p->CFRunLoop = CFRunLoopGetCurrent();
+
+       char HINFO_SWstring[256] = "";
+       OSXVers = mDNSMacOSXSystemBuildNumber(HINFO_SWstring);
 
        // 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.
@@ -4312,16 +5906,16 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
 
        m->hostlabel.c[0]        = 0;
 
-       char *HINFO_HWstring = "Macintosh";
-       char HINFO_HWstring_buffer[256];
        int    get_model[2] = { CTL_HW, HW_MODEL };
        size_t len_model = sizeof(HINFO_HWstring_buffer);
-       if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0)
+       // Names that contain no commas are prototype model names, so we ignore those
+       if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0 && strchr(HINFO_HWstring_buffer, ','))
                HINFO_HWstring = HINFO_HWstring_buffer;
+       HINFO_HWstring_prefixlen = strcspn(HINFO_HWstring, "0123456789");
 
-       char HINFO_SWstring[256] = "";
-       if (mDNSMacOSXSystemBuildNumber(HINFO_SWstring) < 7) m->KnownBugs |= mDNS_KnownBug_PhantomInterfaces;
-       if (mDNSPlatformInit_CanReceiveUnicast())            m->CanReceiveUnicastOn5353 = mDNStrue;
+       if (OSXVers <  OSXVers_10_3_Panther     ) m->KnownBugs |= mDNS_KnownBug_PhantomInterfaces;
+       if (OSXVers >= OSXVers_10_6_SnowLeopard ) m->KnownBugs |= mDNS_KnownBug_LossySyslog;
+       if (mDNSPlatformInit_CanReceiveUnicast()) m->CanReceiveUnicastOn5353 = mDNStrue;
 
        mDNSu32 hlen = mDNSPlatformStrLen(HINFO_HWstring);
        mDNSu32 slen = mDNSPlatformStrLen(HINFO_SWstring);
@@ -4364,14 +5958,15 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
        m->p->usernicelabel.c[0] = 0;
        m->p->NotifyUser         = 0;
        m->p->KeyChainBugTimer   = 0;
-       m->p->SleepLimit         = 0;
+       m->p->WakeAtUTC          = 0;
+       m->p->RequestReSleep     = 0;
+       
+#if APPLE_OSX_mDNSResponder
+       uuid_generate(m->asl_uuid);
+#endif
 
        m->AutoTunnelHostAddr.b[0] = 0;         // Zero out AutoTunnelHostAddr so UpdateInterfaceList() know it has to set it up
 
-       mDNSs32 utc = mDNSPlatformUTC();
-       UpdateInterfaceList(m, utc);
-       SetupActiveInterfaces(m, utc);
-
        NetworkChangedKey_IPv4         = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
        NetworkChangedKey_IPv6         = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
        NetworkChangedKey_Hostnames    = SCDynamicStoreKeyCreateHostNames(NULL);
@@ -4383,6 +5978,19 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
        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);
@@ -4399,11 +6007,53 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
 #endif
 
 #ifndef NO_IOPOWER
-       m->p->PowerConnection = IORegisterForSystemPower(m, &m->p->PowerPortRef, PowerChanged, &m->p->PowerNotifier);
-       if (!m->p->PowerConnection) { LogMsg("mDNSPlatformInit_setup: IORegisterForSystemPower failed"); return(-1); }
-       else CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
+
+#ifndef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+       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
+                       {
+                       iopmerr = IOPMConnectionScheduleWithRunLoop(c, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+                       if (iopmerr) LogMsg("IOPMConnectionScheduleWithRunLoop failed %d", iopmerr);
+                       }
+               }
+       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 CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
+               }
 #endif /* NO_IOPOWER */
 
+#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)
+       // An Apple TV does not actually weigh 3kg, but we assign it a 'nominal' mass of 3kg to indicate that it's 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, "AppleTV",  7)) { SPMetricPortability = 35 /*  3kg */; SPMetricMarginalPower = 10 /*   0W */; SPMetricTotalPower = 73 /*  20W */; }
+       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",
+               HINFO_HWstring_prefixlen, HINFO_HWstring, HINFO_HWstring, SPMetricPortability, SPMetricMarginalPower, SPMetricTotalPower);
+
+       err = WatchForInternetSharingChanges(m);
+       if (err) { LogMsg("WatchForInternetSharingChanges failed %d", err); return(err); }
+#endif // APPLE_OSX_mDNSResponder
+
        return(mStatus_NoError);
        }
 
@@ -4413,6 +6063,13 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
        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
+
        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
@@ -4445,18 +6102,28 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
                m->p->Store    = NULL;
                m->p->StoreRLS = 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; }
 
        mDNSs32 utc = mDNSPlatformUTC();
        MarkAllInterfacesInactive(m, utc);
        ClearInactiveInterfaces(m, utc);
        CloseSocketSet(&m->p->permanentsockets);
 
-       #if APPLE_OSX_mDNSResponder
+#if APPLE_OSX_mDNSResponder
        // clean up tunnels
        while (m->TunnelClients)
                {
                ClientTunnel *cur = m->TunnelClients;
-               LogOperation("mDNSPlatformClose: removing client tunnel %p %##s from list", cur, cur->dstname.c);
+               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;
@@ -4465,18 +6132,18 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
 
        if (AnonymousRacoonConfig)
                {
-               AnonymousRacoonConfig = mDNSfalse;
-               LogOperation("mDNSPlatformClose: Deconfiguring autotunnel");
-               (void)mDNSConfigureServer(kmDNSDown, "");
+               AnonymousRacoonConfig = mDNSNULL;
+               LogInfo("mDNSPlatformClose: Deconfiguring autotunnel");
+               (void)mDNSConfigureServer(kmDNSDown, mDNSNULL);
                }
 
        if (m->AutoTunnelHostAddrActive && m->AutoTunnelHostAddr.b[0])
                {
                m->AutoTunnelHostAddrActive = mDNSfalse;
-               LogOperation("mDNSPlatformClose: Removing AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
+               LogInfo("mDNSPlatformClose: Removing AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
                (void)mDNSAutoTunnelInterfaceUpDown(kmDNSDown, m->AutoTunnelHostAddr.b);
                }
-       #endif // APPLE_OSX_mDNSResponder
+#endif // APPLE_OSX_mDNSResponder
        }
 
 #if COMPILER_LIKES_PRAGMA_MARK
@@ -4484,9 +6151,9 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
 #pragma mark - General Platform Support Layer functions
 #endif
 
-mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
+mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
        {
-       return(mach_absolute_time());
+       return(arc4random());
        }
 
 mDNSexport mDNSs32 mDNSPlatformOneSecond = 1000;
@@ -4533,7 +6200,7 @@ mDNSexport mDNSs32 mDNSPlatformRawTime(void)
                last_mach_absolute_time = this_mach_absolute_time;
                // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xyyy) or later.
                // (This bug happens all the time on 10.3, and we know that's not going to be fixed.)
-               if (mDNSMacOSXSystemBuildNumber(NULL) >= 8)
+               if (OSXVers >= OSXVers_10_4_Tiger)
                        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"
@@ -4557,7 +6224,7 @@ mDNSexport void     mDNSPlatformStrCopy(      void *dst, const void *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 void     mDNSPlatformMemZero(      void *dst,                  mDNSu32 len) { bzero(dst, len); }
+mDNSexport void     mDNSPlatformMemZero(      void *dst,                  mDNSu32 len) { memset(dst, 0, len); }
 #if !(APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING)
 mDNSexport void *   mDNSPlatformMemAllocate(mDNSu32 len) { return(mallocL("mDNSPlatformMemAllocate", len)); }
 #endif
index 17fd2b961c726edfe8fc96cc56bd7e7446e3eda9..d2e0e73bfc9f0aea7850b1fe04dabaf18810ace4 100644 (file)
     Change History (most recent first):
 
 $Log: mDNSMacOSX.h,v $
+Revision 1.104  2009/06/25 23:36:56  cheshire
+To facilitate testing, added command-line switch "-OfferSleepProxyService"
+to re-enable the previously-supported mode of operation where we offer
+sleep proxy service on desktop Macs that are set to never sleep.
+
+Revision 1.103  2009/04/11 00:20:13  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.102  2009/04/06 22:14:02  cheshire
+Need to include IOKit/pwr_mgt/IOPM.h to build for AppleTV
+
+Revision 1.101  2009/04/02 22:21:17  mcguire
+<rdar://problem/6577409> Adopt IOPM APIs
+
+Revision 1.100  2009/02/12 20:57:26  cheshire
+Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
+
+Revision 1.99  2009/02/11 02:31:05  cheshire
+Move SystemWakeForNetworkAccessEnabled into mDNS structure so it's accessible to mDNSCore routines
+
+Revision 1.98  2009/02/07 02:52:19  cheshire
+<rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
+
+Revision 1.97  2009/02/02 22:13:01  cheshire
+Added SystemWakeForNetworkAccessEnabled setting
+
+Revision 1.96  2009/01/17 04:13:57  cheshire
+Added version symbols for Cheetah and Puma
+
+Revision 1.95  2009/01/16 02:32:55  cheshire
+Added SysEventNotifier and SysEventKQueue in mDNS_PlatformSupport_struct
+
+Revision 1.94  2009/01/15 22:24:53  cheshire
+Removed unused ifa_name field from NetworkInterfaceInfoOSX_struct
+
+Revision 1.93  2008/12/10 19:30:01  cheshire
+Added symbolic names for the various OS X versions
+
+Revision 1.92  2008/10/31 23:49:38  mkrochma
+Increased sizecheck limit
+
+Revision 1.91  2008/10/31 22:48:27  cheshire
+Added SCPreferencesRef to mDNS_PlatformSupport_struct
+
+Revision 1.90  2008/10/30 01:04:35  cheshire
+Added WakeAtUTC and SleepTime fields to mDNS_PlatformSupport_struct
+
+Revision 1.89  2008/10/29 18:38:33  mcguire
+Increase sizecheck limits to account for CFRunLoop added to mDNS_PlatformSupport_struct in 64bit builds
+
+Revision 1.88  2008/10/28 20:33:56  cheshire
+Added CFRunLoopRef in mDNS_PlatformSupport_struct, to hold reference to our main thread's CFRunLoop
+
+Revision 1.87  2008/10/28 18:32:09  cheshire
+Added CFSocketRef and CFRunLoopSourceRef in NetworkInterfaceInfoOSX_struct
+
+Revision 1.86  2008/10/22 23:23:53  cheshire
+Moved definition of OSXVers from daemon.c into mDNSMacOSX.c
+
+Revision 1.85  2008/10/21 00:12:00  cheshire
+Added BPF-related fields in NetworkInterfaceInfoOSX_struct
+
+Revision 1.84  2008/10/14 20:20:44  cheshire
+Increase sizecheck limits to account for DNSQuestions added to NetworkInterfaceInfo_struct
+
+Revision 1.83  2008/10/07 21:41:57  mcguire
+Increase sizecheck limits to account for DNSQuestion added to NetworkInterfaceInfo_struct in 64bit builds
+
+Revision 1.82  2008/10/07 15:56:24  cheshire
+Increase sizecheck limits to account for DNSQuestion added to NetworkInterfaceInfo_struct
+
+Revision 1.81  2008/10/03 00:26:25  cheshire
+Export DictionaryIsEnabled() so it's callable from other files
+
+Revision 1.80  2008/10/02 22:47:01  cheshire
+<rdar://problem/6134215> Sleep Proxy: Mac with Internet Sharing should also offer Sleep Proxy service
+Added SCPreferencesRef so we can track whether Internet Sharing is on or off
+
 Revision 1.79  2008/07/30 00:55:56  mcguire
 <rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
 Additional fixes so that we know when a socket has been closed while in a loop reading from it
@@ -120,7 +198,9 @@ Revision 1.52  2006/01/05 21:41:49  cheshire
 #endif
 
 #include <SystemConfiguration/SystemConfiguration.h>
+#include <IOKit/pwr_mgt/IOPM.h>
 #include <IOKit/pwr_mgt/IOPMLib.h>
+#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include "mDNSEmbeddedAPI.h"  // for domain name structure
@@ -156,21 +236,25 @@ struct NetworkInterfaceInfoOSX_struct
        {
        NetworkInterfaceInfo     ifinfo;                        // MUST be the first element in this structure
        NetworkInterfaceInfoOSX *next;
-       mDNSu32                  Exists;                        // 1 = currently exists in getifaddrs list; 0 = doesn't
+       mDNS                    *m;
+       mDNSu8                   Exists;                        // 1 = currently exists in getifaddrs list; 0 = doesn't
                                                                                                // 2 = exists, but McastTxRx state changed
+       mDNSu8                   Flashing;                      // Set if interface appeared for less than 60 seconds and then vanished
+       mDNSu8                   Occulting;                     // Set if interface vanished for less than 60 seconds and then came back
        mDNSs32                  AppearanceTime;        // Time this interface appeared most recently in getifaddrs list
                                                                                                // i.e. the first time an interface is seen, AppearanceTime is set.
                                                                                                // If an interface goes away temporarily and then comes back then
                                                                                                // AppearanceTime is updated to the time of the most recent appearance.
        mDNSs32                  LastSeen;                      // If Exists==0, last time this interface appeared in getifaddrs list
-       mDNSBool                 Flashing;                      // Set if interface appeared for less than 60 seconds and then vanished
-       mDNSBool                 Occulting;                     // Set if interface vanished for less than 60 seconds and then came back
-       char                    *ifa_name;                      // Memory for this is allocated using malloc
        unsigned int             ifa_flags;
        struct in_addr           ifa_v4addr;
        mDNSu32                  scope_id;                      // interface index / IPv6 scope ID
        mDNSEthAddr              BSSID;                         // BSSID of 802.11 base station, if applicable
        u_short                  sa_family;
+       int                      BPF_fd;                        // -1 uninitialized; -2 requested BPF; -3 failed
+       u_int                    BPF_len;
+       CFSocketRef              BPF_cfs;
+       CFRunLoopSourceRef       BPF_rls;
        };
 
 struct mDNS_PlatformSupport_struct
@@ -189,19 +273,39 @@ struct mDNS_PlatformSupport_struct
        // See <rdar://problem/5124399> Not getting Keychain Changed events when enabling BTMM
        mDNSs32                  KeyChainBugTimer;
        mDNSs32                  KeyChainBugInterval;
-       
+
+       CFRunLoopRef             CFRunLoop;
        SCDynamicStoreRef        Store;
        CFRunLoopSourceRef       StoreRLS;
+       CFRunLoopSourceRef       PMRLS;
+       int                      SysEventNotifier;
+       KQueueEntry              SysEventKQueue;
        IONotificationPortRef    PowerPortRef;
        io_connect_t             PowerConnection;
        io_object_t              PowerNotifier;
-       mDNSs32                  SleepLimit;            // Set when we get kIOMessageSystemWillSleep notification
+#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+       IOPMConnection           IOPMConnection;
+#endif
+       SCPreferencesRef         SCPrefs;
        long                     SleepCookie;           // Cookie we need to pass to IOAllowPowerChange()
+       long                     WakeAtUTC;
+       mDNSs32                  RequestReSleep;
        pthread_mutex_t          BigMutex;
        mDNSs32                  BigMutexStartTime;
        int                                              WakeKQueueLoopFD;
        };
 
+extern int OfferSleepProxyService;
+extern int OSXVers;
+#define OSXVers_Base              4
+#define OSXVers_10_0_Cheetah      4
+#define OSXVers_10_1_Puma         5
+#define OSXVers_10_2_Jaguar       6
+#define OSXVers_10_3_Panther      7
+#define OSXVers_10_4_Tiger        8
+#define OSXVers_10_5_Leopard      9
+#define OSXVers_10_6_SnowLeopard 10
+
 extern int KQueueFD;
 
 extern void NotifyOfElusiveBug(const char *title, const char *msg);    // Both strings are UTF-8 text
@@ -216,6 +320,8 @@ extern int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *con
 extern void KQueueLock(mDNS *const m);
 extern void KQueueUnlock(mDNS *const m, const char const *task);
 
+extern mDNSBool DictionaryIsEnabled(CFDictionaryRef dict);
+
 // If any event takes more than WatchDogReportingThreshold milliseconds to be processed, we log a warning message
 // General event categories are:
 //  o Mach client request initiated / terminated
@@ -232,19 +338,15 @@ extern void KQueueUnlock(mDNS *const m, const char const *task);
 // what's causing the problem, we may need to subdivide some categories into finer-grained
 // sub-categories (e.g. "Idle task processing" covers a pretty broad range of sub-tasks).
 
-#if LogAllOperations
-#define WatchDogReportingThreshold 50
-#else
-#define WatchDogReportingThreshold 250
-#endif
+extern int WatchDogReportingThreshold;
 
 struct CompileTimeAssertionChecks_mDNSMacOSX
        {
        // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
        // other overly-large structures instead of having a pointer to them, can inadvertently
        // cause structure sizes (and therefore memory usage) to balloon unreasonably.
-       char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <=  4456) ? 1 : -1];
-       char sizecheck_mDNS_PlatformSupport   [(sizeof(mDNS_PlatformSupport)    <=   368) ? 1 : -1];
+       char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <=  7000) ? 1 : -1];
+       char sizecheck_mDNS_PlatformSupport   [(sizeof(mDNS_PlatformSupport)    <=   476) ? 1 : -1];
        };
 
 #ifdef  __cplusplus
index a0cc39d3602a9a9fe4b6f9881e0298618b55e9e2..bb130ffd450dc1368888d3b47c17b42254e679f9 100644 (file)
-start
 _start
-_dyld_func_lookup
-main
-LogMsg
-mDNS_vsnprintf
-WriteLogMsg
-LogMsgIdent
-KQueueSet
-mDNSMacOSXSystemBuildNumber
-mDNS_Init
-mDNSPlatformTimeInit
-mDNSRandom
-mDNSPlatformRandomSeed
-mDNSPlatformRawTime
-mDNSPlatformInit
-GetUserSpecifiedLocalHostName
-mDNS_snprintf
-SetupSocket
-UpdateInterfaceList
-myGetIfAddrs
-AddInterfaceToList
-SetupAddr
-mDNSSameAddress
-mDNS_SetFQDN
-AppendDomainLabel
-AppendLiteralLabelString
-SameDomainNameCS
-mDNS_Lock
-mDNSPlatformLock
-DomainNameLengthLimit
-mDNSPlatformMemCopy
-mDNS_Unlock
-mDNSPlatformUnlock
-SetupActiveInterfaces
-mDNS_RegisterInterface
-AdvertiseInterface
-mDNS_SetupResourceRecord
-MakeDomainNameFromDNSNameString
-AppendDNSNameString
-mDNS_Register_internal
-InitializeLastAPTime
-SetNextAnnounceProbeTime
-GetRDLength
-ValidateRData
-DomainNameHashValue
-RDataHashValue
-SetTargetToHostName
-SameDomainName
-SetNewRData
-CompressedDomainNameLength
-AcknowledgeRecord
-IdenticalResourceRecord
-SetDomainSecrets
-mDNSKeychainGetSecrets
-getHelperPort
-proxy_mDNSKeychainGetSecrets
-mDNSDynamicStoreSetConfig
-proxy_mDNSDynamicStoreSetConfig
-mDNSCoreInitComplete
-mDNS_StatusCallback
-mDNSPlatformMemSame
-uDNS_SetupDNSConfig
-mDNSPlatformSetDNSConfig
-dns_configuration_copy
-_dns_configuration_server_port
-shared_dns_infoGet
-dns_configuration_free
-mDNSPlatformGetPrimaryInterface
-mDNS_SetPrimaryInterfaceInfo
-udsserver_init
-mDNSPlatformMemZero
-mDNSPlatformStrCopy
-udsSupportAddFDToEventLoop
-mDNS_GetDomains
-AppendDomainName
-mDNS_StartQuery
-mDNS_StartQuery_internal
-CheckForSoonToExpireRecords
-FindDuplicateQuestion
-GetAuthInfoForName
-RegisterLocalOnlyDomainEnumPTR
-mDNSPlatformMemAllocate
-mDNS_Register
-AddAutoBrowseDomain
-udsserver_automatic_browse_domain_changed
-machserver_automatic_browse_domain_changed
-udsserver_handle_configchange
-UpdateDeviceInfoRecord
-KQueueLoop
-mDNS_TimeNow
-mDNS_Execute
-uDNS_Execute
-mDNSv4AddrIsRFC1918
-udsserver_idle
-NetworkChanged
-KQueueLock
-KQueueUnlock
-KQWokenFlushBytes
-connect_callback
-NewRequest
-request_callback
-read_msg
-ConvertHeaderBytes
-handle_enum_request
-get_uint32
-mDNSPlatformInterfaceIDfromInterfaceIndex
-uDNS_RegisterSearchDomains
-put_uint32
-send_all
-mDNSMacOSXNetworkChanged
-ClearInactiveInterfaces
-GetFirstActiveInterface
-InitializeDNSMessage
-putQuestion
-putDomainNameAsLabels
-FindCompressionPointer
-PutResourceRecordTTLWithLimit
-putRData
-mDNSSendDNSMessage
-mDNSPlatformSendUDP
-mDNSAddrIsDNSMulticast
-myKQSocketCallBack
-mDNSCoreReceive
-AddressIsLocalSubnet
-getQuestion
-getDomainName
-ResourceRecordAnswersQuestion
-LocateAuthorities
-GetLargeResourceRecord
-PacketRRConflict
-SameRData
-SameRDataBody
-AddAdditionalsToResponseList
-SendResponses
-mDNSCoreReceiveResponse
-uDNS_recvLLQResponse
-LocateAnswers
-CreateNewCacheEntry
-GetCacheEntity
-SetNextCacheCheckTime
-CacheRecordDeferredAdd
-IdenticalSameNameRecord
-mDNS_HostNameCallback
-SameResourceRecordSignature
-AnswerLocalQuestions
-AnswerLocalOnlyQuestionWithResourceRecord
-enum_result_callback
-ConvertDomainNameToCString_withescape
-ConvertDomainLabelToCString_withescape
-create_reply
-put_string
-CheckCacheExpiration
-AbortUnlinkAndFree
-abort_request
-enum_termination_callback
-mDNS_StopQuery
-mDNS_StopQuery_internal
-udsSupportRemoveFDFromEventLoop
-get_string
-ChopSubTypes
-add_domain_to_browser
-mDNS_StartBrowse
-ConstructServiceName
-IsLocalDomain
-GetNextActiveInterfaceID
-ReconfirmAntecedents
-mDNS_DeregisterInterface
-DeadvertiseInterface
-mDNS_Deregister_internal
-NumCacheRecordsForInterfaceID
-mDNS_UpdateLLQs
-SuspendLLQs
-RestartQueries
-mDNS_AddSearchDomain
-mDNS_NewMessageID
-GetServerForName
-ActivateUnicastQuery
-AddrRequiresPPPConnection
-mDNS_AddDNSServer
-SetExternalAddress
-UpdateSRVRecords
-ReleaseCacheRecord
-ReleaseCacheGroup
-uDNS_CheckCurrentQuestion
-NoTestQuery
-uDNS_ReceiveMsg
-GetLLQOptData
-LocateLLQOptData
-LocateAdditionals
-AnswerCurrentQuestionWithResourceRecord
-FoundInstance
-GenerateNTDResponse
-DeconstructServiceName
-mDNSPlatformInterfaceIndexfromInterfaceID
-get_uint16
-constructQueryMsg
-skipResourceRecord
-FoundDomain
-FreeARElemCallback
-SameNameRecordAnswersQuestion
-queryrecord_result_callback
-put_uint16
-queryrecord_termination_callback
-FoundStaticHostname
-AutomaticBrowseDomainChange
-FindIdenticalRecordInCache
-MakeDomainLabelFromLiteralString
-register_service_instance
-AllocateSubTypes
-mDNS_RegisterService
-ServiceCallback
-regservice_callback
-KeychainChanged
-mDNS_SetSecretForDomain
-DNSDigest_ConstructHMACKeyfromBase64
-StartGetZoneData
-GetZoneData_StartQuery
-AppendDNameListElem
-SetPrefsBrowseDomains
-udsserver_default_reg_domain_changed
-machserver_automatic_registration_domain_changed
-GetServiceTarget
-SetupLocalAutoTunnelInterface_internal
-mDNSAutoTunnelInterfaceUpDown
-proxy_mDNSAutoTunnelInterfaceUpDown
-mDNS_AddDynDNSHostName
-AdvertiseHostname
-mDNS_StartNATOperation_internal
-mDNSConfigureServer
-proxy_mDNSConfigureServer
-mDNSPlatformUDPSocket
-uDNS_SendNATMsg
-LNT_SendDiscoveryMsg
-uDNS_ReceiveNATPMPPacket
-natTraversalHandleAddressReply
-hostnameGetPublicAddressCallback
-natTraversalHandlePortMapReply
-AutoTunnelNATCallback
-GetZoneData_QuestionCallback
-startLLQHandshakeCallback
-startLLQHandshake
-StartLLQNatMap
-mDNSPlatformMemFree
-RecordRegistrationCallback
-sendRecordRegistration
-putZone
-putDeleteRRSet
-putUpdateLease
-MakeTCPConn
-mDNSPlatformTCPSocket
-mDNSPlatformTCPConnect
-tcpKQSocketCallback
-tlsSetupSock
-tlsWriteSock
-tlsReadSock
-LLQNatMapComplete
-mDNS_GrowCache
-tcpCallback
-DNSDigest_SignMessage
-MD5_Update
-md5_block_host_order
-mDNSPlatformUTC
-MD5_Final
-mDNSPlatformWriteTCP
-putLLQ
-serviceRegistrationCallback
-SendServiceRegistration
-putPrereqNameNotInUse
-putEmptyResourceRecord
-mDNSPlatformReadTCP
-DisposeTCPConn
-mDNSPlatformTCPCloseConnection
-GetPktLease
-LocateLeaseOptData
-checkUpdateResult
-GetRRDisplayString_rdb
-startPrivateQueryCallback
-HostnameCallback
-UpdateSRV
-SendServiceDeregistration
-putDeleteAllRRSets
-putDeletionRecord
-StartSRVNatMap
-SameDomainLabel
-CompleteSRVNatMap
-PowerChanged
-mDNSCoreMachineSleep
-uDNS_Sleep
-sendLLQRefresh
-mDNS_StopNATOperation_internal
-mDNS_Reconfirm_internal
-mDNSRandomFromFixedSeed
-DeregisterLocalOnlyDomainEnumPTR
-mDNS_Deregister
-RmvAutoBrowseDomain
-uDNS_Wake
-uDNS_DeregisterRecord
-MakeNegativeCacheRecord
-CompleteDeregistration
-mDNSPlatformUDPClose
-CloseSocketSet
-CancelGetZoneData
-SendRecordDeregistration
-mDNSPlatformStrLen
-TruncateUTF8ToLength
-get_rdata
-mDNS_AddRecordToService
-update_record
-mDNS_Update
-CompleteRDataUpdate
-update_callback
-ShouldSuppressKnownAnswer
-handle_resolve_request
-resolve_result_callback
-put_rdata
-resolve_termination_callback
-regservice_termination_callback
-mDNS_DeregisterService
-browse_termination_callback
-free_service_instance
-FreeExtraRR
-SetNextQueryTime
-AddNewClientTunnel
-AutoTunnelCallback
-FindSourceAddrForIP
-AutoTunnelSetKeys
-mDNSAutoTunnelSetKeys
-proxy_mDNSAutoTunnelSetKeys
-ReissueBlockedQuestions
-read_rr_from_ipc_msg
-CountPeerRegistrations
-RecordUpdatedNiceLabel
-regrecord_callback
-handle_port_mapping_request
-mDNS_StartNATOperation
-port_mapping_create_request_callback
-DNSTypeName
-mDNS_StopQueryWithRemoves
-uDNS_StopLongLivedQuery
-uDNS_ReceiveSSDPPacket
-LNT_ConfigureRouterInfo
-MakeTCPConnection
-tcpConnectionCallback
-LNT_GetExternalAddress
-SendSOAPMsgControlAction
-LNT_MapPort
-LNT_UnmapPort
-PutResourceRecordCappedTTL
-connection_termination
-uDNS_DeregisterService
-SendServiceRemovalNotification
-mDNS_RemoveDynDNSHostName
-mDNS_StopNATOperation
-unlinkSRS
-DDNSSettingEnabled
-sendChallengeResponse
-mDNSPlatformDynDNSHostNameStatusChanged
-UnlinkAuthRecord
-DynDNSHostNameCallback
-port_mapping_termination_callback
-SendDelayedUnicastResponse
-RecordProbeFailure
-mDNS_RenameAndReregisterService
-IncrementLabelSuffix
-LabelContainsSuffix
-AppendLabelSuffix
+__start
+_dyld_stub_binding_helper
+__dyld_func_lookup
+_main
+_LogMsgWithLevel
+_mDNS_vsnprintf
+_mDNSPlatformWriteLogMsg
+_safe_vproc_transaction_begin
+_KQueueSet
+_mDNSMacOSXSystemBuildNumber
+_mDNSDaemonInitialize
+_mDNS_Init
+_mDNSPlatformTimeInit
+_mDNSRandom
+_mDNSPlatformRandomNumber
+_mDNSPlatformRawTime
+_mDNSPlatformInit
+_mDNS_snprintf
+_GetUserSpecifiedLocalHostName
+_SetupSocket
+_SystemWakeForNetworkAccess
+_UpdateInterfaceList
+_myGetIfAddrs
+_AddInterfaceToList
+_SetupAddr
+_NetWakeInterface
+_mDNS_SetFQDN
+_AppendDomainLabel
+_AppendLiteralLabelString
+_mDNS_Lock_
+_mDNSPlatformLock
+_SameDomainNameCS
+_DomainNameLengthLimit
+_mDNSPlatformMemCopy
+_mDNS_Unlock_
+_mDNSPlatformUnlock
+_SetupActiveInterfaces
+_SearchForInterfaceByName
+_mDNS_RegisterInterface
+_AdvertiseInterface
+_mDNS_SetupResourceRecord
+_MakeDomainNameFromDNSNameString
+_AppendDNSNameString
+_mDNS_Register_internal
+_InitializeLastAPTime
+_SetNextAnnounceProbeTime
+_GetRDLength
+_ValidateRData
+_DomainNameHashValue
+_RDataHashValue
+_SetTargetToHostName
+_SameDomainName
+_SetNewRData
+_CompressedDomainNameLength
+_AcknowledgeRecord
+_mDNS_StartBrowse_internal
+_ConstructServiceName
+_AppendDomainName
+_mDNS_StartQuery_internal
+_IsLocalDomain
+_CheckForSoonToExpireRecords
+_GetAuthInfoForQuestion
+_GetAuthInfoForName_internal
+_FindDuplicateQuestion
+_SetNextQueryTime
+_SetDomainSecrets
+_mDNSKeychainGetSecrets
+_getHelperPort
+_proxy_mDNSKeychainGetSecrets
+_mDNS_SetSecretForDomain
+_DNSDigest_ConstructHMACKeyfromBase64
+_mDNSPlatformMemZero
+_UpdateAutoTunnelDomainStatus
+_ConvertDomainLabelToCString_withescape
+_mDNSASLLog
+_mDNSDynamicStoreSetConfig
+_proxy_mDNSDynamicStoreSetConfig
+_ConvertDomainNameToCString_withescape
+_UpdateConfigureServer
+_TunnelServers
+_mDNSCoreInitComplete
+_mDNS_StatusCallback
+_mDNSPlatformMemSame
+_uDNS_SetupDNSConfig
+_mDNSPlatformSetDNSConfig
+_dns_configuration_copy
+___dns_initialize
+__dns_configuration_server_port
+_shared_dns_infoGet
+_CountLabels
+_SkipLeadingLabels
+_dns_configuration_free
+_mDNSPlatformGetPrimaryInterface
+_mDNS_SetPrimaryInterfaceInfo
+_udsserver_init
+_udsSupportAddFDToEventLoop
+_mDNS_GetDomains
+_mDNS_StartQuery
+_RegisterLocalOnlyDomainEnumPTR
+_mDNSPlatformMemAllocate
+_mDNS_Register
+_AddAutoBrowseDomain
+_udsserver_automatic_browse_domain_changed
+_machserver_automatic_browse_domain_changed
+_udsserver_handle_configchange
+_UpdateDeviceInfoRecord
+_AppendDNameListElem
+_SetPrefsBrowseDomains
+_udsserver_default_reg_domain_changed
+_machserver_automatic_registration_domain_changed
+_mDNSMacOSXNetworkChanged
+_mDNSSameAddress
+_ClearInactiveInterfaces
+_mDNSCoreBeSleepProxyServer
+_mDNS_ConfigChanged
+_mDNSPreferencesSetName
+_proxy_mDNSPreferencesSetName
+_SameRDataBody
+_DeregisterLocalOnlyDomainEnumPTR
+_mDNS_Deregister
+_mDNS_Deregister_internal
+_mDNSPlatformMemFree
+_RmvAutoBrowseDomain
+_KQueueLoop
+_mDNS_TimeNow
+_mDNS_Execute
+_SendQueries
+_GetFirstActiveInterface
+_InitializeDNSMessage
+_uDNS_Execute
+_mDNSv4AddrIsRFC1918
+_udsserver_idle
+_connect_callback
+_NewRequest
+_request_callback
+_ConvertHeaderBytes
+_handle_regservice_request
+_get_uint32
+_mDNSPlatformInterfaceIDfromInterfaceIndex
+_get_string
+_mDNSPlatformStrCopy
+_get_uint16
+_ChopSubTypes
+_AuthorizedDomain
+_register_service_instance
+_AllocateSubTypes
+_mDNS_RegisterService
+_ServiceCallback
+_GetServiceTarget
+_SetupLocalAutoTunnelInterface_internal
+_mDNSAutoTunnelInterfaceUpDown
+_proxy_mDNSAutoTunnelInterfaceUpDown
+_NetworkChanged
+_KQueueLock
+_AbortDeregistration
+_mDNS_StartNATOperation_internal
+_put_uint32
+_send_all
+_uDNS_SendNATMsg
+_KQueueUnlock
+_KQWokenFlushBytes
+_handle_queryrecord_request
+_mDNS_NewMessageID
+_GetServerForName
+_ActivateUnicastQuery
+_LastLabel
+_SameDomainLabel
+_uDNS_CheckCurrentQuestion
+_CacheGroupForName
+_MakeNegativeCacheRecord
+_CreateNewCacheEntry
+_GetCacheEntity
+_ResourceRecordAnswersQuestion
+_SetNextCacheCheckTime
+_SameNameRecordAnswersQuestion
+_CheckCacheExpiration
+_CacheRecordDeferredAdd
+_AnswerCurrentQuestionWithResourceRecord
+_queryrecord_result_callback
+_create_reply
+_mDNSPlatformInterfaceIndexfromInterfaceID
+_put_string
+_put_uint16
+_abort_request
+_queryrecord_termination_callback
+_mDNS_StopQuery
+_mDNS_StopQuery_internal
+_putQuestion
+_putDomainNameAsLabels
+_FindCompressionPointer
+_GetNextActiveInterfaceID
+_PutResourceRecordTTLWithLimit
+_putRData
+_mDNSSendDNSMessage
+_putHINFO
+_mDNSPlatformSendUDP
+_mDNSAddrIsDNSMulticast
+_myKQSocketCallBack
+_mDNSCoreReceive
+_mDNSCoreReceiveQuery
+_AddressIsLocalSubnet
+_LocateOptRR
+_LocateAdditionals
+_LocateAuthorities
+_LocateAnswers
+_skipResourceRecord
+_getQuestion
+_getDomainName
+_GetLargeResourceRecord
+_PacketRRConflict
+_AddAdditionalsToResponseList
+_mDNS_HostNameCallback
+_regservice_callback
+_GenerateNTDResponse
+_DeconstructServiceName
+_CountPeerRegistrations
+_RecordUpdatedNiceLabel
+_ClearProxyRecords
+_SendResponses
+_uDNS_recvLLQResponse
+_AnswerAllLocalQuestionsWithLocalAuthRecord
+_handle_regrecord_request
+_read_rr_from_ipc_msg
+_get_rdata
+_regrecord_callback
+_StartGetZoneData
+_GetZoneData_StartQuery
+_SetRecordRetry
+_GetZoneData_QuestionCallback
+_RecordRegistrationGotZoneData
+_SameResourceRecordSignature
+_FindIdenticalRecordInCache
+_mDNS_GrowCache
+_ShouldSuppressKnownAnswer
+_AutoTunnelNATCallback
+_RegisterAutoTunnelRecords
+_SysEventCallBack
+_UpdateSRVRecords
+_UpdateSRV
+_mDNS_DeregisterInterface
+_mDNS_PurgeCacheResourceRecord
+_DeadvertiseInterface
+_NumCacheRecordsForInterfaceID
+_AddrRequiresPPPConnection
+_mDNS_AddDNSServer
+_PurgeOrReconfirmCacheRecord
+_LNT_ClearState
+_UpdateAutoTunnelDomainStatuses
+_ReleaseCacheGroup
+_mDNS_AddDynDNSHostName
+_AdvertiseHostname
+_mDNSConfigureServer
+_mDNSPlatformStrLen
+_proxy_mDNSConfigureServer
+_CancelGetZoneData
+_mDNSPlatformUDPSocket
+_uDNS_ReceiveMsg
+_GetLLQOptData
+_ExpectingUnicastResponseForQuestion
+_UpdateSPSStatus
+_SPSStatusPutNumber
+_mDNSPlatformUDPClose
+_CloseSocketSet
+_SendRecordRegistration
+_putZone
+_putUpdateLease
+_MakeTCPConn
+_mDNSPlatformTCPSocket
+_mDNSPlatformTCPConnect
+_putDeleteRRSet
+_ServiceRegistrationGotZoneData
+_SendServiceRegistration
+_tcpKQSocketCallback
+_tlsSetupSock
+_doSSLHandshake
+_tlsWriteSock
+_tlsReadSock
+_tcpCallback
+_GetAuthInfoForName
+_DNSDigest_SignMessage
+_MD5_Update
+_md5_block_data_order
+_md5_block_host_order
+_mDNSPlatformUTC
+_MD5_Final
+_mDNSPlatformWriteTCP
+_mDNSPlatformReadTCP
+_DisposeTCPConn
+_mDNSPlatformTCPCloseConnection
+_GetPktLease
+_checkUpdateResult
+_HostnameCallback
+_AutoTunnelRecordCallback
+_handle_getproperty_request
+_AbortUnlinkAndFree
+_udsSupportRemoveFDFromEventLoop
+_handle_browse_request
+_add_domain_to_browser
+_mDNS_StartBrowse
+_ReconfirmAntecedents
+_FoundInstance
+_connection_termination
+_startLLQHandshake
+_LLQNATCallback
+_uDNS_RegisterSearchDomains
+_mDNS_AddSearchDomain
+_AnswerLocalQuestionWithLocalAuthRecord
+_enum_result_callback
+_LLQGotZoneData
+_GetLLQEventPort
+_mDNSPlatformSourceAddrForDest
+_putLLQ
+_SetLLQTimer
+_sendLLQRefresh
+_SendDelayedUnicastResponse
+_mDNS_Reconfirm_internal
index 8f8ab2c778c6a518f80e42898df384971cbf0fd2..b4a09226070863b26cbffcbfd44ae8451ded0a6a 100644 (file)
 ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ;
 ; $Log: mDNSResponder.sb,v $
-; Revision 1.25.2.1  2008/07/29 20:48:34  mcguire
-; <rdar://problem/6090007> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
-; merge r1.27 from <rdar://problem/3988320>
+; Revision 1.38  2009/04/16 16:03:08  mcguire
+; <rdar://problem/6792024> abort() causes high CPU usage instead of crash & restart
+;
+; Revision 1.37  2009/04/02 22:21:17  mcguire
+; <rdar://problem/6577409> Adopt IOPM APIs
+;
+; Revision 1.36  2009/03/02 01:32:20  mcguire
+; <rdar://problem/6623264> Seatbelt: Add rule to allow raw sockets
+;
+; Revision 1.35  2009/02/07 02:51:10  cheshire
+; <rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
+; Allow mDNSResponder to access IOPMConnection API
+;
+; Revision 1.34  2008/11/11 00:55:08  mcguire
+; <rdar://problem/6357957> sandbox: need to allow Mach port com.apple.system.DirectoryService.membership_v1
+;
+; Revision 1.33  2008/10/24 02:03:30  cheshire
+; So we can watch for Internet Sharing changes, allow read access to
+; /Library/Preferences/SystemConfiguration/com.apple.nat.plist
+;
+; Revision 1.32  2008/10/07 23:06:58  mcguire
+; <rdar://problem/6276444> Seatbelt: Policy denied Mach service lookup: com.apple.system.logger
+;
+; Revision 1.31  2008/09/24 23:57:27  mcguire
+; <rdar://problem/6227808> need read access to /private/var/db/crls/crlcache.db
+;
+; Revision 1.30  2008/09/11 22:01:51  mcguire
+; re-add accidentally removed log comment
+;
+; Revision 1.29  2008/09/11 20:46:08  mcguire
+; <rdar://problem/6208848> can't write to -Caches-
+;
+; Revision 1.28  2008/09/11 20:04:14  mcguire
+; <rdar://problem/6211355> Instances of \. in regex exprs don't do what is intended
+;
+; Revision 1.27  2008/07/24 21:18:14  cheshire
+; <rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+; Need to allow access to /dev/urandom
+;
+; Revision 1.26  2008/06/03 01:21:12  mcguire
+; <rdar://problem/5902470> add /var/db/mds to sb profile
 ;
 ; Revision 1.25  2008/03/17 18:04:41  mcguire
 ; <rdar://problem/5800476> SC now reads preference file
                                        "com.apple.bsd.dirhelper"
                                        "com.apple.distributed_notifications.2"
                                        "com.apple.ocspd"
+                                       "com.apple.PowerManagement.control"
                                        "com.apple.mDNSResponderHelper"
                                        "com.apple.SecurityServer"
                                        "com.apple.SystemConfiguration.configd"
                                        "com.apple.system.DirectoryService.libinfo_v1"
-                                       "com.apple.system.notification_center"))
+                                       "com.apple.system.DirectoryService.membership_v1"
+                                       "com.apple.system.notification_center"
+                                       "com.apple.system.logger"))
 
 ; Rules to allow the operations mDNSResponder needs start here
 
+(allow signal (target self))
 (allow network*)                       ; Allow networking, including Unix Domain Sockets
+(if (defined? 'system-socket)
+    (allow system-socket))  ; To create raw sockets
 (allow sysctl-read)                    ; To get hardware model information
 (allow file-read-metadata)     ; Needed for dyld to work
 (allow ipc-posix-shm)          ; Needed for POSIX shared memory
 
-(allow file-read-data                 (regex "^/dev/random\$"))
-(allow file-read-data file-write-data (regex "^/dev/console\$"))               ; Needed for syslog early in the boot process
-(allow file-read-data                 (regex "^/dev/autofs_nowait\$")) ; Used by CF to circumvent automount triggers
+(allow file-read-data                 (regex #"^/dev/random$"))
+(allow file-read-data file-write-data (regex #"^/dev/console$"))               ; Needed for syslog early in the boot process
+(allow file-read-data                 (regex #"^/dev/autofs_nowait$")) ; Used by CF to circumvent automount triggers
 
 ; Allow us to read and write our socket
-(allow file-read*     file-write*     (regex "^/private/var/run/mDNSResponder\$"))
+(allow file-read*     file-write*     (regex #"^/private/var/run/mDNSResponder$"))
 
 ; Allow us to read system version, settings, and other miscellaneous necessary file system accesses
-(allow file-read-data                 (regex "^/dev/urandom$"))
-(allow file-read-data                 (regex "^/usr/sbin(/mDNSResponder)?\$"))         ; Needed for CFCopyVersionDictionary()
-(allow file-read-data                 (regex "^/usr/share/icu/.*\$"))
-(allow file-read-data                 (regex "^/usr/share/zoneinfo/.*\$"))
-(allow file-read-data                 (regex "^/Library/Preferences/SystemConfiguration/preferences\.plist\$"))
-(allow file-read-data                 (regex "^/Library/Preferences/(ByHost/)?\.GlobalPreferences.*\.plist\$"))
-(allow file-read-data                 (regex "^/Library/Preferences/com\.apple\.security.*\.plist\$"))
-(allow file-read-data                 (regex "^/Library/Preferences/com\.apple\.crypto\.plist\$"))
-(allow file-read-data                 (regex "^/Library/Security/Trust Settings/Admin\.plist\$"))
-(allow file-read-data                 (regex "^/System/Library/CoreServices/SystemVersion.*\$"))
-(allow file-read-data                 (regex "^/System/Library/Preferences/com\.apple\.security.*\.plist\$"))
-(allow file-read-data                 (regex "^/System/Library/Preferences/com\.apple\.crypto\.plist\$"))
+(allow file-read-data                 (regex #"^/dev/urandom$"))
+(allow file-read-data                 (regex #"^/usr/sbin(/mDNSResponder)?$"))         ; Needed for CFCopyVersionDictionary()
+(allow file-read-data                 (regex #"^/usr/share/icu/.*$"))
+(allow file-read-data                 (regex #"^/usr/share/zoneinfo/.*$"))
+(allow file-read-data                 (regex #"^/Library/Preferences/SystemConfiguration/preferences\.plist$"))
+(allow file-read-data                 (regex #"^/Library/Preferences/SystemConfiguration/com\.apple\.nat\.plist$"))
+(allow file-read-data                 (regex #"^/Library/Preferences/(ByHost/)?\.GlobalPreferences.*\.plist$"))
+(allow file-read-data                 (regex #"^/Library/Preferences/com\.apple\.security.*\.plist$"))
+(allow file-read-data                 (regex #"^/Library/Preferences/com\.apple\.crypto\.plist$"))
+(allow file-read-data                 (regex #"^/Library/Security/Trust Settings/Admin\.plist$"))
+(allow file-read-data                 (regex #"^/System/Library/CoreServices/SystemVersion.*$"))
+(allow file-read-data                 (regex #"^/System/Library/Preferences/com\.apple\.security.*\.plist$"))
+(allow file-read-data                 (regex #"^/System/Library/Preferences/com\.apple\.crypto\.plist$"))
+(allow file-read-data                 (regex #"^/System/Library/SystemConfiguration/PowerManagement\.bundle(/|$)"))
+(allow file-read-data                 (regex #"^/Library/Preferences/SystemConfiguration/com\.apple\.PowerManagement\.plist$"))
 
 ; Allow access to System Keychain
-(allow file-read-data                 (regex "^/System/Library/Security\$"))
-(allow file-read-data                 (regex "^/System/Library/Keychains/.*\$"))
-(allow file-read-data                 (regex "^/Library/Keychains/System\.keychain\$"))
+(allow file-read-data                 (regex #"^/System/Library/Security$"))
+(allow file-read-data                 (regex #"^/System/Library/Keychains/.*$"))
+(allow file-read-data                 (regex #"^/Library/Keychains/System\.keychain$"))
 ; Our Module Directory Services cache
-(allow file-read-data                 (regex "^/private/var/tmp/mds/"))
-(allow file-read* file-write*         (regex "^/private/var/tmp/mds/[0-9]+(/|\$)"))
-
+(allow file-read-data                 (regex #"^/private/var/tmp/mds/"))
+(allow file-read* file-write*         (regex #"^/private/var/tmp/mds/[0-9]+(/|$)"))
+(allow file-read-data                 (regex #"^/private/var/db/mds/"))
+(allow file-read* file-write*         (regex #"^/private/var/db/mds/[0-9]+(/|$)"))
+(allow file-read* file-write*         (regex #"^/private/var/folders/[^/]+/[^/]+/-Caches-/mds(/|$)"))
+; CRL Cache for SSL/TLS connections
+(allow file-read-data                 (regex #"^/private/var/db/crls/crlcache\.db$"))
index cb961b86ca9d350a2be42a521370f8aad6db03c4..cb3660f20be5417c1bc07cb79555cd504ae446cc 100644 (file)
@@ -19,7 +19,6 @@
                                D284BF300ADD81630027CCDF /* PBXTargetDependency */,
                                D284BF260ADD814F0027CCDF /* PBXTargetDependency */,
                                D284BF2A0ADD81530027CCDF /* PBXTargetDependency */,
-                               FFD41DDB0664169900F0C438 /* PBXTargetDependency */,
                        );
                        name = "Build More";
                        productName = "Build All";
                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 */; };
-               4A8202650C56C4C900DDFD48 /* pfkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A8202530C56C36600DDFD48 /* pfkey.c */; };
                4AAE0C9A0C68EA81003882A5 /* mDNSResponderHelper.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */; };
+               4AE9B04B0F39448B0080B59D /* safe_vproc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4AE9B0480F39448B0080B59D /* safe_vproc.c */; };
+               4AE9B04C0F39448B0080B59D /* safe_vproc.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AE9B0490F39448B0080B59D /* safe_vproc.h */; };
+               4AE9B0920F3A52A10080B59D /* safe_vproc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4AE9B0480F39448B0080B59D /* safe_vproc.c */; };
+               4AE9B0930F3A52A20080B59D /* safe_vproc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4AE9B0480F39448B0080B59D /* safe_vproc.c */; };
+               4AE9B0940F3A52AE0080B59D /* safe_vproc.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AE9B0490F39448B0080B59D /* safe_vproc.h */; };
+               4AE9B0950F3A52AE0080B59D /* safe_vproc.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AE9B0490F39448B0080B59D /* safe_vproc.h */; };
                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, ); }; };
                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 */; };
-               D284C04E0ADD95D30027CCDF /* Info-PreferencePane.plist in Resources */ = {isa = PBXBuildFile; fileRef = D284C04D0ADD95D30027CCDF /* Info-PreferencePane.plist */; };
-               DB2CC4560662DE4500335AB3 /* BaseListener.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC4430662DD1100335AB3 /* BaseListener.java */; };
-               DB2CC4570662DE4600335AB3 /* BrowseListener.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC4440662DD1100335AB3 /* BrowseListener.java */; };
-               DB2CC4580662DE4700335AB3 /* DNSRecord.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC4450662DD1100335AB3 /* DNSRecord.java */; };
-               DB2CC4590662DE4700335AB3 /* DNSSD.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC4460662DD1100335AB3 /* DNSSD.java */; };
-               DB2CC45A0662DE4800335AB3 /* DNSSDException.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC4470662DD1100335AB3 /* DNSSDException.java */; };
-               DB2CC45B0662DE4900335AB3 /* DNSSDRegistration.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC4480662DD1100335AB3 /* DNSSDRegistration.java */; };
-               DB2CC45C0662DE4900335AB3 /* DNSSDService.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC4490662DD1100335AB3 /* DNSSDService.java */; };
-               DB2CC45D0662DE4A00335AB3 /* DomainListener.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC44A0662DD1100335AB3 /* DomainListener.java */; };
-               DB2CC45E0662DE4B00335AB3 /* QueryListener.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC44C0662DD1100335AB3 /* QueryListener.java */; };
-               DB2CC45F0662DE4C00335AB3 /* RegisterListener.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC44D0662DD1100335AB3 /* RegisterListener.java */; };
-               DB2CC4600662DE4C00335AB3 /* ResolveListener.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC44E0662DD1100335AB3 /* ResolveListener.java */; };
-               DB2CC4610662DE4D00335AB3 /* TXTRecord.java in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC44F0662DD1100335AB3 /* TXTRecord.java */; };
-               FF2C5FB10A48B8680066DA11 /* DNSSDRecordRegistrar.java in Sources */ = {isa = PBXBuildFile; fileRef = FF2C5FB00A48B8680066DA11 /* DNSSDRecordRegistrar.java */; };
-               FF2C5FB30A48B86E0066DA11 /* RegisterRecordListener.java in Sources */ = {isa = PBXBuildFile; fileRef = FF2C5FB20A48B86E0066DA11 /* RegisterRecordListener.java */; };
                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 */; };
                FFA5724B0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
                FFA572610AF190940055A0F1 /* DNSServiceDiscovery.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = FFA572600AF1908D0055A0F1 /* DNSServiceDiscovery.h */; };
                FFA572640AF190C80055A0F1 /* dns_sd.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = FFA572630AF190C20055A0F1 /* dns_sd.h */; };
+               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 */; };
                        remoteGlobalIDString = 03067D640C83A3700022BE1F;
                        remoteInfo = "Build Some";
                };
-               D284BDEA0ADD77F60027CCDF /* PBXContainerItemProxy */ = {
+               4AE471690EAFF83800A6C5AD /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = DB2CC4530662DD6800335AB3;
-                       remoteInfo = dns_sd.jar;
-               };
-               D284BEB40ADD809A0027CCDF /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = DB2CC4530662DD6800335AB3;
+                       remoteGlobalIDString = 4AE471670EAFF81900A6C5AD;
                        remoteInfo = dns_sd.jar;
                };
                D284BF250ADD814F0027CCDF /* PBXContainerItemProxy */ = {
                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; };
+               4AE9B0480F39448B0080B59D /* safe_vproc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = safe_vproc.c; sourceTree = "<group>"; };
+               4AE9B0490F39448B0080B59D /* safe_vproc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = safe_vproc.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>"; };
                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 /* libdns_sd_debug.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdns_sd_debug.a; sourceTree = BUILT_PRODUCTS_DIR; };
                FFA572450AF18F450055A0F1 /* libdns_sd_profile.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdns_sd_profile.a; sourceTree = BUILT_PRODUCTS_DIR; };
                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 /* libdns_sd.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdns_sd.a; 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; };
-               FFD41DDA0664157900F0C438 /* dns_sd.jar */ = {isa = PBXFileReference; explicitFileType = archive.jar; includeInIndex = 0; path = dns_sd.jar; sourceTree = BUILT_PRODUCTS_DIR; };
                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; };
                        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 */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               DB2CC4520662DD6800335AB3 /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                FFA572360AF18F1C0055A0F1 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                08FB7795FE84155DC02AAC07 /* mDNS Server Sources */ = {
                        isa = PBXGroup;
                        children = (
+                               4AE9B0480F39448B0080B59D /* safe_vproc.c */,
+                               4AE9B0490F39448B0080B59D /* safe_vproc.h */,
                                4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */,
                                2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */,
                                2E35528F0C3A95C100CA1CB7 /* helper-error.h */,
                        isa = PBXGroup;
                        children = (
                                D284C04D0ADD95D30027CCDF /* Info-PreferencePane.plist */,
-                               FFD41DDA0664157900F0C438 /* dns_sd.jar */,
                                D284BE730ADD80740027CCDF /* mDNSResponder */,
                                D284BE950ADD80800027CCDF /* mDNSResponder.debug */,
                                D284BEA30ADD808B0027CCDF /* mDNS */,
                        children = (
                                6575FC20022EB7AA00000109 /* SamplemDNSClient.c */,
                                FF1C919F07021E3F001048AB /* dns-sd.c */,
+                               FF5852100DD27BD300862BDF /* ClientCommon.c */,
                        );
                        name = "Command-Line Clients";
                        sourceTree = "<group>";
                                2ECC11A80C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
                                2E8165E80C5980E300485EB2 /* libpfkey.h in Headers */,
                                2E8165EA0C5980F700485EB2 /* ipsec_strerror.h in Headers */,
+                               4AE9B04C0F39448B0080B59D /* safe_vproc.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                2EDC5E750C39EA640092701B /* helper-server.h in Headers */,
                                2E3552900C3A95C100CA1CB7 /* helper-error.h in Headers */,
                                2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
+                               4AE9B0950F3A52AE0080B59D /* safe_vproc.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                2EDC5E740C39EA640092701B /* helper-server.h in Headers */,
                                2E3552910C3A95C100CA1CB7 /* helper-error.h in Headers */,
                                2ECC11A70C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
+                               4AE9B0940F3A52AE0080B59D /* safe_vproc.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                };
 /* End PBXHeadersBuildPhase section */
 
-/* Begin PBXJavaArchiveBuildPhase section */
-               DB2CC4510662DD6800335AB3 /* JavaArchive */ = {
-                       isa = PBXJavaArchiveBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-/* End PBXJavaArchiveBuildPhase section */
-
-/* Begin PBXLibraryTarget section */
-               DB2CC4530662DD6800335AB3 /* dns_sd.jar */ = {
-                       isa = PBXLibraryTarget;
-                       buildConfigurationList = D284BE1C0ADD78180027CCDF /* Build configuration list for PBXLibraryTarget "dns_sd.jar" */;
+/* 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 = (
-                               DB2CC4500662DD6800335AB3 /* Sources */,
-                               DB2CC4510662DD6800335AB3 /* JavaArchive */,
-                               DB2CC4520662DD6800335AB3 /* Frameworks */,
-                               DB2CC4550662DE1700335AB3 /* ShellScript */,
-                               FFD41DDD06641B4200F0C438 /* ShellScript */,
                        );
+                       buildToolPath = /usr/bin/make;
+                       buildWorkingDirectory = "";
                        comments = "Multiplatform .jar file that implements Java interface to DNS-SD";
                        dependencies = (
                        );
                        name = dns_sd.jar;
-                       productInstallPath = /System/Library/Java/Extensions;
+                       passBuildSettingsInEnvironment = 1;
                        productName = dns_sd.jar;
-                       productReference = FFD41DDA0664157900F0C438 /* dns_sd.jar */;
                };
-/* End PBXLibraryTarget section */
+/* End PBXLegacyTarget section */
 
 /* Begin PBXNativeTarget section */
                2E0405EF0C31955500F13B59 /* mDNSResponderHelper */ = {
                        );
                        comments = "Platform-specific JNI library that bridges dns_sd.jar to <dns_sd.h>.";
                        dependencies = (
-                               D284BEB30ADD809A0027CCDF /* PBXTargetDependency */,
+                               4AE4716A0EAFF83800A6C5AD /* PBXTargetDependency */,
                        );
                        name = libjdns_sd.jnilib;
                        productInstallPath = /usr/lib/java;
                        isa = PBXNativeTarget;
                        buildConfigurationList = D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */;
                        buildPhases = (
-                               030BBF010CE13A2800472F0C /* ShellScript */,
                                D284BEC20ADD80A20027CCDF /* Headers */,
                                D284BEC40ADD80A20027CCDF /* Sources */,
                                D284BECE0ADD80A20027CCDF /* Frameworks */,
                                2E0405EF0C31955500F13B59 /* mDNSResponderHelper */,
                                D284BE970ADD808B0027CCDF /* mDNS tool */,
                                D284BEA50ADD80920027CCDF /* dns-sd tool */,
-                               DB2CC4530662DD6800335AB3 /* dns_sd.jar */,
+                               4AE471670EAFF81900A6C5AD /* dns_sd.jar */,
                                D284BEB20ADD809A0027CCDF /* libjdns_sd.jnilib */,
                                D284BEBF0ADD80A20027CCDF /* dnsextd */,
                                D284BEDB0ADD80A70027CCDF /* ddnswriteconfig */,
                                D284BEF90ADD80B00027CCDF /* InfoPlist.strings in Resources */,
                                D284BEFB0ADD80B00027CCDF /* inprogress.tiff in Resources */,
                                D284BEFC0ADD80B00027CCDF /* installtool in Resources */,
-                               D284C04E0ADD95D30027CCDF /* Info-PreferencePane.plist in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        shellPath = /bin/sh;
                        shellScript = "if [ -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";
                };
-               030BBF010CE13A2800472F0C /* ShellScript */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       inputPaths = (
-                       );
-                       outputPaths = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-                       shellPath = /bin/sh;
-                       shellScript = "rm -f \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\n";
-                       showEnvVarsInLog = 0;
-               };
                D284BE510ADD80740027CCDF /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        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";
+                       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";
                };
                D284BE6C0ADD80740027CCDF /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        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\"\ncc -arch i386 -arch ppc \"${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";
                };
-               DB2CC4550662DE1700335AB3 /* ShellScript */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 12;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-                       shellPath = /bin/sh;
-                       shellScript = "javah -force -J-Xbootclasspath/p:${CONFIGURATION_TEMP_DIR}/dns_sd.jar.build/JavaClasses -o ${CONFIGURATION_TEMP_DIR}/dns_sd.jar.build/DNSSD.java.h com.apple.dnssd.AppleDNSSD com.apple.dnssd.AppleBrowser com.apple.dnssd.AppleResolver com.apple.dnssd.AppleRegistration com.apple.dnssd.AppleQuery com.apple.dnssd.AppleDomainEnum com.apple.dnssd.AppleService com.apple.dnssd.AppleDNSRecord com.apple.dnssd.AppleRecordRegistrar";
-               };
                FF045B6A0C7E4AA600448140 /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 8;
                        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";
                };
-               FFD41DDD06641B4200F0C438 /* ShellScript */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-                       shellPath = /bin/sh;
-                       shellScript = "rm -f ${CONFIGURATION_BUILD_DIR}/dns_sd";
-               };
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
                                2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */,
                                2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */,
                                2E8165E90C5980EE00485EB2 /* pfkey.c in Sources */,
+                               4AE9B04B0F39448B0080B59D /* safe_vproc.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                D284BE630ADD80740027CCDF /* daemon.c in Sources */,
                                2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */,
                                2E96A5320C39C1A50087C4D2 /* helper-stubs.c in Sources */,
+                               4AE9B0930F3A52A20080B59D /* safe_vproc.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                D284BE8B0ADD80800027CCDF /* daemon.c in Sources */,
                                2E0406200C3198B700F13B59 /* helpermsg.defs in Sources */,
                                2E96A5300C39C1A50087C4D2 /* helper-stubs.c in Sources */,
+                               4AE9B0920F3A52A10080B59D /* safe_vproc.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        buildActionMask = 2147483647;
                        files = (
                                D284BEA80ADD80920027CCDF /* dns-sd.c in Sources */,
+                               FFF589B70E37F66800EF515C /* ClientCommon.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                D284BECD0ADD80A20027CCDF /* PlatformCommon.c in Sources */,
                                2EAE955A0C31F4D30021F738 /* helpermsg.defs in Sources */,
                                2E35529E0C3A9E7600CA1CB7 /* helper-stubs.c in Sources */,
-                               4A8202650C56C4C900DDFD48 /* pfkey.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                D284BEFE0ADD80B00027CCDF /* DNSServiceDiscoveryPref.m in Sources */,
                                D284BEFF0ADD80B00027CCDF /* PrivilegedOperations.c in Sources */,
                                D284BF000ADD80B00027CCDF /* ConfigurationAuthority.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               DB2CC4500662DD6800335AB3 /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               DB2CC4560662DE4500335AB3 /* BaseListener.java in Sources */,
-                               DB2CC4570662DE4600335AB3 /* BrowseListener.java in Sources */,
-                               DB2CC4580662DE4700335AB3 /* DNSRecord.java in Sources */,
-                               DB2CC4590662DE4700335AB3 /* DNSSD.java in Sources */,
-                               DB2CC45A0662DE4800335AB3 /* DNSSDException.java in Sources */,
-                               DB2CC45B0662DE4900335AB3 /* DNSSDRegistration.java in Sources */,
-                               DB2CC45C0662DE4900335AB3 /* DNSSDService.java in Sources */,
-                               DB2CC45D0662DE4A00335AB3 /* DomainListener.java in Sources */,
-                               DB2CC45E0662DE4B00335AB3 /* QueryListener.java in Sources */,
-                               DB2CC45F0662DE4C00335AB3 /* RegisterListener.java in Sources */,
-                               DB2CC4600662DE4C00335AB3 /* ResolveListener.java in Sources */,
-                               DB2CC4610662DE4D00335AB3 /* TXTRecord.java in Sources */,
-                               FF2C5FB10A48B8680066DA11 /* DNSSDRecordRegistrar.java in Sources */,
-                               FF2C5FB30A48B86E0066DA11 /* RegisterRecordListener.java in Sources */,
+                               FFF589C10E37F67E00EF515C /* ClientCommon.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        target = 03067D640C83A3700022BE1F /* Build Some */;
                        targetProxy = 03067D850C849CC30022BE1F /* PBXContainerItemProxy */;
                };
-               D284BEB30ADD809A0027CCDF /* PBXTargetDependency */ = {
+               4AE4716A0EAFF83800A6C5AD /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = DB2CC4530662DD6800335AB3 /* dns_sd.jar */;
-                       targetProxy = D284BEB40ADD809A0027CCDF /* PBXContainerItemProxy */;
+                       target = 4AE471670EAFF81900A6C5AD /* dns_sd.jar */;
+                       targetProxy = 4AE471690EAFF83800A6C5AD /* PBXContainerItemProxy */;
                };
                D284BF260ADD814F0027CCDF /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 00AD62BB032D7A0C0CCA2C71 /* Build More */;
                        targetProxy = FFB7657C0AEED97F00583A2C /* PBXContainerItemProxy */;
                };
-               FFD41DDB0664169900F0C438 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = DB2CC4530662DD6800335AB3 /* dns_sd.jar */;
-                       targetProxy = D284BDEA0ADD77F60027CCDF /* PBXContainerItemProxy */;
-               };
 /* End PBXTargetDependency section */
 
 /* Begin PBXVariantGroup section */
                                CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)";
                                COPY_PHASE_STRIP = NO;
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                GCC_WARN_CHECK_SWITCH_STATEMENTS = NO;
                                HEADER_SEARCH_PATHS = "${CONFIGURATION_TEMP_DIR}";
                                INSTALL_PATH = /usr/sbin;
                        };
                        name = Development;
                };
-               D284BE1D0ADD78180027CCDF /* Development */ = {
+               4AE471680EAFF81900A6C5AD /* Development */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-                               CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-                               DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 1;
+                               COPY_PHASE_STRIP = NO;
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
-                               GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-                               INSTALL_PATH = "${SYSTEM_LIBRARY_DIR}/Java/Extensions";
-                               JAVA_ARCHIVE_CLASSES = YES;
-                               JAVA_ARCHIVE_COMPRESSION = YES;
-                               JAVA_ARCHIVE_TYPE = JAR;
-                               JAVA_COMPILER_DEBUGGING_SYMBOLS = NO;
-                               JAVA_COMPILER_SOURCE_VERSION = 1.4;
-                               JAVA_COMPILER_TARGET_VM_VERSION = 1.4;
-                               JAVA_SOURCE_SUBDIR = .;
-                               LIBRARY_STYLE = STATIC;
-                               OTHER_CFLAGS = "";
-                               OTHER_LDFLAGS = "";
-                               OTHER_LIBTOOL_FLAGS = "";
-                               OTHER_REZFLAGS = "";
-                               PRODUCT_NAME = dns_sd;
-                               PURE_JAVA = YES;
-                               REZ_EXECUTABLE = YES;
-                               SECTORDER_FLAGS = "";
-                               STRIPFLAGS = "-S";
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               PRODUCT_NAME = dns_sd.jar;
                        };
                        name = Development;
                };
                                CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
                                CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                OTHER_CFLAGS = "";
                                OTHER_LDFLAGS = "";
                D284BE2C0ADD78180027CCDF /* Development */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
+                               DEAD_CODE_STRIPPING = YES;
                                GCC_PREPROCESSOR_DEFINITIONS = (
                                        "APPLE_OSX_mDNSResponder=1",
                                        "__MigTypeCheck=1",
                                );
                                GCC_TREAT_WARNINGS_AS_ERRORS = YES;
                                MVERS = "\"(Engineering Build)\"";
-                               OTHER_CFLAGS = "-DUSE_SYSTEMCONFIGURATION_PRIVATE_HEADERS";
+                               OTHER_CFLAGS = (
+                                       "-DUSE_SYSTEMCONFIGURATION_PRIVATE_HEADERS",
+                                       "-fwrapv",
+                               );
                                PREBINDING = NO;
+                               STRIP_STYLE = debugging;
                                WARNING_CFLAGS = (
                                        "-W",
                                        "-Wall",
                                CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
                                FRAMEWORK_SEARCH_PATHS = "";
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                HEADER_SEARCH_PATHS = (
                                        ../mDNSShared,
                                INSTALL_PATH = /usr/sbin;
                                LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
                                MACOSX_DEPLOYMENT_TARGET = 10.4;
+                               ORDER_FILE = "${SRCROOT}/mDNSResponder.order";
                                OTHER_CFLAGS = (
                                        "$(inherited)",
                                        "-no-cpp-precomp",
                                OTHER_REZFLAGS = "";
                                PRODUCT_NAME = mDNSResponder;
                                REZ_EXECUTABLE = YES;
-                               SECTORDER_FLAGS = (
-                                       "-sectorder",
-                                       __TEXT,
-                                       __text,
-                                       mDNSResponder.order,
-                               );
-                               STRIPFLAGS = "-S";
                        };
                        name = Development;
                };
                                        __text,
                                        mDNSResponder.order,
                                );
-                               STRIPFLAGS = "-S";
                        };
                        name = Development;
                };
                                CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
                                CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                INSTALL_PATH = /usr/bin;
                                MACOSX_DEPLOYMENT_TARGET = 10.4;
                                PRODUCT_NAME = mDNS;
                                REZ_EXECUTABLE = YES;
                                SECTORDER_FLAGS = "";
-                               STRIPFLAGS = "-S";
                        };
                        name = Development;
                };
                                CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
                                CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                HEADER_SEARCH_PATHS = ../mDNSShared;
                                INSTALL_PATH = /usr/bin;
                                PRODUCT_NAME = "dns-sd";
                                REZ_EXECUTABLE = YES;
                                SECTORDER_FLAGS = "";
-                               STRIPFLAGS = "-S";
                        };
                        name = Development;
                };
                                DYLIB_CURRENT_VERSION = 1;
                                EXECUTABLE_EXTENSION = jnilib;
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_ENABLE_FIX_AND_CONTINUE = 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",
-                                       "${CONFIGURATION_TEMP_DIR}/dns_sd.jar.build",
+                                       "${PROJECT_DERIVED_FILE_DIR}",
                                );
                                INSTALL_PATH = /usr/lib/java;
                                LIBRARY_STYLE = DYNAMIC;
                                PRODUCT_NAME = libjdns_sd;
                                REZ_EXECUTABLE = YES;
                                SECTORDER_FLAGS = "";
-                               STRIPFLAGS = "-S";
                        };
                        name = Development;
                };
                                CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
                                FRAMEWORK_SEARCH_PATHS = "";
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                HEADER_SEARCH_PATHS = (
                                        "${APPLE_INTERNAL_DEVELOPER_DIR}/Headers",
                                PRODUCT_NAME = dnsextd;
                                REZ_EXECUTABLE = YES;
                                SECTORDER_FLAGS = "";
-                               STRIPFLAGS = "-S";
                                YACC = "/usr/bin/bison -y";
                        };
                        name = Development;
                                CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
                                CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                INSTALL_PATH = "/Library/Application Support/Bonjour";
-                               MACOSX_DEPLOYMENT_TARGET = 10.4;
+                               MACOSX_DEPLOYMENT_TARGET = "";
                                OTHER_CFLAGS = "";
                                OTHER_LDFLAGS = "";
                                OTHER_REZFLAGS = "";
                                PRODUCT_NAME = ddnswriteconfig;
                                REZ_EXECUTABLE = YES;
                                SECTORDER_FLAGS = "";
-                               STRIPFLAGS = "-S";
                        };
                        name = Development;
                };
                                CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
                                EXPORTED_SYMBOLS_FILE = "";
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                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.4;
+                               MACOSX_DEPLOYMENT_TARGET = "";
                                OTHER_CFLAGS = "";
                                OTHER_LDFLAGS = "-twolevel_namespace";
                                OTHER_REZFLAGS = "";
                                PRODUCT_NAME = Bonjour;
                                SECTORDER_FLAGS = "";
-                               STRIPFLAGS = "-S";
                                WRAPPER_EXTENSION = prefPane;
                        };
                        name = Development;
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Development;
                };
-               D284BE1C0ADD78180027CCDF /* Build configuration list for PBXLibraryTarget "dns_sd.jar" */ = {
+               4AE471770EAFF84000A6C5AD /* Build configuration list for PBXLegacyTarget "dns_sd.jar" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               D284BE1D0ADD78180027CCDF /* Development */,
+                               4AE471680EAFF81900A6C5AD /* Development */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Development;
diff --git a/mDNSMacOSX/safe_vproc.c b/mDNSMacOSX/safe_vproc.c
new file mode 100644 (file)
index 0000000..eaf41c9
--- /dev/null
@@ -0,0 +1,92 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+
+$Log: safe_vproc.c,v $
+Revision 1.3  2009/02/14 00:09:53  cheshire
+Only log "Compiled without vproc_transaction support" when running on a system
+where we expect that to be available -- if running on a system that doesn't even
+have vproc_transaction, then it doesn't matter that the code was compiled without it.
+
+Revision 1.2  2009/02/09 21:16:17  mcguire
+<rdar://problem/5858533> Adopt vproc_transaction API in mDNSResponder
+additional cleanup: don't alloc memory since we currently only expect to have one transaction
+
+Revision 1.1  2009/02/06 03:06:49  mcguire
+<rdar://problem/5858533> Adopt vproc_transaction API in mDNSResponder
+
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <vproc.h>
+#include "safe_vproc.h"
+#include "mDNSDebug.h"
+
+#ifdef VPROC_HAS_TRANSACTIONS
+
+static vproc_transaction_t transaction = NULL;
+
+void safe_vproc_transaction_begin(void)
+       {
+       if (vproc_transaction_begin)
+               {
+               if (transaction) { LogMsg("safe_vproc_transaction_begin: Already have a transaction"); }
+               else transaction = vproc_transaction_begin(NULL);
+               }
+       }
+       
+void safe_vproc_transaction_end(void)
+       {
+       if (vproc_transaction_end)
+               {
+               if (transaction) { vproc_transaction_end(NULL, transaction); transaction = NULL; }
+               else LogMsg("safe_vproc_transaction_end: No current transaction");
+               }
+       }
+
+#else
+
+#include <stdio.h>
+#include <CoreFoundation/CFString.h>
+
+CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
+CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
+#define OSXVers_10_6_SnowLeopard 10
+
+void safe_vproc_transaction_begin(void)
+       {
+       static int majorversion = 0;
+       if (!majorversion)
+               {
+               CFDictionaryRef vers = _CFCopySystemVersionDictionary();
+               if (vers)
+                       {
+                       char buildver[256];
+                       CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
+                       if (cfbuildver && CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8))
+                               sscanf(buildver, "%d", &majorversion);
+                       CFRelease(vers);
+                       }
+               if (!majorversion || majorversion >= OSXVers_10_6_SnowLeopard)
+                       LogMsg("Compiled without vproc_transaction support");
+               }
+       }
+
+void safe_vproc_transaction_end(void) { }
+
+#endif
diff --git a/mDNSMacOSX/safe_vproc.h b/mDNSMacOSX/safe_vproc.h
new file mode 100644 (file)
index 0000000..79932d1
--- /dev/null
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+
+$Log: safe_vproc.h,v $
+Revision 1.1  2009/02/06 03:06:49  mcguire
+<rdar://problem/5858533> Adopt vproc_transaction API in mDNSResponder
+
+ */
+
+#ifndef __SAFE_VPROC_H
+#define __SAFE_VPROC_H
+
+extern void safe_vproc_transaction_begin(void);
+extern void safe_vproc_transaction_end(void);
+
+#endif /* __SAFE_VPROC_H */
index 6efffc3d081bcb3c70557dc0be4b401fc126521d..bd6137da9cf950d4958c17bd905b453d57a1c4ed 100755 (executable)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: Client.c,v $
+Revision 1.21  2008/11/04 19:46:01  cheshire
+Updated comment about MAX_ESCAPED_DOMAIN_NAME size (should be 1009, not 1005)
+
 Revision 1.20  2007/07/27 19:30:41  cheshire
 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
 to properly reflect tri-state nature of the possible responses
@@ -55,7 +58,7 @@ Typo: Wrote "domC" where it should have said "domainC"
 
 Revision 1.10  2003/11/14 21:27:09  cheshire
 <rdar://problem/3484766>: Security: Crashing bug in mDNSResponder
-Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers.
+Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1009) instead of 256-byte buffers.
 
 Revision 1.9  2003/08/14 02:19:55  cheshire
 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
index ee88102134be85d9e7394b88ed3fec662d7d08fc..c2a033fe8592fa7a2d6699ce45451499eb79cbfa 100644 (file)
     Change History (most recent first):
 
 $Log: Identify.c,v $
+Revision 1.44  2009/01/13 05:31:34  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.43  2008/09/05 22:51:21  cheshire
+Minor cleanup to bring code in sync with TOT, and make "_services" metaquery work again
+
 Revision 1.42  2007/07/27 19:30:41  cheshire
 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
 to properly reflect tri-state nature of the possible responses
@@ -134,7 +140,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS
        __MDNS__mDNSCoreReceive(m, msg, end, srcaddr, srcport, &AllDNSLinkGroup_v4, dstport, InterfaceID);
        }
 
-static void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
+mDNSlocal void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
        {
        (void)m;                // Unused
        (void)question; // Unused
@@ -148,7 +154,7 @@ static void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRec
                }
        }
 
-static void InfoCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
+mDNSlocal void InfoCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
        {
        (void)m;                // Unused
        (void)question; // Unused
@@ -187,10 +193,10 @@ static void InfoCallback(mDNS *const m, DNSQuestion *question, const ResourceRec
                }
 
        // If we've got everything we're looking for, don't need to wait any more
-       if (NumHINFO && (NumAddr || NumAAAA)) StopNow = 1;
+       if (/*NumHINFO && */ (NumAddr || NumAAAA)) StopNow = 1;
        }
 
-static void ServicesCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
+mDNSlocal void ServicesCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
        {
        (void)m;                // Unused
        (void)question; // Unused
@@ -201,13 +207,11 @@ static void ServicesCallback(mDNS *const m, DNSQuestion *question, const Resourc
        if (answer->rrtype == kDNSType_PTR && mDNSSameAddress(&lastsrc, &target))
                {
                NumAnswers++;
-               NumAddr++;
                mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
-               StopNow = 1;
                }
        }
 
-mDNSexport void WaitForAnswer(mDNS *const m, int seconds)
+mDNSlocal void WaitForAnswer(mDNS *const m, int seconds)
        {
        struct timeval end;
        gettimeofday(&end, NULL);
@@ -224,7 +228,11 @@ mDNSexport void WaitForAnswer(mDNS *const m, int seconds)
                FD_ZERO(&readfds);
                gettimeofday(&now, NULL);
                if (remain.tv_usec < now.tv_usec) { remain.tv_usec += 1000000; remain.tv_sec--; }
-               if (remain.tv_sec < now.tv_sec) return;
+               if (remain.tv_sec < now.tv_sec)
+                       {
+                       if (!NumAnswers) printf("No response after %d seconds\n", seconds);
+                       return;
+                       }
                remain.tv_usec -= now.tv_usec;
                remain.tv_sec  -= now.tv_sec;
                mDNSPosixGetFDSet(m, &nfds, &readfds, &remain);
@@ -236,15 +244,16 @@ mDNSexport void WaitForAnswer(mDNS *const m, int seconds)
 
 mDNSlocal mStatus StartQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback)
        {
+       lastsrc = zeroAddr;
        if (qname) MakeDomainNameFromDNSNameString(&q->qname, qname);
+       q->InterfaceID      = mDNSInterface_Any;
        q->Target           = target ? *target : zeroAddr;
        q->TargetPort       = MulticastDNSPort;
        q->TargetQID        = zeroID;
-       q->InterfaceID      = mDNSInterface_Any;
        q->qtype            = qtype;
        q->qclass           = kDNSClass_IN;
        q->LongLived        = mDNSfalse;
-       q->ExpectUnique     = mDNStrue;
+       q->ExpectUnique     = mDNSfalse;        // Don't want to stop after the first response packet
        q->ForceMCast       = mDNStrue;         // Query via multicast, even for apparently uDNS names like 1.1.1.17.in-addr.arpa.
        q->ReturnIntermed   = mDNStrue;
        q->QuestionCallback = callback;
@@ -269,7 +278,7 @@ mDNSlocal void DoOneQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNS
 mDNSlocal int DoQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback)
        {
        DoOneQuery(q, qname, qtype, target, callback);
-       if (StopNow == 0 && target && target->type)
+       if (StopNow == 0 && NumAnswers == 0 && target && target->type)
                {
                mprintf("%##s %s Trying multicast\n", q->qname.c, DNSTypeName(q->qtype));
                DoOneQuery(q, qname, qtype, NULL, callback);
@@ -350,7 +359,7 @@ mDNSexport int main(int argc, char **argv)
                                }
                        mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
                        target.type = mDNSAddrType_IPv6;
-                       bcopy(&s6, &target.ip.v6, sizeof(target.ip.v6));
+                       mDNSPlatformMemCopy(&target.ip.v6, &s6, sizeof(target.ip.v6));
                        DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback);
                        if (StopNow == 2) break;
                        }
@@ -364,25 +373,24 @@ mDNSexport int main(int argc, char **argv)
        
                if (hardware[0] || software[0])
                        {
-                       DNSQuestion q1;
                        printf("HINFO Hardware: %s\n", hardware);
                        printf("HINFO Software: %s\n", software);
-                       // We need to make sure the services query is targeted
-                       if (target.type == 0) target = hostaddr;
-                       StartQuery(&q1, "_services._dns-sd._udp.local.", kDNSQType_ANY, &target, ServicesCallback);
-                       WaitForAnswer(&mDNSStorage, 4);
-                       mDNS_StopQuery(&mDNSStorage, &q1);
-                       if (StopNow == 2) break;
                        }
-               else if (NumAnswers)
+               else if (NumAnswers) printf("%s has no HINFO record\n", hostname);
+               else printf("Incorrect dot-local hostname, address, or no mDNSResponder running on that machine\n");
+
+               if (NumAnswers)
                        {
-                       printf("Host has no HINFO record; Best guess is ");
-                       if (id.b[1]) printf("mDNSResponder-%d\n", id.b[1]);
-                       else if (NumAAAA) printf("very early Panther build (mDNSResponder-33 or earlier)\n");
-                       else printf("Jaguar version of mDNSResponder with no IPv6 support\n");
+                       // Because of the way we use lastsrc in ServicesCallback, we need to clear the cache to make sure we're getting fresh answers
+                       mDNS *const m = &mDNSStorage;
+                       mDNSu32 slot;
+                       CacheGroup *cg;
+                       CacheRecord *rr;
+                       FORALL_CACHERECORDS(slot, cg, rr) mDNS_PurgeCacheResourceRecord(m, rr);
+                       if (target.type == 0) target = hostaddr;                // Make sure the services query is targeted
+                       DoQuery(&q, "_services._dns-sd._udp.local.", kDNSType_PTR, &target, ServicesCallback);
+                       if (StopNow == 2) break;
                        }
-               else
-                       printf("Incorrect dot-local hostname, address, or no mDNSResponder running on that machine\n");
                }
 
        mDNS_Close(&mDNSStorage);
index 0a4763ff66dfcfa1e99a6ab285eeaf664ef6093f..82e78b03a06ea9abfea45a1c49ba7ababbdf8609 100755 (executable)
 # then try typing "gmake os=xxx" instead.
 #
 # $Log: Makefile,v $
+# Revision 1.83  2009/02/02 19:44:06  cheshire
+# Use "-fwrapv" option to tell compiler that the code is written assuming that
+# signed arithmetic is implemented using the twos-complement representation
+# (this is pretty much universally true on today's processors).
+# <http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Code-Gen-Options.html>
+# Without this option, gcc may decide that because the C language
+# does not require processors to use twos-complement representation, that means
+# gcc is free to do some "creative" optimizations that don't preserve the overflow
+# behaviour of twos-complement arithmetic. See also "-fstrict-overflow":
+# <http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Optimize-Options.html>
+#
+# Revision 1.82  2009/01/12 22:48:00  cheshire
+# Don't need to include "." in the "#include" search path
+#
+# Revision 1.81  2009/01/11 03:20:06  mkrochma
+# <rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
+#
+# Revision 1.80  2008/11/03 23:27:51  cheshire
+# Defined __MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4 to stop build failures on Leopard
+#
+# Revision 1.79  2008/10/24 01:59:59  mcguire
+# <rdar://problem/6257159> Build Failure: Need to stop using Jam
+#
 # Revision 1.78  2007/10/22 20:16:49  cheshire
 # Got rid of jaguar and panther from list of target platforms;
 # changed "os=tiger" to "os=x" (which works with both Tiger and Leopard)
 LIBVERS = 1
 
 COREDIR = ../mDNSCore
-SHAREDDIR = ../mDNSShared
+SHAREDDIR ?= ../mDNSShared
 JDK = /usr/jdk
 
 CC = @cc
@@ -300,7 +323,7 @@ LD = ld -shared
 CP = cp
 RM = rm
 LN = ln -s -f
-CFLAGS_COMMON = -I. -I$(COREDIR) -I$(SHAREDDIR) -I$(OBJDIR) -W -Wall -DPID_FILE=\"/var/run/mdnsd.pid\" -DMDNS_UDS_SERVERPATH=\"/var/run/mdnsd\"
+CFLAGS_COMMON = -I$(COREDIR) -I$(SHAREDDIR) -I$(OBJDIR) -fwrapv -W -Wall -DPID_FILE=\"/var/run/mdnsd.pid\" -DMDNS_UDS_SERVERPATH=\"/var/run/mdnsd\"
 CFLAGS_PTHREAD =
 LINKOPTS =
 LINKOPTS_PTHREAD = -lpthread
@@ -319,15 +342,16 @@ else
 # 1. We want to make small binaries, suitable for putting into hardware devices
 # 2. Some of the code analysis warnings only work when some form of optimization is enabled
 CFLAGS_DEBUG = -Os -DMDNS_DEBUGMSGS=0 
-OBJDIR = objects/prod
-BUILDDIR = build/prod
+OBJDIR ?= objects/prod
+BUILDDIR ?= build/prod
 STRIP = strip -S 
 endif
 
 # Configure per-OS peculiarities
 ifeq ($(os),solaris)
+CFLAGS_DEBUG = -O0 -DMDNS_DEBUGMSGS=0
 CFLAGS_OS = -DNOT_HAVE_DAEMON -DNOT_HAVE_SA_LEN -DNOT_HAVE_SOCKLEN_T -DNOT_HAVE_IF_NAMETOINDEX \
-        -DLOG_PERROR=0 -D_XPG4_2 -D__EXTENSIONS__ -DHAVE_BROKEN_RECVIF_NAME
+        -DLOG_PERROR=0 -D_XPG4_2 -D__EXTENSIONS__ -DHAVE_BROKEN_RECVIF_NAME -DTARGET_OS_SOLARIS
 CC = gcc
 LD = gcc -shared
 LINKOPTS = -lsocket -lnsl -lresolv
@@ -375,7 +399,10 @@ LDCONFIG = ldconfig
 else
 
 ifeq ($(os),x)
-CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror -Wdeclaration-after-statement #-Wunreachable-code
+# We have to define __MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4 or on Leopard
+# we get build failures: ‘daemon’ is deprecated (declared at /usr/include/stdlib.h:283)
+CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror -Wdeclaration-after-statement \
+       -D__MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4 #-Wunreachable-code
 CC = @gcc-4.0
 LD = $(CC) -dynamiclib
 LINKOPTS = -lSystem
@@ -450,10 +477,8 @@ install: setup InstalledDaemon InstalledStartup InstalledLib InstalledManPages I
 
 # 'setup' sets up the build directory structure the way we want
 setup:
-       @if test ! -d objects     ; then mkdir objects     ; fi
-       @if test ! -d build       ; then mkdir build       ; fi
-       @if test ! -d $(OBJDIR)   ; then mkdir $(OBJDIR)   ; fi
-       @if test ! -d $(BUILDDIR) ; then mkdir $(BUILDDIR) ; fi
+       @if test ! -d $(OBJDIR)   ; then mkdir -p $(OBJDIR)   ; fi
+       @if test ! -d $(BUILDDIR) ; then mkdir -p $(BUILDDIR) ; fi
 
 # clean removes targets and objects
 clean:
@@ -593,6 +618,7 @@ $(NSSINSTPATH)/$(NSSLIBFILE): $(BUILDDIR)/$(NSSLIBFILE)
 #############################################################################
 
 # The following targets build Java wrappers for the dns-sd.h API.
+# Note that the JavaForXcode targets are used when building the project for OS X using Xcode
 
 JAVAC = $(JDK)/bin/javac
 JAVAH = $(JDK)/bin/javah
@@ -600,6 +626,29 @@ JAVADOC = $(JDK)/bin/javadoc
 JAR = $(JDK)/bin/jar
 JAVACFLAGS = $(CFLAGS) $(JAVACFLAGS_OS) -I$(JDK)/include
 
+JavaForXcode_: setup $(BUILDDIR)/dns_sd.jar $(PROJECT_DERIVED_FILE_DIR)/DNSSD.java.h
+       @echo $@ done
+       
+$(PROJECT_DERIVED_FILE_DIR)/DNSSD.java.h: $(OBJDIR)/DNSSD.java.h
+       @if test ! -d $(PROJECT_DERIVED_FILE_DIR) ; then mkdir -p $(PROJECT_DERIVED_FILE_DIR) ; fi
+       $(CP) $< $@
+
+JavaForXcode_clean:
+       @if test -d $(OBJDIR) ; then rm -r $(OBJDIR) ; fi
+       @if test -f $(PROJECT_DERIVED_FILE_DIR)/DNSSD.java.h ; then $(RM) $(PROJECT_DERIVED_FILE_DIR)/DNSSD.java.h ; fi
+       @if test -f $(BUILDDIR)/dns_sd.jar ; then $(RM) $(BUILDDIR)/dns_sd.jar ; fi
+       @echo $@ done
+
+JavaForXcode_installhdrs:
+       @echo $@ NOOP
+
+JavaForXcode_install: JavaForXcode_ $(DSTROOT)/$(SYSTEM_LIBRARY_DIR)/Java/Extensions/dns_sd.jar
+       @echo $@ done
+
+$(DSTROOT)/$(SYSTEM_LIBRARY_DIR)/Java/Extensions/dns_sd.jar: $(BUILDDIR)/dns_sd.jar
+       @if test ! -d $(DSTROOT)/$(SYSTEM_LIBRARY_DIR)/Java/Extensions ; then mkdir -p $(DSTROOT)/$(SYSTEM_LIBRARY_DIR)/Java/Extensions ; fi
+       $(CP) $< $@
+
 Java: setup $(BUILDDIR)/dns_sd.jar $(BUILDDIR)/libjdns_sd.$(LDSUFFIX)
        @echo "Java wrappers done"
 
@@ -636,7 +685,9 @@ $(OBJDIR)/DNSSD.java.h: $(OBJDIR)/com/apple/dnssd/DNSSD.class
                com.apple.dnssd.AppleRegistration \
                com.apple.dnssd.AppleQuery \
                com.apple.dnssd.AppleDomainEnum \
-               com.apple.dnssd.AppleService 
+               com.apple.dnssd.AppleService \
+               com.apple.dnssd.AppleDNSRecord \
+               com.apple.dnssd.AppleRecordRegistrar
 
 #############################################################################
 
index 9f26ea0330bdb26f26bf6cb1370e1ef0c3b73362..f873ea3f40ad87b95094102d8e49f5959c313a77 100644 (file)
     Change History (most recent first):
 
 $Log: NetMonitor.c,v $
+Revision 1.94  2009/04/24 00:31:56  cheshire
+<rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
+Added code to display NSEC records
+
+Revision 1.93  2009/01/13 05:31:34  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.92  2009/01/11 03:20:06  mkrochma
+<rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
+
+Revision 1.91  2008/11/13 22:08:07  cheshire
+Show additional records in Query packets
+
+Revision 1.90  2008/09/05 22:20:26  cheshire
+<rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+Add "UDPSocket *src" parameter in mDNSPlatformSendUDP call
+
 Revision 1.89  2007/05/17 19:12:42  cheshire
 Tidy up code layout
 
@@ -95,7 +112,7 @@ Use IFNAMSIZ (more portable) instead of IF_NAMESIZE
 
 #include <stdio.h>                     // For printf()
 #include <stdlib.h>                    // For malloc()
-#include <string.h>                    // For bcopy()
+#include <string.h>                    // For strrchr(), strcmp()
 #include <time.h>                      // For "struct tm" etc.
 #include <signal.h>                    // For SIGINT, SIGTERM
 #include <netdb.h>                     // For gethostbyname()
@@ -361,7 +378,7 @@ mDNSlocal void SendUnicastQuery(mDNS *const m, HostEntry *entry, domainname *nam
                InterfaceID = mDNSInterface_Any;        // Send query from our unicast reply socket
                }
 
-       mDNSSendDNSMessage(&mDNSStorage, &query, qptr, InterfaceID, target, MulticastDNSPort, mDNSNULL, mDNSNULL);
+       mDNSSendDNSMessage(&mDNSStorage, &query, qptr, InterfaceID, mDNSNULL, target, MulticastDNSPort, mDNSNULL, mDNSNULL);
        }
 
 mDNSlocal void AnalyseHost(mDNS *const m, HostEntry *entry, const mDNSInterfaceID InterfaceID)
@@ -583,6 +600,12 @@ mDNSlocal void DisplayResourceRecord(const mDNSAddr *const srcaddr, const char *
                                                        } break;
                case kDNSType_AAAA:     n += mprintf("%.16a", &rd->ipv6); break;
                case kDNSType_SRV:      n += mprintf("%##s:%d", rd->srv.target.c, mDNSVal16(rd->srv.port)); break;
+               case kDNSType_NSEC:     {
+                                                       int i;
+                                                       for (i=0; i<255; i++)
+                                                               if (rd->nsec.bitmap[i>>3] & (128 >> (i&7)))
+                                                                       n += mprintf("%s ", DNSTypeName(i));
+                                                       } break;
                default:                        {
                                                        mDNSu8 *s = rd->data;
                                                        while (s < rdend && p < buffer+MaxWidth)
@@ -693,6 +716,14 @@ mDNSlocal void DisplayQuery(mDNS *const m, const DNSMessage *const msg, const mD
                if (!ptr) { DisplayError(srcaddr, ep, end, "AUTHORITY"); return; }
                }
 
+       for (i=0; i<msg->h.numAdditionals; i++)
+               {
+               const mDNSu8 *ep = ptr;
+               ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &pkt);
+               if (!ptr) { DisplayError(srcaddr, ep, end, "ADDITIONAL"); return; }
+               DisplayResourceRecord(srcaddr, "    ", &pkt.r.resrec);
+               }
+
        if (entry) AnalyseHost(m, entry, InterfaceID);
        }
 
@@ -943,7 +974,7 @@ mDNSexport int main(int argc, char **argv)
                        else if (inet_pton(AF_INET6, argv[i], &s6) == 1)
                                {
                                a.type = mDNSAddrType_IPv6;
-                               bcopy(&s6, &a.ip.v6, sizeof(a.ip.v6));
+                               mDNSPlatformMemCopy(&a.ip.v6, &s6, sizeof(a.ip.v6));
                                }
                        else
                                {
index be0523f86df6c54c51a07ca9dcea96b94524df72..4d1926535f910fed85810e49d4df4579132f8f96 100644 (file)
        Change History (most recent first):
 
 $Log: PosixDaemon.c,v $
+Revision 1.49  2009/04/30 20:07:51  mcguire
+<rdar://problem/6822674> Support multiple UDSs from launchd
+
+Revision 1.48  2009/04/11 01:43:28  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.47  2009/01/11 03:20:06  mkrochma
+<rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
+
+Revision 1.46  2008/11/03 23:09:15  cheshire
+Don't need to include mDNSDebug.h as well as mDNSEmbeddedAPI.h
+
+Revision 1.45  2008/10/03 18:25:17  cheshire
+Instead of calling "m->MainCallback" function pointer directly, call mDNSCore routine "mDNS_ConfigChanged(m);"
+
+Revision 1.44  2008/09/15 23:52:30  cheshire
+<rdar://problem/6218902> mDNSResponder-177 fails to compile on Linux with .desc pseudo-op
+Made __crashreporter_info__ symbol conditional, so we only use it for OS X build
+
 Revision 1.43  2007/10/22 20:05:34  cheshire
 Use mDNSPlatformSourceAddrForDest instead of FindSourceAddrForIP
 
@@ -79,8 +98,8 @@ Only use mallocL/freeL debugging routines when building mDNSResponder, not dnsex
 #include <sys/types.h>
 
 #include "mDNSEmbeddedAPI.h"
-#include "mDNSDebug.h"
 #include "mDNSPosix.h"
+#include "mDNSUNP.h"           // For daemon()
 #include "uds_daemon.h"
 #include "PlatformCommon.h"
 
@@ -130,7 +149,7 @@ static void Reconfigure(mDNS *m)
        mDNSPlatformSourceAddrForDest(&DynDNSIP, &dummy);
        if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
        if (DynDNSIP.type)       mDNS_SetPrimaryInterfaceInfo(m, &DynDNSIP, NULL, NULL);
-       m->MainCallback(m, mStatus_ConfigChanged);
+       mDNS_ConfigChanged(m);
        }
 
 // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
@@ -156,9 +175,9 @@ mDNSlocal void ParseCmdLinArgs(int argc, char **argv)
 mDNSlocal void DumpStateLog(mDNS *const m)
 // Dump a little log of what we've been up to.
        {
-       LogMsgIdent(mDNSResponderVersionString, "---- BEGIN STATE LOG ----");
+       LogMsg("---- BEGIN STATE LOG ----");
        udsserver_info(m);
-       LogMsgIdent(mDNSResponderVersionString, "----  END STATE LOG  ----");
+       LogMsg("----  END STATE LOG  ----");
        }
 
 mDNSlocal mStatus MainLoop(mDNS *m) // Loop until we quit.
@@ -209,13 +228,13 @@ int main(int argc, char **argv)
 
        ParseCmdLinArgs(argc, argv);
 
-       LogMsgIdent(mDNSResponderVersionString, "starting");
+       LogMsg("%s starting", mDNSResponderVersionString);
 
        err = mDNS_Init(&mDNSStorage, &PlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses, 
                                        mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext); 
 
        if (mStatus_NoError == err)
-               err = udsserver_init(dnssd_InvalidSocket);
+               err = udsserver_init(mDNSNULL, 0);
                
        Reconfigure(&mDNSStorage);
 
@@ -232,11 +251,11 @@ int main(int argc, char **argv)
        if (mStatus_NoError == err)
                err = MainLoop(&mDNSStorage);
  
-       LogMsgIdent(mDNSResponderVersionString, "stopping");
+       LogMsg("%s stopping", mDNSResponderVersionString);
 
        mDNS_Close(&mDNSStorage);
 
-       if (udsserver_exit(dnssd_InvalidSocket) < 0)
+       if (udsserver_exit() < 0)
                LogMsg("ExitCallback: udsserver_exit failed");
  
  #if MDNS_DEBUGMSGS > 0
@@ -269,9 +288,11 @@ mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
        // No-op, for now
        }
 
+#if _BUILDING_XCODE_PROJECT_
 // If the process crashes, then this string will be magically included in the automatically-generated crash log
 const char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5;
 asm(".desc ___crashreporter_info__, 0x10");
+#endif
 
 // For convenience when using the "strings" command, this is the last thing in the file
 #if mDNSResponderVersion > 1
index 5ae68090a24eb59fdc88053a5bd198337b6fdca6..dd76ac718bc302ce228498fb3bf999f0c4f9463e 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: ProxyResponder.c,v $
+Revision 1.45  2008/11/04 19:46:01  cheshire
+Updated comment about MAX_ESCAPED_DOMAIN_NAME size (should be 1009, not 1005)
+
 Revision 1.44  2007/04/22 20:16:25  cheshire
 Fix compiler errors (const parameter declarations)
 
@@ -84,7 +87,7 @@ Add support for mDNSResponder on Linux.
 
 Revision 1.24  2003/11/14 21:27:09  cheshire
 <rdar://problem/3484766>: Security: Crashing bug in mDNSResponder
-Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers.
+Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1009) instead of 256-byte buffers.
 
 Revision 1.23  2003/10/30 19:39:28  cheshire
 Fix warnings on certain compilers
index 9a4d13a98fffc2178d274e506f7cd6c6b5657f56..67cc817472882a1b40260c42f78e02fda87cbbb9 100755 (executable)
     Change History (most recent first):
 
 $Log: Responder.c,v $
+Revision 1.36  2009/01/15 03:39:08  mkrochma
+Fix warning about ignoring return value of daemon
+
+Revision 1.35  2009/01/13 05:31:34  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.34  2009/01/11 03:20:06  mkrochma
+<rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
+
 Revision 1.33  2007/04/16 20:49:39  cheshire
 Fix compile errors for mDNSPosix build
 
@@ -126,6 +135,7 @@ First checkin
 
 #include "mDNSEmbeddedAPI.h"// Defines the interface to the client layer above
 #include "mDNSPosix.h"    // Defines the specific types needed to run mDNS on this platform
+#include "mDNSUNP.h"           // For daemon()
 
 #include <assert.h>
 #include <stdio.h>                     // For printf()
@@ -404,7 +414,7 @@ static void ParseArguments(int argc, char **argv)
                        while (optind < argc)
                                {
                                gServiceText[gServiceTextLen] = strlen(argv[optind]);
-                               memcpy(gServiceText+gServiceTextLen+1, argv[optind], gServiceText[gServiceTextLen]);
+                               mDNSPlatformMemCopy(gServiceText+gServiceTextLen+1, argv[optind], gServiceText[gServiceTextLen]);
                                gServiceTextLen += 1 + gServiceText[gServiceTextLen];
                                optind++;
                                }
@@ -636,7 +646,7 @@ static mStatus RegisterServicesInFile(const char *filePath)
                                                unsigned int newlen = textLen + 1 + len;
                                                if (len == 0 || newlen >= sizeof(text)) break;
                                                text[textLen] = len;
-                                               memcpy(text + textLen + 1, rawText, len);
+                                               mDNSPlatformMemCopy(text + textLen + 1, rawText, len);
                                                textLen = newlen;
                                                }
                                        else
@@ -726,11 +736,12 @@ int main(int argc, char **argv)
     // because printf has no format specified for pid_t.
     
     if (gDaemon) {
+       int result;
         if (gMDNSPlatformPosixVerboseLevel > 0) {
             fprintf(stderr, "%s: Starting in daemon mode\n", gProgramName);
         }
-        daemon(0,0);
-        {
+        result = daemon(0,0);
+        if (result == 0) {
             FILE *fp;
             int  junk;
             
@@ -740,6 +751,9 @@ int main(int argc, char **argv)
                 junk = fclose(fp);
                 assert(junk == 0);
             }
+        } else {
+            fprintf(stderr, "%s: Could not run as daemon - exiting\n", gProgramName);
+            exit(result);
         }
     } else {
         if (gMDNSPlatformPosixVerboseLevel > 0) {
index 403f160fbd2bf4082bd9dfdc61f92cd01ca73433..70defbda7f9b4ec2f68bd28e4c102928f2cc51e5 100755 (executable)
        Change History (most recent first):
 
 $Log: mDNSPosix.c,v $
+Revision 1.108  2009/01/25 03:16:46  mkrochma
+Added skeleton definition of mDNSPlatformSetLocalARP
+
+Revision 1.107  2009/01/07 08:25:03  mkrochma
+Added skeleton definition of mDNSPlatformUpdateProxyList
+
+Revision 1.106  2008/10/22 17:19:57  cheshire
+Don't need to define BPF_fd any more (it's now per-interface, not global)
+
+Revision 1.105  2008/10/03 23:34:08  cheshire
+Added skeleton definition of mDNSPlatformSendRawPacket
+
+Revision 1.104  2008/09/05 22:16:48  cheshire
+<rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+Add "UDPSocket *src" parameter in mDNSPlatformSendUDP
+
 Revision 1.103  2007/10/02 19:31:17  cheshire
 In ParseDNSServers, should use strncasecmp for case-insensitive compare
 
@@ -246,13 +262,15 @@ mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipA
 
 // 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, const mDNSAddr *dst, mDNSIPPort dstPort)
+       mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstPort)
        {
        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
+
        assert(m != NULL);
        assert(msg != NULL);
        assert(end != NULL);
@@ -477,6 +495,26 @@ 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 mDNSPlatformSetLocalARP(const mDNSv4Addr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
+       {
+       (void)tpa;                      // Unused
+       (void)tha;                      // Unused
+       (void)InterfaceID;                      // Unused
+       }       
 
 mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
        {
index 852883d7baea669b66b7c78b5984889b686a8f17..d32406e5bffbce5ef6164c2d4149ff396bae04a7 100755 (executable)
     Change History (most recent first):
 
 $Log: mDNSUNP.c,v $
+Revision 1.40  2009/01/13 05:31:34  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.39  2009/01/11 03:20:06  mkrochma
+<rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
+
+Revision 1.38  2009/01/10 22:54:42  mkrochma
+<rdar://problem/5797544> Fixes from Igor Seleznev to get mdnsd working on Linux
+
+Revision 1.37  2008/10/23 22:33:24  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
 Revision 1.36  2008/04/21 18:21:22  mkrochma
 <rdar://problem/5877307> Need to free ifi_netmask
 Submitted by Igor Seleznev
@@ -145,6 +157,7 @@ First checkin
 #include <stdlib.h>
 #include <sys/uio.h>
 #include <sys/ioctl.h>
+#include <signal.h>
 #include <unistd.h>
 #include <stdio.h>
 
@@ -178,7 +191,7 @@ First checkin
 #if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX
 #include <net/if_var.h>
 #include <netinet/in_var.h>
-// NOTE: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
+// Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
 #endif
 
 #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
@@ -503,7 +516,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
                                struct in6_ifreq ifr6;
                                if (sockf6 == -1)
                                        sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
-                               bzero(&ifr6, sizeof(ifr6));
+                               memset(&ifr6, 0, sizeof(ifr6));
                                memcpy(&ifr6.ifr_name,           &ifr->ifr_name, sizeof(ifr6.ifr_name          ));
                                memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
                                if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) goto gotError;
@@ -673,6 +686,11 @@ struct in_pktinfo
             strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen);
 #endif
             pktp->ipi_ifindex = sdl->sdl_index;
+#ifdef HAVE_BROKEN_RECVIF_NAME
+                       if (sdl->sdl_index == 0) {
+                               pktp->ipi_ifindex = *(uint_t*)sdl;
+                       }
+#endif            
             assert(pktp->ipi_ifname[IFI_NAME - 1] == 0);
             // null terminated because of memset above
             continue;
index ecbbc712cb69ab68d84a2559c765273f4fa3b42c..5af2f8e222816e585c48a1f092add064d06b74a1 100755 (executable)
@@ -335,7 +335,7 @@ enum
 
 #define DNS_LABEL_MAXLEN 63
        // Maximum length of a single DNS label
-#define DNS_NAME_MAXLEN 255
+#define DNS_NAME_MAXLEN 256
        // Maximum length of a DNS name
 
 //----------
@@ -486,7 +486,7 @@ const int MDNS_VERBOSE = 0;
        // This enables verbose syslog messages
        // If zero, only "imporant" messages will appear in syslog
 
-#define k_hostname_maxlen 255
+#define k_hostname_maxlen 256
        // As per RFC1034 and RFC1035
 #define k_aliases_max 15
 #define k_addrs_max 15
@@ -1826,7 +1826,7 @@ init_config ()
                        temp_config = (config_t *) malloc (sizeof (config_t));
                        if (temp_config)
                        {
-                               // NOTE: This code will leak memory if initialisation fails
+                               // Note: This code will leak memory if initialisation fails
                                // repeatedly.  This should only happen in the case of a memory
                                // error, so I'm not sure if it's a meaningful problem. - AW
                                *temp_config = k_empty_config;
index 7a0f87c1083c2b541ecd79ed67f87d8c5c7cbeb7..1e0eca19381490dbd016bcdd3cfac5caa3346531 100755 (executable)
@@ -1,15 +1,10 @@
-Microsoft Visual Studio Solution File, Format Version 8.00\r
+Microsoft Visual Studio Solution File, Format Version 9.00\r
+# Visual Studio 2005\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLL", "mDNSWindows\DLL\dnssd.vcproj", "{AB581101-18F0-46F6-B56A-83A6B1EA657E}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mDNSResponder", "mDNSWindows\SystemService\Service.vcproj", "{C1D98254-BA27-4427-A3BE-A68CA2CC5F69}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NSPTool", "mDNSWindows\NSPTool\NSPTool.vcproj", "{208B3A9F-1CA0-4D1D-9D6C-C61616F94705}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdnsNSP", "mDNSWindows\mdnsNSP\mdnsNSP.vcproj", "{F4F15529-F0EB-402F-8662-73C5797EE557}"\r
        ProjectSection(ProjectDependencies) = postProject\r
@@ -18,16 +13,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdnsNSP", "mDNSWindows\mdns
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPlugin", "Clients\ExplorerPlugin\ExplorerPlugin.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
        ProjectSection(ProjectDependencies) = postProject\r
-               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5} = {3A2B6325-3053-4236-84BD-AA9BE2E323E5}\r
        EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizard", "Clients\PrinterSetupWizard\PrinterSetupWizard.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
        ProjectSection(ProjectDependencies) = postProject\r
-               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLL.NET", "mDNSWindows\DLL.NET\dnssd_NET.vcproj", "{9C6701E2-82B7-44B7-9B5E-3897D9153F79}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5} = {3A2B6325-3053-4236-84BD-AA9BE2E323E5}\r
        EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ControlPanel", "mDNSWindows\ControlPanel\ControlPanel.vcproj", "{F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}"\r
@@ -35,29 +26,27 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ControlPanel", "mDNSWindows
                {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
        EndProjectSection\r
 EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizardLocRes", "Clients\PrinterSetupWizard\PrinterSetupWizardLocRes.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizardLocRes", "Clients\PrinterSetupWizard\PrinterSetupWizardLocRes.vcproj", "{967F5375-0176-43D3-ADA3-22EE25551C37}"\r
        ProjectSection(ProjectDependencies) = postProject\r
                {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
        EndProjectSection\r
 EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizardRes", "Clients\PrinterSetupWizard\PrinterSetupWizardRes.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizardRes", "Clients\PrinterSetupWizard\PrinterSetupWizardRes.vcproj", "{CFCCB176-6CAA-472B-B0A2-90511C8E2E52}"\r
        ProjectSection(ProjectDependencies) = postProject\r
                {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
        EndProjectSection\r
 EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginLocRes", "Clients\ExplorerPlugin\ExplorerPluginLocRes.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginLocRes", "Clients\ExplorerPlugin\ExplorerPluginLocRes.vcproj", "{1643427B-F226-4AD6-B413-97DA64D5C6B4}"\r
        ProjectSection(ProjectDependencies) = postProject\r
                {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
        EndProjectSection\r
 EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginRes", "Clients\ExplorerPlugin\ExplorerPluginRes.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginRes", "Clients\ExplorerPlugin\ExplorerPluginRes.vcproj", "{871B1492-B4A4-4B57-9237-FA798484D7D7}"\r
        ProjectSection(ProjectDependencies) = postProject\r
                {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
        EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dns-sd", "Clients\DNS-SD.VisualStudio\dns-sd.vcproj", "{AA230639-E115-4A44-AA5A-44A61235BA50}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Java", "mDNSWindows\Java\Java.vcproj", "{9CE2568A-3170-41C6-9F20-A0188A9EC114}"\r
        ProjectSection(ProjectDependencies) = postProject\r
@@ -70,84 +59,146 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JavaSamples", "Clients\Java
        EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ControlPanel (Vista)", "mDNSWindows\ControlPanel\ControlPanelExe.vcproj", "{0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLLStub", "mDNSWindows\DLLStub\DLLStub.vcproj", "{3A2B6325-3053-4236-84BD-AA9BE2E323E5}"\r
        ProjectSection(ProjectDependencies) = postProject\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
        EndProjectSection\r
 EndProject\r
 Global\r
-       GlobalSection(SolutionConfiguration) = preSolution\r
-               Debug = Debug\r
-               Release = Release\r
-       EndGlobalSection\r
-       GlobalSection(ProjectDependencies) = postSolution\r
-       EndGlobalSection\r
-       GlobalSection(ProjectConfiguration) = postSolution\r
-               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug.ActiveCfg = Debug|Win32\r
-               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug.Build.0 = Debug|Win32\r
-               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release.ActiveCfg = Release|Win32\r
-               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release.Build.0 = Release|Win32\r
-               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug.ActiveCfg = Debug|Win32\r
-               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug.Build.0 = Debug|Win32\r
-               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release.ActiveCfg = Release|Win32\r
-               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release.Build.0 = Release|Win32\r
-               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug.ActiveCfg = Debug|Win32\r
-               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug.Build.0 = Debug|Win32\r
-               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release.ActiveCfg = Release|Win32\r
-               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release.Build.0 = Release|Win32\r
-               {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug.ActiveCfg = Debug|Win32\r
-               {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug.Build.0 = Debug|Win32\r
-               {F4F15529-F0EB-402F-8662-73C5797EE557}.Release.ActiveCfg = Release|Win32\r
-               {F4F15529-F0EB-402F-8662-73C5797EE557}.Release.Build.0 = Release|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.ActiveCfg = Debug|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.Build.0 = Debug|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.ActiveCfg = Release|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.Build.0 = Release|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.ActiveCfg = Debug|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.Build.0 = Debug|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.ActiveCfg = Release|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.Build.0 = Release|Win32\r
-               {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Debug.ActiveCfg = Debug|Win32\r
-               {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Debug.Build.0 = Debug|Win32\r
-               {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Release.ActiveCfg = Release|Win32\r
-               {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Release.Build.0 = Release|Win32\r
-               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug.ActiveCfg = Debug|Win32\r
-               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug.Build.0 = Debug|Win32\r
-               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release.ActiveCfg = Release|Win32\r
-               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release.Build.0 = Release|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.ActiveCfg = Debug|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.Build.0 = Debug|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.ActiveCfg = Release|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.Build.0 = Release|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.ActiveCfg = Debug|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.Build.0 = Debug|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.ActiveCfg = Release|Win32\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.Build.0 = Release|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.ActiveCfg = Debug|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.Build.0 = Debug|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.ActiveCfg = Release|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.Build.0 = Release|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.ActiveCfg = Debug|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.Build.0 = Debug|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.ActiveCfg = Release|Win32\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.Build.0 = Release|Win32\r
-               {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug.ActiveCfg = Debug|Win32\r
-               {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug.Build.0 = Debug|Win32\r
-               {AA230639-E115-4A44-AA5A-44A61235BA50}.Release.ActiveCfg = Release|Win32\r
-               {AA230639-E115-4A44-AA5A-44A61235BA50}.Release.Build.0 = Release|Win32\r
-               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Debug.ActiveCfg = Debug|Win32\r
-               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Debug.Build.0 = Debug|Win32\r
-               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release.ActiveCfg = Release|Win32\r
-               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release.Build.0 = Release|Win32\r
-               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug.ActiveCfg = Debug|Win32\r
-               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug.Build.0 = Debug|Win32\r
-               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Release.ActiveCfg = Release|Win32\r
-               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Release.Build.0 = Release|Win32\r
-               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Debug.ActiveCfg = Debug|Win32\r
-               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Debug.Build.0 = Debug|Win32\r
-               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Release.ActiveCfg = Release|Win32\r
-               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Release.Build.0 = Release|Win32\r
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+               Debug|Win32 = Debug|Win32\r
+               Debug|x64 = Debug|x64\r
+               Release|Win32 = Release|Win32\r
+               Release|x64 = Release|x64\r
        EndGlobalSection\r
-       GlobalSection(ExtensibilityGlobals) = postSolution\r
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug|Win32.Build.0 = Debug|Win32\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug|x64.ActiveCfg = Debug|x64\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug|x64.Build.0 = Debug|x64\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release|Win32.ActiveCfg = Release|Win32\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release|Win32.Build.0 = Release|Win32\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release|x64.ActiveCfg = Release|x64\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release|x64.Build.0 = Release|x64\r
+               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug|Win32.Build.0 = Debug|Win32\r
+               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug|x64.ActiveCfg = Debug|x64\r
+               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug|x64.Build.0 = Debug|x64\r
+               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release|Win32.ActiveCfg = Release|Win32\r
+               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release|Win32.Build.0 = Release|Win32\r
+               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release|x64.ActiveCfg = Release|x64\r
+               {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release|x64.Build.0 = Release|x64\r
+               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug|Win32.Build.0 = Debug|Win32\r
+               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug|x64.ActiveCfg = Debug|x64\r
+               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug|x64.Build.0 = Debug|x64\r
+               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release|Win32.ActiveCfg = Release|Win32\r
+               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release|Win32.Build.0 = Release|Win32\r
+               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release|x64.ActiveCfg = Release|x64\r
+               {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release|x64.Build.0 = Release|x64\r
+               {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug|Win32.Build.0 = Debug|Win32\r
+               {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug|x64.ActiveCfg = Debug|x64\r
+               {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug|x64.Build.0 = Debug|x64\r
+               {F4F15529-F0EB-402F-8662-73C5797EE557}.Release|Win32.ActiveCfg = Release|Win32\r
+               {F4F15529-F0EB-402F-8662-73C5797EE557}.Release|Win32.Build.0 = Release|Win32\r
+               {F4F15529-F0EB-402F-8662-73C5797EE557}.Release|x64.ActiveCfg = Release|x64\r
+               {F4F15529-F0EB-402F-8662-73C5797EE557}.Release|x64.Build.0 = Release|x64\r
+               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug|Win32.Build.0 = Debug|Win32\r
+               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug|x64.ActiveCfg = Debug|x64\r
+               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug|x64.Build.0 = Debug|x64\r
+               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release|Win32.ActiveCfg = Release|Win32\r
+               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release|Win32.Build.0 = Release|Win32\r
+               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release|x64.ActiveCfg = Release|x64\r
+               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release|x64.Build.0 = Release|x64\r
+               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug|Win32.Build.0 = Debug|Win32\r
+               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug|x64.ActiveCfg = Debug|x64\r
+               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug|x64.Build.0 = Debug|x64\r
+               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release|Win32.ActiveCfg = Release|Win32\r
+               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release|Win32.Build.0 = Release|Win32\r
+               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release|x64.ActiveCfg = Release|x64\r
+               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release|x64.Build.0 = Release|x64\r
+               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug|Win32.Build.0 = Debug|Win32\r
+               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug|x64.ActiveCfg = Debug|x64\r
+               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug|x64.Build.0 = Debug|x64\r
+               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release|Win32.ActiveCfg = Release|Win32\r
+               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release|Win32.Build.0 = Release|Win32\r
+               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release|x64.ActiveCfg = Release|x64\r
+               {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release|x64.Build.0 = Release|x64\r
+               {967F5375-0176-43D3-ADA3-22EE25551C37}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {967F5375-0176-43D3-ADA3-22EE25551C37}.Debug|Win32.Build.0 = Debug|Win32\r
+               {967F5375-0176-43D3-ADA3-22EE25551C37}.Debug|x64.ActiveCfg = Debug|x64\r
+               {967F5375-0176-43D3-ADA3-22EE25551C37}.Debug|x64.Build.0 = Debug|x64\r
+               {967F5375-0176-43D3-ADA3-22EE25551C37}.Release|Win32.ActiveCfg = Release|Win32\r
+               {967F5375-0176-43D3-ADA3-22EE25551C37}.Release|Win32.Build.0 = Release|Win32\r
+               {967F5375-0176-43D3-ADA3-22EE25551C37}.Release|x64.ActiveCfg = Release|x64\r
+               {967F5375-0176-43D3-ADA3-22EE25551C37}.Release|x64.Build.0 = Release|x64\r
+               {CFCCB176-6CAA-472B-B0A2-90511C8E2E52}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {CFCCB176-6CAA-472B-B0A2-90511C8E2E52}.Debug|Win32.Build.0 = Debug|Win32\r
+               {CFCCB176-6CAA-472B-B0A2-90511C8E2E52}.Debug|x64.ActiveCfg = Debug|x64\r
+               {CFCCB176-6CAA-472B-B0A2-90511C8E2E52}.Debug|x64.Build.0 = Debug|x64\r
+               {CFCCB176-6CAA-472B-B0A2-90511C8E2E52}.Release|Win32.ActiveCfg = Release|Win32\r
+               {CFCCB176-6CAA-472B-B0A2-90511C8E2E52}.Release|Win32.Build.0 = Release|Win32\r
+               {CFCCB176-6CAA-472B-B0A2-90511C8E2E52}.Release|x64.ActiveCfg = Release|x64\r
+               {CFCCB176-6CAA-472B-B0A2-90511C8E2E52}.Release|x64.Build.0 = Release|x64\r
+               {1643427B-F226-4AD6-B413-97DA64D5C6B4}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {1643427B-F226-4AD6-B413-97DA64D5C6B4}.Debug|Win32.Build.0 = Debug|Win32\r
+               {1643427B-F226-4AD6-B413-97DA64D5C6B4}.Debug|x64.ActiveCfg = Debug|x64\r
+               {1643427B-F226-4AD6-B413-97DA64D5C6B4}.Debug|x64.Build.0 = Debug|x64\r
+               {1643427B-F226-4AD6-B413-97DA64D5C6B4}.Release|Win32.ActiveCfg = Release|Win32\r
+               {1643427B-F226-4AD6-B413-97DA64D5C6B4}.Release|Win32.Build.0 = Release|Win32\r
+               {1643427B-F226-4AD6-B413-97DA64D5C6B4}.Release|x64.ActiveCfg = Release|x64\r
+               {1643427B-F226-4AD6-B413-97DA64D5C6B4}.Release|x64.Build.0 = Release|x64\r
+               {871B1492-B4A4-4B57-9237-FA798484D7D7}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {871B1492-B4A4-4B57-9237-FA798484D7D7}.Debug|Win32.Build.0 = Debug|Win32\r
+               {871B1492-B4A4-4B57-9237-FA798484D7D7}.Debug|x64.ActiveCfg = Debug|x64\r
+               {871B1492-B4A4-4B57-9237-FA798484D7D7}.Debug|x64.Build.0 = Debug|x64\r
+               {871B1492-B4A4-4B57-9237-FA798484D7D7}.Release|Win32.ActiveCfg = Release|Win32\r
+               {871B1492-B4A4-4B57-9237-FA798484D7D7}.Release|Win32.Build.0 = Release|Win32\r
+               {871B1492-B4A4-4B57-9237-FA798484D7D7}.Release|x64.ActiveCfg = Release|x64\r
+               {871B1492-B4A4-4B57-9237-FA798484D7D7}.Release|x64.Build.0 = Release|x64\r
+               {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug|Win32.Build.0 = Debug|Win32\r
+               {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug|x64.ActiveCfg = Debug|x64\r
+               {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug|x64.Build.0 = Debug|x64\r
+               {AA230639-E115-4A44-AA5A-44A61235BA50}.Release|Win32.ActiveCfg = Release|Win32\r
+               {AA230639-E115-4A44-AA5A-44A61235BA50}.Release|Win32.Build.0 = Release|Win32\r
+               {AA230639-E115-4A44-AA5A-44A61235BA50}.Release|x64.ActiveCfg = Release|x64\r
+               {AA230639-E115-4A44-AA5A-44A61235BA50}.Release|x64.Build.0 = Release|x64\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Debug|Win32.Build.0 = Debug|Win32\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Debug|x64.ActiveCfg = Debug|x64\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release|Win32.ActiveCfg = Release|Win32\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release|Win32.Build.0 = Release|Win32\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release|x64.ActiveCfg = Release|x64\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug|Win32.Build.0 = Debug|Win32\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug|x64.ActiveCfg = Debug|x64\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Release|Win32.ActiveCfg = Release|Win32\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Release|Win32.Build.0 = Release|Win32\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Release|x64.ActiveCfg = Release|x64\r
+               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Debug|Win32.Build.0 = Debug|Win32\r
+               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Debug|x64.ActiveCfg = Debug|x64\r
+               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Debug|x64.Build.0 = Debug|x64\r
+               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Release|Win32.ActiveCfg = Release|Win32\r
+               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Release|Win32.Build.0 = Release|Win32\r
+               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Release|x64.ActiveCfg = Release|x64\r
+               {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Release|x64.Build.0 = Release|x64\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Debug|Win32.Build.0 = Debug|Win32\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Debug|x64.ActiveCfg = Debug|x64\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Debug|x64.Build.0 = Debug|x64\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Release|Win32.ActiveCfg = Release|Win32\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Release|Win32.Build.0 = Release|Win32\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Release|x64.ActiveCfg = Release|x64\r
+               {3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Release|x64.Build.0 = Release|x64\r
        EndGlobalSection\r
-       GlobalSection(ExtensibilityAddIns) = postSolution\r
+       GlobalSection(SolutionProperties) = preSolution\r
+               HideSolutionNode = FALSE\r
        EndGlobalSection\r
 EndGlobal\r
index 4623e373dffd02685f069ee7f93a7f70a7727554..e0ab8a461cf1f505c7fb6bbbd4424dbb73cb3a3d 100644 (file)
     Change History (most recent first):
     
 $Log: CommonServices.h,v $
+Revision 1.11  2009/03/30 19:51:29  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
+Revision 1.10  2009/01/11 03:20:06  mkrochma
+<rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
+
+Revision 1.9  2009/01/10 22:03:43  mkrochma
+<rdar://problem/5797507> dnsextd fails to build on Linux
+
 Revision 1.8  2007/01/17 19:16:59  cheshire
 Only define ssize_t if it's not already defined
 
@@ -92,6 +102,16 @@ Common Services and portability support for various platforms.
        #endif
 #endif
 
+// Solaris
+
+#if( !defined( TARGET_OS_SOLARIS ) )
+       #if( defined(solaris) || (defined(__SVR4) && defined(sun)) )
+               #define TARGET_OS_SOLARIS               1
+       #else
+               #define TARGET_OS_SOLARIS               0
+       #endif
+#endif
+
 // Palm
 
 #if( !defined( TARGET_OS_PALM ) )
@@ -108,7 +128,7 @@ Common Services and portability support for various platforms.
        
        // No predefined macro for VxWorks so just assume VxWorks if nothing else is set.
        
-       #if( !macintosh && !__MACH__  && !defined( __linux__ ) && !defined( __PALMOS_TRAPS__ ) && !defined( __PALMOS_ARMLET__ ) && !defined( _WIN32 ) )
+       #if( !macintosh && !__MACH__  && !defined( __linux__ ) && !defined ( __SVR4 ) && !defined ( __sun ) && !defined( __PALMOS_TRAPS__ ) && !defined( __PALMOS_ARMLET__ ) && !defined( _WIN32 ) )
                #define TARGET_OS_VXWORKS               1
        #else
                #define TARGET_OS_VXWORKS               0
@@ -148,6 +168,9 @@ Common Services and portability support for various platforms.
 //===========================================================================================================================
 
 #if( !KERNEL )
+       #if defined(WIN32) && !defined(_WSPIAPI_COUNTOF)
+               #define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+       #endif
        #include        <stddef.h>
 #endif
        
@@ -196,7 +219,26 @@ Common Services and portability support for various platforms.
        
 #elif( TARGET_OS_LINUX )
        
-       // Linux (no special includes yet).
+       // Linux
+       
+       #include        <stdint.h>
+       #include        <arpa/inet.h>
+       
+#elif( TARGET_OS_SOLARIS )
+       
+       // Solaris
+
+       #include        <stdint.h>
+
+       #include        <arpa/inet.h>
+       #include        <arpa/nameser.h>
+
+       #if ( defined( BYTE_ORDER ) && defined( LITTLE_ENDIAN ) && ( BYTE_ORDER == LITTLE_ENDIAN ) )
+               #define TARGET_RT_LITTLE_ENDIAN         1
+       #endif
+       #if ( defined( BYTE_ORDER ) && defined( BIG_ENDIAN ) && ( BYTE_ORDER == BIG_ENDIAN ) )
+               #define TARGET_RT_BIG_ENDIAN            1
+       #endif
 
 #elif( TARGET_OS_PALM )
        
index 9ecb7cb6d384590306ca8dcf892432daa717f29b..e608869f8618b47239f317e0f3cd74ee6eab73c6 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: DNSSD.java,v $
+Revision 1.16  2008/11/04 20:06:20  cheshire
+<rdar://problem/6186231> Change MAX_DOMAIN_NAME to 256
+
 Revision 1.15  2007/03/13 00:28:03  vazquez
 <rdar://problem/4625928> Java: Rename exported symbols in libjdns_sd.jnilib
 
@@ -126,7 +129,7 @@ abstract public class       DNSSD
        public static final int         REGISTRATION_DOMAINS = ( 1 << 7 );
 
        /** Maximum length, in bytes, of a domain name represented as an escaped C-String. */
-    public static final int     MAX_DOMAIN_NAME = 1005;
+    public static final int     MAX_DOMAIN_NAME = 1009;
 
        /** Pass for ifIndex to specify all available interfaces. */
     public static final int     ALL_INTERFACES = 0;
index 434c2f1a5b684cbb3833fd832a99341d1950b78b..c3bf9ccf0218a7a361133ef07a143cbcb2f31176 100644 (file)
     Change History (most recent first):
 
 $Log: PlatformCommon.c,v $
+Revision 1.21  2009/04/11 00:20:24  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.20  2008/10/09 22:26:05  cheshire
+Save space by not showing high-resolution timestamp in LogMsgNoIdent() lines
+
+Revision 1.19  2008/07/14 17:43:36  mkrochma
+Fix previous check in so connect still gets called
+
+Revision 1.18  2008/07/12 17:19:41  mkrochma
+<rdar://problem/6068351> mDNSResponder PlatformCommon.c uses sin_len even on non-compliant platforms
+
 Revision 1.17  2008/03/05 00:19:09  cheshire
 Conditionalize LogTimeStamps so it's specific to APPLE_OSX, for now
 
@@ -97,19 +109,26 @@ mDNSexport void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAdd
        {
        union { struct sockaddr s; struct sockaddr_in a4; struct sockaddr_in6 a6; } addr;
        socklen_t len = sizeof(addr);
+       socklen_t inner_len = 0;
        int sock = socket(AF_INET, SOCK_DGRAM, 0);
        src->type = mDNSAddrType_None;
        if (sock == -1) return;
        if (dst->type == mDNSAddrType_IPv4)
                {
-               addr.a4.sin_len         = sizeof(addr.a4);
+               inner_len = sizeof(addr.a4);
+               #ifndef NOT_HAVE_SA_LEN
+               addr.a4.sin_len         = inner_len;
+               #endif
                addr.a4.sin_family      = AF_INET;
                addr.a4.sin_port        = 1;    // Not important, any port will do
                addr.a4.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
                }
        else if (dst->type == mDNSAddrType_IPv6)
                {
-               addr.a6.sin6_len      = sizeof(addr.a6);
+               inner_len = sizeof(addr.a6);
+               #ifndef NOT_HAVE_SA_LEN
+               addr.a6.sin6_len      = inner_len;
+               #endif
                addr.a6.sin6_family   = AF_INET6;
                addr.a6.sin6_flowinfo = 0;
                addr.a6.sin6_port     = 1;      // Not important, any port will do
@@ -117,8 +136,8 @@ mDNSexport void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAdd
                addr.a6.sin6_scope_id = 0;
                }
        else return;
-       
-       if ((connect(sock, &addr.s, addr.s.sa_len)) < 0)
+
+       if ((connect(sock, &addr.s, inner_len)) < 0)
                { LogMsg("mDNSPlatformSourceAddrForDest: connect %#a failed errno %d (%s)", dst, errno, strerror(errno)); goto exit; }
 
        if ((getsockname(sock, &addr.s, &len)) < 0)
@@ -202,7 +221,7 @@ mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
        }
 #endif
 
-mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, int logoptflags)
+mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, mDNSLogLevel_t loglevel)
        {
 #if APPLE_OSX_mDNSResponder && LogTimeStamps
        extern mDNS mDNSStorage;
@@ -214,7 +233,7 @@ mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, i
        if (mDNS_DebugMode)     // In debug mode we write to stderr
                {
 #if APPLE_OSX_mDNSResponder && LogTimeStamps
-               if (mDNSPlatformClockDivisor)
+               if (ident && ident[0] && mDNSPlatformClockDivisor)
                        fprintf(stderr,"%8d.%03d: %s\n", (int)(t/1000), ms, buffer);
                else
 #endif
@@ -223,13 +242,28 @@ mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, i
                }
        else                            // else, in production mode, we write to syslog
                {
-               openlog(ident, LOG_CONS | logoptflags, LOG_DAEMON);
+               static int log_inited = 0;
+               
+               int syslog_level = LOG_ERR;
+               switch (loglevel) 
+                       {
+                       case MDNS_LOG_MSG:       syslog_level = LOG_ERR;     break;
+                       case MDNS_LOG_OPERATION: syslog_level = LOG_WARNING; break;
+                       case MDNS_LOG_SPS:       syslog_level = LOG_NOTICE;  break;
+                       case MDNS_LOG_INFO:      syslog_level = LOG_INFO;    break;
+                       case MDNS_LOG_DEBUG:     syslog_level = LOG_DEBUG;   break;
+                       default:
+                       fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel);
+                       fflush(stderr);
+                       }
+               
+               if (!log_inited) { openlog(ident, LOG_CONS, LOG_DAEMON); log_inited++; }
+
 #if APPLE_OSX_mDNSResponder && LogTimeStamps
-               if (mDNSPlatformClockDivisor)
-                       syslog(LOG_ERR, "%8d.%03d: %s", (int)(t/1000), ms, buffer);
+               if (ident && ident[0] && mDNSPlatformClockDivisor)
+                       syslog(syslog_level, "%8d.%03d: %s", (int)(t/1000), ms, buffer);
                else
 #endif
-                       syslog(LOG_ERR, "%s", buffer);
-               closelog();
+                       syslog(syslog_level, "%s", buffer);
                }
        }
index 4dd99a76192ef39fec953020cceb507bf849a701..3169a5a21ab28b8f2dc5c30f705396ea8e183fd8 100644 (file)
  * 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 earler
+ *  => 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 1760300
+#define _DNS_SD_H 2120100
 
 #ifdef  __cplusplus
     extern "C" {
@@ -115,7 +115,6 @@ typedef INT32       int32_t;
 #elif defined(_WIN32)
 #include <windows.h>
 #define _UNUSED
-#define bzero(a, b) memset(a, 0, b)
 #ifndef _MSL_STDINT_H
 typedef UINT8       uint8_t;
 typedef INT8        int8_t;
@@ -242,11 +241,9 @@ enum
      * 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)
      */
 
-    /* Previous name for kDNSServiceFlagsReturnIntermediates flag (not used externally) */
-    #define kDNSServiceFlagsReturnCNAME kDNSServiceFlagsReturnIntermediates
-
     kDNSServiceFlagsNonBrowsable        = 0x2000,
     /* A service registered with the NonBrowsable flag set can be resolved using
      * DNSServiceResolve(), but will not be discoverable using DNSServiceBrowse().
@@ -256,7 +253,7 @@ enum
      * an associated PTR record.
      */
 
-    kDNSServiceFlagsShareConnection     = 0x4000
+    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
@@ -284,24 +281,38 @@ enum
      * 1. Collective kDNSServiceFlagsMoreComing flag
      * When callbacks are invoked using a shared DNSServiceRef, the
      * kDNSServiceFlagsMoreComing flag applies collectively to *all* active
-     * operations sharing the same DNSServiceRef. If the MoreComing flag is
-     * set it means that there are more results queued on this DNSServiceRef,
+     * 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 DNSServiceRef that need updating,
-     * not just the UI elements related to the particular callback that happened
-     * to be the last one to be invoked.
+     * 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.
      *
-     * 2. Only share DNSServiceRef's created with DNSServiceCreateConnection
+     * 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.
      *
-     * 3. Don't Double-Deallocate
+     * 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))
@@ -311,7 +322,7 @@ enum
      * 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.
      *
-     * 4. Thread Safety
+     * 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
@@ -319,6 +330,9 @@ enum
      * lock or take similar appropriate precautions to serialize those calls.
      */
 
+    kDNSServiceFlagsSuppressUnusable    = 0x8000
+    /* Placeholder definition, for future use
+     */
     };
 
 /* Possible protocols for DNSServiceNATPortMappingCreate(). */
@@ -400,9 +414,19 @@ enum
     kDNSServiceType_SSHFP     = 44,     /* SSH Key Fingerprint */
     kDNSServiceType_IPSECKEY  = 45,     /* IPSECKEY */
     kDNSServiceType_RRSIG     = 46,     /* RRSIG */
-    kDNSServiceType_NSEC      = 47,     /* NSEC */
+    kDNSServiceType_NSEC      = 47,     /* Denial of Existence */
     kDNSServiceType_DNSKEY    = 48,     /* DNSKEY */
-    kDNSServiceType_DHCID     = 49,     /* DHCID */
+    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. */
@@ -460,15 +484,15 @@ enum
 /* 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 1005
+#define kDNSServiceMaxDomainName 1009
 
 /*
  * Notes on DNS Name Escaping
  *   -- or --
- * "Why is kDNSServiceMaxDomainName 1005, when the maximum legal domain name is 255 bytes?"
+ * "Why is kDNSServiceMaxDomainName 1009, when the maximum legal domain name is 256 bytes?"
  *
- * All strings used in DNS-SD are UTF-8 strings.
- * With few exceptions, most are also escaped using standard DNS escaping rules:
+ * 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
@@ -493,7 +517,7 @@ enum
  * _service._udp, where the "service" part is 1-14 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 255 bytes.
+ * 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
@@ -979,7 +1003,9 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister
  *
  * rdata:           The raw rdata to be contained in the added resource record.
  *
- * ttl:             The time to live of the resource record, in seconds. Pass 0 to use a default value.
+ * 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).
@@ -1019,6 +1045,8 @@ DNSServiceErrorType DNSSD_API DNSServiceAddRecord
  * 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.
@@ -1600,7 +1628,7 @@ DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef);
  *                  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
- *                  DNSServiceRefDealloocate()).
+ *                  DNSServiceRefDeallocate()).
  *
  * flags:           Possible values are kDNSServiceFlagsShared or kDNSServiceFlagsUnique
  *                  (see flag type definitions for details).
@@ -1620,7 +1648,9 @@ DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef);
  *
  * 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. Pass 0 to use a default value.
+ * 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.)
@@ -1704,25 +1734,66 @@ DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
 
 /* DNSServiceNATPortMappingCreate
  *
- * Request a port mapping in the NAT gateway which maps a port on the local machine
- * to a public port on the NAT.
+ * Request a port mapping in the NAT gateway, which maps a port on the local machine
+ * to an external port on the NAT.
+ *
  * 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
- * public IP address and the public port that has been allocated for this client.
- * The client should then record this public IP address and port using whatever
+ * 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 public IP address and port for the service are recorded in the global DNS.
+ * 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 public port being mapped for this client. Over the lifetime of any long-lived
+ * 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().
@@ -1737,14 +1808,14 @@ DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
  *                  For other failures, will indicate the failure that occurred, and the other
  *                  parameters are undefined.
  *
- * publicAddress:   Four byte IPv4 address in network byte order.
+ * externalAddress: Four byte IPv4 address in network byte order.
  *
  * protocol:        Will be kDNSServiceProtocol_UDP or kDNSServiceProtocol_TCP or both.
  *
- * privatePort:     The port on the local machine that was mapped.
+ * internalPort:    The port on the local machine that was mapped.
  *
- * publicPort:      The actual public port in the NAT gateway that was mapped.
- *                  This is very likely to be different than the requested public port.
+ * 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
@@ -1763,11 +1834,11 @@ typedef void (DNSSD_API *DNSServiceNATPortMappingReply)
     DNSServiceFlags                  flags,
     uint32_t                         interfaceIndex,
     DNSServiceErrorType              errorCode,
-    uint32_t                         publicAddress,    /* four byte IPv4 address in network byte order */
+    uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
     DNSServiceProtocol               protocol,
-    uint16_t                         privatePort,
-    uint16_t                         publicPort,       /* may be different than the requested port */
-    uint32_t                         ttl,              /* may be different than the requested ttl */
+    uint16_t                         internalPort,
+    uint16_t                         externalPort,      /* may be different than the requested port     */
+    uint32_t                         ttl,               /* may be different than the requested ttl      */
     void                             *context
     );
 
@@ -1786,14 +1857,14 @@ typedef void (DNSSD_API *DNSServiceNATPortMappingReply)
  *
  * 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 privatePort parameter.
- *                  To just discover the NAT gateway's public IP address, pass zero for protocol,
- *                  privatePort, publicPort and ttl.
+ *                  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.
  *
- * privatePort:     The port number in network byte order on the local machine which is listening for packets.
+ * internalPort:    The port number in network byte order on the local machine which is listening for packets.
  *
- * publicPort:      The requested public port in network byte order in the NAT gateway that you would
- *                  like to map to the private port. Pass 0 if you don't care which public port is chosen for you.
+ * 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
@@ -1817,8 +1888,8 @@ typedef void (DNSSD_API *DNSServiceNATPortMappingReply)
  *                  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 public IP address (e.g. for UI
- *                  display) then pass zero for protocol, privatePort, publicPort and ttl.
+ *                  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
@@ -1826,12 +1897,12 @@ DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
     DNSServiceRef                    *sdRef,
     DNSServiceFlags                  flags,
     uint32_t                         interfaceIndex,
-    DNSServiceProtocol               protocol,         /* TCP and/or UDP */
-    uint16_t                         privatePort,      /* network byte order */
-    uint16_t                         publicPort,       /* network byte order */
-    uint32_t                         ttl,              /* time to live in seconds */
+    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 */
+    void                             *context           /* may be NULL             */
     );
 
 
@@ -1850,7 +1921,7 @@ DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
  * Parameters:
  *
  * fullName:        A pointer to a buffer that where the resulting full domain name is to be written.
- *                  The buffer must be kDNSServiceMaxDomainName (1005) bytes in length to
+ *                  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.
@@ -1863,11 +1934,11 @@ DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
  * 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 0 on success, -1 on error.
+ * return value:    Returns kDNSServiceErr_NoError (0) on success, kDNSServiceErr_BadParam on error.
  *
  */
 
-int DNSSD_API DNSServiceConstructFullName
+DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
     (
     char                            *fullName,
     const char                      *service,      /* may be NULL */
@@ -1988,7 +2059,7 @@ void DNSSD_API TXTRecordDeallocate
  *
  * key:             A null-terminated string which only contains printable ASCII
  *                  values (0x20-0x7E), excluding '=' (0x3D). Keys should be
- *                  8 characters or less (not counting the terminating null).
+ *                  9 characters or fewer (not counting the terminating null).
  *
  * valueSize:       The size of the value.
  *
@@ -2087,13 +2158,13 @@ const void * DNSSD_API TXTRecordGetBytesPtr
  * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1);
  * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2);
  * ...
- * bcopy(val1ptr, myval1, len1);
- * bcopy(val2ptr, myval2, 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 bcopy()
+ * 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
@@ -2203,7 +2274,7 @@ uint16_t DNSSD_API TXTRecordGetCount
  * 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
- *                  8 characters or less. To hold the maximum possible
+ *                  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.
index 807ced9fcaeba35f66fbd843216a39613ed3edba..d272f0f0c55aae952dd35437ee9f3279da61810b 100644 (file)
     Change History (most recent first):
 
 $Log: dnsextd.c,v $
+Revision 1.97  2009/01/13 05:31:34  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.96  2009/01/13 00:45:41  cheshire
+Uncommented "#ifdef NOT_HAVE_DAEMON" check
+
+Revision 1.95  2009/01/12 22:47:13  cheshire
+Only include "mDNSUNP.h" when building on a system that requires the "daemon()" definition (currently only Solaris)
+
+Revision 1.94  2009/01/11 03:20:06  mkrochma
+<rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
+
+Revision 1.93  2008/12/17 05:06:53  cheshire
+Increased maximum DNS Update lifetime from 20 minutes to 2 hours -- now that we have Sleep Proxy,
+having clients wake every fifteen minutes to renew their record registrations is no longer reasonable.
+
+Revision 1.92  2008/11/13 19:09:36  cheshire
+Updated rdataOPT code
+
+Revision 1.91  2008/11/04 23:06:51  cheshire
+Split RDataBody union definition into RDataBody and RDataBody2, and removed
+SOA from the normal RDataBody union definition, saving 270 bytes per AuthRecord
+
+Revision 1.90  2008/10/03 18:18:57  cheshire
+Define dummy "mDNS_ConfigChanged(mDNS *const m)" routine to avoid link errors
+
+Revision 1.89  2008/09/15 23:52:30  cheshire
+<rdar://problem/6218902> mDNSResponder-177 fails to compile on Linux with .desc pseudo-op
+Made __crashreporter_info__ symbol conditional, so we only use it for OS X build
+
 Revision 1.88  2008/03/06 21:26:11  cheshire
 Moved duplicated STRINGIFY macro from individual C files to DNSCommon.h
 
@@ -191,6 +221,11 @@ Revision 1.42  2006/07/05 22:48:19  cheshire
 #include <time.h>
 #include <errno.h>
 
+// Solaris doesn't have daemon(), so we define it here
+#ifdef NOT_HAVE_DAEMON
+#include "../mDNSPosix/mDNSUNP.h"              // For daemon()
+#endif // NOT_HAVE_DAEMON
+
 // Compatibility workaround
 #ifndef AF_LOCAL
 #define AF_LOCAL AF_UNIX
@@ -591,7 +626,7 @@ RecvPacket
 
                pkt = malloc(allocsize);
                require_action_quiet( pkt, exit, err = mStatus_NoMemoryErr; LogErr( "RecvPacket", "malloc" ) );
-               bzero( pkt, sizeof( *pkt ) );
+               mDNSPlatformMemZero( pkt, sizeof( *pkt ) );
                }
        
        pkt->len = msglen;
@@ -600,7 +635,7 @@ RecvPacket
        if ( getpeername( fd, ( struct sockaddr* ) &pkt->src, &srclen ) || ( srclen != sizeof( pkt->src ) ) )
                {
                LogErr("RecvPacket", "getpeername");
-               bzero(&pkt->src, sizeof(pkt->src));
+               mDNSPlatformMemZero(&pkt->src, sizeof(pkt->src));
                }
 
        nread = my_recv(sock, &pkt->msg, msglen, closed );
@@ -703,7 +738,7 @@ mDNSlocal mDNSBool IsLLQRequest(PktMsg *pkt)
                if (!ptr) { Log("Unable to read additional record"); goto end; }
                }
 
-       if ( lcr.r.resrec.rrtype == kDNSType_OPT && lcr.r.resrec.rdlength >= LLQ_OPT_RDLEN && lcr.r.resrec.rdata->u.opt.opt == kDNSOpt_LLQ )
+       if ( lcr.r.resrec.rrtype == kDNSType_OPT && lcr.r.resrec.rdlength >= DNSOpt_LLQData_Space && lcr.r.resrec.rdata->u.opt[0].opt == kDNSOpt_LLQ )
                {
                result = mDNStrue;
                }
@@ -926,7 +961,7 @@ mDNSlocal CacheRecord *CopyCacheRecord(const CacheRecord *orig, domainname *name
        cr = malloc(size);
        if (!cr) { LogErr("CopyCacheRecord", "malloc"); return NULL; }
        memcpy(cr, orig, size);
-       cr->resrec.rdata = (RData*)&cr->rdatastorage;
+       cr->resrec.rdata = (RData*)&cr->smallrdatastorage;
        cr->resrec.name = name;
        
        return cr;
@@ -947,7 +982,7 @@ mDNSlocal void RehashTable(DaemonInfo *d)
        VLog("Rehashing lease table (new size %d buckets)", newnbuckets);
        new = malloc(sizeof(RRTableElem *) * newnbuckets);
        if (!new) { LogErr("RehashTable", "malloc");  return; }
-       bzero(new, newnbuckets * sizeof(RRTableElem *));
+       mDNSPlatformMemZero(new, newnbuckets * sizeof(RRTableElem *));
 
        for (i = 0; i < d->nbuckets; i++)
                {
@@ -1008,7 +1043,7 @@ mDNSlocal mDNSu8 *putRRSetDeletion(DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit,
        ptr[1] = (mDNSu8)(rr->rrtype  &  0xFF);
        ptr[2] = (mDNSu8)((mDNSu16)kDNSQClass_ANY >> 8);
        ptr[3] = (mDNSu8)((mDNSu16)kDNSQClass_ANY &  0xFF);
-       bzero(ptr+4, sizeof(rr->rroriginalttl) + sizeof(rr->rdlength)); // zero ttl/rdata
+       mDNSPlatformMemZero(ptr+4, sizeof(rr->rroriginalttl) + sizeof(rr->rdlength)); // zero ttl/rdata
        msg->h.mDNS_numUpdates++;
        return ptr + 10;
        }
@@ -1208,7 +1243,7 @@ mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d)
 
        // setup our sockaddr
 
-       bzero( &d->addr, sizeof( d->addr ) );
+       mDNSPlatformMemZero( &d->addr, sizeof( d->addr ) );
        d->addr.sin_addr.s_addr = zerov4Addr.NotAnInteger;
        d->addr.sin_port                = UnicastDNSPort.NotAnInteger;
        d->addr.sin_family              = AF_INET;
@@ -1218,7 +1253,7 @@ mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d)
 
        // setup nameserver's sockaddr
 
-       bzero(&d->ns_addr, sizeof(d->ns_addr));
+       mDNSPlatformMemZero(&d->ns_addr, sizeof(d->ns_addr));
        d->ns_addr.sin_family   = AF_INET;
        inet_pton( AF_INET, LOOPBACK, &d->ns_addr.sin_addr );
        d->ns_addr.sin_port             = NSIPCPort.NotAnInteger;
@@ -1281,7 +1316,7 @@ mDNSlocal int InitLeaseTable(DaemonInfo *d)
        d->nelems = 0;
        d->table = malloc(sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS);
        if (!d->table) { LogErr("InitLeaseTable", "malloc"); return -1; }
-       bzero(d->table, sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS);
+       mDNSPlatformMemZero(d->table, sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS);
        return 0;
        }
 
@@ -1328,7 +1363,7 @@ SetupSockets
 
        // set up sockets on which we receive llq requests
 
-       bzero(&self->llq_addr, sizeof(self->llq_addr));
+       mDNSPlatformMemZero(&self->llq_addr, sizeof(self->llq_addr));
        self->llq_addr.sin_family               = AF_INET;
        self->llq_addr.sin_addr.s_addr  = zerov4Addr.NotAnInteger;
        self->llq_addr.sin_port                 = ( self->llq_port.NotAnInteger ) ? self->llq_port.NotAnInteger : DNSEXTPort.NotAnInteger;
@@ -1370,7 +1405,7 @@ SetupSockets
 
        self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 );
        require_action( dnssd_SocketValid(self->tlssd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
-       bzero(&daddr, sizeof(daddr));
+       mDNSPlatformMemZero(&daddr, sizeof(daddr));
        daddr.sin_family                = AF_INET;
        daddr.sin_addr.s_addr   = zerov4Addr.NotAnInteger;
        daddr.sin_port                  = ( self->private_port.NotAnInteger ) ? self->private_port.NotAnInteger : PrivateDNSPort.NotAnInteger;
@@ -1580,7 +1615,7 @@ mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
                                tmp = malloc(allocsize);
                                if (!tmp) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; }
                                memcpy(&tmp->rr, &lcr.r, sizeof(CacheRecord) + rr->rdlength - InlineCacheRDSize);
-                               tmp->rr.resrec.rdata = (RData *)&tmp->rr.rdatastorage;
+                               tmp->rr.resrec.rdata = (RData *)&tmp->rr.smallrdatastorage;
                                AssignDomainName(&tmp->name, rr->name);
                                tmp->rr.resrec.name = &tmp->name;
                                tmp->expire = tv.tv_sec + (unsigned)lease;
@@ -1661,15 +1696,15 @@ HandleRequest
                        static const mDNSOpaque16 UpdateRefused = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update, kDNSFlag1_RC_Refused } };
                        Log("Rejecting Update Request with %d additions but no lease", adds);
                        reply = malloc(sizeof(*reply));
-                       bzero(&reply->src, sizeof(reply->src));
+                       mDNSPlatformMemZero(&reply->src, sizeof(reply->src));
                        reply->len = sizeof(DNSMessageHeader);
                        reply->zone = NULL;
                        reply->isZonePublic = 0;
                        InitializeDNSMessage(&reply->msg.h, request->msg.h.id, UpdateRefused);
                        return(reply);
                        }
-               if (lease > 1200)       // Don't allow lease greater than 20 minutes
-                       lease = 1200;
+               if (lease > 7200)       // Don't allow lease greater than two hours; typically 90-minute renewal period
+                       lease = 7200;
                }
        // Send msg to server, read reply
 
@@ -1772,18 +1807,17 @@ exit:
 // Set fields of an LLQ OPT Resource Record
 mDNSlocal void FormatLLQOpt(AuthRecord *opt, int opcode, const mDNSOpaque64 *const id, mDNSs32 lease)
        {
-       bzero(opt, sizeof(*opt));
+       mDNSPlatformMemZero(opt, sizeof(*opt));
        mDNS_SetupResourceRecord(opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
        opt->resrec.rrclass = NormalMaxDNSMessageData;
-       opt->resrec.rdlength = LLQ_OPT_RDLEN;
-       opt->resrec.rdestimate = LLQ_OPT_RDLEN;
-       opt->resrec.rdata->u.opt.opt = kDNSOpt_LLQ;
-       opt->resrec.rdata->u.opt.optlen = sizeof(LLQOptData);
-       opt->resrec.rdata->u.opt.OptData.llq.vers  = kLLQ_Vers;
-       opt->resrec.rdata->u.opt.OptData.llq.llqOp = opcode;
-       opt->resrec.rdata->u.opt.OptData.llq.err   = LLQErr_NoError;
-       opt->resrec.rdata->u.opt.OptData.llq.id    = *id;
-       opt->resrec.rdata->u.opt.OptData.llq.llqlease = lease;
+       opt->resrec.rdlength   = sizeof(rdataOPT);      // One option in this OPT record
+       opt->resrec.rdestimate = sizeof(rdataOPT);
+       opt->resrec.rdata->u.opt[0].opt = kDNSOpt_LLQ;
+       opt->resrec.rdata->u.opt[0].u.llq.vers  = kLLQ_Vers;
+       opt->resrec.rdata->u.opt[0].u.llq.llqOp = opcode;
+       opt->resrec.rdata->u.opt[0].u.llq.err   = LLQErr_NoError;
+       opt->resrec.rdata->u.opt[0].u.llq.id    = *id;
+       opt->resrec.rdata->u.opt[0].u.llq.llqlease = lease;
        }
 
 // Calculate effective remaining lease of an LLQ
@@ -2481,14 +2515,14 @@ mDNSlocal int RecvLLQ( DaemonInfo *d, PktMsg *pkt, TCPSocket *sock )
 
        // validate OPT
        if (opt.r.resrec.rrtype != kDNSType_OPT) { Log("Malformatted LLQ from %s: last Additional not an OPT RR", addr); goto end; }
-       if (opt.r.resrec.rdlength < pkt->msg.h.numQuestions * LLQ_OPT_RDLEN) { Log("Malformatted LLQ from %s: OPT RR to small (%d bytes for %d questions)", addr, opt.r.resrec.rdlength, pkt->msg.h.numQuestions); }
+       if (opt.r.resrec.rdlength < pkt->msg.h.numQuestions * DNSOpt_LLQData_Space) { Log("Malformatted LLQ from %s: OPT RR to small (%d bytes for %d questions)", addr, opt.r.resrec.rdlength, pkt->msg.h.numQuestions); }
        
        // dispatch each question
        for (i = 0; i < pkt->msg.h.numQuestions; i++)
                {
                qptr = getQuestion(&pkt->msg, qptr, end, 0, &q);
                if (!qptr) { Log("Malformatted LLQ from %s: cannot read question %d", addr, i); goto end; }
-               llq = (LLQOptData *)&opt.r.resrec.rdata->u.opt.OptData.llq + i; // point into OptData at index i
+               llq = (LLQOptData *)&opt.r.resrec.rdata->u.opt[0].u.llq + i; // point into OptData at index i
                if (llq->vers != kLLQ_Vers) { Log("LLQ from %s contains bad version %d (expected %d)", addr, llq->vers, kLLQ_Vers); goto end; }
                
                e = LookupLLQ(d, pkt->src, &q.qname, q.qtype, &llq->id);
@@ -2702,7 +2736,7 @@ RecvUDPMessage
        context = malloc( sizeof( UDPContext ) );
        require_action( context, exit, err = mStatus_NoMemoryErr ; LogErr( "RecvUDPMessage", "malloc" ) );
 
-       bzero( context, sizeof( *context ) );
+       mDNSPlatformMemZero( context, sizeof( *context ) );
        context->d = self;
        context->sd = sd;
 
@@ -2940,7 +2974,7 @@ AcceptTCPConnection
        
        context = ( TCPContext* ) malloc( sizeof( TCPContext ) );
        require_action( context, exit, err = mStatus_NoMemoryErr; LogErr( "AcceptTCPConnection", "malloc" ) );
-       bzero( context, sizeof( sizeof( TCPContext ) ) );
+       mDNSPlatformMemZero( context, sizeof( sizeof( TCPContext ) ) );
        context->d               = self;
        newSock = accept( sd, ( struct sockaddr* ) &context->cliaddr, &clilen );
        require_action( newSock != -1, exit, err = mStatus_UnknownErr; LogErr( "AcceptTCPConnection", "accept" ) );
@@ -3158,7 +3192,7 @@ int main(int argc, char *argv[])
 
        d = malloc(sizeof(*d));
        if (!d) { LogErr("main", "malloc"); exit(1); }
-       bzero(d, sizeof(DaemonInfo));
+       mDNSPlatformMemZero(d, sizeof(DaemonInfo));
 
        // Setup the public SRV record names
 
@@ -3224,6 +3258,7 @@ int main(int argc, char *argv[])
 // It's an error for these routines to actually be called, so perhaps we should log any call
 // to them.
 void mDNSCoreInitComplete( mDNS * const m, mStatus result) { ( void ) m; ( void ) result; }
+void mDNS_ConfigChanged(mDNS *const m)  { ( void ) m; }
 void mDNSCoreMachineSleep(mDNS * const m, mDNSBool wake) { ( void ) m; ( void ) wake; }
 void mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end,
                                 const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
@@ -3262,6 +3297,8 @@ mDNS mDNSStorage;
 // The "@(#) " pattern is a special prefix the "what" command looks for
 const char mDNSResponderVersionString_SCCS[] = "@(#) dnsextd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
 
+#if _BUILDING_XCODE_PROJECT_
 // If the process crashes, then this string will be magically included in the automatically-generated crash log
 const char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5;
 asm(".desc ___crashreporter_info__, 0x10");
+#endif
index be64cbd65df0a76b61dc8948b524618d494ff7ad..352828fedde6e1fae86dc50f73c09ebaaaeb4df6 100644 (file)
     Change History (most recent first):
 
 $Log: dnsextd_lexer.l,v $
+Revision 1.6  2008/07/18 17:40:46  cheshire
+Removed redundant definition of "YY_NO_UNPUT" (not needed now that we use "%option nounput" instead)
+
+Revision 1.5  2008/06/24 18:32:26  mcguire
+<rdar://problem/6024542> flex producing .c files that result in warnings
+
 Revision 1.4  2007/05/25 20:01:43  cheshire
 <rdar://problem/5226767> /usr/bin/flex failures prevent mDNSResponder from building
 Only define "int yylineno" on flex 2.5.4 and earlier
@@ -47,8 +53,6 @@ extern YYSTYPE yylval;
 int yylineno = 1;
 #endif
 
-#define YY_NO_UNPUT
-
 int  yylex(void);
 
 static char*
@@ -69,6 +73,7 @@ StripQuotes
 
 %}
 
+%option nounput
 %%
 
 options                                                                return OPTIONS;
index 8332df5f9af8bb145d40b4ea5521451eb6255f13..943be297f981a101275e884fe7210b8b0ac383ed 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: dnsextd_parser.y,v $
+Revision 1.9  2009/01/11 03:20:06  mkrochma
+<rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
+
 Revision 1.8  2007/03/21 19:47:50  cheshire
 <rdar://problem/4789463> Leak: On error path in ParseConfig
 
@@ -49,8 +52,8 @@ Revision 1.1  2006/07/06 00:09:05  cheshire
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <mDNSEmbeddedAPI.h>
-#include <DebugServices.h>
+#include "mDNSEmbeddedAPI.h"
+#include "DebugServices.h"
 #include "dnsextd.h"
 
 void yyerror( const char* error );
index 01ffaff9fbf4d601579b49cdf94530f4a2ec670d..d5d46c8b02a1d0e763d470702cbc91d72754e78a 100644 (file)
    Change History (most recent first):
 
 $Log: dnssd_clientlib.c,v $
+Revision 1.21  2009/04/01 21:10:11  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows. Use _stricmp and _strnicmp.
+
+Revision 1.20  2008/11/26 20:57:37  cheshire
+For consistency with other similar macros, renamed mdnsIsDigit/mdnsIsLetter/mdnsValidHostChar
+to mDNSIsDigit/mDNSIsLetter/mDNSValidHostChar
+
+Revision 1.19  2008/11/04 21:15:18  cheshire
+<rdar://problem/5969564> Potential buffer overflows in DNSServiceConstructFullName
+
 Revision 1.18  2007/11/30 23:06:10  cheshire
 Fixed compile warning: declaration of 'index' shadows a global declaration
 
@@ -101,6 +111,8 @@ like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code
 #if defined(_WIN32)
 // disable warning "conversion from <data> to uint16_t"
 #pragma warning(disable:4244)
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp 
 #endif
 
 /*********************************************************************************************
@@ -109,7 +121,10 @@ like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code
  *
  *********************************************************************************************/
 
-#define mdnsIsDigit(X)     ((X) >= '0' && (X) <= '9')
+#define mDNSIsDigit(X)     ((X) >= '0' && (X) <= '9')
+
+// DomainEndsInDot returns 1 if name ends with a dot, 0 otherwise
+// (DNSServiceConstructFullName depends this returning 1 for true, rather than any non-zero value meaning true)
 
 static int DomainEndsInDot(const char *dom)
        {
@@ -117,7 +132,7 @@ static int DomainEndsInDot(const char *dom)
                {
                if (dom[0] == '\\') // advance past escaped byte sequence
                        {
-                       if (mdnsIsDigit(dom[1]) && mdnsIsDigit(dom[2]) && mdnsIsDigit(dom[3]))
+                       if (mDNSIsDigit(dom[1]) && mDNSIsDigit(dom[2]) && mDNSIsDigit(dom[3]))
                                dom += 4;                       // If "\ddd"    then skip four
                        else dom += 2;                  // else if "\x" then skip two
                        }
@@ -153,52 +168,66 @@ static uint8_t *InternalTXTRecordSearch
  *
  *********************************************************************************************/
 
-int DNSSD_API DNSServiceConstructFullName
+// Note: Need to make sure we don't write more than kDNSServiceMaxDomainName (1009) bytes to fullName
+// In earlier builds this constant was defined to be 1005, so to avoid buffer overruns on clients
+// compiled with that constant we'll actually limit the output to 1005 bytes.
+
+DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
        (
-       char                      *fullName,
-       const char                *service,      /* may be NULL */
-       const char                *regtype,
-       const char                *domain
+       char       *const fullName,
+       const char *const service,      // May be NULL
+       const char *const regtype,
+       const char *const domain
        )
        {
-       unsigned long len;
-       unsigned char c;
-       char *fn = fullName;
-       const char *s = service;
-       const char *r = regtype;
-       const char *d = domain;
+       const size_t len = !regtype ? 0 : strlen(regtype) - DomainEndsInDot(regtype);
+       char       *fn   = fullName;
+       char *const lim  = fullName + 1005;
+       const char *s    = service;
+       const char *r    = regtype;
+       const char *d    = domain;
+
+       // regtype must be at least "x._udp" or "x._tcp"
+       if (len < 6 || !domain || !domain[0]) return kDNSServiceErr_BadParam;
+       if (strncasecmp((regtype + len - 4), "_tcp", 4) && strncasecmp((regtype + len - 4), "_udp", 4)) return kDNSServiceErr_BadParam;
 
        if (service && *service)
                {
                while (*s)
                        {
-                       c = (unsigned char)*s++;
-                       if (c == '.' || (c == '\\')) *fn++ = '\\'; // escape dot and backslash literals
-                       else if (c <= ' ') // escape non-printable characters
+                       unsigned char c = *s++;                         // Needs to be unsigned, or values like 0xFF will be interpreted as < 32
+                       if (c <= ' ')                                           // Escape non-printable characters
                                {
+                               if (fn+4 >= lim) goto fail;
                                *fn++ = '\\';
-                               *fn++ = (char) ('0' + (c / 100));
-                               *fn++ = (char) ('0' + (c / 10) % 10);
-                               c = (unsigned char)('0' + (c % 10));
+                               *fn++ = '0' + (c / 100);
+                               *fn++ = '0' + (c /  10) % 10;
+                               c     = '0' + (c      ) % 10;
                                }
+                       else if (c == '.' || (c == '\\'))       // Escape dot and backslash literals
+                               {
+                               if (fn+2 >= lim) goto fail;
+                               *fn++ = '\\';
+                               }
+                       else
+                               if (fn+1 >= lim) goto fail;
                        *fn++ = (char)c;
                        }
                *fn++ = '.';
                }
 
-       if (!regtype) return -1;
-       len = (unsigned long) strlen(regtype);
-       if (DomainEndsInDot(regtype)) len--;
-       if (len < 6) return -1; // regtype must be at least "x._udp" or "x._tcp"
-       if (strncasecmp((regtype + len - 4), "_tcp", 4) && strncasecmp((regtype + len - 4), "_udp", 4)) return -1;
-       while (*r) *fn++ = *r++;
-       if (!DomainEndsInDot(regtype)) *fn++ = '.';
-
-       if (!domain || !domain[0]) return -1;
-       while (*d) *fn++ = *d++;
-       if (!DomainEndsInDot(domain)) *fn++ = '.';
+       while (*r) if (fn+1 >= lim) goto fail; else *fn++ = *r++;
+       if (!DomainEndsInDot(regtype)) { if (fn+1 >= lim) goto fail; else *fn++ = '.'; }
+
+       while (*d) if (fn+1 >= lim) goto fail; else *fn++ = *d++;
+       if (!DomainEndsInDot(domain)) { if (fn+1 >= lim) goto fail; else *fn++ = '.'; }
+
+       *fn = '\0';
+       return kDNSServiceErr_NoError;
+
+fail:
        *fn = '\0';
-       return 0;
+       return kDNSServiceErr_BadParam;
        }
 
 /*********************************************************************************************
index 3aac7eda9ce460f4a096d9201b6e7ba34e79b958..832601921d19bef28e48f9698f1460ac2f7aeec1 100644 (file)
        Change History (most recent first):
 
 $Log: dnssd_clientstub.c,v $
+Revision 1.134  2009/06/19 23:13:24  cheshire
+<rdar://problem/6990066> Library: crash at handle_resolve_response + 183
+Added check for NULL after calling get_string
+
+Revision 1.133  2009/05/27 22:19:12  cheshire
+Remove questionable uses of errno
+
+Revision 1.132  2009/05/26 21:31:07  herscher
+Fix compile errors on Windows
+
+Revision 1.131  2009/05/26 04:48:19  herscher
+<rdar://problem/6844819> ExplorerPlugin does not work in B4W 2.0
+
+Revision 1.130  2009/05/02 01:29:48  mcguire
+<rdar://problem/6847601> spin calling DNSServiceProcessResult if errno was set to EWOULDBLOCK by an unrelated call
+
+Revision 1.129  2009/05/01 19:18:50  cheshire
+<rdar://problem/6843645> Using duplicate DNSServiceRefs when sharing a connection should return an error
+
+Revision 1.128  2009/04/01 21:09:35  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows.
+
+Revision 1.127  2009/03/03 21:38:19  cheshire
+Improved "deliver_request ERROR" message
+
+Revision 1.126  2009/02/12 21:02:22  cheshire
+Commented out BPF "Sending fd" debugging message
+
+Revision 1.125  2009/02/12 20:28:32  cheshire
+Added some missing "const" declarations
+
+Revision 1.124  2009/02/10 01:44:39  cheshire
+<rdar://problem/6553729> DNSServiceUpdateRecord fails with kDNSServiceErr_BadReference for otherwise valid reference
+
+Revision 1.123  2009/01/19 00:49:21  mkrochma
+Type cast size_t values to unsigned long
+
+Revision 1.122  2009/01/18 03:51:37  mkrochma
+Fix warning in deliver_request on Linux
+
+Revision 1.121  2009/01/16 23:34:37  cheshire
+<rdar://problem/6504143> Uninitialized error code variable in error handling path in deliver_request
+
+Revision 1.120  2009/01/13 05:31:35  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.119  2009/01/11 03:45:08  mkrochma
+Stop type casting num_written and num_read to int
+
+Revision 1.118  2009/01/11 03:20:06  mkrochma
+<rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
+
+Revision 1.117  2009/01/10 22:03:43  mkrochma
+<rdar://problem/5797507> dnsextd fails to build on Linux
+
+Revision 1.116  2009/01/05 16:55:24  cheshire
+<rdar://problem/6452199> Stuck in "Examining available disks"
+ConnectionResponse handler was accidentally matching the parent DNSServiceRef before
+finding the appropriate subordinate DNSServiceRef for the operation in question.
+
+Revision 1.115  2008/12/18 00:19:11  mcguire
+<rdar://problem/6452199> Stuck in "Examining available disks"
+
+Revision 1.114  2008/12/10 02:11:43  cheshire
+ARMv5 compiler doesn't like uncommented stuff after #endif
+
+Revision 1.113  2008/12/04 03:23:05  cheshire
+Preincrement UID counter before we use it -- it helps with debugging if we know the all-zeroes ID should never appear
+
+Revision 1.112  2008/11/25 22:56:54  cheshire
+<rdar://problem/6377257> Make library code more defensive when client calls DNSServiceProcessResult with bad DNSServiceRef repeatedly
+
+Revision 1.111  2008/10/28 17:58:44  cheshire
+If client code keeps calling DNSServiceProcessResult repeatedly after an error, rate-limit the
+"DNSServiceProcessResult called with DNSServiceRef with no ProcessReply function" log messages
+
+Revision 1.110  2008/10/23 23:38:58  cheshire
+For Windows compatibility, instead of "strerror(errno)" use "dnssd_strerror(dnssd_errno)"
+
+Revision 1.109  2008/10/23 23:06:17  cheshire
+Removed () from dnssd_errno macro definition -- it's not a function and doesn't need any arguments
+
+Revision 1.108  2008/10/23 22:33:24  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
+Revision 1.107  2008/10/20 21:50:11  cheshire
+Improved /dev/bpf error message
+
+Revision 1.106  2008/10/20 15:37:18  cheshire
+Log error message if opening /dev/bpf fails
+
+Revision 1.105  2008/09/27 01:26:34  cheshire
+Added handler to pass back BPF fd when requested
+
+Revision 1.104  2008/09/23 01:36:00  cheshire
+Updated code to use internalPort/externalPort terminology, instead of the old privatePort/publicPort
+terms (which could be misleading, because the word "private" suggests security).
+
+Revision 1.103  2008/07/24 18:51:13  cheshire
+Removed spurious spaces
+
 Revision 1.102  2008/02/25 19:16:19  cheshire
 <rdar://problem/5708953> Problems with DNSServiceGetAddrInfo API
 Was returning a bogus result (NULL pointer) when following a CNAME referral
@@ -215,9 +316,13 @@ Minor textual tidying
 
 #if defined(_WIN32)
 
+       #define _SSIZE_T
+       #include <CommonServices.h>
+       #include <DebugServices.h>
        #include <winsock2.h>
        #include <ws2tcpip.h>
        #include <windows.h>
+       #include <stdarg.h>
        
        #define sockaddr_mdns sockaddr_in
        #define AF_MDNS AF_INET
@@ -233,9 +338,22 @@ Minor textual tidying
        #define sleep(X) Sleep((X) * 1000)
        
        static int g_initWinsock = 0;
-
+       #define LOG_WARNING kDebugLevelWarning
+       static void syslog( int priority, const char * message, ...)
+               {
+               va_list args;
+               int len;
+               char * buffer;
+               DWORD err = WSAGetLastError();
+               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>
@@ -268,7 +386,7 @@ typedef struct _DNSServiceRef_t DNSServiceOp;
 typedef struct _DNSRecordRef_t DNSRecord;
 
 // client stub callback to process message from server and deliver results to client application
-typedef void (*ProcessReplyFn)(DNSServiceOp *sdr, CallbackHeader *cbh, char *msg, char *end);
+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))
@@ -306,7 +424,7 @@ struct _DNSRecordRef_t
 static int write_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 (send(sd, buf, len, MSG_WAITALL) != len)   return -1;
+       //if (send(sd, buf, len, MSG_WAITALL) != len) return -1;
        while (len)
                {
                ssize_t num_written = send(sd, buf, len, 0);
@@ -314,9 +432,9 @@ static int write_all(dnssd_sock_t sd, char *buf, int len)
                        {
                        // Should never happen. If it does, it indicates some OS bug,
                        // or that the mDNSResponder daemon crashed (which should never happen).
-                       syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %d/%d %d %s", sd, num_written, len,
-                               (num_written < 0) ? errno           : 0,
-                               (num_written < 0) ? strerror(errno) : "");
+                       syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%d %d %s", sd, num_written, len,
+                               (num_written < 0) ? dnssd_errno                 : 0,
+                               (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
                        return -1;
                        }
                buf += num_written;
@@ -325,7 +443,9 @@ static int write_all(dnssd_sock_t sd, char *buf, int len)
        return 0;
        }
 
-// Read len bytes. Return 0 on success, -1 on error
+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.
@@ -338,15 +458,15 @@ static int read_all(dnssd_sock_t sd, char *buf, int len)
                        {
                        // Should never happen. If it does, it indicates some OS bug,
                        // or that the mDNSResponder daemon crashed (which should never happen).
-                       syslog(LOG_WARNING, "dnssd_clientstub read_all(%d) failed %d/%d %d %s", sd, num_read, len,
-                               (num_read < 0) ? errno           : 0,
-                               (num_read < 0) ? strerror(errno) : "");
-                       return -1;
+                       syslog(LOG_WARNING, "dnssd_clientstub read_all(%d) failed %ld/%d %d %s", sd, num_read, len,
+                               (num_read < 0) ? dnssd_errno                 : 0,
+                               (num_read < 0) ? dnssd_strerror(dnssd_errno) : "");
+                       return (num_read < 0 && dnssd_errno == dnssd_EWOULDBLOCK) ? read_all_wouldblock : read_all_fail;
                        }
                buf += num_read;
                len -= num_read;
                }
-       return 0;
+       return read_all_success;
        }
 
 // Returns 1 if more bytes remain to be read on socket descriptor sd, 0 otherwise
@@ -385,7 +505,7 @@ static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int
 #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
                struct timeval time;
                if (gettimeofday(&time, NULL) < 0)
-                       { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", errno, strerror(errno)); return NULL; }
+                       { 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)(time.tv_sec & 0xFFF), (unsigned long)(time.tv_usec));
                *len += strlen(ctrl_path) + 1;
@@ -401,7 +521,7 @@ static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int
        msg = malloc(*len);
        if (!msg) { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: malloc failed"); return NULL; }
 
-       bzero(msg, *len);
+       memset(msg, 0, *len);
        hdr = (ipc_msg_hdr *)msg;
        hdr->version                = VERSION;
        hdr->datalen                = datalen;
@@ -464,7 +584,7 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
                        syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with NULL DNSServiceRef");
                        return kDNSServiceErr_BadParam;
                        }
-               if (!DNSServiceRefValid(*ref))
+               if (!DNSServiceRefValid(*ref) || (*ref)->op != connection_request || (*ref)->primary)
                        {
                        syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with invalid DNSServiceRef %p %08X %08X",
                                (*ref), (*ref)->sockfd, (*ref)->validator);
@@ -505,11 +625,12 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
                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;
-               if (++(*ref)->uid.u32[0] == 0) ++(*ref)->uid.u32[1];    // In parent DNSServiceOp increment UID counter
                //printf("ConnectToServer sharing socket %d\n", sdr->sockfd);
                }
        else
@@ -522,14 +643,14 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
                sdr->validator = sdr->sockfd ^ ValidatorBits;
                if (!dnssd_SocketValid(sdr->sockfd))
                        {
-                       syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: socket failed %d %s", errno, strerror(errno));
+                       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", errno, strerror(errno));
+                       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;
@@ -559,6 +680,9 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
        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
@@ -566,7 +690,7 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
        char *const data = (char *)hdr + sizeof(ipc_msg_hdr);
        #endif
        dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
-       DNSServiceErrorType err;
+       DNSServiceErrorType err = kDNSServiceErr_Unknown;       // Default for the "goto cleanup" cases
        int MakeSeparateReturnSocket = 0;
 
        // Note: need to check hdr->op, not sdr->op.
@@ -593,14 +717,14 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
                        dnssd_sockaddr_t caddr;
                        dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
                        listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
-                       if (!dnssd_SocketValid(listenfd)) goto cleanup;
+                       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) goto cleanup;
-                       if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) goto cleanup;
-                       listen(listenfd, 1);
+                       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
@@ -611,7 +735,7 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
                        int bindresult;
                        dnssd_sockaddr_t caddr;
                        listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
-                       if (!dnssd_SocketValid(listenfd)) goto cleanup;
+                       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
@@ -623,16 +747,13 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
                        mask = umask(0);
                        bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
                        umask(mask);
-                       if (bindresult < 0) goto cleanup;
-                       listen(listenfd, 1);
+                       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 (pipe(sp) < 0)
-                       //      syslog(LOG_WARNING, "dnssd_clientstub ERROR: pipe() failed errno %d (%s)", errno, strerror(errno));
-                       if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0)
-                               syslog(LOG_WARNING, "dnssd_clientstub ERROR: socketpair() failed errno %d (%s)", errno, strerror(errno));
+                       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]
@@ -649,27 +770,33 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
        // 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) datalen--;
+       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 %ld bytes", datalen + sizeof(ipc_msg_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 writing %d", i);
-               if (write_all(sdr->sockfd, ((char *)hdr)+i, 1) < 0) goto cleanup;
+               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) goto cleanup;
+       if (write_all(sdr->sockfd, (char *)hdr, datalen + sizeof(ipc_msg_hdr)) < 0)
+               {
+               syslog(LOG_WARNING, "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;
-       else
+       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 block in accept for a few milliseconds waiting for the daemon to connect back to us,
@@ -677,7 +804,7 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
                dnssd_sockaddr_t daddr;
                dnssd_socklen_t len = sizeof(daddr);
                errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
-               if (!dnssd_SocketValid(errsd)) goto cleanup;
+               if (!dnssd_SocketValid(errsd)) deliver_request_bailout("accept");
 #else
 
 #if APPLE_OSX_mDNSResponder
@@ -696,6 +823,22 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
                struct msghdr msg;
                struct cmsghdr *cmsg;
                char cbuf[CMSG_SPACE(sizeof(dnssd_sock_t))];
+
+               if (sdr->op == send_bpf)        // Okay to use sdr->op when checking for 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_name       = 0;
                msg.msg_namelen    = 0;
                msg.msg_iov        = &vec;
@@ -719,19 +862,19 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
                        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
+#endif // DEBUG_64BIT_SCM_RIGHTS
 
                if (sendmsg(sdr->sockfd, &msg, 0) < 0)
                        {
-                       syslog(LOG_WARNING, "dnssd_clientstub ERROR: sendmsg failed read sd=%d write sd=%d errno %d (%s)",
-                               errsd, listenfd, errno, strerror(errno));
+                       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 // DEBUG_64BIT_SCM_RIGHTS
 
 #endif
                // Close our end of the socketpair *before* blocking in read_all to get the four-byte error code.
@@ -743,7 +886,9 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
 
        // At this point we may block in read_all for a few milliseconds waiting for the daemon to send us the error code,
        // but that's okay -- the daemon is a trusted service and we know if won't take more than a few milliseconds to respond.
-       if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0)
+       if (sdr->op == send_bpf)        // Okay to use sdr->op when checking for op == send_bpf
+               err = kDNSServiceErr_NoError;
+       else 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);
@@ -758,10 +903,11 @@ cleanup:
 #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, errno, strerror(errno));
+                       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;
        }
@@ -808,7 +954,9 @@ DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
 
        if (!sdRef->ProcessReply)
                {
-               syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with DNSServiceRef with no ProcessReply function");
+               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;
                }
 
@@ -820,22 +968,21 @@ DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
                // 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
-               if (read_all(sdRef->sockfd, (void *)&cbh.ipc_hdr, sizeof(cbh.ipc_hdr)) < 0)
+               // 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)
                        {
-                       if (dnssd_errno() != dnssd_EWOULDBLOCK)
-                               {
-                               sdRef->ProcessReply = NULL;
-                               return kDNSServiceErr_ServiceNotRunning;
-                               }
-                       else
+                       sdRef->ProcessReply = NULL;
+                       return kDNSServiceErr_ServiceNotRunning;
+                       }
+               else if (result == read_all_wouldblock)
+                       {
+                       if (morebytes && sdRef->logcounter < 100)
                                {
-                               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;
+                               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);
@@ -856,7 +1003,7 @@ DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
                        }
                else
                        {
-                       char *ptr = data;
+                       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);
@@ -960,7 +1107,7 @@ DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void *
        return kDNSServiceErr_NoError;
        }
 
-static void handle_resolve_response(DNSServiceOp *sdr, CallbackHeader *cbh, char *data, char *end)
+static void handle_resolve_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *end)
        {
        char fullname[kDNSServiceMaxDomainName];
        char target[kDNSServiceMaxDomainName];
@@ -970,7 +1117,7 @@ static void handle_resolve_response(DNSServiceOp *sdr, CallbackHeader *cbh, char
 
        get_string(&data, end, fullname, kDNSServiceMaxDomainName);
        get_string(&data, end, target,   kDNSServiceMaxDomainName);
-       if (data + 2 > end) data = NULL;
+       if (!data || data + 2 > end) data = NULL;
        else
                {
                port.b[0] = *data++;
@@ -1027,12 +1174,12 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve
        return err;
        }
 
-static void handle_query_response(DNSServiceOp *sdr, CallbackHeader *cbh, char *data, char *end)
+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;
-       char *rdata;
+       const char *rdata;
 
        get_string(&data, end, name, kDNSServiceMaxDomainName);
        rrtype  = get_uint16(&data, end);
@@ -1086,11 +1233,11 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
        return err;
        }
 
-static void handle_addrinfo_response(DNSServiceOp *sdr, CallbackHeader *cbh, char *data, char *end)
+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;
-       char *rdata;
+       const char *rdata;
        uint32_t ttl;
 
        get_string(&data, end, hostname, kDNSServiceMaxDomainName);
@@ -1112,7 +1259,7 @@ static void handle_addrinfo_response(DNSServiceOp *sdr, CallbackHeader *cbh, cha
                const struct sockaddr *const sa = (rrtype == kDNSServiceType_A) ? (struct sockaddr*)&sa4 : (struct sockaddr*)&sa6;
                if (rrtype == kDNSServiceType_A)
                        {
-                       bzero(&sa4, sizeof(sa4));
+                       memset(&sa4, 0, sizeof(sa4));
                        #ifndef NOT_HAVE_SA_LEN
                        sa4.sin_len = sizeof(struct sockaddr_in);
                        #endif
@@ -1122,7 +1269,7 @@ static void handle_addrinfo_response(DNSServiceOp *sdr, CallbackHeader *cbh, cha
                        }
                else
                        {
-                       bzero(&sa6, sizeof(sa6));
+                       memset(&sa6, 0, sizeof(sa6));
                        #ifndef NOT_HAVE_SA_LEN
                        sa6.sin6_len = sizeof(struct sockaddr_in6);
                        #endif
@@ -1181,7 +1328,7 @@ DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
        return err;
        }
        
-static void handle_browse_response(DNSServiceOp *sdr, CallbackHeader *cbh, char *data, char *end)
+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);
@@ -1247,7 +1394,7 @@ DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags
        return err;
        }
 
-static void handle_regservice_response(DNSServiceOp *sdr, CallbackHeader *cbh, char *data, char *end)
+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);
@@ -1318,7 +1465,7 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister
        return err;
        }
 
-static void handle_enumeration_response(DNSServiceOp *sdr, CallbackHeader *cbh, char *data, char *end)
+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);
@@ -1362,7 +1509,7 @@ DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
        return err;
        }
 
-static void ConnectionResponse(DNSServiceOp *sdr, CallbackHeader *cbh, char *data, char *end)
+static void ConnectionResponse(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *const data, const char *const end)
        {
        DNSRecordRef rref = cbh->ipc_hdr.client_context.context;
        (void)data; // Unused
@@ -1371,13 +1518,15 @@ static void ConnectionResponse(DNSServiceOp *sdr, CallbackHeader *cbh, char *dat
        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
-               while (sdr && (sdr->uid.u32[0] != cbh->ipc_hdr.client_context.u32[0] || sdr->uid.u32[1] != cbh->ipc_hdr.client_context.u32[1]))
-                       sdr = sdr->next;
-               // NOTE: We may sometimes not find a matching DNSServiceOp, in the case where the client has
+               // 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 (sdr && sdr->ProcessReply) sdr->ProcessReply(sdr, cbh, data, end);
-               // WARNING: Don't touch sdr after this -- client may have called DNSServiceRefDeallocate
+               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;
                }
 
@@ -1385,7 +1534,7 @@ static void ConnectionResponse(DNSServiceOp *sdr, CallbackHeader *cbh, char *dat
                rref->AppCallback(rref->sdr, rref, cbh->cb_flags, cbh->cb_err, rref->AppContext);
        else
                {
-               syslog(LOG_WARNING, "dnssd_clientstub handle_regrecord_response: sdr->op != connection_request");
+               syslog(LOG_WARNING, "dnssd_clientstub ConnectionResponse: sdr->op != connection_request");
                rref->AppCallback(rref->sdr, rref, 0, kDNSServiceErr_Unknown, rref->AppContext);
                }
        // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
@@ -1531,7 +1680,6 @@ DNSServiceErrorType DNSSD_API DNSServiceAddRecord
        rref->record_index = sdRef->max_index++;
        rref->sdr = sdRef;
        *RecordRef = rref;
-       hdr->client_context.context = rref;
        hdr->reg_index = rref->record_index;
 
        return deliver_request(hdr, sdRef);             // Will free hdr for us
@@ -1649,31 +1797,31 @@ DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
        return err;
        }
 
-static void handle_port_mapping_response(DNSServiceOp *sdr, CallbackHeader *cbh, char *data, char *end)
+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 = 0;
-       union { uint16_t s; u_char b[2]; } privatePort;
-       union { uint16_t s; u_char b[2]; } publicPort;
+       union { uint16_t s; u_char b[2]; } internalPort;
+       union { uint16_t s; u_char b[2]; } externalPort;
        uint32_t ttl = 0;
 
-       if (data + 13 > end) data = NULL;
+       if (!data || data + 13 > end) data = NULL;
        else
                {
-               addr       .b[0] = *data++;
-               addr       .b[1] = *data++;
-               addr       .b[2] = *data++;
-               addr       .b[3] = *data++;
-               protocol         = *data++;
-               privatePort.b[0] = *data++;
-               privatePort.b[1] = *data++;
-               publicPort .b[0] = *data++;
-               publicPort .b[1] = *data++;
-               ttl              = get_uint32(&data, end);
+               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) syslog(LOG_WARNING, "dnssd_clientstub handle_port_mapping_response: error reading result from daemon");
-       else ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, addr.l, protocol, privatePort.s, publicPort.s, ttl, sdr->AppContext);
+       else ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, addr.l, protocol, internalPort.s, externalPort.s, ttl, sdr->AppContext);
        // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
        }
 
@@ -1683,8 +1831,8 @@ DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
        DNSServiceFlags                     flags,
        uint32_t                            interfaceIndex,
        uint32_t                            protocol,     /* TCP and/or UDP */
-       uint16_t                            privatePortInNetworkByteOrder,
-       uint16_t                            publicPortInNetworkByteOrder,
+       uint16_t                            internalPortInNetworkByteOrder,
+       uint16_t                            externalPortInNetworkByteOrder,
        uint32_t                            ttl,          /* time to live in seconds */
        DNSServiceNATPortMappingReply       callBack,
        void                                *context      /* may be NULL */
@@ -1693,8 +1841,8 @@ DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
        char *ptr;
        size_t len;
        ipc_msg_hdr *hdr;
-       union { uint16_t s; u_char b[2]; } privatePort = { privatePortInNetworkByteOrder };
-       union { uint16_t s; u_char b[2]; } publicPort  = { publicPortInNetworkByteOrder };
+       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
@@ -1702,8 +1850,8 @@ DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
        len = sizeof(flags);
        len += sizeof(interfaceIndex);
        len += sizeof(protocol);
-       len += sizeof(privatePort);
-       len += sizeof(publicPort);
+       len += sizeof(internalPort);
+       len += sizeof(externalPort);
        len += sizeof(ttl);
 
        hdr = create_hdr(port_mapping_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
@@ -1712,10 +1860,10 @@ DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
        put_flags(flags, &ptr);
        put_uint32(interfaceIndex, &ptr);
        put_uint32(protocol, &ptr);
-       *ptr++ = privatePort.b[0];
-       *ptr++ = privatePort.b[1];
-       *ptr++ = publicPort .b[0];
-       *ptr++ = publicPort .b[1];
+       *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
index 2e167471c6dbfbf125da3ce49349639c03e53552..f929ec0402a90373cb5ba05928d55f28c3b9e261 100644 (file)
        Change History (most recent first):
 
 $Log: dnssd_ipc.c,v $
+Revision 1.23  2009/04/01 21:10:34  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+
+Revision 1.22  2009/02/12 20:28:31  cheshire
+Added some missing "const" declarations
+
+Revision 1.21  2008/10/23 23:21:31  cheshire
+Moved definition of dnssd_strerror() to be with the definition of dnssd_errno, in dnssd_ipc.h
+
 Revision 1.20  2007/07/23 22:12:53  cheshire
 <rdar://problem/5352299> Make mDNSResponder more defensive against malicious local clients
 
@@ -75,6 +84,32 @@ Update to APSL 2.0
 
 #include "dnssd_ipc.h"
 
+#if defined(_WIN32)
+
+char *win32_strerror(int inErrorCode)
+       {
+       static char buffer[1024];
+       DWORD       n;
+       memset(buffer, 0, sizeof(buffer));
+       n = FormatMessageA(
+                       FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                       NULL,
+                       (DWORD) inErrorCode,
+                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                       buffer,
+                       sizeof(buffer),
+                       NULL);
+       if (n > 0)
+               {
+               // Remove any trailing CR's or LF's since some messages have them.
+               while ((n > 0) && isspace(((unsigned char *) buffer)[n - 1]))
+                       buffer[--n] = '\0';
+               }
+       return buffer;
+       }
+
+#endif
+
 void put_uint32(const uint32_t l, char **ptr)
        {
        (*ptr)[0] = (char)((l >> 24) &  0xFF);
@@ -84,7 +119,7 @@ void put_uint32(const uint32_t l, char **ptr)
        *ptr += sizeof(uint32_t);
        }
 
-uint32_t get_uint32(char **ptr, char *end)
+uint32_t get_uint32(const char **ptr, const char *end)
        {
        if (!*ptr || *ptr + sizeof(uint32_t) > end)
                {
@@ -106,7 +141,7 @@ void put_uint16(uint16_t s, char **ptr)
        *ptr += sizeof(uint16_t);
        }
 
-uint16_t get_uint16(char **ptr, char *end)
+uint16_t get_uint16(const char **ptr, const char *end)
        {
        if (!*ptr || *ptr + sizeof(uint16_t) > end)
                {
@@ -129,7 +164,7 @@ int put_string(const char *str, char **ptr)
        return 0;
        }
 
-int get_string(char **ptr, char *end, char *buffer, int buflen)
+int get_string(const char **ptr, const char *const end, char *buffer, int buflen)
        {
        if (!*ptr)
                {
@@ -157,7 +192,7 @@ void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr)
        *ptr += rdlen;
        }
 
-char *get_rdata(char **ptr, char *end, int rdlen)
+const char *get_rdata(const char **ptr, const char *end, int rdlen)
        {
        if (!*ptr || *ptr + rdlen > end)
                {
@@ -166,7 +201,7 @@ char *get_rdata(char **ptr, char *end, int rdlen)
                }
        else
                {
-               char *rd = *ptr;
+               const char *rd = *ptr;
                *ptr += rdlen;
                return rd;
                }
index 4cd2f207bb2065e9831b377838656d935eb9ad2d..92976f7465ad2872cd35af2560afa93ed236ec94 100644 (file)
     Change History (most recent first):
 
 $Log: dnssd_ipc.h,v $
+Revision 1.46  2009/05/27 22:20:44  cheshire
+Removed unused dnssd_errno_assign() (we have no business writing to errno -- we should only read it)
+
+Revision 1.45  2009/05/26 21:31:07  herscher
+Fix compile errors on Windows
+
+Revision 1.44  2009/02/12 20:28:31  cheshire
+Added some missing "const" declarations
+
+Revision 1.43  2008/10/23 23:21:31  cheshire
+Moved definition of dnssd_strerror() to be with the definition of dnssd_errno, in dnssd_ipc.h
+
+Revision 1.42  2008/10/23 23:06:17  cheshire
+Removed () from dnssd_errno macro definition -- it's not a function and doesn't need any arguments
+
+Revision 1.41  2008/09/27 01:04:09  cheshire
+Added "send_bpf" to list of request_op_t operation codes
+
 Revision 1.40  2007/09/07 20:56:03  cheshire
 Renamed uint32_t field in client_context_t from "ptr64" to more accurate name "u32"
 
@@ -157,7 +175,8 @@ Update to APSL 2.0
 #      define dnssd_sock_t                     SOCKET
 #      define dnssd_socklen_t          int
 #      define dnssd_close(sock)        closesocket(sock)
-#      define dnssd_errno()            WSAGetLastError()
+#      define dnssd_errno                      WSAGetLastError()
+#      define dnssd_strerror(X)        win32_strerror(X)
 #      define ssize_t                          int
 #      define getpid                           _getpid
 #else
@@ -178,7 +197,8 @@ Update to APSL 2.0
 #      define dnssd_sock_t                     int
 #      define dnssd_socklen_t          unsigned int
 #      define dnssd_close(sock)        close(sock)
-#      define dnssd_errno()            errno
+#      define dnssd_errno                      errno
+#      define dnssd_strerror(X)        strerror(X)
 #endif
 
 #if defined(USE_TCP_LOOPBACK)
@@ -241,6 +261,7 @@ typedef enum
        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
 
        cancel_request = 63
     } request_op_t;
@@ -289,10 +310,10 @@ typedef packedstruct
 // 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(char **ptr, char *end);
+uint32_t get_uint32(const char **ptr, const char *end);
 
 void put_uint16(uint16_t s, char **ptr);
-uint16_t get_uint16(char **ptr, char *end);
+uint16_t get_uint16(const char **ptr, const char *end);
 
 #define put_flags put_uint32
 #define get_flags get_uint32
@@ -301,10 +322,10 @@ uint16_t get_uint16(char **ptr, char *end);
 #define get_error_code get_uint32
 
 int put_string(const char *str, char **ptr);
-int get_string(char **ptr, char *end, char *buffer, int buflen);
+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);
-char *get_rdata(char **ptr, char *end, int rdlen);  // return value is rdata pointed to by *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);
index 4d0adbc6891b793837e3cb7531a279d3e4c7aa75..60154d12194fcd2512140c966e908d06fa6f21fc 100644 (file)
     Change History (most recent first):
 
 $Log: mDNSDebug.c,v $
+Revision 1.16  2009/04/11 01:43:28  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.15  2009/04/11 00:20:26  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.14  2008/11/26 00:01:08  cheshire
+Get rid of "Unknown" tag in SIGINFO output on Leopard
+
 Revision 1.13  2007/12/01 00:40:30  cheshire
 Fixes from Bob Bradley for building on EFI
 
@@ -82,7 +91,8 @@ Changes necessary to support mDNSResponder on Linux.
 
 #include "mDNSEmbeddedAPI.h"
 
-mDNSexport LogLevel_t mDNS_LogLevel = MDNS_LOG_INITIAL_LEVEL;
+mDNSexport int mDNS_LoggingEnabled = 0;
+mDNSexport int mDNS_PacketLoggingEnabled = 0;
 
 #if MDNS_DEBUGMSGS
 mDNSexport int mDNS_DebugMode = mDNStrue;
@@ -92,18 +102,6 @@ mDNSexport int mDNS_DebugMode = mDNSfalse;
 
 // Note, this uses mDNS_vsnprintf instead of standard "vsnprintf", because mDNS_vsnprintf knows
 // how to print special data types like IP addresses and length-prefixed domain names
-#if MDNS_DEBUGMSGS
-mDNSexport void debugf_(const char *format, ...)
-       {
-       char buffer[512];
-       va_list ptr;
-       va_start(ptr,format);
-       buffer[mDNS_vsnprintf(buffer, sizeof(buffer), format, ptr)] = 0;
-       va_end(ptr);
-       mDNSPlatformWriteDebugMsg(buffer);
-       }
-#endif
-
 #if MDNS_DEBUGMSGS > 1
 mDNSexport void verbosedebugf_(const char *format, ...)
        {
@@ -117,55 +115,34 @@ mDNSexport void verbosedebugf_(const char *format, ...)
 #endif
 
 // Log message with default "mDNSResponder" ident string at the start
-mDNSexport void LogMsg(const char *format, ...)
+mDNSlocal void LogMsgWithLevelv(mDNSLogLevel_t logLevel, const char *format, va_list ptr)
        {
        char buffer[512];
-       va_list ptr;
-       va_start(ptr,format);
        buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
-       va_end(ptr);
-       mDNSPlatformWriteLogMsg(ProgramName, buffer, 0);
+       mDNSPlatformWriteLogMsg(ProgramName, buffer, logLevel);
        }
 
-// Log message with specified ident string at the start
-mDNSexport void LogMsgIdent(const char *ident, const char *format, ...)
-       {
-       char buffer[512];
-       va_list ptr;
-       va_start(ptr,format);
-       buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
-       va_end(ptr);
-       mDNSPlatformWriteLogMsg(ident, buffer, ident && *ident ? LOG_PID : 0);
+#define LOG_HELPER_BODY(L) \
+       { \
+       va_list ptr; \
+       va_start(ptr,format); \
+       LogMsgWithLevelv(L, format, ptr); \
+       va_end(ptr); \
        }
 
-// Log message with no ident string at the start
-mDNSexport void LogMsgNoIdent(const char *format, ...)
-       {
-       char buffer[512];
-       va_list ptr;
-       va_start(ptr,format);
-       buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
-       va_end(ptr);
-       mDNSPlatformWriteLogMsg("", buffer, 0);
-       }
+// see mDNSDebug.h
+#if !MDNS_HAS_VA_ARG_MACROS
+void debug_noop(const char *format, ...)  { (void) format; }
+void LogMsg_(const char *format, ...)       LOG_HELPER_BODY(MDNS_LOG_MSG)
+void LogOperation_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_OPERATION)
+void LogSPS_(const char *format, ...)       LOG_HELPER_BODY(MDNS_LOG_SPS)
+void LogInfo_(const char *format, ...)      LOG_HELPER_BODY(MDNS_LOG_INFO)
+#endif
 
-mDNSlocal const char *CStringForLogLevel(LogLevel_t level)
-       {
-       switch (level) 
-               {
-               case MDNS_LOG_NONE:          return "MDNS_LOG_NONE";
-//             case MDNS_LOG_ERROR:         return "MDNS_LOG_ERROR";
-//             case MDNS_LOG_WARN:          return "MDNS_LOG_WARN";
-//             case MDNS_LOG_INFO:          return "MDNS_LOG_INFO";
-//             case MDNS_LOG_DEBUG:         return "MDNS_LOG_DEBUG";
-               case MDNS_LOG_VERBOSE_DEBUG: return "MDNS_LOG_VERBOSE_DEBUG";
-               default:                     return "MDNS_LOG_UNKNOWN"; 
-               }
-       }
+#if MDNS_DEBUGMSGS
+void debugf_(const char *format, ...)      LOG_HELPER_BODY(MDNS_LOG_DEBUG)
+#endif
 
-mDNSexport void SigLogLevel(void)
-       {
-       if (mDNS_LogLevel < MDNS_LOG_VERBOSE_DEBUG) mDNS_LogLevel++;
-       else mDNS_LogLevel = MDNS_LOG_NONE;
-       LogMsg("Log Level Changed to %s", CStringForLogLevel(mDNS_LogLevel));
-       }
+// Log message with default "mDNSResponder" ident string at the start
+mDNSexport void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...)
+       LOG_HELPER_BODY(logLevel)
index a94f24c6360f549dd0d98c537cf6078f3b3764e9..e383eb641c221e51ba522f08a1e375e4ba73b56f 100644 (file)
 .\" limitations under the License.
 .\"
 .\" $Log: mDNSResponder.8,v $
+.\" Revision 1.10  2009/04/20 16:12:13  mcguire
+.\" <rdar://problem/6807798> manpage: roff errors
+.\"
+.\" Revision 1.9  2009/04/11 00:20:27  jessic2
+.\" <rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+.\"
 .\" Revision 1.8  2006/10/06 17:31:33  mkrochma
 .\" <rdar://problem/4769407> Typo in man page for mDNSResponder(8)
 .\"
@@ -47,7 +53,7 @@
 .\"
 .Sh NAME
 .Nm mDNSResponder
-.Nd Multicast DNS daemon    \" Name Description for whatis database
+.Nd Multicast and Unicast DNS daemon    \" Name Description for whatis database
 .\" 
 .Sh SYNOPSIS
 .Nm
 (also known as
 .Nm mdnsd
 on some systems)
-is a daemon invoked at boot time to implement Multicast DNS
-and DNS Service Discovery.
+is a daemon invoked at boot time to implement Multicast DNS and DNS Service Discovery. On
+Mac OS X 10.6 (Snow Leopard), 
+.Nm 
+is also the system-wide Unicast DNS Resolver.
 .Pp
 .Nm
-listens UDP port 5353 for Multicast DNS Query packets.
+listens on UDP port 5353 for Multicast DNS Query packets.
 When it receives a query for which it knows an answer,
 .Nm
 issues the appropriate Multicast DNS Reply packet.
 .Pp
 .Nm
-also performs Multicast DNS Queries on behalf of client processes,
-and maintains a cache of the replies.
+also performs Unicast and Multicast DNS Queries on behalf of client processes, and 
+maintains a cache of the replies.
 .Pp
 .Nm
 has no user-specifiable command-line argument, and users should not run
 .Nm
 manually.
 .Pp
-To examine
-.Nm Ns 's internal state, for debugging and diagnostic purposes,
-send it a SIGINFO signal, and it will then dump a snapshot summary
-of its internal state to
-.Pa /var/log/system.log Ns , e.g.
+.Ss LOGGING
+There are several methods with which to examine 
+.Nm Ns 's internal state for debugging and diagnostic purposes. The syslog(1)
+logging levels map as follows:
+.Pp
+.Dl Error - Error messages
+.Dl Warning - Client-initiated operations
+.Dl Notice - Sleep proxy operations
+.Dl Info - Informational messages
+.Pp
+By default, only log level Error is logged.
+.Pp
+A SIGUSR1 signal toggles additional logging, with Warning and Notice
+enabled by default:
+.Pp
+.Dl % sudo killall -USR1 mDNSResponder
+.Pp
+Once this logging is enabled, users can additionally use syslog(1)
+to change the log filter for the process. For example, to enable log levels Emergency - Debug:
+.Pp
+.Dl % sudo syslog -c mDNSResponder -d
+.Pp
+A SIGUSR2 signal toggles packet logging:
+.Pp
+.Dl % sudo killall -USR2 mDNSResponder
+.Pp
+A SIGINFO signal will dump a snapshot summary of the internal state to 
+.Pa /var/log/system.log Ns :
 .Pp
-.Dl sudo killall -INFO mDNSResponder
+.Dl sudo killall -INFO mDNSResponder
 .Sh FILES
 .Pa /usr/sbin/mDNSResponder \" Pathname
 .\"
index a01eb085727093790aa79ff5e63d4948f3300265..dfae86ed0568faa6ec936acca49b01ffb274a01c 100644 (file)
        Change History (most recent first):
 
 $Log: uds_daemon.c,v $
+Revision 1.461  2009/06/19 23:15:07  cheshire
+<rdar://problem/6990066> Library: crash at handle_resolve_response + 183
+Made resolve_result_callback code more defensive and improved LogOperation messages
+
+Revision 1.460  2009/05/26 21:31:07  herscher
+Fix compile errors on Windows
+
+Revision 1.459  2009/04/30 20:07:51  mcguire
+<rdar://problem/6822674> Support multiple UDSs from launchd
+
+Revision 1.458  2009/04/25 00:59:06  mcguire
+Change a few stray LogInfo to LogOperation
+
+Revision 1.457  2009/04/22 01:19:57  jessic2
+<rdar://problem/6814585> Daemon: mDNSResponder is logging garbage for error codes because it's using %ld for int 32
+
+Revision 1.456  2009/04/21 01:56:34  jessic2
+<rdar://problem/6803941> BTMM: Back out change for preventing other local users from sending packets to your BTMM machines
+
+Revision 1.455  2009/04/20 19:19:57  cheshire
+<rdar://problem/6803941> BTMM: If multiple local users are logged in to same BTMM account, all but one fail
+Don't need "empty info->u.browser.browsers list" debugging message, now that we expect this to be
+a case that can legitimately happen.
+
+Revision 1.454  2009/04/18 20:56:43  jessic2
+<rdar://problem/6803941> BTMM: If multiple local users are logged in to same BTMM account, all but one fail
+
+Revision 1.453  2009/04/11 00:20:29  jessic2
+<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+
+Revision 1.452  2009/04/07 01:17:42  jessic2
+<rdar://problem/6747917> BTMM: Multiple accounts lets me see others' remote services & send packets to others' remote hosts
+
+Revision 1.451  2009/04/02 22:34:26  jessic2
+<rdar://problem/6305347> Race condition: If fd has already been closed, SO_NOSIGPIPE returns errno 22 (Invalid argument)
+
+Revision 1.450  2009/04/01 21:11:28  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows. Workaround use of recvmsg.
+
+Revision 1.449  2009/03/17 19:44:25  cheshire
+<rdar://problem/6688927> Don't let negative unicast answers block Multicast DNS responses
+
+Revision 1.448  2009/03/17 04:53:40  cheshire
+<rdar://problem/6688927> Don't let negative unicast answers block Multicast DNS responses
+
+Revision 1.447  2009/03/17 04:41:32  cheshire
+Moved LogOperation message to after check for "if (answer->RecordType == kDNSRecordTypePacketNegative)"
+
+Revision 1.446  2009/03/04 01:47:35  cheshire
+Include m->ProxyRecords in SIGINFO output
+
+Revision 1.445  2009/03/03 23:04:44  cheshire
+For clarity, renamed "MAC" field to "HMAC" (Host MAC, as opposed to Interface MAC)
+
+Revision 1.444  2009/03/03 22:51:55  cheshire
+<rdar://problem/6504236> Sleep Proxy: Waking on same network but different interface will cause conflicts
+
+Revision 1.443  2009/02/27 02:28:41  cheshire
+Need to declare "const AuthRecord *ar;"
+
+Revision 1.442  2009/02/27 00:58:17  cheshire
+Improved detail of SIGINFO logging for m->DuplicateRecords
+
+Revision 1.441  2009/02/24 22:18:59  cheshire
+Include interface name for interface-specific AuthRecords
+
+Revision 1.440  2009/02/21 01:38:08  cheshire
+Added report of m->SleepState value in SIGINFO output
+
+Revision 1.439  2009/02/18 23:38:44  cheshire
+<rdar://problem/6600780> Could not write data to client 13 - aborting connection
+Eliminated unnecessary "request_state *request" field from the reply_state structure.
+
+Revision 1.438  2009/02/18 23:23:14  cheshire
+Cleaned up debugging log messages
+
+Revision 1.437  2009/02/17 23:29:05  cheshire
+Throttle logging to a slower rate when running on SnowLeopard
+
+Revision 1.436  2009/02/13 06:28:02  cheshire
+Converted LogOperation messages to LogInfo
+
+Revision 1.435  2009/02/12 20:57:26  cheshire
+Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
+
+Revision 1.434  2009/02/12 20:28:31  cheshire
+Added some missing "const" declarations
+
+Revision 1.433  2009/02/10 01:44:39  cheshire
+<rdar://problem/6553729> DNSServiceUpdateRecord fails with kDNSServiceErr_BadReference for otherwise valid reference
+
+Revision 1.432  2009/02/10 01:38:56  cheshire
+Move regservice_termination_callback() earlier in file in preparation for subsequent work
+
+Revision 1.431  2009/02/07 01:48:55  cheshire
+In SIGINFO output include sequence number for proxied records
+
+Revision 1.430  2009/01/31 21:58:05  cheshire
+<rdar://problem/4786302> Implement logic to determine when to send dot-local lookups via Unicast
+Only want to do unicast dot-local lookups for address queries and conventional (RFC 2782) SRV queries
+
+Revision 1.429  2009/01/31 00:45:26  cheshire
+<rdar://problem/4786302> Implement logic to determine when to send dot-local lookups via Unicast
+Further refinements
+
+Revision 1.428  2009/01/30 19:52:31  cheshire
+Eliminated unnecessary duplicated "dnssd_sock_t sd" fields in service_instance and reply_state structures
+
+Revision 1.427  2009/01/24 01:48:43  cheshire
+<rdar://problem/4786302> Implement logic to determine when to send dot-local lookups via Unicast
+
+Revision 1.426  2009/01/16 21:07:08  cheshire
+In SIGINFO "Duplicate Records" list, show expiry time for Sleep Proxy records
+
+Revision 1.425  2009/01/16 20:53:16  cheshire
+Include information about Sleep Proxy records in SIGINFO output
+
+Revision 1.424  2009/01/12 22:43:50  cheshire
+Fixed "unused variable" warning when SO_NOSIGPIPE is not defined
+
+Revision 1.423  2009/01/10 22:54:42  mkrochma
+<rdar://problem/5797544> Fixes from Igor Seleznev to get mdnsd working on Linux
+
+Revision 1.422  2009/01/10 01:52:48  cheshire
+Include DuplicateRecords and LocalOnlyQuestions in SIGINFO output
+
+Revision 1.421  2008/12/17 05:05:26  cheshire
+Fixed alignment of NAT mapping syslog messages
+
+Revision 1.420  2008/12/12 00:52:05  cheshire
+mDNSPlatformSetBPF is now called mDNSPlatformReceiveBPF_fd
+
+Revision 1.419  2008/12/10 02:11:44  cheshire
+ARMv5 compiler doesn't like uncommented stuff after #endif
+
+Revision 1.418  2008/12/09 05:12:53  cheshire
+Updated debugging messages
+
+Revision 1.417  2008/12/04 03:38:12  cheshire
+Miscellaneous defensive coding changes and improvements to debugging log messages
+
+Revision 1.416  2008/12/02 22:02:12  cheshire
+<rdar://problem/6320621> Adding domains after TXT record updates registers stale TXT record data
+
+Revision 1.415  2008/11/26 20:35:59  cheshire
+Changed some "LogOperation" debugging messages to "debugf"
+
+Revision 1.414  2008/11/26 00:02:25  cheshire
+Improved SIGINFO output to list AutoBrowseDomains and AutoRegistrationDomains
+
+Revision 1.413  2008/11/25 04:48:58  cheshire
+Added logging to show whether Sleep Proxy Service is active
+
+Revision 1.412  2008/11/24 23:05:43  cheshire
+Additional checking in uds_validatelists()
+
+Revision 1.411  2008/11/05 21:41:39  cheshire
+Updated LogOperation message
+
+Revision 1.410  2008/11/04 20:06:20  cheshire
+<rdar://problem/6186231> Change MAX_DOMAIN_NAME to 256
+
+Revision 1.409  2008/10/31 23:44:22  cheshire
+Fixed compile error in Posix build
+
+Revision 1.408  2008/10/29 21:32:33  cheshire
+Align "DNSServiceEnumerateDomains ... RESULT" log messages
+
+Revision 1.407  2008/10/27 07:34:36  cheshire
+Additional sanity checks for debugging
+
+Revision 1.406  2008/10/23 23:55:56  cheshire
+Fixed some missing "const" declarations
+
+Revision 1.405  2008/10/23 23:21:31  cheshire
+Moved definition of dnssd_strerror() to be with the definition of dnssd_errno, in dnssd_ipc.h
+
+Revision 1.404  2008/10/23 23:06:17  cheshire
+Removed () from dnssd_errno macro definition -- it's not a function and doesn't need any arguments
+
+Revision 1.403  2008/10/23 22:33:25  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
+Revision 1.402  2008/10/22 19:47:59  cheshire
+Instead of SameRData(), use equivalent IdenticalSameNameRecord() macro
+
+Revision 1.401  2008/10/22 17:20:40  cheshire
+Don't give up if setsockopt SO_NOSIGPIPE fails
+
+Revision 1.400  2008/10/21 01:06:57  cheshire
+Pass BPF fd to mDNSMacOSX.c using mDNSPlatformSetBPF() instead of just writing it into a shared global variable
+
+Revision 1.399  2008/10/20 22:06:42  cheshire
+Updated debugging log messages
+
+Revision 1.398  2008/10/03 18:25:17  cheshire
+Instead of calling "m->MainCallback" function pointer directly, call mDNSCore routine "mDNS_ConfigChanged(m);"
+
+Revision 1.397  2008/10/02 22:26:21  cheshire
+Moved declaration of BPF_fd from uds_daemon.c to mDNSMacOSX.c, where it really belongs
+
+Revision 1.396  2008/09/30 01:04:55  cheshire
+Made BPF code a bit more defensive, to ignore subsequent BPF fds if we get passed more than one
+
+Revision 1.395  2008/09/27 01:28:43  cheshire
+Added code to receive and store BPF fd when passed via a send_bpf message
+
+Revision 1.394  2008/09/23 04:12:40  cheshire
+<rdar://problem/6238774> Remove "local" from the end of _services._dns-sd._udp PTR records
+Added a special-case to massage these new records for Bonjour Browser's benefit
+
+Revision 1.393  2008/09/23 03:01:58  cheshire
+Added operation logging of domain enumeration results
+
+Revision 1.392  2008/09/18 22:30:06  cheshire
+<rdar://problem/6230679> device-info record not removed when last service deregisters
+
+Revision 1.391  2008/09/18 22:05:44  cheshire
+Fixed "DNSServiceRegister ... ADDED" message to have escaping consistent with
+the other DNSServiceRegister operation messages
+
+Revision 1.390  2008/09/16 21:06:56  cheshire
+Improved syslog output to show if q->LongLived flag is set for multicast questions
+
+Revision 1.389  2008/07/25 22:34:11  mcguire
+fix sizecheck issues for 64bit
+
+Revision 1.388  2008/07/01 01:40:02  mcguire
+<rdar://problem/5823010> 64-bit fixes
+
 Revision 1.387  2008/02/26 21:24:13  cheshire
 Fixed spelling mistake in comment
 
@@ -51,7 +281,7 @@ Revision 1.377  2007/10/30 23:48:20  cheshire
 Improved SIGINFO listing of question state
 
 Revision 1.376  2007/10/30 20:43:54  cheshire
-Fixed compiler warning when LogAllOperations is turned off
+Fixed compiler warning when LogClientOperations is turned off
 
 Revision 1.375  2007/10/26 22:51:38  cheshire
 Improved SIGINFO output to show timers for AuthRecords and ServiceRegistrations
@@ -656,29 +886,7 @@ Revision 1.189  2006/01/06 00:56:31  cheshire
 
 #if defined(_WIN32)
 #include <process.h>
-#define dnssd_strerror(X) win32_strerror(X)
 #define usleep(X) Sleep(((X)+999)/1000)
-mDNSlocal char *win32_strerror(int inErrorCode)
-       {
-       static char buffer[1024];
-       DWORD       n;
-       memset(buffer, 0, sizeof(buffer));
-       n = FormatMessageA(
-                       FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-                       NULL,
-                       (DWORD) inErrorCode,
-                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                       buffer,
-                       sizeof(buffer),
-                       NULL);
-       if (n > 0)
-               {
-               // Remove any trailing CR's or LF's since some messages have them.
-               while ((n > 0) && isspace(((unsigned char *) buffer)[n - 1]))
-                       buffer[--n] = '\0';
-               }
-       return buffer;
-       }
 #else
 #include <fcntl.h>
 #include <errno.h>
@@ -686,11 +894,11 @@ mDNSlocal char *win32_strerror(int inErrorCode)
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/resource.h>
-#define dnssd_strerror(X) strerror(X)
 #endif
 
 #include <stdlib.h>
 #include <stdio.h>
+
 #include "mDNSEmbeddedAPI.h"
 #include "DNSCommon.h"
 #include "uDNS.h"
@@ -732,7 +940,7 @@ typedef struct registered_record_entry
        struct registered_record_entry *next;
        mDNSu32 key;
        AuthRecord *rr;                         // Pointer to variable-sized AuthRecord
-       client_context_t client_context;
+       client_context_t regrec_client_context;
        request_state *request;
        } registered_record_entry;
 
@@ -743,7 +951,6 @@ typedef struct service_instance
        {
        struct service_instance *next;
        request_state *request;
-       dnssd_sock_t sd;
        AuthRecord *subtypes;
        mDNSBool renameonmemfree;               // Set on config change when we deregister original name
     mDNSBool clientnotified;           // Has client been notified of successful registration yet?
@@ -763,22 +970,22 @@ typedef struct browser_t
 struct request_state
        {
        request_state *next;
-       request_state *primary;                 // If this operation is on a shared socket, pointer to
-                                                                       // primary request_state for the original DNSServiceConnect() operation
+       request_state *primary;                 // If this operation is on a shared socket, pointer to primary
+                                                                       // request_state for the original DNSServiceConnect() operation
        dnssd_sock_t sd;
        dnssd_sock_t errsd;
        mDNSu32 uid;
 
-       // NOTE: On a shared connection these fields in the primary structure, including hdr, are re-used
+       // Note: On a shared connection these fields in the primary structure, including hdr, are re-used
        // for each new request. This is because, until we've read the ipc_msg_hdr to find out what the
        // operation is, we don't know if we're going to need to allocate a new request_state or not.
        transfer_state ts;
-       mDNSu32 hdr_bytes;                              // bytes of header already read
-       ipc_msg_hdr hdr;
-       mDNSu32 data_bytes;                             // bytes of message data already read
-       char *msgbuf;                                   // pointer to data storage to pass to free()
-       char *msgptr;                                   // pointer to data to be read from (may be modified)
-       char *msgend;                                   // pointer to byte after last byte of message
+       mDNSu32        hdr_bytes;               // bytes of header already read
+       ipc_msg_hdr    hdr;
+       mDNSu32        data_bytes;              // bytes of message data already read
+       char          *msgbuf;                  // pointer to data storage to pass to free()
+       const char    *msgptr;                  // pointer to data to be read from (may be modified)
+       char          *msgend;                  // pointer to byte after last byte of message
 
        // reply, termination, error, and client context info
        int no_reply;                                   // don't send asynchronous replies to client
@@ -829,12 +1036,16 @@ struct request_state
                        } pm;
                struct
                        {
+#if 0
+                       DNSServiceFlags flags;
+#endif
                        DNSQuestion q_all;
                        DNSQuestion q_default;
                        } enumeration;
                struct
                        {
                        DNSQuestion q;
+                       DNSQuestion q2;
                        } queryrecord;
                struct
                        {
@@ -844,7 +1055,6 @@ struct request_state
                        const ResourceRecord *srv;
                        mDNSs32 ReportTime;
                        } resolve;
-                ;
                } u;
        };
 
@@ -858,16 +1068,11 @@ typedef struct
 
 typedef struct reply_state
        {
-       dnssd_sock_t sd;
-       transfer_state ts;
+       struct reply_state *next;               // If there are multiple unsent replies
+       mDNSu32 totallen;
        mDNSu32 nwriten;
-       mDNSu32 len;
-       request_state *request;         // the request that this answers
-       struct reply_state *next;       // if there are multiple unsent replies
-       char *msgbuf;                           // pointer to malloc'd buffer
-       ipc_msg_hdr *mhdr;                      // pointer into message buffer - allows fields to be changed after message is formatted
-       reply_hdr *rhdr;
-       char *sdata;                            // pointer to start of call-specific data
+       ipc_msg_hdr mhdr[1];
+       reply_hdr rhdr[1];
        } reply_state;
 
 // ***************************************************************************
@@ -906,7 +1111,7 @@ mDNSexport DNameListElem *AutoRegistrationDomains; // Domains where we automatic
 
 mDNSlocal void FatalError(char *errmsg)
        {
-       LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno()));
+       LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno));
        *(long*)0 = 0;  // On OS X abort() doesn't generate a crash log, but writing to zero does
        abort();                // On platforms where writing to zero doesn't generate an exception, abort instead
        }
@@ -922,15 +1127,21 @@ mDNSlocal mDNSu32 dnssd_htonl(mDNSu32 l)
 // hack to search-replace perror's to LogMsg's
 mDNSlocal void my_perror(char *errmsg)
        {
-       LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno()));
+       LogMsg("%s: %d (%s)", errmsg, dnssd_errno, dnssd_strerror(dnssd_errno));
        }
 
 mDNSlocal void abort_request(request_state *req)
        {
+       if (req->terminate == (req_termination_fn)~0)
+               { LogMsg("abort_request: ERROR: Attempt to abort operation %p with req->terminate %p", req, req->terminate); return; }
+       
        // First stop whatever mDNSCore operation we were doing
        if (req->terminate) req->terminate(req);
 
-       // Now, if this request_state is not subbordinate to some other primary, close file descriptor and discard replies
+       if (!dnssd_SocketValid(req->sd))
+               { LogMsg("abort_request: ERROR: Attempt to abort operation %p with invalid fd %d",     req, req->sd);        return; }
+       
+       // Now, if this request_state is not subordinate to some other primary, close file descriptor and discard replies
        if (!req->primary)
                {
                if (req->errsd != req->sd) LogOperation("%3d: Removing FD and closing errsd %d", req->sd, req->errsd);
@@ -942,19 +1153,20 @@ mDNSlocal void abort_request(request_state *req)
                        {
                        reply_state *ptr = req->replies;
                        req->replies = req->replies->next;
-                       if (ptr->msgbuf) freeL("reply_state msgbuf (abort)", ptr->msgbuf);
                        freeL("reply_state (abort)", ptr);
                        }
                }
 
-// Set req->sd to something invalid, so that udsserver_idle knows to unlink and free this structure
+       // Set req->sd to something invalid, so that udsserver_idle knows to unlink and free this structure
 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
        // Don't use dnssd_InvalidSocket (-1) because that's the sentinel value MACOSX_MDNS_MALLOC_DEBUGGING uses
        // for detecting when the memory for an object is inadvertently freed while the object is still on some list
-       req->sd = -2;
+       req->sd = req->errsd = -2;
 #else
-       req->sd = dnssd_InvalidSocket;
+       req->sd = req->errsd = dnssd_InvalidSocket;
 #endif
+       // We also set req->terminate to a bogus value so we know if abort_request() gets called again for this request
+       req->terminate = (req_termination_fn)~0;
        }
 
 mDNSlocal void AbortUnlinkAndFree(request_state *req)
@@ -963,38 +1175,33 @@ mDNSlocal void AbortUnlinkAndFree(request_state *req)
        abort_request(req);
        while (*p && *p != req) p=&(*p)->next;
        if (*p) { *p = req->next; freeL("request_state/AbortUnlinkAndFree", req); }
+       else LogMsg("AbortUnlinkAndFree: ERROR: Attempt to abort operation %p not in list", req);
        }
 
 mDNSlocal reply_state *create_reply(const reply_op_t op, const size_t datalen, request_state *const request)
        {
        reply_state *reply;
-       int totallen = (int) (datalen + sizeof(ipc_msg_hdr));
 
        if ((unsigned)datalen < sizeof(reply_hdr))
                {
-               LogMsg("ERROR: create_reply - data length less than lenght of required fields");
+               LogMsg("ERROR: create_reply - data length less than length of required fields");
                return NULL;
                }
 
-       reply = mallocL("reply_state", sizeof(reply_state));
+       reply = mallocL("reply_state", sizeof(reply_state) + datalen - sizeof(reply_hdr));
        if (!reply) FatalError("ERROR: malloc");
-       mDNSPlatformMemZero(reply, sizeof(reply_state));
-       reply->ts      = t_morecoming;
-       reply->sd      = request->sd;
-       reply->request = request;
-       reply->len     = totallen;
-       reply->msgbuf  = mallocL("reply_state msgbuf", totallen);
-       if (!reply->msgbuf) FatalError("ERROR: malloc");
-       mDNSPlatformMemZero(reply->msgbuf, totallen);
-       reply->mhdr    = (ipc_msg_hdr *)reply->msgbuf;
-       reply->rhdr    = (reply_hdr *)(reply->msgbuf + sizeof(ipc_msg_hdr));
-       reply->sdata   = reply->msgbuf + sizeof(ipc_msg_hdr) + sizeof(reply_hdr);
-       reply->mhdr->version   = VERSION;
-       reply->mhdr->datalen   = datalen;
-       reply->mhdr->ipc_flags = 0;
-       reply->mhdr->op        = op;
+       
+       reply->next     = mDNSNULL;
+       reply->totallen = datalen + sizeof(ipc_msg_hdr);
+       reply->nwriten  = 0;
+
+       reply->mhdr->version        = VERSION;
+       reply->mhdr->datalen        = datalen;
+       reply->mhdr->ipc_flags      = 0;
+       reply->mhdr->op             = op;
        reply->mhdr->client_context = request->hdr.client_context;
-       reply->mhdr->reg_index = 0;
+       reply->mhdr->reg_index      = 0;
+
        return reply;
        }
 
@@ -1047,7 +1254,7 @@ mDNSlocal mStatus GenerateNTDResponse(const domainname *const servicename, const
                (*rep)->rhdr->error = dnssd_htonl(err);
 
                // Build reply body
-               data = (*rep)->sdata;
+               data = (char *)&(*rep)->rhdr[1];
                put_string(namestr, &data);
                put_string(typestr, &data);
                put_string(domstr, &data);
@@ -1056,6 +1263,46 @@ mDNSlocal mStatus GenerateNTDResponse(const domainname *const servicename, const
                }
        }
 
+// Special support to enable the DNSServiceBrowse call made by Bonjour Browser
+// Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
+mDNSlocal void GenerateBonjourBrowserResponse(const domainname *const servicename, const mDNSInterfaceID id,
+       request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
+       {
+       char namestr[MAX_DOMAIN_LABEL+1];
+       char typestr[MAX_ESCAPED_DOMAIN_NAME];
+       static const char domstr[] = ".";
+       int len;
+       char *data;
+
+       *rep = NULL;
+
+       // 1. Put first label in namestr
+       ConvertDomainLabelToCString_unescaped((const domainlabel *)servicename, namestr);
+
+       // 2. Put second label and "local" into typestr
+       mDNS_snprintf(typestr, sizeof(typestr), "%#s.local.", SecondLabel(servicename));
+
+       // Calculate reply data length
+       len = sizeof(DNSServiceFlags);
+       len += sizeof(mDNSu32);  // if index
+       len += sizeof(DNSServiceErrorType);
+       len += (int) (strlen(namestr) + 1);
+       len += (int) (strlen(typestr) + 1);
+       len += (int) (strlen(domstr) + 1);
+
+       // Build reply header
+       *rep = create_reply(op, len, request);
+       (*rep)->rhdr->flags = dnssd_htonl(flags);
+       (*rep)->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, id));
+       (*rep)->rhdr->error = dnssd_htonl(err);
+
+       // Build reply body
+       data = (char *)&(*rep)->rhdr[1];
+       put_string(namestr, &data);
+       put_string(typestr, &data);
+       put_string(domstr, &data);
+       }
+
 // Returns a resource record (allocated w/ malloc) containing the data found in an IPC message
 // Data must be in the following format: flags, interfaceIndex, name, rrtype, rrclass, rdlen, rdata, (optional) ttl
 // (ttl only extracted/set if ttl argument is non-zero). Returns NULL for a bad-parameter error
@@ -1064,11 +1311,11 @@ mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, i
        DNSServiceFlags flags  = get_flags(&request->msgptr, request->msgend);
        mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
        char name[256];
-       int str_err   = get_string(&request->msgptr, request->msgend, name, sizeof(name));
-       mDNSu16 type  = get_uint16(&request->msgptr, request->msgend);
-       mDNSu16 class = get_uint16(&request->msgptr, request->msgend);
-       mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
-       char *rdata   = get_rdata(&request->msgptr, request->msgend, rdlen);
+       int         str_err = get_string(&request->msgptr, request->msgend, name, sizeof(name));
+       mDNSu16     type    = get_uint16(&request->msgptr, request->msgend);
+       mDNSu16     class   = get_uint16(&request->msgptr, request->msgend);
+       mDNSu16     rdlen   = get_uint16(&request->msgptr, request->msgend);
+       const char *rdata   = get_rdata (&request->msgptr, request->msgend, rdlen);
        mDNSu32 ttl   = GetTTL ? get_uint32(&request->msgptr, request->msgend) : 0;
        int storage_size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
        AuthRecord *rr;
@@ -1127,10 +1374,39 @@ mDNSlocal void send_all(dnssd_sock_t s, const char *ptr, int len)
        // (four bytes for a typical error code return, 12 bytes for DNSServiceGetProperty(DaemonVersion)).
        // If it does fail, we don't attempt to handle this failure, but we do log it so we know something is wrong.
        if (n < len)
-               LogMsg("ERROR: send_all(%d) wrote %d of %d errno %d %s",
-                       s, n, len, dnssd_errno(), dnssd_strerror(dnssd_errno()));
+               LogMsg("ERROR: send_all(%d) wrote %d of %d errno %d (%s)",
+                       s, n, len, dnssd_errno, dnssd_strerror(dnssd_errno));
        }
 
+#if 0
+mDNSlocal mDNSBool AuthorizedDomain(const request_state * const request, const domainname * const d, const DNameListElem * const doms)
+{
+       const           DNameListElem   *delem = mDNSNULL;
+       int             bestDelta       = -1;                                   // the delta of the best match, lower is better
+       int             dLabels         = 0;
+       mDNSBool        allow           = mDNSfalse;
+       
+       if (SystemUID(request->uid)) return mDNStrue;
+       
+       dLabels = CountLabels(d);
+       for (delem = doms; delem; delem = delem->next)
+               {
+               if (delem->uid)
+                       {
+                       int     delemLabels = CountLabels(&delem->name);
+                       int delta               = dLabels - delemLabels;
+                       if ((bestDelta == -1 || delta <= bestDelta) && SameDomainName(&delem->name, SkipLeadingLabels(d, delta)))
+                               {
+                               bestDelta = delta;
+                               allow = (allow || (delem->uid == request->uid));
+                               }
+                       }
+               }
+       
+       return bestDelta == -1 ? mDNStrue : allow;
+}
+#endif
+
 // ***************************************************************************
 #if COMPILER_LIKES_PRAGMA_MARK
 #pragma mark -
@@ -1140,11 +1416,11 @@ mDNSlocal void send_all(dnssd_sock_t s, const char *ptr, int len)
 mDNSexport void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result)
        {
        ExtraResourceRecord *extra = (ExtraResourceRecord *)rr->RecordContext;
-       (void)m;  //unused
+       (void)m;  // Unused
 
        if (result != mStatus_MemFree) { LogMsg("Error: FreeExtraRR invoked with unexpected error %d", result); return; }
 
-       LogOperation("     FreeExtraRR %s", RRDisplayString(m, &rr->resrec));
+       LogInfo("     FreeExtraRR %s", RRDisplayString(m, &rr->resrec));
 
        if (rr->resrec.rdata != &rr->rdatastorage)
                freeL("Extra RData", rr->resrec.rdata);
@@ -1192,11 +1468,11 @@ mDNSexport int CountPeerRegistrations(mDNS *const m, ServiceRecordSet *const srs
        ServiceRecordSet *s;
 
        for (rr = m->ResourceRecords; rr; rr=rr->next)
-               if (rr->resrec.rrtype == kDNSType_SRV && SameDomainName(rr->resrec.name, r->name) && !SameRData(&rr->resrec, r))
+               if (rr->resrec.rrtype == kDNSType_SRV && SameDomainName(rr->resrec.name, r->name) && !IdenticalSameNameRecord(&rr->resrec, r))
                        count++;
 
        for (s = m->ServiceRegistrations; s; s = s->uDNS_next)
-               if (s->state != regState_Unregistered && SameDomainName(s->RR_SRV.resrec.name, r->name) && !SameRData(&s->RR_SRV.resrec, r))
+               if (s->state != regState_Unregistered && SameDomainName(s->RR_SRV.resrec.name, r->name) && !IdenticalSameNameRecord(&s->RR_SRV.resrec, r))
                        count++;
 
        verbosedebugf("%d peer registrations for %##s", count, r->name->c);
@@ -1220,25 +1496,24 @@ mDNSlocal void SendServiceRemovalNotification(ServiceRecordSet *const srs)
        reply_state *rep;
        service_instance *instance = srs->ServiceContext;
        if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, 0, mStatus_NoError) != mStatus_NoError)
-               LogMsg("%3d: SendServiceRemovalNotification: %##s is not valid DNS-SD SRV name", instance->sd, srs->RR_SRV.resrec.name->c);
+               LogMsg("%3d: SendServiceRemovalNotification: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
        else { append_reply(instance->request, rep); instance->clientnotified = mDNSfalse; }
        }
 
 // service registration callback performs three duties - frees memory for deregistered services,
-// handles name conflicts, and delivers completed registration information to the client (via
-// process_service_registraion())
+// handles name conflicts, and delivers completed registration information to the client
 mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
        {
        mStatus err;
        mDNSBool SuppressError = mDNSfalse;
        service_instance *instance = srs->ServiceContext;
        reply_state         *rep;
-#if LogAllOperations || MDNS_DEBUGMSGS
-       char *fmt = (result == mStatus_NoError)      ? "%3d: DNSServiceRegister(%##s, %u) REGISTERED"    :
-                               (result == mStatus_MemFree)      ? "%3d: DNSServiceRegister(%##s, %u) DEREGISTERED"  :
-                               (result == mStatus_NameConflict) ? "%3d: DNSServiceRegister(%##s, %u) NAME CONFLICT" :
-                                                                  "%3d: DNSServiceRegister(%##s, %u) %s %d";
-#endif
+       char *fmt = "";
+       if (mDNS_LoggingEnabled)
+               fmt = (result == mStatus_NoError)      ? "%3d: DNSServiceRegister(%##s, %u) REGISTERED"    :
+                         (result == mStatus_MemFree)      ? "%3d: DNSServiceRegister(%##s, %u) DEREGISTERED"  :
+                         (result == mStatus_NameConflict) ? "%3d: DNSServiceRegister(%##s, %u) NAME CONFLICT" :
+                                                            "%3d: DNSServiceRegister(%##s, %u) %s %d";
        (void)m; // Unused
        if (!srs)      { LogMsg("regservice_callback: srs is NULL %d",                 result); return; }
        if (!instance) { LogMsg("regservice_callback: srs->ServiceContext is NULL %d", result); return; }
@@ -1249,7 +1524,8 @@ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, m
                !instance->default_local)
                SuppressError = mDNStrue;
 
-       LogOperation(fmt, instance->sd, srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port), SuppressError ? "suppressed error" : "CALLBACK", result);
+       LogOperation(fmt, instance->request ? instance->request->sd : -99,
+               srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port), SuppressError ? "suppressed error" : "CALLBACK", result);
 
        if (!instance->request && result != mStatus_MemFree) { LogMsg("regservice_callback: instance->request is NULL %d", result); return; }
 
@@ -1266,7 +1542,7 @@ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, m
                        }
 
                if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
-                       LogMsg("%3d: regservice_callback: %##s is not valid DNS-SD SRV name", instance->sd, srs->RR_SRV.resrec.name->c);
+                       LogMsg("%3d: regservice_callback: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
                else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
 
                if (instance->request->u.servicereg.autoname && CountPeerRegistrations(m, srs) == 0)
@@ -1278,7 +1554,7 @@ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, m
                        {
                        instance->renameonmemfree = 0;
                        err = mDNS_RenameAndReregisterService(m, srs, &instance->request->u.servicereg.name);
-                       if (err) LogMsg("ERROR: regservice_callback - RenameAndReregisterService returned %ld", err);
+                       if (err) LogMsg("ERROR: regservice_callback - RenameAndReregisterService returned %d", err);
                        // error should never happen - safest to log and continue
                        }
                else
@@ -1292,7 +1568,7 @@ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, m
                                {
                                // On conflict for an autoname service, rename and reregister *all* autoname services
                                IncrementLabelSuffix(&m->nicelabel, mDNStrue);
-                               m->MainCallback(m, mStatus_ConfigChanged);      // will call back into udsserver_handle_configchange()
+                               mDNS_ConfigChanged(m);  // Will call back into udsserver_handle_configchange()
                                }
                        else    // On conflict for a non-autoname service, rename and reregister just that one service
                                {
@@ -1305,7 +1581,7 @@ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, m
                        if (!SuppressError) 
                                {
                                if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
-                                       LogMsg("%3d: regservice_callback: %##s is not valid DNS-SD SRV name", instance->sd, srs->RR_SRV.resrec.name->c);
+                                       LogMsg("%3d: regservice_callback: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
                                else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
                                }
                        unlink_and_free_service_instance(instance);
@@ -1316,7 +1592,7 @@ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, m
                if (!SuppressError) 
                        {
                        if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
-                               LogMsg("%3d: regservice_callback: %##s is not valid DNS-SD SRV name", instance->sd, srs->RR_SRV.resrec.name->c);
+                               LogMsg("%3d: regservice_callback: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
                        else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
                        }
                }
@@ -1341,7 +1617,7 @@ mDNSlocal void regrecord_callback(mDNS *const m, AuthRecord *rr, mStatus result)
                request_state *request = re->request;
                int len = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + sizeof(DNSServiceErrorType);
                reply_state *reply = create_reply(reg_record_reply_op, len, request);
-               reply->mhdr->client_context = re->client_context;
+               reply->mhdr->client_context = re->regrec_client_context;
                reply->rhdr->flags = dnssd_htonl(0);
                reply->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, rr->resrec.InterfaceID));
                reply->rhdr->error = dnssd_htonl(result);
@@ -1370,6 +1646,8 @@ mDNSlocal void connection_termination(request_state *request)
                        {
                        // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
                        request_state *tmp = *req;
+                       if (tmp->primary == tmp) LogMsg("connection_termination ERROR (*req)->primary == *req for %p %d",                  tmp, tmp->sd);
+                       if (tmp->replies)        LogMsg("connection_termination ERROR How can subordinate req %p %d have replies queued?", tmp, tmp->sd);
                        abort_request(tmp);
                        *req = tmp->next;
                        freeL("request_state/connection_termination", tmp);
@@ -1391,7 +1669,7 @@ mDNSlocal void connection_termination(request_state *request)
 mDNSlocal void handle_cancel_request(request_state *request)
        {
        request_state **req = &all_requests;
-       LogOperation("%3d: Cancel %X%08X", request->sd, request->hdr.client_context.u32[1], request->hdr.client_context.u32[0]);
+       LogOperation("%3d: Cancel %08X %08X", request->sd, request->hdr.client_context.u32[1], request->hdr.client_context.u32[0]);
        while (*req)
                {
                if ((*req)->primary == request &&
@@ -1421,12 +1699,15 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request)
                re->key = request->hdr.reg_index;
                re->rr = rr;
                re->request = request;
-               re->client_context = request->hdr.client_context;
+               re->regrec_client_context = request->hdr.client_context;
                rr->RecordContext = re;
                rr->RecordCallback = regrecord_callback;
                re->next = request->u.reg_recs;
                request->u.reg_recs = re;
        
+#if 0
+               if (!AuthorizedDomain(request, rr->resrec.name, AutoRegistrationDomains))       return (mStatus_NoError);
+#endif
                if (rr->resrec.rroriginalttl == 0)
                        rr->resrec.rroriginalttl = DefaultTTLforRRType(rr->resrec.rrtype);
        
@@ -1436,7 +1717,49 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request)
        return(err);
        }
 
-mDNSlocal mStatus add_record_to_service(request_state *request, service_instance *instance, mDNSu16 rrtype, mDNSu16 rdlen, char *rdata, mDNSu32 ttl)
+mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m);
+
+mDNSlocal void regservice_termination_callback(request_state *request)
+       {
+       if (!request) { LogMsg("regservice_termination_callback context is NULL"); return; }
+       while (request->u.servicereg.instances)
+               {
+               service_instance *p = request->u.servicereg.instances;
+               request->u.servicereg.instances = request->u.servicereg.instances->next;
+               // only safe to free memory if registration is not valid, i.e. deregister fails (which invalidates p)
+               LogOperation("%3d: DNSServiceRegister(%##s, %u) STOP",
+                       request->sd, p->srs.RR_SRV.resrec.name->c, mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port));
+
+               // Clear backpointer *before* calling mDNS_DeregisterService/unlink_and_free_service_instance
+               // We don't need unlink_and_free_service_instance to cut its element from the list, because we're already advancing
+               // request->u.servicereg.instances as we work our way through the list, implicitly cutting one element at a time
+               // We can't clear p->request *after* the calling mDNS_DeregisterService/unlink_and_free_service_instance
+               // because by then we might have already freed p
+               p->request = NULL;
+               if (mDNS_DeregisterService(&mDNSStorage, &p->srs)) unlink_and_free_service_instance(p);
+               // Don't touch service_instance *p after this -- it's likely to have been freed already
+               }
+       if (request->u.servicereg.txtdata)
+               { freeL("service_info txtdata", request->u.servicereg.txtdata); request->u.servicereg.txtdata = NULL; }
+       if (request->u.servicereg.autoname)
+               {
+               // Clear autoname before calling UpdateDeviceInfoRecord() so it doesn't mistakenly include this in its count of active autoname registrations
+               request->u.servicereg.autoname = mDNSfalse;
+               UpdateDeviceInfoRecord(&mDNSStorage);
+               }
+       }
+
+mDNSlocal request_state *LocateSubordinateRequest(request_state *request)
+       {
+       request_state *req;
+       for (req = all_requests; req; req = req->next)
+               if (req->primary == request &&
+                       req->hdr.client_context.u32[0] == request->hdr.client_context.u32[0] &&
+                       req->hdr.client_context.u32[1] == request->hdr.client_context.u32[1]) return(req);
+       return(request);
+       }
+
+mDNSlocal mStatus add_record_to_service(request_state *request, service_instance *instance, mDNSu16 rrtype, mDNSu16 rdlen, const char *rdata, mDNSu32 ttl)
        {
        ServiceRecordSet *srs = &instance->srs;
        mStatus result;
@@ -1461,16 +1784,22 @@ mDNSlocal mStatus handle_add_request(request_state *request)
        {
        service_instance *i;
        mStatus result = mStatus_UnknownErr;
-       DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
-       mDNSu16        rrtype = get_uint16(&request->msgptr, request->msgend);
-       mDNSu16        rdlen  = get_uint16(&request->msgptr, request->msgend);
-       char           *rdata = get_rdata(&request->msgptr, request->msgend, rdlen);
-       mDNSu32        ttl    = get_uint32(&request->msgptr, request->msgend);
+       DNSServiceFlags flags  = get_flags (&request->msgptr, request->msgend);
+       mDNSu16         rrtype = get_uint16(&request->msgptr, request->msgend);
+       mDNSu16         rdlen  = get_uint16(&request->msgptr, request->msgend);
+       const char     *rdata  = get_rdata (&request->msgptr, request->msgend, rdlen);
+       mDNSu32         ttl    = get_uint32(&request->msgptr, request->msgend);
        if (!ttl) ttl = DefaultTTLforRRType(rrtype);
        (void)flags; // Unused
 
        if (!request->msgptr) { LogMsg("%3d: DNSServiceAddRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
 
+       // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
+       if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
+
+       if (request->terminate != regservice_termination_callback)
+               { LogMsg("%3d: DNSServiceAddRecord(not a registered service ref)", request->sd); return(mStatus_BadParamErr); }
+
        LogOperation("%3d: DNSServiceAddRecord(%##s, %s, %d)", request->sd,
                (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL, DNSTypeName(rrtype), rdlen);
 
@@ -1490,7 +1819,7 @@ mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd
        if (oldrd != &rr->rdatastorage) freeL("RData/update_callback", oldrd);
        }
 
-mDNSlocal mStatus update_record(AuthRecord *rr, mDNSu16 rdlen, char *rdata, mDNSu32 ttl)
+mDNSlocal mStatus update_record(AuthRecord *rr, mDNSu16 rdlen, const char *rdata, mDNSu32 ttl)
        {
        int rdsize;
        RData *newrd;
@@ -1509,32 +1838,36 @@ mDNSlocal mStatus update_record(AuthRecord *rr, mDNSu16 rdlen, char *rdata, mDNS
        if (rr->resrec.rrtype == kDNSType_TXT && rdlen == 0) { rdlen = 1; newrd->u.txt.c[0] = 0; }
 
        result = mDNS_Update(&mDNSStorage, rr, ttl, rdlen, newrd, update_callback);
-       if (result) { LogMsg("ERROR: mDNS_Update - %ld", result); freeL("RData/update_record", newrd); }
+       if (result) { LogMsg("ERROR: mDNS_Update - %d", result); freeL("RData/update_record", newrd); }
        return result;
        }
 
 mDNSlocal mStatus handle_update_request(request_state *request)
        {
+       const ipc_msg_hdr *const hdr = &request->hdr;
        mStatus result = mStatus_BadReferenceErr;
        service_instance *i;
        AuthRecord *rr = NULL;
 
        // get the message data
-       DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);   // flags unused
-       mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
-       char *rdata = get_rdata(&request->msgptr, request->msgend, rdlen);
-       mDNSu32 ttl = get_uint32(&request->msgptr, request->msgend);
+       DNSServiceFlags flags = get_flags (&request->msgptr, request->msgend);  // flags unused
+       mDNSu16         rdlen = get_uint16(&request->msgptr, request->msgend);
+       const char     *rdata = get_rdata (&request->msgptr, request->msgend, rdlen);
+       mDNSu32         ttl   = get_uint32(&request->msgptr, request->msgend);
        (void)flags; // Unused
 
        if (!request->msgptr) { LogMsg("%3d: DNSServiceUpdateRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
 
+       // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
+       if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
+
        if (request->terminate == connection_termination)
                {
                // update an individually registered record
                registered_record_entry *reptr;
                for (reptr = request->u.reg_recs; reptr; reptr = reptr->next)
                        {
-                       if (reptr->key == request->hdr.reg_index)
+                       if (reptr->key == hdr->reg_index)
                                {
                                result = update_record(reptr->rr, rdlen, rdata, ttl);
                                goto end;
@@ -1544,15 +1877,33 @@ mDNSlocal mStatus handle_update_request(request_state *request)
                goto end;
                }
 
+       if (request->terminate != regservice_termination_callback)
+               { LogMsg("%3d: DNSServiceUpdateRecord(not a registered service ref)", request->sd); return(mStatus_BadParamErr); }
+
+       // update the saved off TXT data for the service
+       if (hdr->reg_index == TXT_RECORD_INDEX)
+               {
+               if (request->u.servicereg.txtdata)
+                       { freeL("service_info txtdata", request->u.servicereg.txtdata); request->u.servicereg.txtdata = NULL; }
+               if (rdlen > 0)
+                       {
+                       request->u.servicereg.txtdata = mallocL("service_info txtdata", rdlen);
+                       if (!request->u.servicereg.txtdata) FatalError("ERROR: handle_update_request - malloc");
+                       mDNSPlatformMemCopy(request->u.servicereg.txtdata, rdata, rdlen);
+                       }
+               else
+                       request->u.servicereg.txtdata = NULL;
+               }
+
        // update a record from a service record set
        for (i = request->u.servicereg.instances; i; i = i->next)
                {
-               if (request->hdr.reg_index == TXT_RECORD_INDEX) rr = &i->srs.RR_TXT;
+               if (hdr->reg_index == TXT_RECORD_INDEX) rr = &i->srs.RR_TXT;
                else
                        {
                        ExtraResourceRecord *e;
                        for (e = i->srs.Extras; e; e = e->next)
-                               if (e->ClientID == request->hdr.reg_index) { rr = &e->r; break; }
+                               if (e->ClientID == hdr->reg_index) { rr = &e->r; break; }
                        }
 
                if (!rr) { result = mStatus_BadReferenceErr; goto end; }
@@ -1562,9 +1913,10 @@ mDNSlocal mStatus handle_update_request(request_state *request)
                }
 
 end:
-       LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s)", request->sd,
-               (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL,
-               rr ? DNSTypeName(rr->resrec.rrtype) : "<NONE>");
+       if (request->terminate == regservice_termination_callback)
+               LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s)", request->sd,
+                       (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL,
+                       rr ? DNSTypeName(rr->resrec.rrtype) : "<NONE>");
 
        return(result);
        }
@@ -1585,7 +1937,7 @@ mDNSlocal mStatus remove_record(request_state *request)
        err = mDNS_Deregister(&mDNSStorage, e->rr);
        if (err)
                {
-               LogMsg("ERROR: remove_record, mDNS_Deregister: %ld", err);
+               LogMsg("ERROR: remove_record, mDNS_Deregister: %d", err);
                freeL("registered_record_entry AuthRecord remove_record", e->rr);
                }
        freeL("registered_record_entry remove_record", e);
@@ -1615,8 +1967,13 @@ mDNSlocal mStatus handle_removerecord_request(request_state *request)
 
        if (!request->msgptr) { LogMsg("%3d: DNSServiceRemoveRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
 
+       // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
+       if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
+
        if (request->terminate == connection_termination)
                err = remove_record(request);  // remove individually registered record
+       else if (request->terminate != regservice_termination_callback)
+               { LogMsg("%3d: DNSServiceRemoveRecord(not a registered service ref)", request->sd); return(mStatus_BadParamErr); }
        else
                {
                service_instance *i;
@@ -1715,7 +2072,11 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain
        for (ptr = &request->u.servicereg.instances; *ptr; ptr = &(*ptr)->next)
                {
                if (SameDomainName(&(*ptr)->domain, domain))
-                       { LogMsg("register_service_instance: domain %##s already registered", domain->c); return mStatus_AlreadyRegistered; }
+                       {
+                       LogMsg("register_service_instance: domain %##s already registered for %#s.%##s",
+                               domain->c, &request->u.servicereg.name, &request->u.servicereg.type);
+                       return mStatus_AlreadyRegistered;
+                       }
                }
 
        // Special-case hack: We don't advertise SMB service in AutoTunnel domains, because AutoTunnel
@@ -1734,7 +2095,6 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain
 
        instance->next            = mDNSNULL;
        instance->request         = request;
-       instance->sd              = request->sd;
        instance->subtypes        = AllocateSubTypes(request->u.servicereg.num_subtypes, request->u.servicereg.type_as_string);
        instance->renameonmemfree = 0;
        instance->clientnotified  = mDNSfalse;
@@ -1744,9 +2104,6 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain
        if (request->u.servicereg.num_subtypes && !instance->subtypes)
                { unlink_and_free_service_instance(instance); instance = NULL; FatalError("ERROR: malloc"); }
 
-       LogOperation("%3d: DNSServiceRegister(%#s.%##s%##s, %u) ADDING",
-               instance->sd, &request->u.servicereg.name, &request->u.servicereg.type, domain->c, mDNSVal16(request->u.servicereg.port));
-
        result = mDNS_RegisterService(&mDNSStorage, &instance->srs,
                &request->u.servicereg.name, &request->u.servicereg.type, domain,
                request->u.servicereg.host.c[0] ? &request->u.servicereg.host : NULL,
@@ -1755,7 +2112,12 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain
                instance->subtypes, request->u.servicereg.num_subtypes,
                request->u.servicereg.InterfaceID, regservice_callback, instance);
 
-       if (!result) *ptr = instance;           // Append this to the end of our request->u.servicereg.instances list
+       if (!result)
+               {
+               *ptr = instance;                // Append this to the end of our request->u.servicereg.instances list
+               LogOperation("%3d: DNSServiceRegister(%##s, %u) ADDED",
+                       instance->request->sd, instance->srs.RR_SRV.resrec.name->c, mDNSVal16(request->u.servicereg.port));
+               }
        else
                {
                LogMsg("register_service_instance %#s.%##s%##s error %d",
@@ -1766,33 +2128,6 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain
        return result;
        }
 
-mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m);
-
-mDNSlocal void regservice_termination_callback(request_state *request)
-       {
-       if (!request) { LogMsg("regservice_termination_callback context is NULL"); return; }
-       while (request->u.servicereg.instances)
-               {
-               service_instance *p = request->u.servicereg.instances;
-               request->u.servicereg.instances = request->u.servicereg.instances->next;
-               // only safe to free memory if registration is not valid, i.e. deregister fails (which invalidates p)
-               LogOperation("%3d: DNSServiceRegister(%##s, %u) STOP",
-                       request->sd, p->srs.RR_SRV.resrec.name->c, mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port));
-
-               // Clear backpointer *before* calling mDNS_DeregisterService/unlink_and_free_service_instance
-               // We don't need unlink_and_free_service_instance to cut its element from the list, because we're already advancing
-               // request->u.servicereg.instances as we work our way through the list, implicitly cutting one element at a time
-               // We can't clear p->request *after* the calling mDNS_DeregisterService/unlink_and_free_service_instance
-               // because by then we might have already freed p
-               p->request = NULL;
-               if (mDNS_DeregisterService(&mDNSStorage, &p->srs)) unlink_and_free_service_instance(p);
-               // Don't touch service_instance *p after this -- it's likely to have been freed already
-               }
-       if (request->u.servicereg.txtdata)
-               { freeL("service_info txtdata", request->u.servicereg.txtdata); request->u.servicereg.txtdata = NULL; }
-       if (request->u.servicereg.autoname) UpdateDeviceInfoRecord(&mDNSStorage);
-       }
-
 mDNSlocal void udsserver_default_reg_domain_changed(const DNameListElem *const d, const mDNSBool add)
        {
        request_state *request;
@@ -1963,24 +2298,32 @@ mDNSlocal mStatus handle_regservice_request(request_state *request)
 
        LogOperation("%3d: DNSServiceRegister(\"%s\", \"%s\", \"%s\", \"%s\", %u) START",
                request->sd, name, request->u.servicereg.type_as_string, domain, host, mDNSVal16(request->u.servicereg.port));
+
+       // We need to unconditionally set request->terminate, because even if we didn't successfully
+       // start any registrations right now, subsequent configuration changes may cause successful
+       // registrations to be added, and we'll need to cancel them before freeing this memory.
+       // We also need to set request->terminate first, before adding additional service instances,
+       // because the uds_validatelists uses the request->terminate function pointer to determine
+       // what kind of request this is, and therefore what kind of list validation is required.
+       request->terminate = regservice_termination_callback;
+
        err = register_service_instance(request, &d);
 
-       // Set request->terminate first, before adding additional service instances, because the
-       // uds_validatelists uses the request->terminate function pointer to determine what kind
-       // of request this is, and therefore what kind of list validation is required.
+#if 0
+       err = AuthorizedDomain(request, &d, AutoRegistrationDomains) ? register_service_instance(request, &d) : mStatus_NoError;
+#endif
        if (!err)
                {
-               request->terminate = regservice_termination_callback;
                if (request->u.servicereg.autoname) UpdateDeviceInfoRecord(&mDNSStorage);
-               }
 
-       if (!err && !*domain)
-               {
-               DNameListElem *ptr;
-               // note that we don't report errors for non-local, non-explicit domains
-               for (ptr = AutoRegistrationDomains; ptr; ptr = ptr->next)
-                       if (!ptr->uid || SystemUID(request->uid) || request->uid == ptr->uid)
-                               register_service_instance(request, &ptr->name);
+               if (!*domain)
+                       {
+                       DNameListElem *ptr;
+                       // Note that we don't report errors for non-local, non-explicit domains
+                       for (ptr = AutoRegistrationDomains; ptr; ptr = ptr->next)
+                               if (!ptr->uid || SystemUID(request->uid) || request->uid == ptr->uid)
+                                       register_service_instance(request, &ptr->name);
+                       }
                }
 
        return(err);
@@ -2004,11 +2347,21 @@ mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const Resourc
 
        if (GenerateNTDResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError) != mStatus_NoError)
                {
+               if (SameDomainName(&req->u.browser.regtype, (const domainname*)"\x09_services\x07_dns-sd\x04_udp"))
+                       {
+                       // Special support to enable the DNSServiceBrowse call made by Bonjour Browser
+                       // Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
+                       GenerateBonjourBrowserResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError);
+                       goto bonjourbrowserhack;
+                       }
+
                LogMsg("%3d: FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
                        req->sd, answer->name->c, answer->rdata->u.name.c);
                return;
                }
 
+bonjourbrowserhack:
+
        LogOperation("%3d: DNSServiceBrowse(%##s, %s) RESULT %s %d: %s",
                req->sd, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "Add" : "Rmv",
                mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID), RRDisplayString(m, answer));
@@ -2041,8 +2394,9 @@ mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d
                {
                b->next = info->u.browser.browsers;
                info->u.browser.browsers = b;
+               LogOperation("%3d: DNSServiceBrowse(%##s) START", info->sd, b->q.qname.c);
                }
-               return err;
+       return err;
        }
 
 mDNSlocal void browse_termination_callback(request_state *info)
@@ -2124,7 +2478,7 @@ mDNSlocal void RegisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int
        mStatus err;
        ARListElem *ptr = mDNSPlatformMemAllocate(sizeof(*ptr));
 
-       LogOperation("Incrementing %s refcount for %##s",
+       debugf("Incrementing %s refcount for %##s",
                (type == mDNS_DomainTypeBrowse         ) ? "browse domain   " :
                (type == mDNS_DomainTypeRegistration   ) ? "registration dom" :
                (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
@@ -2151,7 +2505,7 @@ mDNSlocal void DeregisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, in
        ARListElem **ptr = &LocalDomainEnumRecords;
        domainname lhs; // left-hand side of PTR, for comparison
 
-       LogOperation("Decrementing %s refcount for %##s",
+       debugf("Decrementing %s refcount for %##s",
                (type == mDNS_DomainTypeBrowse         ) ? "browse domain   " :
                (type == mDNS_DomainTypeRegistration   ) ? "registration dom" :
                (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
@@ -2251,8 +2605,8 @@ mDNSexport void udsserver_handle_configchange(mDNS *const m)
        {
        request_state *req;
        service_instance *ptr;
-       DNameListElem *RegDomains;
-       DNameListElem *BrowseDomains;
+       DNameListElem *RegDomains = NULL;
+       DNameListElem *BrowseDomains = NULL;
        DNameListElem *p;
 
        UpdateDeviceInfoRecord(m);
@@ -2381,12 +2735,20 @@ mDNSlocal mStatus handle_browse_request(request_state *request)
        request->u.browser.browsers = NULL;
 
        LogOperation("%3d: DNSServiceBrowse(\"%##s\", \"%s\") START", request->sd, request->u.browser.regtype.c, domain);
+
+       // We need to unconditionally set request->terminate, because even if we didn't successfully
+       // start any browses right now, subsequent configuration changes may cause successful
+       // browses to be added, and we'll need to cancel them before freeing this memory.
+       request->terminate = browse_termination_callback;
+
        if (domain[0])
                {
                if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
                err = add_domain_to_browser(request, &d);
+#if 0
+               err = AuthorizedDomain(request, &d, AutoBrowseDomains) ? add_domain_to_browser(request, &d) : mStatus_NoError;
+#endif
                }
-
        else
                {
                DNameListElem *sdom;
@@ -2402,8 +2764,6 @@ mDNSlocal mStatus handle_browse_request(request_state *request)
                                }
                }
 
-       if (!err) request->terminate = browse_termination_callback;
-
        return(err);
        }
 
@@ -2422,17 +2782,12 @@ mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, con
        request_state *req = question->QuestionContext;
        (void)m; // Unused
 
-       LogOperation("%3d: DNSServiceResolve(%##s, %s) %s %s",
-               req->sd, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "ADD" : "RMV", RRDisplayString(m, answer));
-
-       // This code used to do this trick of just keeping a copy of the pointer to
-       // the answer record in the cache, but the unicast query code doesn't currently
-       // put its answer records in the cache, so for now we can't do this.
+       LogOperation("%3d: DNSServiceResolve(%##s) %s %s", req->sd, question->qname.c, AddRecord ? "ADD" : "RMV", RRDisplayString(m, answer));
 
        if (!AddRecord)
                {
-               if (answer->rrtype == kDNSType_SRV && req->u.resolve.srv == answer) req->u.resolve.srv = mDNSNULL;
-               if (answer->rrtype == kDNSType_TXT && req->u.resolve.txt == answer) req->u.resolve.txt = mDNSNULL;
+               if (req->u.resolve.srv == answer) req->u.resolve.srv = mDNSNULL;
+               if (req->u.resolve.txt == answer) req->u.resolve.txt = mDNSNULL;
                return;
                }
 
@@ -2459,16 +2814,17 @@ mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, con
        rep->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID));
        rep->rhdr->error = dnssd_htonl(kDNSServiceErr_NoError);
 
-       data = rep->sdata;
+       data = (char *)&rep->rhdr[1];
 
        // write reply data to message
        put_string(fullname, &data);
        put_string(target, &data);
-       *data++ = req->u.resolve.srv->rdata->u.srv.port.b[0];
-       *data++ = req->u.resolve.srv->rdata->u.srv.port.b[1];
+       *data++ =  req->u.resolve.srv->rdata->u.srv.port.b[0];
+       *data++ =  req->u.resolve.srv->rdata->u.srv.port.b[1];
        put_uint16(req->u.resolve.txt->rdlength, &data);
-       put_rdata(req->u.resolve.txt->rdlength, req->u.resolve.txt->rdata->u.data, &data);
+       put_rdata (req->u.resolve.txt->rdlength, req->u.resolve.txt->rdata->u.data, &data);
 
+       LogOperation("%3d: DNSServiceResolve(%s) RESULT   %s:%d", req->sd, fullname, target, mDNSVal16(req->u.resolve.srv->rdata->u.srv.port));
        append_reply(req, rep);
        }
 
@@ -2528,8 +2884,13 @@ mDNSlocal mStatus handle_resolve_request(request_state *request)
        request->u.resolve.qtxt.ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
        request->u.resolve.qtxt.QuestionCallback = resolve_result_callback;
        request->u.resolve.qtxt.QuestionContext  = request;
+
        request->u.resolve.ReportTime            = NonZeroTime(mDNS_TimeNow(&mDNSStorage) + 130 * mDNSPlatformOneSecond);
 
+#if 0
+       if (!AuthorizedDomain(request, &fqdn, AutoBrowseDomains))       return(mStatus_NoError);
+#endif
+
        // ask the questions
        LogOperation("%3d: DNSServiceResolve(%##s) START", request->sd, request->u.resolve.qsrv.qname.c);
        err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qsrv);
@@ -2537,10 +2898,9 @@ mDNSlocal mStatus handle_resolve_request(request_state *request)
                {
                err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qtxt);
                if (err) mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
+               else request->terminate = resolve_termination_callback;
                }
 
-       if (!err) request->terminate = resolve_termination_callback;
-
        return(err);
        }
 
@@ -2565,18 +2925,43 @@ mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question,
        DNSServiceErrorType error = kDNSServiceErr_NoError;
        (void)m; // Unused
 
-       LogOperation("%3d: %s(%##s, %s) %s %s", req->sd,
-               req->hdr.op == query_request ? "DNSServiceQueryRecord" : "DNSServiceGetAddrInfo",
-               question->qname.c, DNSTypeName(question->qtype), AddRecord ? "ADD" : "RMV", RRDisplayString(m, answer));
+#if APPLE_OSX_mDNSResponder
+       if (question == &req->u.queryrecord.q2)
+               {
+               mDNS_StopQuery(&mDNSStorage, question);
+               // If we got a non-negative answer for our "local SOA" test query, start an additional parallel unicast query
+               if (answer->RecordType == kDNSRecordTypePacketNegative ||
+                       (question->qtype == req->u.queryrecord.q.qtype && SameDomainName(&question->qname, &req->u.queryrecord.q.qname)))
+                       question->QuestionCallback = mDNSNULL;
+               else
+                       {
+                       *question              = req->u.queryrecord.q;
+                       question->InterfaceID  = mDNSInterface_Unicast;
+                       question->ExpectUnique = mDNStrue;
+                       mStatus err = mDNS_StartQuery(&mDNSStorage, question);
+                       if (!err) LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) unicast", req->sd, question->qname.c, DNSTypeName(question->qtype));
+                       else LogMsg("%3d: ERROR: queryrecord_result_callback %##s %s mDNS_StartQuery: %d", req->sd, question->qname.c, DNSTypeName(question->qtype), (int)err);
+                       }
+               return;
+               }
+#endif // APPLE_OSX_mDNSResponder
 
        if (answer->RecordType == kDNSRecordTypePacketNegative)
                {
+               // When we're doing parallel unicast and multicast queries for dot-local names (for supporting Microsoft
+               // Active Directory sites) we need to ignore negative unicast answers. Otherwise we'll generate negative
+               // answers for just about every single multicast name we ever look up, since the Microsoft Active Directory
+               // server is going to assert that pretty much every single multicast name doesn't exist.
+               if (!answer->InterfaceID && IsLocalDomain(answer->name)) return;
                error = kDNSServiceErr_NoSuchRecord;
-               ConvertDomainNameToCString(&question->qname, name);
                AddRecord = mDNStrue;
                }
-       else
-               ConvertDomainNameToCString(answer->name, name);
+
+       ConvertDomainNameToCString(answer->name, name);
+
+       LogOperation("%3d: %s(%##s, %s) %s %s", req->sd,
+               req->hdr.op == query_request ? "DNSServiceQueryRecord" : "DNSServiceGetAddrInfo",
+               question->qname.c, DNSTypeName(question->qtype), AddRecord ? "ADD" : "RMV", RRDisplayString(m, answer));
 
        len = sizeof(DNSServiceFlags);  // calculate reply data length
        len += sizeof(mDNSu32);         // interface index
@@ -2592,29 +2977,19 @@ mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question,
        rep->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID));
        rep->rhdr->error = dnssd_htonl(error);
 
-       data = rep->sdata;
-
-       put_string(name, &data);
+       data = (char *)&rep->rhdr[1];
 
-       if (answer->RecordType == kDNSRecordTypePacketNegative)
-               {
-               put_uint16(question->qtype, &data);
-               put_uint16(question->qclass, &data);
-               put_uint16(0, &data);
-               put_rdata(0, mDNSNULL, &data);
-               put_uint32(0, &data);
-               }
-       else
-               {
-               put_uint16(answer->rrtype, &data);
-               put_uint16(answer->rrclass, &data);
-               put_uint16(answer->rdlength, &data);
-               //put_rdata(answer->rdlength, answer->rdata->u.data, &data);
+       put_string(name,             &data);
+       put_uint16(answer->rrtype,   &data);
+       put_uint16(answer->rrclass,  &data);
+       put_uint16(answer->rdlength, &data);
+       // We need to use putRData here instead of the crude put_rdata function, because the crude put_rdata
+       // function just does a blind memory copy without regard to structures that may have holes in them.
+       if (answer->rdlength)
                if (!putRData(mDNSNULL, (mDNSu8 *)data, (mDNSu8 *)rep->rhdr + len, answer))
                        LogMsg("queryrecord_result_callback putRData failed %d", (mDNSu8 *)rep->rhdr + len - (mDNSu8 *)data);
-               data += answer->rdlength;
-               put_uint32(AddRecord ? answer->rroriginalttl : 0, &data);
-               }
+       data += answer->rdlength;
+       put_uint32(AddRecord ? answer->rroriginalttl : 0, &data);
 
        append_reply(req, rep);
        }
@@ -2624,10 +2999,12 @@ mDNSlocal void queryrecord_termination_callback(request_state *request)
        LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) STOP",
                request->sd, request->u.queryrecord.q.qname.c, DNSTypeName(request->u.queryrecord.q.qtype));
        mDNS_StopQuery(&mDNSStorage, &request->u.queryrecord.q);  // no need to error check
+       if (request->u.queryrecord.q2.QuestionCallback) mDNS_StopQuery(&mDNSStorage, &request->u.queryrecord.q2);
        }
 
 mDNSlocal mStatus handle_queryrecord_request(request_state *request)
        {
+       DNSQuestion *const q = &request->u.queryrecord.q;
        char name[256];
        mDNSu16 rrtype, rrclass;
        mStatus err;
@@ -2644,26 +3021,63 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request)
        if (!request->msgptr)
                { LogMsg("%3d: DNSServiceQueryRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
 
-       mDNSPlatformMemZero(&request->u.queryrecord.q, sizeof(&request->u.queryrecord.q));
+       mDNSPlatformMemZero(&request->u.queryrecord, sizeof(request->u.queryrecord));
 
-       request->u.queryrecord.q.InterfaceID      = InterfaceID;
-       request->u.queryrecord.q.Target           = zeroAddr;
-       if (!MakeDomainNameFromDNSNameString(&request->u.queryrecord.q.qname, name)) return(mStatus_BadParamErr);
-       request->u.queryrecord.q.qtype            = rrtype;
-       request->u.queryrecord.q.qclass           = rrclass;
-       request->u.queryrecord.q.LongLived        = (flags & kDNSServiceFlagsLongLivedQuery     ) != 0;
-       request->u.queryrecord.q.ExpectUnique     = mDNSfalse;
-       request->u.queryrecord.q.ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
-       request->u.queryrecord.q.ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
-       request->u.queryrecord.q.QuestionCallback = queryrecord_result_callback;
-       request->u.queryrecord.q.QuestionContext  = request;
+       q->InterfaceID      = InterfaceID;
+       q->Target           = zeroAddr;
+       if (!MakeDomainNameFromDNSNameString(&q->qname, name))                  return(mStatus_BadParamErr);
+#if 0
+       if (!AuthorizedDomain(request, &q->qname, AutoBrowseDomains))   return (mStatus_NoError);
+#endif
+       q->qtype            = rrtype;
+       q->qclass           = rrclass;
+       q->LongLived        = (flags & kDNSServiceFlagsLongLivedQuery     ) != 0;
+       q->ExpectUnique     = mDNSfalse;
+       q->ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
+       q->ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
+       q->QuestionCallback = queryrecord_result_callback;
+       q->QuestionContext  = request;
+
+       LogOperation("%3d: DNSServiceQueryRecord(%##s, %s, %X) START", request->sd, q->qname.c, DNSTypeName(q->qtype), flags);
+       err = mDNS_StartQuery(&mDNSStorage, q);
+       if (err) LogMsg("%3d: ERROR: DNSServiceQueryRecord %##s %s mDNS_StartQuery: %d", request->sd, q->qname.c, DNSTypeName(q->qtype), (int)err);
+       else request->terminate = queryrecord_termination_callback;
 
-       LogOperation("%3d: DNSServiceQueryRecord(%##s, %s, %X) START",
-               request->sd, request->u.queryrecord.q.qname.c, DNSTypeName(request->u.queryrecord.q.qtype), flags);
-       err = mDNS_StartQuery(&mDNSStorage, &request->u.queryrecord.q);
-       if (err) LogMsg("ERROR: mDNS_StartQuery: %d", (int)err);
+#if APPLE_OSX_mDNSResponder
+       // Workaround for networks using Microsoft Active Directory using "local" as a private internal top-level domain
+       extern domainname ActiveDirectoryPrimaryDomain;
+       #define VALID_MSAD_SRV_TRANSPORT(T) (SameDomainLabel((T)->c, (const mDNSu8 *)"\x4_tcp") || SameDomainLabel((T)->c, (const mDNSu8 *)"\x4_udp"))
+       #define VALID_MSAD_SRV(Q) ((Q)->qtype == kDNSType_SRV && VALID_MSAD_SRV_TRANSPORT(SecondLabel(&(Q)->qname)))
 
-       if (!err) request->terminate = queryrecord_termination_callback;
+       if (!q->ForceMCast && SameDomainLabel(LastLabel(&q->qname), (const mDNSu8 *)&localdomain))
+               if (q->qtype == kDNSType_A || q->qtype == kDNSType_AAAA || VALID_MSAD_SRV(q))
+                       {
+                       int labels = CountLabels(&q->qname);
+                       DNSQuestion *const q2 = &request->u.queryrecord.q2;
+                       *q2              = *q;
+                       q2->InterfaceID  = mDNSInterface_Unicast;
+                       q2->ExpectUnique = mDNStrue;
+       
+                       // For names of the form "<one-or-more-labels>.bar.local." we always do a second unicast query in parallel.
+                       // For names of the form "<one-label>.local." it's less clear whether we should do a unicast query.
+                       // If the name being queried is exactly the same as the name in the DHCP "domain" option (e.g. the DHCP
+                       // "domain" is my-small-company.local, and the user types "my-small-company.local" into their web browser)
+                       // then that's a hint that it's worth doing a unicast query. Otherwise, we first check to see if the
+                       // site's DNS server claims there's an SOA record for "local", and if so, that's also a hint that queries
+                       // for names in the "local" domain will be safely answered privately before they hit the root name servers.
+                       if (labels == 2 && !SameDomainName(&q->qname, &ActiveDirectoryPrimaryDomain))
+                               {
+                               AssignDomainName(&q2->qname, &localdomain);
+                               q2->qtype          = kDNSType_SOA;
+                               q2->LongLived      = mDNSfalse;
+                               q2->ForceMCast     = mDNSfalse;
+                               q2->ReturnIntermed = mDNStrue;
+                               }
+                       err = mDNS_StartQuery(&mDNSStorage, q2);
+                       if (!err) LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) unicast", request->sd, q2->qname.c, DNSTypeName(q2->qtype));
+                       else LogMsg("%3d: ERROR: DNSServiceQueryRecord %##s %s mDNS_StartQuery: %d", request->sd, q2->qname.c, DNSTypeName(q2->qtype), (int)err);
+                       }
+#endif // APPLE_OSX_mDNSResponder
 
        return(err);
        }
@@ -2688,9 +3102,9 @@ mDNSlocal reply_state *format_enumeration_reply(request_state *request,
 
        reply = create_reply(enumeration_reply_op, len, request);
        reply->rhdr->flags = dnssd_htonl(flags);
-       reply->rhdr->ifi = dnssd_htonl(ifi);
+       reply->rhdr->ifi   = dnssd_htonl(ifi);
        reply->rhdr->error = dnssd_htonl(err);
-       data = reply->sdata;
+       data = (char *)&reply->rhdr[1];
        put_string(domain, &data);
        return reply;
        }
@@ -2711,7 +3125,11 @@ mDNSlocal void enum_result_callback(mDNS *const m,
        (void)m; // Unused
 
        if (answer->rrtype != kDNSType_PTR) return;
-       
+
+#if 0
+       if (!AuthorizedDomain(request, &answer->rdata->u.name, request->u.enumeration.flags ? AutoRegistrationDomains : AutoBrowseDomains)) return;
+#endif
+
        // We only return add/remove events for the browse and registration lists
        // For the default browse and registration answers, we only give an "ADD" event
        if (question == &request->u.enumeration.q_default && !AddRecord) return;
@@ -2728,6 +3146,9 @@ mDNSlocal void enum_result_callback(mDNS *const m,
        // network, so we just pass kDNSServiceInterfaceIndexAny
        reply = format_enumeration_reply(request, domain, flags, kDNSServiceInterfaceIndexAny, kDNSServiceErr_NoError);
        if (!reply) { LogMsg("ERROR: enum_result_callback, format_enumeration_reply"); return; }
+
+       LogOperation("%3d: DNSServiceEnumerateDomains(%#2s) RESULT %s: %s", request->sd, question->qname.c, AddRecord ? "Add" : "Rmv", domain);
+
        append_reply(request, reply);
        }
 
@@ -2748,6 +3169,11 @@ mDNSlocal mStatus handle_enum_request(request_state *request)
        // allocate context structures
        uDNS_RegisterSearchDomains(&mDNSStorage);
 
+#if 0
+       // mark which kind of enumeration we're doing so we can (de)authorize certain domains
+       request->u.enumeration.flags = reg;
+#endif
+
        // enumeration requires multiple questions, so we must link all the context pointers so that
        // necessary context can be reached from the callbacks
        request->u.enumeration.q_all    .QuestionContext = request;
@@ -2765,8 +3191,8 @@ mDNSlocal mStatus handle_enum_request(request_state *request)
                {
                err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_default, t_default, NULL, InterfaceID, enum_result_callback, request);
                if (err) mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
+               else request->terminate = enum_termination_callback;
                }
-       if (!err) request->terminate = enum_termination_callback;
 
        return(err);
        }
@@ -2874,7 +3300,7 @@ mDNSlocal void port_mapping_create_request_callback(mDNS *m, NATTraversalInfo *n
        rep->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, n->InterfaceID));
        rep->rhdr->error = dnssd_htonl(n->Result);
 
-       data = rep->sdata;
+       data = (char *)&rep->rhdr[1];
 
        *data++ = request->u.pm.NATinfo.ExternalAddress.b[0];
        *data++ = request->u.pm.NATinfo.ExternalAddress.b[1];
@@ -2939,7 +3365,8 @@ mDNSlocal mStatus handle_port_mapping_request(request_state *request)
        LogOperation("%3d: DNSServiceNATPortMappingCreate(%X, %u, %u, %d) START", request->sd,
                protocol, mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease);
        err = mDNS_StartNATOperation(&mDNSStorage, &request->u.pm.NATinfo);
-       if (!err) request->terminate = port_mapping_termination_callback;
+       if (err) LogMsg("ERROR: mDNS_StartNATOperation: %d", (int)err);
+       else request->terminate = port_mapping_termination_callback;
 
        return(err);
        }
@@ -2973,12 +3400,14 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
 
        DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
        mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
+
+       mDNSPlatformMemZero(&request->u.addrinfo, sizeof(request->u.addrinfo));
        request->u.addrinfo.interface_id = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
+       request->u.addrinfo.flags        = flags;
+       request->u.addrinfo.protocol     = get_uint32(&request->msgptr, request->msgend);
+
        if (interfaceIndex && !request->u.addrinfo.interface_id) return(mStatus_BadParamErr);
-       request->u.addrinfo.flags = flags;
-       request->u.addrinfo.protocol = get_uint32(&request->msgptr, request->msgend);
-       if (request->u.addrinfo.protocol > (kDNSServiceProtocol_IPv4|kDNSServiceProtocol_IPv6))
-               return(mStatus_BadParamErr);
+       if (request->u.addrinfo.protocol > (kDNSServiceProtocol_IPv4|kDNSServiceProtocol_IPv6)) return(mStatus_BadParamErr);
 
        if (get_string(&request->msgptr, request->msgend, hostname, 256) < 0) return(mStatus_BadParamErr);
 
@@ -2987,6 +3416,10 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
        if (!MakeDomainNameFromDNSNameString(&d, hostname))
                { LogMsg("ERROR: handle_addrinfo_request: bad hostname: %s", hostname); return(mStatus_BadParamErr); }
 
+#if 0
+       if (!AuthorizedDomain(request, &d, AutoBrowseDomains))  return (mStatus_NoError);
+#endif
+
        if (!request->u.addrinfo.protocol)
                {
                NetworkInterfaceInfo *i;
@@ -3049,6 +3482,8 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
                        {
                        LogMsg("ERROR: mDNS_StartQuery: %d", (int)err);
                        request->u.addrinfo.q6.QuestionContext = mDNSNULL;
+                       if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv4)    // If we started a query for IPv4,
+                               addrinfo_termination_callback(request);                                         // we need to cancel it
                        }
                }
 
@@ -3114,7 +3549,7 @@ mDNSlocal void read_msg(request_state *req)
                                { LogMsg("%3d: ERROR: client version 0x%08X daemon version 0x%08X", req->sd, req->hdr.version, VERSION); req->ts = t_error; return; }
 
                        // Largest conceivable single request is a DNSServiceRegisterRecord() or DNSServiceAddRecord()
-                       // with 64kB of rdata. Adding 1005 byte for a maximal domain name, plus a safety margin
+                       // with 64kB of rdata. Adding 1009 byte for a maximal domain name, plus a safety margin
                        // for other overhead, this means any message above 70kB is definitely bogus.
                        if (req->hdr.datalen > 70000)
                                { LogMsg("%3d: ERROR: read_msg - hdr.datalen %lu (%X) > 70000", req->sd, req->hdr.datalen, req->hdr.datalen); req->ts = t_error; return; }
@@ -3134,6 +3569,7 @@ mDNSlocal void read_msg(request_state *req)
                {
                mDNSu32 nleft = req->hdr.datalen - req->data_bytes;
                int nread;
+#if !defined(_WIN32)
                struct iovec vec = { req->msgbuf + req->data_bytes, nleft };    // Tell recvmsg where we want the bytes put
                struct msghdr msg;
                struct cmsghdr *cmsg;
@@ -3146,25 +3582,41 @@ mDNSlocal void read_msg(request_state *req)
                msg.msg_controllen = sizeof(cbuf);
                msg.msg_flags      = 0;
                nread = recvmsg(req->sd, &msg, 0);
+#else
+               nread = recv(req->sd, (char *)req->msgbuf + req->data_bytes, nleft, 0);
+#endif
                if (nread == 0) { req->ts = t_terminated; return; }
                if (nread < 0) goto rerror;
                req->data_bytes += nread;
                if (req->data_bytes > req->hdr.datalen)
                        { LogMsg("%3d: ERROR: read_msg - read too many data bytes", req->sd); req->ts = t_error; return; }
+#if !defined(_WIN32)
                cmsg = CMSG_FIRSTHDR(&msg);
 #if DEBUG_64BIT_SCM_RIGHTS
                LogMsg("%3d: Expecting %d %d %d %d", req->sd, sizeof(cbuf),       sizeof(cbuf),   SOL_SOCKET,       SCM_RIGHTS);
                LogMsg("%3d: Got       %d %d %d %d", req->sd, msg.msg_controllen, cmsg->cmsg_len, cmsg->cmsg_level, cmsg->cmsg_type);
-#endif DEBUG_64BIT_SCM_RIGHTS
+#endif // DEBUG_64BIT_SCM_RIGHTS
                if (msg.msg_controllen == sizeof(cbuf) &&
                        cmsg->cmsg_len     == sizeof(cbuf) &&
                        cmsg->cmsg_level   == SOL_SOCKET   &&
                        cmsg->cmsg_type    == SCM_RIGHTS)
                        {
-                       req->errsd = *(dnssd_sock_t *)CMSG_DATA(cmsg);
+#if APPLE_OSX_mDNSResponder
+                       // Strictly speaking BPF_fd belongs solely in the platform support layer, but because
+                       // of privilege separation on Mac OS X we need to get BPF_fd from mDNSResponderHelper,
+                       // and it's convenient to repurpose the existing fd-passing code here for that task
+                       if (req->hdr.op == send_bpf)
+                               {
+                               dnssd_sock_t x = *(dnssd_sock_t *)CMSG_DATA(cmsg);
+                               LogOperation("%3d: Got BPF %d", req->sd, x);
+                               mDNSPlatformReceiveBPF_fd(&mDNSStorage, x);
+                               }
+                       else
+#endif // APPLE_OSX_mDNSResponder
+                               req->errsd = *(dnssd_sock_t *)CMSG_DATA(cmsg);
 #if DEBUG_64BIT_SCM_RIGHTS
                        LogMsg("%3d: read req->errsd %d", req->sd, req->errsd);
-#endif DEBUG_64BIT_SCM_RIGHTS
+#endif // DEBUG_64BIT_SCM_RIGHTS
                        if (req->data_bytes < req->hdr.datalen)
                                {
                                LogMsg("%3d: Client sent error socket %d via SCM_RIGHTS with req->data_bytes %d < req->hdr.datalen %d",
@@ -3173,6 +3625,7 @@ mDNSlocal void read_msg(request_state *req)
                                return;
                                }
                        }
+#endif
                }
 
        // If our header and data are both complete, see if we need to make our separate error return socket
@@ -3183,6 +3636,7 @@ mDNSlocal void read_msg(request_state *req)
                        dnssd_sockaddr_t cliaddr;
 #if defined(USE_TCP_LOOPBACK)
                        mDNSOpaque16 port;
+                       int opt = 1;
                        port.b[0] = req->msgptr[0];
                        port.b[1] = req->msgptr[1];
                        req->msgptr += 2;
@@ -3213,10 +3667,10 @@ mDNSlocal void read_msg(request_state *req)
                                {
 #if !defined(USE_TCP_LOOPBACK)
                                struct stat sb;
-                               LogMsg("%3d: read_msg: Couldn't connect to error return path socket “%s” errno %d %s",
-                                       req->sd, cliaddr.sun_path, dnssd_errno(), dnssd_strerror(dnssd_errno()));
+                               LogMsg("%3d: read_msg: Couldn't connect to error return path socket “%s” errno %d (%s)",
+                                       req->sd, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
                                if (stat(cliaddr.sun_path, &sb) < 0)
-                                       LogMsg("%3d: read_msg: stat failed “%s” errno %d %s", req->sd, cliaddr.sun_path, dnssd_errno(), dnssd_strerror(dnssd_errno()));
+                                       LogMsg("%3d: read_msg: stat failed “%s” errno %d (%s)", req->sd, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
                                else
                                        LogMsg("%3d: read_msg: file “%s” mode %o (octal) uid %d gid %d", req->sd, cliaddr.sun_path, sb.st_mode, sb.st_uid, sb.st_gid);
 #endif
@@ -3225,15 +3679,15 @@ mDNSlocal void read_msg(request_state *req)
                                }
        
 got_errfd:
-                       LogOperation("%3d: Using separate error socket %d", req->sd, req->errsd);
+                       LogOperation("%3d: Error socket %d created %08X %08X", req->sd, req->errsd, req->hdr.client_context.u32[1], req->hdr.client_context.u32[0]);
 #if defined(_WIN32)
                        if (ioctlsocket(req->errsd, FIONBIO, &opt) != 0)
 #else
                        if (fcntl(req->errsd, F_SETFL, fcntl(req->errsd, F_GETFL, 0) | O_NONBLOCK) != 0)
 #endif
                                {
-                               LogMsg("%3d: ERROR: could not set control socket to non-blocking mode errno %d %s",
-                                       req->sd, dnssd_errno(), dnssd_strerror(dnssd_errno()));
+                               LogMsg("%3d: ERROR: could not set control socket to non-blocking mode errno %d (%s)",
+                                       req->sd, dnssd_errno, dnssd_strerror(dnssd_errno));
                                req->ts = t_error;
                                return;
                                }
@@ -3245,8 +3699,8 @@ got_errfd:
        return;
 
 rerror:
-       if (dnssd_errno() == dnssd_EWOULDBLOCK || dnssd_errno() == dnssd_EINTR) return;
-       LogMsg("%3d: ERROR: read_msg errno %d %s", req->sd, dnssd_errno(), dnssd_strerror(dnssd_errno()));
+       if (dnssd_errno == dnssd_EWOULDBLOCK || dnssd_errno == dnssd_EINTR) return;
+       LogMsg("%3d: ERROR: read_msg errno %d (%s)", req->sd, dnssd_errno, dnssd_strerror(dnssd_errno));
        req->ts = t_error;
        }
 
@@ -3270,6 +3724,7 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
        read_msg(req);
        if (req->ts == t_morecoming) return;
        if (req->ts == t_terminated || req->ts == t_error) { AbortUnlinkAndFree(req); return; }
+       if (req->ts != t_complete) { LogMsg("req->ts %d != t_complete", req->ts); AbortUnlinkAndFree(req); return; }
 
        if (req->hdr.version != VERSION)
                {
@@ -3295,6 +3750,7 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
                case getproperty_request:      min_size = 2;                                                                           break;
                case port_mapping_request:     min_size += sizeof(mDNSu32) + 4 /* udp/tcp */ + 4 /* int/ext port */    + 4 /* ttl */;  break;
                case addrinfo_request:         min_size += sizeof(mDNSu32) + 4 /* v4/v6 */   + 1 /* hostname */;                       break;
+               case send_bpf:                 // Same as cancel_request below
                case cancel_request:           min_size = 0;                                                                           break;
                default: LogMsg("ERROR: validate_message - unsupported req type: %d", req->hdr.op); min_size = -1;                     break;
                }
@@ -3332,27 +3788,26 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
        else switch(req->hdr.op)
                {
                // These are all operations that have their own first-class request_state object
-               case connection_request:
-                       LogOperation("%3d: DNSServiceCreateConnection START", req->sd);
-                       req->terminate = connection_termination;
-                       break;
-               case resolve_request:              err = handle_resolve_request     (req); break;
-               case query_request:                err = handle_queryrecord_request (req); break;
-               case browse_request:               err = handle_browse_request      (req); break;
-               case reg_service_request:          err = handle_regservice_request  (req); break;
-               case enumeration_request:          err = handle_enum_request        (req); break;
-               case reconfirm_record_request:     err = handle_reconfirm_request   (req); break;
-               case setdomain_request:            err = handle_setdomain_request   (req); break;
-               case getproperty_request:                handle_getproperty_request (req); break;
-               case port_mapping_request:         err = handle_port_mapping_request(req); break;
-               case addrinfo_request:             err = handle_addrinfo_request    (req); break;
+               case connection_request:           LogOperation("%3d: DNSServiceCreateConnection START", req->sd);
+                                                      req->terminate = connection_termination; break;
+               case resolve_request:              err = handle_resolve_request     (req);  break;
+               case query_request:                err = handle_queryrecord_request (req);  break;
+               case browse_request:               err = handle_browse_request      (req);  break;
+               case reg_service_request:          err = handle_regservice_request  (req);  break;
+               case enumeration_request:          err = handle_enum_request        (req);  break;
+               case reconfirm_record_request:     err = handle_reconfirm_request   (req);  break;
+               case setdomain_request:            err = handle_setdomain_request   (req);  break;
+               case getproperty_request:                handle_getproperty_request (req);  break;
+               case port_mapping_request:         err = handle_port_mapping_request(req);  break;
+               case addrinfo_request:             err = handle_addrinfo_request    (req);  break;
+               case send_bpf:                     /* Do nothing for send_bpf */            break;
 
                // These are all operations that work with an existing request_state object
-               case reg_record_request:           err = handle_regrecord_request   (req); break;
-               case add_record_request:           err = handle_add_request         (req); break;
-               case update_record_request:        err = handle_update_request      (req); break;
-               case remove_record_request:        err = handle_removerecord_request(req); break;
-               case cancel_request:                     handle_cancel_request      (req); break;
+               case reg_record_request:           err = handle_regrecord_request   (req);  break;
+               case add_record_request:           err = handle_add_request         (req);  break;
+               case update_record_request:        err = handle_update_request      (req);  break;
+               case remove_record_request:        err = handle_removerecord_request(req);  break;
+               case cancel_request:                     handle_cancel_request      (req);  break;
                default: LogMsg("%3d: ERROR: Unsupported UDS req: %d", req->sd, req->hdr.op);
                }
 
@@ -3361,16 +3816,17 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
 
        // There's no return data for a cancel request (DNSServiceRefDeallocate returns no result)
        // For a DNSServiceGetProperty call, the handler already generated the response, so no need to do it again here
-       if (req->hdr.op != cancel_request && req->hdr.op != getproperty_request)
+       if (req->hdr.op != cancel_request && req->hdr.op != getproperty_request && req->hdr.op != send_bpf)
                {
-               err = dnssd_htonl(err);
-               send_all(req->errsd, (const char *)&err, sizeof(err));
+               const mStatus err_netorder = dnssd_htonl(err);
+               send_all(req->errsd, (const char *)&err_netorder, sizeof(err_netorder));
                if (req->errsd != req->sd)
                        {
-                       LogOperation("%3d: Closing error socket %d", req->sd, req->errsd);
+                       LogOperation("%3d: Error socket %d closed  %08X %08X (%d)",
+                               req->sd, req->errsd, req->hdr.client_context.u32[1], req->hdr.client_context.u32[0], err);
                        dnssd_close(req->errsd);
                        req->errsd = req->sd;
-                       // Also need to reset the parent's errsd, if this is a subbordinate operation
+                       // Also need to reset the parent's errsd, if this is a subordinate operation
                        if (req->primary) req->primary->errsd = req->primary->sd;
                        }
                }
@@ -3389,27 +3845,24 @@ mDNSlocal void connect_callback(int fd, short filter, void *info)
        {
        dnssd_sockaddr_t cliaddr;
        dnssd_socklen_t len = (dnssd_socklen_t) sizeof(cliaddr);
-       dnssd_sock_t sd = accept(listenfd, (struct sockaddr*) &cliaddr, &len);
+       dnssd_sock_t sd = accept(fd, (struct sockaddr*) &cliaddr, &len);
+#if defined(SO_NOSIGPIPE) || defined(_WIN32)
        const unsigned long optval = 1;
+#endif
 
-       (void)fd; // Unused
        (void)filter; // Unused
        (void)info; // Unused
 
        if (!dnssd_SocketValid(sd))
                {
-               if (dnssd_errno() != dnssd_EWOULDBLOCK) my_perror("ERROR: accept");
+               if (dnssd_errno != dnssd_EWOULDBLOCK) my_perror("ERROR: accept");
                return;
                }
 
 #ifdef SO_NOSIGPIPE
        // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
        if (setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
-               {
-               my_perror("ERROR: setsockopt - SO_NOSIGPIPE - aborting client");
-               dnssd_close(sd);
-               return;
-               }
+               LogMsg("%3d: WARNING: setsockopt - SO_NOSIGPIPE %d (%s)", sd, dnssd_errno, dnssd_strerror(dnssd_errno));
 #endif
 
 #if defined(_WIN32)
@@ -3429,26 +3882,66 @@ mDNSlocal void connect_callback(int fd, short filter, void *info)
                request->sd    = sd;
                request->errsd = sd;
 #if APPLE_OSX_mDNSResponder
-       struct xucred x;
-       socklen_t xucredlen = sizeof(x);
-       if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 && x.cr_version == XUCRED_VERSION) request->uid = x.cr_uid;
-       else my_perror("ERROR: getsockopt, LOCAL_PEERCRED");
-       debugf("LOCAL_PEERCRED %d %u %u %d", xucredlen, x.cr_version, x.cr_uid, x.cr_ngroups);
-#endif APPLE_OSX_mDNSResponder
+               struct xucred x;
+               socklen_t xucredlen = sizeof(x);
+               if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 && x.cr_version == XUCRED_VERSION) request->uid = x.cr_uid;
+               else my_perror("ERROR: getsockopt, LOCAL_PEERCRED");
+               debugf("LOCAL_PEERCRED %d %u %u %d", xucredlen, x.cr_version, x.cr_uid, x.cr_ngroups);
+#endif // APPLE_OSX_mDNSResponder
                LogOperation("%3d: Adding FD for uid %u", request->sd, request->uid);
                udsSupportAddFDToEventLoop(sd, request_callback, request);
                }
        }
 
-mDNSexport int udsserver_init(dnssd_sock_t skt)
+mDNSlocal mDNSBool uds_socket_setup(dnssd_sock_t skt)
+       {
+#if defined(SO_NP_EXTENSIONS)
+       struct          so_np_extensions sonpx;
+       socklen_t       optlen = sizeof(struct so_np_extensions);
+       sonpx.npx_flags = SONPX_SETOPTSHUT;
+       sonpx.npx_mask  = SONPX_SETOPTSHUT;
+       if (setsockopt(skt, SOL_SOCKET, SO_NP_EXTENSIONS, &sonpx, optlen) < 0)
+               my_perror("WARNING: could not set sockopt - SO_NP_EXTENSIONS");
+#endif
+#if defined(_WIN32)
+       // SEH: do we even need to do this on windows?
+       // This socket will be given to WSAEventSelect which will automatically set it to non-blocking
+       u_long opt = 1;
+       if (ioctlsocket(skt, FIONBIO, &opt) != 0)
+#else
+       if (fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK) != 0)
+#endif
+               {
+               my_perror("ERROR: could not set listen socket to non-blocking mode");
+               return mDNSfalse;
+               }
+
+       if (listen(skt, LISTENQ) != 0)
+               {
+               my_perror("ERROR: could not listen on listen socket");
+               return mDNSfalse;
+               }
+
+       if (mStatus_NoError != udsSupportAddFDToEventLoop(skt, connect_callback, (void *) NULL))
+               {
+               my_perror("ERROR: could not add listen socket to event loop");
+               return mDNSfalse;
+               }
+       else LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", skt);
+       
+       return mDNStrue;
+       }
+
+mDNSexport int udsserver_init(dnssd_sock_t skts[], mDNSu32 count)
        {
        dnssd_sockaddr_t laddr;
        int ret;
+       mDNSu32 i = 0;
 #if defined(_WIN32)
        u_long opt = 1;
 #endif
 
-       LogOperation("udsserver_init");
+       LogInfo("udsserver_init");
 
        // If a particular platform wants to opt out of having a PID file, define PID_FILE to be ""
        if (PID_FILE[0])
@@ -3461,8 +3954,12 @@ mDNSexport int udsserver_init(dnssd_sock_t skt)
                        }
                }
 
-       if (dnssd_SocketValid(skt))
-               listenfd = skt;
+       if (skts)
+               {
+               for (i = 0; i < count; i++)
+                       if (dnssd_SocketValid(skts[i]) && !uds_socket_setup(skts[i]))
+                               goto error;
+               }
        else
                {
                listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
@@ -3489,7 +3986,7 @@ mDNSexport int udsserver_init(dnssd_sock_t skt)
                #else
                        {
                        mode_t mask = umask(0);
-                       unlink(MDNS_UDS_SERVERPATH);  //OK if this fails
+                       unlink(MDNS_UDS_SERVERPATH);  // OK if this fails
                        laddr.sun_family = AF_LOCAL;
                        #ifndef NOT_HAVE_SA_LEN
                        // According to Stevens (section 3.2), there is no portable way to
@@ -3506,33 +4003,10 @@ mDNSexport int udsserver_init(dnssd_sock_t skt)
                                }
                        }
                #endif
+               
+               if (!uds_socket_setup(listenfd)) goto error;
                }
 
-#if defined(_WIN32)
-       // SEH: do we even need to do this on windows?
-       // This socket will be given to WSAEventSelect which will automatically set it to non-blocking
-       if (ioctlsocket(listenfd, FIONBIO, &opt) != 0)
-#else
-       if (fcntl(listenfd, F_SETFL, fcntl(listenfd, F_GETFL, 0) | O_NONBLOCK) != 0)
-#endif
-               {
-               my_perror("ERROR: could not set listen socket to non-blocking mode");
-               goto error;
-               }
-
-       if (listen(listenfd, LISTENQ) != 0)
-               {
-               my_perror("ERROR: could not listen on listen socket");
-               goto error;
-               }
-
-       if (mStatus_NoError != udsSupportAddFDToEventLoop(listenfd, connect_callback, (void *) NULL))
-               {
-               my_perror("ERROR: could not add listen socket to event loop");
-               goto error;
-               }
-       else LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", listenfd);
-
 #if !defined(PLATFORM_NO_RLIMIT)
        {
        // Set maximum number of open file descriptors
@@ -3576,11 +4050,11 @@ error:
        return -1;
        }
 
-mDNSexport int udsserver_exit(dnssd_sock_t skt)
+mDNSexport int udsserver_exit(void)
        {
        // If the launching environment created no listening socket,
        // that means we created it ourselves, so we should clean it up on exit
-       if (!dnssd_SocketValid(skt))
+       if (dnssd_SocketValid(listenfd))
                {
                dnssd_close(listenfd);
 #if !defined(USE_TCP_LOOPBACK)
@@ -3612,7 +4086,8 @@ mDNSlocal void LogClientInfo(mDNS *const m, request_state *req)
                {
                service_instance *ptr;
                for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
-                       LogMsgNoIdent("%3d: DNSServiceRegister         %##s %u", req->sd, ptr->srs.RR_SRV.resrec.name->c, SRS_PORT(&ptr->srs));
+                       LogMsgNoIdent("%3d: DNSServiceRegister         %##s %u/%u",
+                               req->sd, ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port), SRS_PORT(&ptr->srs));
                }
        else if (req->terminate == browse_termination_callback)
                {
@@ -3646,18 +4121,62 @@ mDNSlocal void LogClientInfo(mDNS *const m, request_state *req)
                LogMsgNoIdent("%3d: Unrecognized operation %p", req->sd, req->terminate);
        }
 
-mDNSexport void udsserver_info(mDNS *const m)
+mDNSlocal void LogAuthRecords(mDNS *const m, const mDNSs32 now, AuthRecord *ResourceRecords, int *proxy)
        {
-       mDNSs32 now = mDNS_TimeNow(m);
-       mDNSu32 CacheUsed = 0, CacheActive = 0;
-       mDNSu32 slot;
-       CacheGroup *cg;
-       CacheRecord *cr;
+       if (!ResourceRecords) LogMsgNoIdent("<None>");
+       else
+               {
+               const AuthRecord *ar;
+               mDNSEthAddr owner = zeroEthAddr;
+               LogMsgNoIdent("    Int    Next  Expire   State");
+               for (ar = ResourceRecords; ar; ar=ar->next)
+                       {
+                       NetworkInterfaceInfo *info = (NetworkInterfaceInfo *)ar->resrec.InterfaceID;
+                       if (ar->WakeUp.HMAC.l[0]) (*proxy)++;
+                       if (!mDNSSameEthAddress(&owner, &ar->WakeUp.HMAC))
+                               {
+                               owner = ar->WakeUp.HMAC;
+                               if (ar->WakeUp.password.l[0])
+                                       LogMsgNoIdent("Proxying for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &ar->WakeUp.HMAC, &ar->WakeUp.IMAC, &ar->WakeUp.password, ar->WakeUp.seq);
+                               else if (!mDNSSameEthAddress(&ar->WakeUp.HMAC, &ar->WakeUp.IMAC))
+                                       LogMsgNoIdent("Proxying for H-MAC %.6a I-MAC %.6a seq %d",               &ar->WakeUp.HMAC, &ar->WakeUp.IMAC,                       ar->WakeUp.seq);
+                               else
+                                       LogMsgNoIdent("Proxying for %.6a seq %d",                                &ar->WakeUp.HMAC,                                         ar->WakeUp.seq);
+                               }
+                       if (AuthRecord_uDNS(ar))
+                               LogMsgNoIdent("%7d %7d %7d %7d %s",
+                                       ar->ThisAPInterval / mDNSPlatformOneSecond,
+                                       (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
+                                       ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
+                                       ar->state, ARDisplayString(m, ar));
+                       else if (ar->resrec.InterfaceID != mDNSInterface_LocalOnly)
+                               LogMsgNoIdent("%7d %7d %7d %7s %s",
+                                       ar->ThisAPInterval / mDNSPlatformOneSecond,
+                                       ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0,
+                                       ar->TimeExpire    ? (ar->TimeExpire                      - now) / mDNSPlatformOneSecond : 0,
+                                       info ? info->ifname : "ALL",
+                                       ARDisplayString(m, ar));
+                       else
+                               LogMsgNoIdent("                             LO %s", ARDisplayString(m, ar));
+                       usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
+                       }
+               }
+       }
 
-       LogMsgNoIdent("Timenow 0x%08lX (%ld)", (mDNSu32)now, now);
+mDNSexport void udsserver_info(mDNS *const m)
+       {
+       const mDNSs32 now = mDNS_TimeNow(m);
+       mDNSu32 CacheUsed = 0, CacheActive = 0, slot;
+       int ProxyA = 0, ProxyD = 0;
+       const CacheGroup *cg;
+       const CacheRecord *cr;
+       const DNSQuestion *q;
+       const DNameListElem *d;
+
+       LogMsgNoIdent("Timenow 0x%08lX (%d)", (mDNSu32)now, now);
        LogMsgNoIdent("------------ Cache -------------");
 
-       LogMsgNoIdent("Slt Q     TTL if    U Type rdlen");
+       LogMsgNoIdent("Slt Q     TTL if     U Type rdlen");
        for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
                for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
                        {
@@ -3668,7 +4187,7 @@ mDNSexport void udsserver_info(mDNS *const m)
                                NetworkInterfaceInfo *info = (NetworkInterfaceInfo *)cr->resrec.InterfaceID;
                                CacheUsed++;
                                if (cr->CRActiveQuestion) CacheActive++;
-                               LogMsgNoIdent("%3d %s%8ld %-6s%s %-6s%s",
+                               LogMsgNoIdent("%3d %s%8ld %-7s%s %-6s%s",
                                        slot,
                                        cr->CRActiveQuestion ? "*" : " ",
                                        remain,
@@ -3677,7 +4196,7 @@ mDNSexport void udsserver_info(mDNS *const m)
                                        (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? " " : "+",
                                        DNSTypeName(cr->resrec.rrtype),
                                        CRDisplayString(m, cr));
-                               usleep(1000);   // Limit rate a little so we don't flood syslog too fast
+                               usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
                                }
                        }
 
@@ -3688,26 +4207,10 @@ mDNSexport void udsserver_info(mDNS *const m)
        LogMsgNoIdent("Cache currently contains %lu entities; %lu referenced by active questions", CacheUsed, CacheActive);
 
        LogMsgNoIdent("--------- Auth Records ---------");
-       if (!m->ResourceRecords) LogMsgNoIdent("<None>");
-       else
-               {
-               AuthRecord *ar;
-               LogMsgNoIdent("    Int    Next  Expire   State");
-               for (ar = m->ResourceRecords; ar; ar=ar->next)
-                       if (AuthRecord_uDNS(ar))
-                               LogMsgNoIdent("%7d %7d %7d %7d %s",
-                                       ar->ThisAPInterval / mDNSPlatformOneSecond,
-                                       (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
-                                       ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
-                                       ar->state, ARDisplayString(m, ar));
-                       else if (ar->resrec.InterfaceID != mDNSInterface_LocalOnly)
-                               LogMsgNoIdent("%7d %7d               M %s",
-                                       ar->ThisAPInterval / mDNSPlatformOneSecond,
-                                       ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0,
-                                       ARDisplayString(m, ar));
-                       else
-                               LogMsgNoIdent("                             LO %s", ARDisplayString(m, ar));
-               }
+       LogAuthRecords(m, now, m->ResourceRecords, &ProxyA);
+
+       LogMsgNoIdent("------ Duplicate Records -------");
+       LogAuthRecords(m, now, m->DuplicateRecords, &ProxyD);
 
        LogMsgNoIdent("----- ServiceRegistrations -----");
        if (!m->ServiceRegistrations) LogMsgNoIdent("<None>");
@@ -3727,10 +4230,9 @@ mDNSexport void udsserver_info(mDNS *const m)
        if (!m->Questions) LogMsgNoIdent("<None>");
        else
                {
-               DNSQuestion *q;
                CacheUsed = 0;
                CacheActive = 0;
-               LogMsgNoIdent("   Int  Next if    T  NumAns Type  Name");
+               LogMsgNoIdent("   Int  Next if     T  NumAns Type  Name");
                for (q = m->Questions; q; q=q->next)
                        {
                        mDNSs32 i = q->ThisQInterval / mDNSPlatformOneSecond;
@@ -3738,18 +4240,24 @@ mDNSexport void udsserver_info(mDNS *const m)
                        NetworkInterfaceInfo *info = (NetworkInterfaceInfo *)q->InterfaceID;
                        CacheUsed++;
                        if (q->ThisQInterval) CacheActive++;
-                       LogMsgNoIdent("%6d%6d %-6s%s%s %5d  %-6s%##s%s",
+                       LogMsgNoIdent("%6d%6d %-7s%s%s %5d  %-6s%##s%s",
                                i, n,
                                info ? info->ifname : mDNSOpaque16IsZero(q->TargetQID) ? "" : "-U-",
-                               mDNSOpaque16IsZero(q->TargetQID) ? " " : q->LongLived ? "L" : "O", // mDNS, long-lived, or one-shot query?
+                               mDNSOpaque16IsZero(q->TargetQID) ? (q->LongLived ? "l" : " ") : (q->LongLived ? "L" : "O"),
                                q->AuthInfo    ? "P" : " ",
                                q->CurrentAnswers,
                                DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
-                       usleep(1000);   // Limit rate a little so we don't flood syslog too fast
+                       usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
                        }
                LogMsgNoIdent("%lu question%s; %lu active", CacheUsed, CacheUsed > 1 ? "s" : "", CacheActive);
                }
 
+       LogMsgNoIdent("----- Local-Only Questions -----");
+       if (!m->LocalOnlyQuestions) LogMsgNoIdent("<None>");
+       else for (q = m->LocalOnlyQuestions; q; q=q->next)
+               LogMsgNoIdent("                       %5d  %-6s%##s%s",
+                       q->CurrentAnswers, DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
+
        LogMsgNoIdent("---- Active Client Requests ----");
        if (!all_requests) LogMsgNoIdent("<None>");
        else
@@ -3757,6 +4265,7 @@ mDNSexport void udsserver_info(mDNS *const m)
                request_state *req;
                for (req = all_requests; req; req=req->next)
                        LogClientInfo(m, req);
+               usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
                }
 
        LogMsgNoIdent("-------- NAT Traversals --------");
@@ -3767,16 +4276,17 @@ mDNSexport void udsserver_info(mDNS *const m)
                for (nat = m->NATTraversals; nat; nat=nat->next)
                        {
                        if (nat->Protocol)
-                               LogMsgNoIdent("%p %s Int %5d Ext %5d Err %d Retry %d Interval %d Expire %d",
+                               LogMsgNoIdent("%p %s Int %5d Ext %5d Err %d Retry %5d Interval %5d Expire %5d",
                                        nat, nat->Protocol == NATOp_MapTCP ? "TCP" : "UDP",
                                        mDNSVal16(nat->IntPort), mDNSVal16(nat->ExternalPort), nat->Result,
                                        nat->retryPortMap ? (nat->retryPortMap - now) / mDNSPlatformOneSecond : 0,
                                        nat->retryInterval / mDNSPlatformOneSecond,
                                        nat->ExpiryTime ? (nat->ExpiryTime - now) / mDNSPlatformOneSecond : 0);
                        else
-                               LogMsgNoIdent("%p Address Request Retry %d Interval %d", nat,
+                               LogMsgNoIdent("%p Address Request               Retry %5d Interval %5d", nat,
                                        (m->retryGetAddr - now) / mDNSPlatformOneSecond,
                                        m->retryIntervalGetAddr / mDNSPlatformOneSecond);
+                       usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
                        }
                }
 
@@ -3790,7 +4300,7 @@ mDNSexport void udsserver_info(mDNS *const m)
                }
 
        #if APPLE_OSX_mDNSResponder
-       LogMsgNoIdent("--------- TunnelClients ---------");
+       LogMsgNoIdent("--------- TunnelClients --------");
        if (!m->TunnelClients) LogMsgNoIdent("<None>");
        else
                {
@@ -3799,18 +4309,56 @@ mDNSexport void udsserver_info(mDNS *const m)
                        LogMsgNoIdent("%##s local %.16a %.4a remote %.16a %.4a %5d interval %d",
                                c->dstname.c, &c->loc_inner, &c->loc_outer, &c->rmt_inner, &c->rmt_outer, mDNSVal16(c->rmt_outer_port), c->q.ThisQInterval);
                }
-       #endif
+       #endif // APPLE_OSX_mDNSResponder
+
+       LogMsgNoIdent("---------- Misc State ----------");
+
+       LogMsgNoIdent("PrimaryMAC:   %.6a", &m->PrimaryMAC);
+
+       LogMsgNoIdent("m->SleepState %d (%s) seq %d",
+               m->SleepState,
+               m->SleepState == SleepState_Awake        ? "Awake"        :
+               m->SleepState == SleepState_Transferring ? "Transferring" : 
+               m->SleepState == SleepState_Sleeping     ? "Sleeping"     : "?",
+               m->SleepSeqNum);
+
+       if (!m->SPSSocket) LogMsgNoIdent("Not offering Sleep Proxy Service");
+       else LogMsgNoIdent("Offering Sleep Proxy Service: %#s", m->SPSRecords.RR_SRV.resrec.name->c);
+
+       if (m->ProxyRecords == ProxyA + ProxyD) LogMsgNoIdent("ProxyRecords: %d + %d = %d", ProxyA, ProxyD, ProxyA + ProxyD);
+       else LogMsgNoIdent("ProxyRecords: MISMATCH %d + %d = %d ≠ %d", ProxyA, ProxyD, ProxyA + ProxyD, m->ProxyRecords);
+
+       LogMsgNoIdent("------ Auto Browse Domains -----");
+       if (!AutoBrowseDomains) LogMsgNoIdent("<None>");
+       else for (d=AutoBrowseDomains; d; d=d->next) LogMsgNoIdent("%##s", d->name.c);
+
+       LogMsgNoIdent("--- Auto Registration Domains --");
+       if (!AutoRegistrationDomains) LogMsgNoIdent("<None>");
+       else for (d=AutoRegistrationDomains; d; d=d->next) LogMsgNoIdent("%##s", d->name.c);
        }
 
 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
 mDNSexport void uds_validatelists(void)
        {
-       request_state *req;
+       const request_state *req, *p;
        for (req = all_requests; req; req=req->next)
                {
                if (req->next == (request_state *)~0 || (req->sd < 0 && req->sd != -2))
                        LogMemCorruption("UDS request list: %p is garbage (%d)", req, req->sd);
 
+               if (req->primary == req)
+                       LogMemCorruption("UDS request list: req->primary should not point to self %p/%d", req, req->sd);
+
+               if (req->primary && req->replies)
+                       LogMemCorruption("UDS request list: Subordinate request %p/%d/%p should not have replies (%p)",
+                               req, req->sd, req->primary && req->replies);
+
+               p = req->primary;
+               if ((long)p & 3)
+                       LogMemCorruption("UDS request list: req %p primary %p is misaligned (%d)", req, p, req->sd);
+               else if (p && (p->next == (request_state *)~0 || (p->sd < 0 && p->sd != -2)))
+                       LogMemCorruption("UDS request list: req %p primary %p is garbage (%d)", req, p, p->sd);
+
                reply_state *rep;
                for (rep = req->replies; rep; rep=rep->next)
                  if (rep->next == (reply_state *)~0)
@@ -3818,24 +4366,24 @@ mDNSexport void uds_validatelists(void)
 
                if (req->terminate == connection_termination)
                        {
-                       registered_record_entry *p;
-                       for (p = req->u.reg_recs; p; p=p->next)
-                               if (p->next == (registered_record_entry *)~0)
-                                       LogMemCorruption("UDS req->u.reg_recs: %p is garbage", p);
+                       registered_record_entry *r;
+                       for (r = req->u.reg_recs; r; r=r->next)
+                               if (r->next == (registered_record_entry *)~0)
+                                       LogMemCorruption("UDS req->u.reg_recs: %p is garbage", r);
                        }
                else if (req->terminate == regservice_termination_callback)
                        {
-                       service_instance *p;
-                       for (p = req->u.servicereg.instances; p; p=p->next)
-                               if (p->next == (service_instance *)~0)
-                                       LogMemCorruption("UDS req->u.servicereg.instances: %p is garbage", p);
+                       service_instance *s;
+                       for (s = req->u.servicereg.instances; s; s=s->next)
+                               if (s->next == (service_instance *)~0)
+                                       LogMemCorruption("UDS req->u.servicereg.instances: %p is garbage", s);
                        }
                else if (req->terminate == browse_termination_callback)
                        {
-                       browser_t *p;
-                       for (p = req->u.browser.browsers; p; p=p->next)
-                               if (p->next == (browser_t *)~0)
-                                       LogMemCorruption("UDS req->u.browser.browsers: %p is garbage", p);
+                       browser_t *b;
+                       for (b = req->u.browser.browsers; b; b=b->next)
+                               if (b->next == (browser_t *)~0)
+                                       LogMemCorruption("UDS req->u.browser.browsers: %p is garbage", b);
                        }
                }
 
@@ -3857,38 +4405,37 @@ mDNSexport void uds_validatelists(void)
                if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
                        LogMemCorruption("AutoRegistrationDomains: %p is garbage (%d)", d, d->name.c[0]);
        }
-#endif
+#endif // APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
 
-mDNSlocal int send_msg(reply_state *rep)
+mDNSlocal int send_msg(request_state *const req)
        {
+       reply_state *const rep = req->replies;          // Send the first waiting reply
        ssize_t nwriten;
-       if (!rep->msgbuf) { LogMsg("ERROR: send_msg called with NULL message buffer"); return(rep->ts = t_error); }
-       if (rep->request->no_reply) { freeL("reply_state msgbuf (no_reply)", rep->msgbuf); return(rep->ts = t_complete); }
+       if (req->no_reply) return(t_complete);
 
        ConvertHeaderBytes(rep->mhdr);
-       nwriten = send(rep->sd, rep->msgbuf + rep->nwriten, rep->len - rep->nwriten, 0);
+       nwriten = send(req->sd, (char *)&rep->mhdr + rep->nwriten, rep->totallen - rep->nwriten, 0);
        ConvertHeaderBytes(rep->mhdr);
 
        if (nwriten < 0)
                {
-               if (dnssd_errno() == dnssd_EINTR || dnssd_errno() == dnssd_EWOULDBLOCK) nwriten = 0;
+               if (dnssd_errno == dnssd_EINTR || dnssd_errno == dnssd_EWOULDBLOCK) nwriten = 0;
                else
                        {
 #if !defined(PLATFORM_NO_EPIPE)
-                       if (dnssd_errno() == EPIPE)
-                               return(rep->request->ts = rep->ts = t_terminated);
+                       if (dnssd_errno == EPIPE)
+                               return(req->ts = t_terminated);
                        else
 #endif
                                {
-                               LogMsg("send_msg ERROR: failed to write %d bytes to fd %d errno %d %s",
-                                       rep->len - rep->nwriten, rep->sd, dnssd_errno(), dnssd_strerror(dnssd_errno()));
-                               return(rep->ts = t_error);
+                               LogMsg("send_msg ERROR: failed to write %d of %d bytes to fd %d errno %d (%s)",
+                                       rep->totallen - rep->nwriten, rep->totallen, req->sd, dnssd_errno, dnssd_strerror(dnssd_errno));
+                               return(t_error);
                                }
                        }
                }
        rep->nwriten += nwriten;
-       if (rep->nwriten == rep->len) { freeL("reply_state msgbuf (t_complete)", rep->msgbuf); rep->ts = t_complete; }
-       return rep->ts;
+       return (rep->nwriten == rep->totallen) ? t_complete : t_morecoming;
        }
 
 mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
@@ -3898,53 +4445,60 @@ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
 
        while (*req)
                {
-               if ((*req)->terminate == resolve_termination_callback)
-                       if ((*req)->u.resolve.ReportTime && now - (*req)->u.resolve.ReportTime >= 0)
+               request_state *const r = *req;
+
+               if (r->terminate == resolve_termination_callback)
+                       if (r->u.resolve.ReportTime && now - r->u.resolve.ReportTime >= 0)
                                {
-                               (*req)->u.resolve.ReportTime = 0;
+                               r->u.resolve.ReportTime = 0;
                                LogMsgNoIdent("Client application bug: DNSServiceResolve(%##s) active for over two minutes. "
-                                       "This places considerable burden on the network.", (*req)->u.resolve.qsrv.qname.c);
+                                       "This places considerable burden on the network.", r->u.resolve.qsrv.qname.c);
                                }
 
-               while ((*req)->replies)         // Send queued replies
+               // Note: Only primary req's have reply lists, not subordinate req's.
+               while (r->replies)              // Send queued replies
                        {
                        transfer_state result;
-                       if ((*req)->replies->next) (*req)->replies->rhdr->flags |= dnssd_htonl(kDNSServiceFlagsMoreComing);
-                       result = send_msg((*req)->replies);     // Returns t_morecoming if buffer full because client is not reading
+                       if (r->replies->next) r->replies->rhdr->flags |= dnssd_htonl(kDNSServiceFlagsMoreComing);
+                       result = send_msg(r);   // Returns t_morecoming if buffer full because client is not reading
                        if (result == t_complete)
                                {
-                               reply_state *fptr = (*req)->replies;
-                               (*req)->replies = (*req)->replies->next;
+                               reply_state *fptr = r->replies;
+                               r->replies = r->replies->next;
                                freeL("reply_state/udsserver_idle", fptr);
-                               (*req)->time_blocked = 0; // reset failure counter after successful send
+                               r->time_blocked = 0; // reset failure counter after successful send
                                continue;
                                }
-                       else if (result == t_terminated || result == t_error) abort_request(*req);
+                       else if (result == t_terminated || result == t_error)
+                               {
+                               LogMsg("%3d: Could not write data to client because of error - aborting connection", r->sd);
+                               LogClientInfo(&mDNSStorage, r);
+                               abort_request(r);
+                               }
                        break;
                        }
 
-               if ((*req)->replies)            // If we failed to send everything, check our time_blocked timer
+               if (r->replies)         // If we failed to send everything, check our time_blocked timer
                        {
-                       if (!(*req)->time_blocked) (*req)->time_blocked = NonZeroTime(now);
-                       if (now - (*req)->time_blocked >= 60 * mDNSPlatformOneSecond)
+                       if (!r->time_blocked) r->time_blocked = NonZeroTime(now);
+                       if (now - r->time_blocked >= 60 * mDNSPlatformOneSecond)
                                {
-                               LogMsg("Could not write data to client %d after %ld seconds - aborting connection",
-                                       (*req)->sd, (now - (*req)->time_blocked) / mDNSPlatformOneSecond);
-                               LogClientInfo(&mDNSStorage, *req);
-                               abort_request(*req);
+                               LogMsg("%3d: Could not write data to client after %ld seconds - aborting connection", r->sd,
+                                       (now - r->time_blocked) / mDNSPlatformOneSecond);
+                               LogClientInfo(&mDNSStorage, r);
+                               abort_request(r);
                                }
                        else if (nextevent - now > mDNSPlatformOneSecond) nextevent = now + mDNSPlatformOneSecond;
                        }
 
-               if (!dnssd_SocketValid((*req)->sd)) // If this request is finished, unlink it from the list and free the memory
+               if (!dnssd_SocketValid(r->sd)) // If this request is finished, unlink it from the list and free the memory
                        {
                        // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
-                       request_state *tmp = *req;
-                       *req = tmp->next;
-                       freeL("request_state/udsserver_idle", tmp);
+                       *req = r->next;
+                       freeL("request_state/udsserver_idle", r);
                        }
                else
-                       req = &(*req)->next;
+                       req = &r->next;
                }
        return nextevent;
        }
@@ -3954,10 +4508,10 @@ struct CompileTimeAssertionChecks_uds_daemon
        // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
        // other overly-large structures instead of having a pointer to them, can inadvertently
        // cause structure sizes (and therefore memory usage) to balloon unreasonably.
-       char sizecheck_request_state          [(sizeof(request_state)           <= 1800) ? 1 : -1];
-       char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <=   30) ? 1 : -1];
-       char sizecheck_service_instance       [(sizeof(service_instance)        <= 6000) ? 1 : -1];
-       char sizecheck_browser_t              [(sizeof(browser_t)               <= 1000) ? 1 : -1];
-       char sizecheck_reply_hdr              [(sizeof(reply_hdr)               <=   20) ? 1 : -1];
-       char sizecheck_reply_state            [(sizeof(reply_state)             <=   40) ? 1 : -1];
+       char sizecheck_request_state          [(sizeof(request_state)           <= 1760) ? 1 : -1];
+       char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <=   40) ? 1 : -1];
+       char sizecheck_service_instance       [(sizeof(service_instance)        <= 6552) ? 1 : -1];
+       char sizecheck_browser_t              [(sizeof(browser_t)               <=  992) ? 1 : -1];
+       char sizecheck_reply_hdr              [(sizeof(reply_hdr)               <=   12) ? 1 : -1];
+       char sizecheck_reply_state            [(sizeof(reply_state)             <=   64) ? 1 : -1];
        };
index 0d102e4d09f5d803b3c330ec4bec567bd48939a6..b6d966eae5ba4b1a920012a3cb0f043842c703c9 100644 (file)
     Change History (most recent first):
 
 $Log: uds_daemon.h,v $
+Revision 1.27  2009/04/30 20:07:51  mcguire
+<rdar://problem/6822674> Support multiple UDSs from launchd
+
+Revision 1.26  2008/10/02 22:26:21  cheshire
+Moved declaration of BPF_fd from uds_daemon.c to mDNSMacOSX.c, where it really belongs
+
+Revision 1.25  2008/09/27 01:08:25  cheshire
+Added external declaration of "dnssd_sock_t BPF_fd"
+
 Revision 1.24  2007/09/19 20:25:17  cheshire
 Deleted outdated comment
 
@@ -109,11 +118,11 @@ Changes necessary to support mDNSResponder on Linux.
 
 #define SRS_PORT(S) mDNSVal16((S)->RR_SRV.resrec.rdata->u.srv.port)
 
-extern int udsserver_init(dnssd_sock_t skt);
+extern int udsserver_init(dnssd_sock_t skts[], mDNSu32 count);
 extern mDNSs32 udsserver_idle(mDNSs32 nextevent);
 extern void udsserver_info(mDNS *const m);     // print out info about current state
 extern void udsserver_handle_configchange(mDNS *const m);
-extern int udsserver_exit(dnssd_sock_t skt);   // should be called prior to app exit
+extern int udsserver_exit(void);       // should be called prior to app exit
 
 /* Routines that uds_daemon expects to link against: */
 
index 6a72d23285850289afbb5bd0b2b00002b67ebd41..97a597b02541c77dbf0f3a1138ad23b8ba151a6d 100644 (file)
     Change History (most recent first):
 
 $Log: mDNSVxWorks.c,v $
+Revision 1.35  2009/01/13 05:31:35  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.34  2008/10/03 18:25:18  cheshire
+Instead of calling "m->MainCallback" function pointer directly, call mDNSCore routine "mDNS_ConfigChanged(m);"
+
 Revision 1.33  2007/03/22 18:31:48  cheshire
 Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
 
@@ -251,7 +257,7 @@ mStatus     mDNSPlatformInit( mDNS * const inMDNS )
        
        // Do minimal initialization to get the task started and so we can cleanup safely if an error occurs.
        
-       memset( &gMDNSPlatformSupport, 0, sizeof( gMDNSPlatformSupport ) );
+       mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) );
        if( !inMDNS->p ) inMDNS->p      = &gMDNSPlatformSupport;
        inMDNS->p->unicastSS.info       = NULL;
        inMDNS->p->unicastSS.sockV4     = kInvalidSocketRef;
@@ -896,7 +902,7 @@ mDNSlocal mStatus   UpdateInterfaceList( mDNS *const inMDNS, mDNSs32 inUTC )
                        struct in6_ifreq                        ifr6;
                        
                        sa6 = (struct sockaddr_in6 *) ifa->ifa_addr;
-                       memset( &ifr6, 0, sizeof( ifr6 ) );
+                       mDNSPlatformMemZero( &ifr6, sizeof( ifr6 ) );
                        strcpy( ifr6.ifr_name, ifa->ifa_name );
                        ifr6.ifr_addr = *sa6;
                        if( ioctl( infoSock, SIOCGIFAFLAG_IN6, (int) &ifr6 ) != -1 )
@@ -1374,7 +1380,7 @@ mDNSlocal mStatus SetupSocket( mDNS *const inMDNS, const mDNSAddr *inAddr, mDNSB
                
                // Start listening for packets.
                
-               memset( &sa4, 0, sizeof( sa4 ) );
+               mDNSPlatformMemZero( &sa4, sizeof( sa4 ) );
                sa4.sin_len                     = sizeof( sa4 );
                sa4.sin_family          = AF_INET;
                sa4.sin_port            = port.NotAnInteger;
@@ -1431,7 +1437,7 @@ mDNSlocal mStatus SetupSocket( mDNS *const inMDNS, const mDNSAddr *inAddr, mDNSB
                
                // Start listening for packets.
                
-               memset( &sa6, 0, sizeof( sa6 ) );
+               mDNSPlatformMemZero( &sa6, sizeof( sa6 ) );
                sa6.sin6_len            = sizeof( sa6 );
                sa6.sin6_family         = AF_INET6;
                sa6.sin6_port           = port.NotAnInteger;
@@ -1592,7 +1598,7 @@ mDNSlocal mStatus ProcessCommand( mDNS * const inMDNS )
                        SetupActiveInterfaces( inMDNS, utc );
                        
                        mDNSPlatformUnlock( inMDNS );
-                       if( inMDNS->MainCallback ) inMDNS->MainCallback( inMDNS, mStatus_ConfigChanged );       
+                       mDNS_ConfigChanged(inMDNS);
                        break;
                
                case kMDNSPipeCommandCodeQuit:                  // Quit: just set a flag so the task exits cleanly.
index 19020a912e8845e7046d9471940a834cb512c18e..a4a30a33bff1831f5998ae8d6b8539659d65a422 100644 (file)
        Change History (most recent first):
 
 $Log: mDNSVxWorksIPv4Only.c,v $
+Revision 1.34  2009/01/13 05:31:35  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.33  2008/11/04 19:51:13  cheshire
+Updated comment about MAX_ESCAPED_DOMAIN_NAME size (should be 1009, not 1005)
+
+Revision 1.32  2008/10/03 18:25:18  cheshire
+Instead of calling "m->MainCallback" function pointer directly, call mDNSCore routine "mDNS_ConfigChanged(m);"
+
 Revision 1.31  2007/03/22 18:31:49  cheshire
 Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
 
@@ -94,7 +103,7 @@ Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
 
 Revision 1.10  2003/11/14 21:27:09  cheshire
 <rdar://problem/3484766>: Security: Crashing bug in mDNSResponder
-Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers.
+Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1009) instead of 256-byte buffers.
 
 Revision 1.9  2003/11/14 20:59:09  cheshire
 Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
@@ -410,7 +419,7 @@ mStatus     mDNSPlatformInit( mDNS * const inMDNS )
        
        // Initialize variables.
 
-       memset( &gMDNSPlatformSupport, 0, sizeof( gMDNSPlatformSupport ) );
+       mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) );
        inMDNS->p                                                       = &gMDNSPlatformSupport;
        inMDNS->p->commandPipe                          = ERROR;
        inMDNS->p->task                                         = ERROR;
@@ -549,7 +558,7 @@ mStatus
        item = (MDNSInterfaceItem *) inInterfaceID;
        check( item->sendingSocketRef != kInvalidSocketRef );
        
-       memset( &addr, 0, sizeof( addr ) );
+       mDNSPlatformMemZero( &addr, sizeof( addr ) );
        addr.sin_family                 = AF_INET;
        addr.sin_port                   = inDstPort.NotAnInteger;
        addr.sin_addr.s_addr    = inDstIP->ip.v4.NotAnInteger;
@@ -1237,7 +1246,7 @@ mDNSlocal mStatus
                
                // Bind to the multicast DNS address and port 5353.
                
-               memset( &addr, 0, sizeof( addr ) );
+               mDNSPlatformMemZero( &addr, sizeof( addr ) );
                addr.sin_family                 = AF_INET;
                addr.sin_port                   = inPort.NotAnInteger;
                addr.sin_addr.s_addr    = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
@@ -1252,7 +1261,7 @@ mDNSlocal mStatus
                // Bind to the interface address and multicast DNS port.
                
                ip.NotAnInteger                 = ipv4->sin_addr.s_addr;
-               memset( &addr, 0, sizeof( addr ) );
+               mDNSPlatformMemZero( &addr, sizeof( addr ) );
                addr.sin_family                 = AF_INET;
                addr.sin_port                   = MulticastDNSPort.NotAnInteger;
                addr.sin_addr.s_addr    = ip.NotAnInteger;
@@ -1447,14 +1456,11 @@ mDNSlocal void  ProcessCommandReconfigure( mDNS *inMDNS )
        
        // Inform clients of the change.
        
-       if( inMDNS->MainCallback )
-       {
-               inMDNS->MainCallback( inMDNS, mStatus_ConfigChanged );
-       }
+       mDNS_ConfigChanged(m);
        
        // Force mDNS to update.
        
-       mDNSCoreMachineSleep( inMDNS, mDNSfalse );
+       mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this
        
        // Bump the config ID so the main processing loop detects the configuration change.
        
index bcf0f7a0cd0ba07edc01b11d00f153d01071f5eb..ea2d9b76203c69928b28c5a9621347048316bb23 100755 (executable)
     Change History (most recent first):
 
 $Log: ConfigPropertySheet.cpp,v $
+Revision 1.7  2009/07/01 19:20:37  herscher
+<rdar://problem/6713286> UI changes for configuring sleep proxy settings.
+
+Revision 1.6  2009/03/30 19:57:45  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.5  2006/08/14 23:25:28  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -57,6 +64,7 @@ CConfigPropertySheet::CConfigPropertySheet()
        AddPage(&m_firstPage);
        AddPage(&m_secondPage);
        AddPage(&m_thirdPage);
+       AddPage(&m_fourthPage );
 
        InitializeCriticalSection( &m_lock );
 }
@@ -125,7 +133,7 @@ CConfigPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam)
 //     CConfigPropertySheet::OnDataReady
 //---------------------------------------------------------------------------------------------------------------------------
 
-LONG
+LRESULT
 CConfigPropertySheet::OnDataReady(WPARAM inWParam, LPARAM inLParam)
 {
        if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
@@ -154,7 +162,7 @@ CConfigPropertySheet::OnDataReady(WPARAM inWParam, LPARAM inLParam)
 //     CConfigPropertySheet::OnRegistryChanged
 //---------------------------------------------------------------------------------------------------------------------------
 
-afx_msg LONG
+afx_msg LRESULT
 CConfigPropertySheet::OnRegistryChanged( WPARAM inWParam, LPARAM inLParam )
 {
        DEBUG_UNUSED( inWParam );
index b92fc1fce994f2e1f0e5ad613fb2082e6728c6a3..00dd137d032ed8c8eb4c8bfcb5e0bca9efbd42c5 100755 (executable)
     Change History (most recent first):
 
 $Log: ConfigPropertySheet.h,v $
+Revision 1.7  2009/07/01 19:20:37  herscher
+<rdar://problem/6713286> UI changes for configuring sleep proxy settings.
+
+Revision 1.6  2009/03/30 19:58:47  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.5  2006/08/14 23:25:28  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -33,6 +40,7 @@ Revision 1.4  2005/03/03 19:55:21  shersche
 #include "FirstPage.h"
 #include "SecondPage.h"
 #include "ThirdPage.h"
+#include "FourthPage.h"
 
 #include <RegNames.h>
 #include <dns_sd.h>
@@ -60,6 +68,7 @@ protected:
        CFirstPage      m_firstPage;
        CSecondPage     m_secondPage;
        CThirdPage m_thirdPage;
+       CFourthPage m_fourthPage;
 
        //{{AFX_VIRTUAL(CConfigPropertySheet)
        //}}AFX_VIRTUAL
@@ -72,11 +81,8 @@ protected:
 
        afx_msg BOOL    OnInitDialog();
        afx_msg BOOL    OnCommand( WPARAM wParam, LPARAM lParam );
-
-       afx_msg LONG    OnDataReady( WPARAM inWParam, LPARAM inLParam );
-
-       afx_msg LONG    OnRegistryChanged( WPARAM inWParam, LPARAM inLParam );
-
+       afx_msg LRESULT OnDataReady( WPARAM inWParam, LPARAM inLParam );
+       afx_msg LRESULT OnRegistryChanged( WPARAM inWParam, LPARAM inLParam );
        void                    OnEndDialog();
 
 private:
index 9348d53c3f18714fb23d219b62a40dbd12070119..fb85d9a1c78863312b9b6362cfcb98ed7e6b6538 100755 (executable)
     Change History (most recent first):
 
 $Log: ControlPanel.cpp,v $
+Revision 1.5  2009/03/30 20:00:19  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.4  2007/04/27 20:42:11  herscher
 <rdar://problem/5078828> mDNS: Bonjour Control Panel for Windows doesn't work on Vista
 
@@ -304,7 +308,7 @@ CCPApp::OnExit()
 //---------------------------------------------------------------------------------------------------------------------------
 
 LRESULT
-CCPApp::OnCplMsg(HWND hWndCPl, UINT uMsg, LONG lParam1, LONG lParam2)
+CCPApp::OnCplMsg(HWND hWndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
 {
        LRESULT lResult = 1;
 
index 72bae45ebf1f8770a2311d61d6626523651b5361..035b0d14f469740de11596850cb311b89e0bd0f9 100644 (file)
@@ -136,6 +136,16 @@ BEGIN
     PUSHBUTTON      "Remove",IDC_REMOVE_BROWSE_DOMAIN,205,100,50,14
 END
 
+IDR_APPLET_PAGE4 DIALOGEX 0, 0, 262, 140
+STYLE DS_SETFONT | WS_CHILD | WS_CAPTION
+CAPTION "Power Management"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
+BEGIN
+    CONTROL         "Allow Bonjour to wake this machine on network access.",IDC_POWER_MANAGEMENT,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,19,199,8
+    LTEXT           "Warning: Allowing Bonjour to bring the computer out of standby may cause this computer to periodically wakeup to refresh its network state.",IDC_STATIC,13,41,227,20
+END
+
 IDR_ADD_BROWSE_DOMAIN DIALOGEX 0, 0, 230, 95
 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | 
     WS_SYSMENU
index 5fcd30d29337105278a438a6d658e4cb5d880593..ffdb6ffd91ec41de0a6be7d37f03369542ddc8d8 100755 (executable)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="ControlPanel"\r
-       SccProjectName=""\r
-       SccLocalPath=""\r
-       Keyword="MFCProj">\r
+       ProjectGUID="{F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}"\r
+       Keyword="MFCProj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       ATLMinimizesCRunTimeLibraryUsage="FALSE">\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName=".\Debug/ControlPanel.tlb"\r
+                               HeaderFileName=""\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;DEBUG=1;UNICODE;_UNICODE;_WINDOWS;_USRDLL"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;DEBUG=1;UNICODE;_UNICODE;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
                                RuntimeLibrary="1"\r
                                UsePrecompiledHeader="0"\r
                                PrecompiledHeaderThrough=""\r
                                PrecompiledHeaderFile=""\r
-                               AssemblerListingLocation=".\Debug/"\r
-                               ObjectFile=".\Debug/"\r
-                               ProgramDataBaseFileName=".\Debug/"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
                                WarningLevel="4"\r
-                               SuppressStartupBanner="TRUE"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="4"\r
-                               DisableSpecificWarnings="4311;4312"/>\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               DisableSpecificWarnings="4311;4312"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../DLL/Debug/dnssd.lib ws2_32.lib"\r
-                               OutputFile="Debug/Bonjour.cpl"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/Bonjour.cpl"\r
                                LinkIncremental="2"\r
-                               SuppressStartupBanner="TRUE"\r
+                               SuppressStartupBanner="true"\r
                                ModuleDefinitionFile=".\ControlPanel.def"\r
-                               GenerateDebugInformation="TRUE"\r
-                               ProgramDatabaseFile=".\Debug/ControlPanel.pdb"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile=".\$(IntDir)\ControlPanel.pdb"\r
                                SubSystem="2"\r
-                               ImportLibrary=".\Debug/Bonjour.lib"\r
-                               TargetMachine="1"/>\r
+                               ImportLibrary=".\$(OutDir)\Bonjour.lib"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ControlPanel.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
-                               MkTypLibCompatible="TRUE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               TargetEnvironment="1"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
                                TypeLibraryName=".\Debug/ControlPanel.tlb"\r
-                               HeaderFileName=""/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               HeaderFileName=""\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;DEBUG=1;UNICODE;_UNICODE;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               RuntimeLibrary="1"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderThrough=""\r
+                               PrecompiledHeaderFile=""\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               DisableSpecificWarnings="4311;4312"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
-                               Culture="6153"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/Bonjour.cpl"\r
+                               LinkIncremental="2"\r
+                               SuppressStartupBanner="true"\r
+                               ModuleDefinitionFile=".\ControlPanel.def"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile=".\$(IntDir)\ControlPanel.pdb"\r
+                               SubSystem="2"\r
+                               ImportLibrary=".\$(OutDir)\Bonjour.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ControlPanel64.manifest"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       ATLMinimizesCRunTimeLibraryUsage="FALSE">\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName=".\Release/ControlPanel.tlb"\r
+                               HeaderFileName=""\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
                                InlineFunctionExpansion="1"\r
                                AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICODE;_UNICODE"\r
-                               StringPooling="TRUE"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
                                RuntimeLibrary="0"\r
-                               EnableFunctionLevelLinking="TRUE"\r
+                               EnableFunctionLevelLinking="true"\r
                                UsePrecompiledHeader="0"\r
-                               AssemblerListingLocation=".\Release/"\r
-                               ObjectFile=".\Release/"\r
-                               ProgramDataBaseFileName=".\Release/"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
                                WarningLevel="4"\r
-                               SuppressStartupBanner="TRUE"\r
-                               DisableSpecificWarnings="4702"/>\r
+                               SuppressStartupBanner="true"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../DLL/Release/dnssd.lib ws2_32.lib"\r
-                               OutputFile="Release/Bonjour.cpl"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/Bonjour.cpl"\r
                                LinkIncremental="1"\r
-                               SuppressStartupBanner="TRUE"\r
+                               SuppressStartupBanner="true"\r
                                ModuleDefinitionFile=".\ControlPanel.def"\r
-                               ProgramDatabaseFile=".\Release/ControlPanel.pdb"\r
+                               ProgramDatabaseFile=".\$(IntDir)\ControlPanel.pdb"\r
                                SubSystem="2"\r
-                               ImportLibrary=".\Release/Bonjour.lib"\r
-                               TargetMachine="1"/>\r
+                               ImportLibrary=".\$(OutDir)\Bonjour.lib"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ControlPanel.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
-                               MkTypLibCompatible="TRUE"\r
-                               SuppressStartupBanner="TRUE"\r
-                               TargetEnvironment="1"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
                                TypeLibraryName=".\Release/ControlPanel.tlb"\r
-                               HeaderFileName=""/>\r
+                               HeaderFileName=""\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
-                       <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="true"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
-                               Culture="6153"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/Bonjour.cpl"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               ModuleDefinitionFile=".\ControlPanel.def"\r
+                               ProgramDatabaseFile=".\$(IntDir)\ControlPanel.pdb"\r
+                               SubSystem="2"\r
+                               ImportLibrary=".\$(OutDir)\Bonjour.lib"\r
+                               TargetMachine="17"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCALinkTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ControlPanel64.manifest"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
-                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+                       >\r
                        <File\r
-                               RelativePath="ConfigDialog.cpp">\r
+                               RelativePath="ConfigDialog.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Release|x64"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="ConfigPropertySheet.cpp">\r
+                               RelativePath="ConfigPropertySheet.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Release|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="ControlPanel.cpp">\r
+                               RelativePath="ControlPanel.cpp"\r
+                               >\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="ControlPanel.def">\r
+                               RelativePath="ControlPanel.def"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="FirstPage.cpp">\r
+                               RelativePath="FirstPage.cpp"\r
+                               >\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="SecondPage.cpp">\r
+                               RelativePath=".\FourthPage.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="SecondPage.cpp"\r
+                               >\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Release|x64"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="SharedSecret.cpp">\r
+                               RelativePath="SharedSecret.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="stdafx.cpp">\r
+                               RelativePath="stdafx.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
                                                PreprocessorDefinitions=""\r
-                                               UsePrecompiledHeader="0"/>\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Release|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
                                                PreprocessorDefinitions=""\r
-                                               UsePrecompiledHeader="0"/>\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="ThirdPage.cpp">\r
+                               RelativePath="ThirdPage.cpp"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
-                       Filter="h;hpp;hxx;hm;inl">\r
+                       Filter="h;hpp;hxx;hm;inl"\r
+                       >\r
                        <File\r
-                               RelativePath="..\CommonServices.h">\r
+                               RelativePath="ConfigDialog.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ConfigDialog.h">\r
+                               RelativePath="ConfigPropertySheet.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ConfigPropertySheet.h">\r
+                               RelativePath="ControlPanel.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ControlPanel.h">\r
+                               RelativePath="FirstPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="FirstPage.h">\r
+                               RelativePath=".\FourthPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="Resource.h">\r
+                               RelativePath="Resource.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="SecondPage.h">\r
+                               RelativePath="SecondPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="SharedSecret.h">\r
+                               RelativePath="SharedSecret.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="stdafx.h">\r
+                               RelativePath="stdafx.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ThirdPage.h">\r
+                               RelativePath="ThirdPage.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"\r
+                       >\r
                        <File\r
-                               RelativePath="res\configurator.ico">\r
+                               RelativePath="res\configurator.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\controlpanel.ico">\r
+                               RelativePath="res\controlpanel.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ControlPanelDll.rc">\r
+                               RelativePath=".\res\ControlPanel.rc2"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\ControlPanelDll.rc2">\r
+                               RelativePath=".\ControlPanelDll.rc"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\failure.ico">\r
+                               RelativePath="res\failure.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\success.ico">\r
+                               RelativePath="res\success.ico"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Support"\r
-                       Filter="">\r
+                       >\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\CommonServices.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\DebugServices.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\DebugServices.h"\r
+                               >\r
+                       </File>\r
                        <File\r
-                               RelativePath="..\DebugServices.c">\r
+                               RelativePath="..\..\mDNSShared\dns_sd.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\DebugServices.h">\r
+                               RelativePath="..\Secret.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dns_sd.h">\r
+                               RelativePath="..\Secret.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\WinServices.cpp">\r
+                               RelativePath="..\WinServices.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\WinServices.h">\r
+                               RelativePath="..\WinServices.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r
        <Globals>\r
+               <Global\r
+                       Name="RESOURCE_FILE"\r
+                       Value="ControlPanelDll.rc"\r
+               />\r
        </Globals>\r
 </VisualStudioProject>\r
index bcf8cb1ad1c02269095d607f9f490c6401fd4c10..5d1f4957ea1b46d156c9ed574ca76edc7d4b1db7 100644 (file)
@@ -62,15 +62,6 @@ BEGIN
 END\r
 \r
 \r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// RT_MANIFEST\r
-//\r
-\r
-2            RT_MANIFEST             "res\\ControlPanel.dll.manifest"\r
-\r
-\r
-\r
 #ifdef APSTUDIO_INVOKED\r
 /////////////////////////////////////////////////////////////////////////////\r
 //\r
index 995997c33650ae6fa3c76f41c97bd9bf89958675..4ea5f954b9dbf0bace4262d2022d8b7b47f8f53b 100644 (file)
@@ -62,15 +62,6 @@ BEGIN
 END\r
 \r
 \r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// RT_MANIFEST\r
-//\r
-\r
-1            RT_MANIFEST             "res\\ControlPanel.exe.manifest"\r
-\r
-\r
-\r
 #ifdef APSTUDIO_INVOKED\r
 /////////////////////////////////////////////////////////////////////////////\r
 //\r
index dee51a8e2aa4dd1d343f5128f02597d793997f41..c97f43045be6d73bd4d104ad7c43486182f34e23 100755 (executable)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="ControlPanel (Vista)"\r
        ProjectGUID="{0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}"\r
-       SccProjectName=""\r
-       SccLocalPath=""\r
-       Keyword="MFCProj">\r
+       Keyword="MFCProj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="ExeBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="ExeBuild\$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       ATLMinimizesCRunTimeLibraryUsage="FALSE">\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="false"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;DEBUG=1;UNICODE;_UNICODE;_WINDOWS;WINVER=0x0501"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="TRUE"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;DEBUG=1;UNICODE;_UNICODE;_WINDOWS;WINVER=0x0501;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="1"\r
                                UsePrecompiledHeader="0"\r
                                PrecompiledHeaderThrough=""\r
                                PrecompiledHeaderFile=""\r
-                               AssemblerListingLocation=".\Debug/"\r
-                               ObjectFile=".\Debug/"\r
-                               ProgramDataBaseFileName=".\Debug/"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
                                WarningLevel="4"\r
-                               SuppressStartupBanner="TRUE"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="4"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
                                CallingConvention="0"\r
-                               DisableSpecificWarnings="4311;4312"/>\r
+                               DisableSpecificWarnings="4311;4312"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../DLL/Debug/dnssd.lib ws2_32.lib"\r
-                               OutputFile="Debug/ControlPanel.exe"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/ControlPanel.exe"\r
                                LinkIncremental="2"\r
-                               SuppressStartupBanner="TRUE"\r
-                               GenerateDebugInformation="TRUE"\r
-                               ProgramDatabaseFile=".\Debug/ControlPanel.pdb"\r
+                               SuppressStartupBanner="true"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)\ControlPanel.pdb"\r
                                SubSystem="2"\r
                                EntryPointSymbol="wWinMainCRTStartup"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ControlPanel.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="ExeBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="ExeBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
-                               MkTypLibCompatible="FALSE"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;DEBUG=1;UNICODE;_UNICODE;_WINDOWS;WINVER=0x0501;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderThrough=""\r
+                               PrecompiledHeaderFile=""\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="0"\r
+                               DisableSpecificWarnings="4311;4312"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/ControlPanel.exe"\r
+                               LinkIncremental="2"\r
+                               SuppressStartupBanner="true"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)\ControlPanel.pdb"\r
+                               SubSystem="2"\r
+                               EntryPointSymbol="wWinMainCRTStartup"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ControlPanel64.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="ExeBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="ExeBuild\$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        UseOfMFC="1"\r
-                       CharacterSet="2">\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="false"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
                                InlineFunctionExpansion="1"\r
                                AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0501;UNICODE;_UNICODE"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="FALSE"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0501;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="false"\r
                                RuntimeLibrary="0"\r
-                               EnableFunctionLevelLinking="TRUE"\r
-                               TreatWChar_tAsBuiltInType="TRUE"\r
+                               EnableFunctionLevelLinking="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
                                UsePrecompiledHeader="0"\r
-                               ObjectFile=".\Release/"\r
-                               ProgramDataBaseFileName=".\Release/"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
                                WarningLevel="4"\r
-                               SuppressStartupBanner="TRUE"\r
-                               DisableSpecificWarnings="4702"/>\r
+                               SuppressStartupBanner="true"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../DLL/Release/dnssd.lib ws2_32.lib"\r
-                               OutputFile="Release/ControlPanel.exe"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/ControlPanel.exe"\r
                                LinkIncremental="1"\r
-                               SuppressStartupBanner="TRUE"\r
-                               ProgramDatabaseFile=".\Release/ControlPanel.pdb"\r
+                               SuppressStartupBanner="true"\r
+                               ProgramDatabaseFile="$(OutDir)\ControlPanel.pdb"\r
                                SubSystem="2"\r
                                OptimizeReferences="0"\r
                                EnableCOMDATFolding="0"\r
                                EntryPointSymbol="wWinMainCRTStartup"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ControlPanel.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="ExeBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="ExeBuild\$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       UseOfMFC="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
-                               MkTypLibCompatible="FALSE"/>\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0501;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="false"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="true"\r
+                               TreatWChar_tAsBuiltInType="true"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               ObjectFile="$(IntDir)\"\r
+                               ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               DisableSpecificWarnings="4702"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
                                Culture="1033"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)/ControlPanel.exe"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               ProgramDatabaseFile="$(OutDir)\ControlPanel.pdb"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="0"\r
+                               EnableCOMDATFolding="0"\r
+                               EntryPointSymbol="wWinMainCRTStartup"\r
+                               TargetMachine="17"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCALinkTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\ControlPanel64.manifest"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
-                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+                       >\r
                        <File\r
-                               RelativePath="ConfigDialog.cpp">\r
+                               RelativePath="ConfigDialog.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Release|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="ConfigPropertySheet.cpp">\r
+                               RelativePath="ConfigPropertySheet.cpp"\r
+                               >\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath=".\ControlPanelExe.cpp">\r
+                               RelativePath=".\ControlPanelExe.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="FirstPage.cpp">\r
+                               RelativePath="FirstPage.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Release|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\FourthPage.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="SecondPage.cpp">\r
+                               RelativePath="SecondPage.cpp"\r
+                               >\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
-                                               PreprocessorDefinitions=""/>\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="SharedSecret.cpp">\r
+                               RelativePath="SharedSecret.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="stdafx.cpp">\r
+                               RelativePath="stdafx.cpp"\r
+                               >\r
                                <FileConfiguration\r
-                                       Name="Debug|Win32">\r
+                                       Name="Debug|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="0"\r
                                                PreprocessorDefinitions=""\r
-                                               UsePrecompiledHeader="0"/>\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
                                </FileConfiguration>\r
                                <FileConfiguration\r
-                                       Name="Release|Win32">\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               PreprocessorDefinitions=""\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
                                        <Tool\r
                                                Name="VCCLCompilerTool"\r
                                                Optimization="2"\r
                                                PreprocessorDefinitions=""\r
-                                               UsePrecompiledHeader="0"/>\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               PreprocessorDefinitions=""\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
-                               RelativePath="ThirdPage.cpp">\r
+                               RelativePath="ThirdPage.cpp"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
-                       Filter="h;hpp;hxx;hm;inl">\r
+                       Filter="h;hpp;hxx;hm;inl"\r
+                       >\r
                        <File\r
-                               RelativePath="..\CommonServices.h">\r
+                               RelativePath="ConfigDialog.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ConfigDialog.h">\r
+                               RelativePath="ConfigPropertySheet.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ConfigPropertySheet.h">\r
+                               RelativePath=".\ControlPanelExe.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\ControlPanelExe.h">\r
+                               RelativePath="FirstPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="FirstPage.h">\r
+                               RelativePath=".\FourthPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="Resource.h">\r
+                               RelativePath="Resource.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="SecondPage.h">\r
+                               RelativePath="SecondPage.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="SharedSecret.h">\r
+                               RelativePath="SharedSecret.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="stdafx.h">\r
+                               RelativePath="stdafx.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ThirdPage.h">\r
+                               RelativePath="ThirdPage.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"\r
+                       >\r
                        <File\r
-                               RelativePath="res\configurator.ico">\r
+                               RelativePath="res\configurator.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\controlpanel.ico">\r
+                               RelativePath="res\controlpanel.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="ControlPanelExe.rc">\r
+                               RelativePath=".\res\ControlPanel.rc2"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\ControlPanelExe.rc2">\r
+                               RelativePath=".\ControlPanelExe.rc"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\failure.ico">\r
+                               RelativePath="res\failure.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="res\success.ico">\r
+                               RelativePath="res\success.ico"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Support"\r
-                       Filter="">\r
+                       >\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\CommonServices.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\DebugServices.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\DebugServices.h"\r
+                               >\r
+                       </File>\r
                        <File\r
-                               RelativePath="..\DebugServices.c">\r
+                               RelativePath="..\..\mDNSShared\dns_sd.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\DebugServices.h">\r
+                               RelativePath="..\Secret.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dns_sd.h">\r
+                               RelativePath="..\Secret.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\WinServices.cpp">\r
+                               RelativePath="..\WinServices.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\WinServices.h">\r
+                               RelativePath="..\WinServices.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r
index 5d6c90afec817c491e808578833b883c598934ed..3fc3180141aad25d9399ff2044f58ce65426ba14 100755 (executable)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: FirstPage.cpp,v $
+Revision 1.7  2009/06/22 23:25:10  herscher
+<rdar://problem/5265747> ControlPanel doesn't display key and password in dialog box. Refactor Lsa calls into Secret.h and Secret.c, which is used by both the ControlPanel and mDNSResponder system service.
+
 Revision 1.6  2006/08/14 23:25:28  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -132,7 +135,7 @@ void CFirstPage::OnBnClickedSharedSecret()
 
        CSharedSecret dlg;
 
-       dlg.m_key = name;
+       dlg.Load( name );
 
        if ( dlg.DoModal() == IDOK )
        {
diff --git a/mDNSWindows/ControlPanel/FourthPage.cpp b/mDNSWindows/ControlPanel/FourthPage.cpp
new file mode 100755 (executable)
index 0000000..c1f9849
--- /dev/null
@@ -0,0 +1,191 @@
+/* -*- 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.
+
+    Change History (most recent first):
+
+$Log: FourthPage.cpp,v $
+Revision 1.1  2009/07/01 19:20:37  herscher
+<rdar://problem/6713286> UI changes for configuring sleep proxy settings.
+
+
+
+*/
+
+#include "FourthPage.h"
+#include "resource.h"
+
+#include "ConfigPropertySheet.h"
+#include "SharedSecret.h"
+
+#include <WinServices.h>
+    
+#define MAX_KEY_LENGTH 255
+
+
+IMPLEMENT_DYNCREATE(CFourthPage, CPropertyPage)
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+//     CFourthPage::CFourthPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CFourthPage::CFourthPage()
+:
+       CPropertyPage(CFourthPage::IDD)
+{
+       //{{AFX_DATA_INIT(CFourthPage)
+       //}}AFX_DATA_INIT
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+//     CFourthPage::~CFourthPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CFourthPage::~CFourthPage()
+{
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+//     CFourthPage::DoDataExchange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CFourthPage::DoDataExchange(CDataExchange* pDX)
+{
+       CPropertyPage::DoDataExchange(pDX);
+       //{{AFX_DATA_MAP(CFourthPage)
+       //}}AFX_DATA_MAP
+       DDX_Control(pDX, IDC_POWER_MANAGEMENT, m_checkBox);
+}
+
+BEGIN_MESSAGE_MAP(CFourthPage, CPropertyPage)
+       //{{AFX_MSG_MAP(CFourthPage)
+       //}}AFX_MSG_MAP\r
+       ON_BN_CLICKED(IDC_POWER_MANAGEMENT, &CFourthPage::OnBnClickedPowerManagement)\r
+END_MESSAGE_MAP()
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+//     CFourthPage::SetModified
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CFourthPage::SetModified( BOOL bChanged )
+{
+       m_modified = bChanged;
+
+       CPropertyPage::SetModified( bChanged );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+//     CFourthPage::OnSetActive
+//---------------------------------------------------------------------------------------------------------------------------
+
+BOOL
+CFourthPage::OnSetActive()
+{
+       CConfigPropertySheet    *       psheet;
+       HKEY                                            key = NULL;
+       DWORD                                           dwSize;
+       DWORD                                           enabled;
+       DWORD                                           err;
+       BOOL                                            b = CPropertyPage::OnSetActive();
+
+       psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
+       require_quiet( psheet, exit );
+
+       m_checkBox.SetCheck( 0 );
+
+       // Now populate the browse domain box
+
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", &key );
+       require_noerr( err, exit );
+
+       dwSize = sizeof( DWORD );
+       err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+       require_noerr( err, exit );
+
+       m_checkBox.SetCheck( enabled );
+exit:
+
+       if ( key )
+       {
+               RegCloseKey( key );
+       }
+
+       return b;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+//     CFourthPage::OnOK
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CFourthPage::OnOK()
+{
+       if ( m_modified )
+       {
+               Commit();
+       }
+}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+//     CFourthPage::Commit
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CFourthPage::Commit()
+{
+       HKEY            key             = NULL;
+       DWORD           enabled;
+       DWORD           err;
+
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", &key );
+       require_noerr( err, exit );
+
+       enabled = m_checkBox.GetCheck();
+       err = RegSetValueEx( key, L"Enabled", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
+       require_noerr( err, exit );
+       
+exit:
+
+       if ( key )
+       {
+               RegCloseKey( key );
+       }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+//     CFourthPage::OnBnClickedRemoveBrowseDomain
+//---------------------------------------------------------------------------------------------------------------------------
+
+\r
+void CFourthPage::OnBnClickedPowerManagement()\r
+{\r
+       char buf[ 256 ];\r
+\r
+       sprintf( buf, "check box: %d", m_checkBox.GetCheck() );\r
+       OutputDebugStringA( buf );\r
+       // TODO: Add your control notification handler code here\r
+\r
+       SetModified( TRUE );\r
+}\r
diff --git a/mDNSWindows/ControlPanel/FourthPage.h b/mDNSWindows/ControlPanel/FourthPage.h
new file mode 100755 (executable)
index 0000000..9ec8a29
--- /dev/null
@@ -0,0 +1,93 @@
+/* -*- 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.
+
+    Change History (most recent first):
+
+$Log: FourthPage.h,v $
+Revision 1.1  2009/07/01 19:20:37  herscher
+<rdar://problem/6713286> UI changes for configuring sleep proxy settings.
+
+
+*/
+
+#pragma once
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include <DebugServices.h>
+#include <list>
+#include "afxcmn.h"
+
+#include "afxwin.h"
+
+
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+//     CFourthPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+class CFourthPage : public CPropertyPage
+{
+public:
+       CFourthPage();
+       ~CFourthPage();
+
+protected:
+
+       //{{AFX_DATA(CFourthPage)
+       enum { IDD = IDR_APPLET_PAGE4 };
+       //}}AFX_DATA
+
+       //{{AFX_VIRTUAL(CFourthPage)
+       virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+       //}}AFX_VIRTUAL
+
+       DECLARE_DYNCREATE(CFourthPage)
+
+       //{{AFX_MSG(CFourthPage)
+       //}}AFX_MSG
+       DECLARE_MESSAGE_MAP()
+       
+private:
+       
+       typedef std::list<CString> StringList;
+
+       afx_msg BOOL
+       OnSetActive();
+       
+       afx_msg void
+       OnOK();
+       
+       void
+       SetModified( BOOL bChanged = TRUE );
+       
+       void
+       Commit();
+
+       BOOL                    m_modified;
+
+public:
+private:
+
+       CButton m_checkBox;
+
+public:
+\r
+       afx_msg void OnBnClickedPowerManagement();\r
+};
index 8633fd7bdcea481da2b0df09c6f1f22c01fe86d0..b74366ebfda0d03261c64fc42d6bf2099400f33b 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: SharedSecret.cpp,v $
+Revision 1.7  2009/06/22 23:25:11  herscher
+<rdar://problem/5265747> ControlPanel doesn't display key and password in dialog box. Refactor Lsa calls into Secret.h and Secret.c, which is used by both the ControlPanel and mDNSResponder system service.
+
 Revision 1.6  2007/06/12 20:06:06  herscher
 <rdar://problem/5263387> ControlPanel was inadvertently adding a trailing dot to all key names.
 
@@ -39,22 +42,14 @@ Revision 1.2  2005/03/03 19:55:22  shersche
 // SharedSecret.cpp : implementation file
 //
 
+
+#include <Secret.h>
 #include "stdafx.h"
 #include "SharedSecret.h"
+#include <WinServices.h>
 
 #include <DebugServices.h>
-#include <ntsecapi.h>
-
-//---------------------------------------------------------------------------------------------------------------------------
-//     Private declarations
-//---------------------------------------------------------------------------------------------------------------------------
 
-static BOOL
-InitLsaString
-                       (
-                       PLSA_UNICODE_STRING     pLsaString,
-                       LPCWSTR                         pwszString
-                       );
 
 // SharedSecret dialog
 
@@ -98,129 +93,46 @@ BEGIN_MESSAGE_MAP(CSharedSecret, CDialog)
 END_MESSAGE_MAP()
 
 
-
 //---------------------------------------------------------------------------------------------------------------------------
-//     CSharedSecret::Commit
+//     CSharedSecret::Load
 //---------------------------------------------------------------------------------------------------------------------------
 
 void
-CSharedSecret::Commit( CString zone )
+CSharedSecret::Load( CString zone )
 {
-       LSA_OBJECT_ATTRIBUTES   attrs;
-       LSA_HANDLE                              handle = NULL;
-       NTSTATUS                                res;
-       LSA_UNICODE_STRING              lucZoneName;
-       LSA_UNICODE_STRING              lucKeyName;
-       LSA_UNICODE_STRING              lucSecretName;
-       BOOL                                    ok;
-       OSStatus                                err;
-
-       // If there isn't a trailing dot, add one because the mDNSResponder
-       // presents names with the trailing dot.
-
-       if ( zone.ReverseFind( '.' ) != ( zone.GetLength() - 1 ) )
-       {
-               zone += '.';
-       }
+       char    zoneUTF8[ 256 ];
+       char    outDomain[ 256 ];
+       char    outKey[ 256 ];
+       char    outSecret[ 256 ];
 
-       if ( m_key.ReverseFind( '.' ) != ( m_key.GetLength() - 1 ) )
+       StringObjectToUTF8String( zone, zoneUTF8, sizeof( zoneUTF8 ) );
+
+       if ( LsaGetSecret( zoneUTF8, outDomain, sizeof( outDomain ) / sizeof( TCHAR ), outKey, sizeof( outKey ) / sizeof( TCHAR ), outSecret, sizeof( outSecret ) / sizeof( TCHAR ) ) )
        {
-               m_key += '.';
+               m_key           = outKey;
+               m_secret        = outSecret;
        }
-
-       // <rdar://problem/4192119>
-       //
-       // Prepend "$" to the key name, so that there will
-       // be no conflict between the zone name and the key
-       // name
-
-       m_key.Insert( 0, L"$" );
-
-       // attrs are reserved, so initialize to zeroes.
-
-       ZeroMemory( &attrs, sizeof( attrs ) );
-
-       // Get a handle to the Policy object on the local system
-
-       res = LsaOpenPolicy( NULL, &attrs, POLICY_ALL_ACCESS, &handle );
-       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-       require_noerr( err, exit );
-
-       // Intializing PLSA_UNICODE_STRING structures
-
-       ok = InitLsaString( &lucZoneName, zone );
-       err = translate_errno( ok, errno_compat(), kUnknownErr );
-       require_noerr( err, exit );
-       ok = InitLsaString( &lucKeyName, m_key );
-       err = translate_errno( ok, errno_compat(), kUnknownErr );
-       require_noerr( err, exit );
-
-       ok = InitLsaString( &lucSecretName, m_secret );
-       err = translate_errno( ok, errno_compat(), kUnknownErr );
-       require_noerr( err, exit );
-
-       // Store the private data.
-
-       res = LsaStorePrivateData( handle, &lucZoneName, &lucKeyName );
-       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-       require_noerr( err, exit );
-
-       res = LsaStorePrivateData( handle, &lucKeyName, &lucSecretName );
-       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-       require_noerr( err, exit );
-
-exit:
-
-       if ( handle )
+       else
        {
-               LsaClose( handle );
-               handle = NULL;
+               m_key = zone;
        }
-
-       return;
 }
 
 
 //---------------------------------------------------------------------------------------------------------------------------
-//     InitLsaString
+//     CSharedSecret::Commit
 //---------------------------------------------------------------------------------------------------------------------------
 
-static BOOL
-InitLsaString
-               (
-               PLSA_UNICODE_STRING     pLsaString,
-               LPCWSTR                         pwszString
-               )
+void
+CSharedSecret::Commit( CString zone )
 {
-       size_t  dwLen   = 0;
-       BOOL    ret             = FALSE;
-       
-       if ( pLsaString == NULL )
-       {
-               goto exit;
-       }
-
-       if ( pwszString != NULL ) 
-       {
-               dwLen = wcslen(pwszString);
-
-               // String is too large
-               if (dwLen > 0x7ffe)
-               {
-                       goto exit;
-               }
-       }
-
-       // Store the string.
-  
-       pLsaString->Buffer                      = (WCHAR *) pwszString;
-       pLsaString->Length                      = (USHORT) dwLen * sizeof(WCHAR);
-       pLsaString->MaximumLength       = (USHORT)(dwLen+1) * sizeof(WCHAR);
-
-       ret = TRUE;
+       char    zoneUTF8[ 256 ];
+       char    keyUTF8[ 256 ];
+       char    secretUTF8[ 256 ];
 
-exit:
+       StringObjectToUTF8String( zone, zoneUTF8, sizeof( zoneUTF8 ) );
+       StringObjectToUTF8String( m_key, keyUTF8, sizeof( keyUTF8 ) );
+       StringObjectToUTF8String( m_secret, secretUTF8, sizeof( secretUTF8 ) );
 
-       return ret;
+       LsaSetSecret( zoneUTF8, keyUTF8, secretUTF8 );
 }
index f5f64351c597599c7d584e892f932593ba85aa2a..73aef5b4c68cabfb79180c7b42d45bb77884c26b 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: SharedSecret.h,v $
+Revision 1.5  2009/06/22 23:25:11  herscher
+<rdar://problem/5265747> ControlPanel doesn't display key and password in dialog box. Refactor Lsa calls into Secret.h and Secret.c, which is used by both the ControlPanel and mDNSResponder system service.
+
 Revision 1.4  2006/08/14 23:25:28  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -50,6 +53,9 @@ public:
 // Dialog Data
        enum { IDD = IDR_SECRET };
 
+       void
+       Load( CString zone );
+
        void
        Commit( CString zone );
 
diff --git a/mDNSWindows/ControlPanel/res/ControlPanel.manifest b/mDNSWindows/ControlPanel/res/ControlPanel.manifest
new file mode 100644 (file)
index 0000000..4879215
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+       <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Apple.Bonjour.ControlPanel" type="win32"/>
+       <description>Control Panel applet for configuring Wide-Area Bonjour.</description>
+       <dependency>
+               <dependentAssembly>
+                       <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*" />
+               </dependentAssembly>
+       </dependency>
+       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+               <security>
+                       <requestedPrivileges>
+                               <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
+                       </requestedPrivileges>
+               </security>
+       </trustInfo>
+</assembly>
diff --git a/mDNSWindows/ControlPanel/res/ControlPanel64.manifest b/mDNSWindows/ControlPanel/res/ControlPanel64.manifest
new file mode 100644 (file)
index 0000000..a47a4e2
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+       <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Apple.Bonjour.ControlPanel" type="win32"/>
+       <description>Control Panel applet for configuring Wide-Area Bonjour.</description>
+       <dependency>
+               <dependentAssembly>
+                       <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*" />
+               </dependentAssembly>
+       </dependency>
+       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+               <security>
+                       <requestedPrivileges>
+                               <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
+                       </requestedPrivileges>
+               </security>
+       </trustInfo>
+</assembly>
index 3a0fec7e98cf86369157085f2c7137562351db5c..e82d604477d6b15ed4009bd8aca9c38ac23602a3 100644 (file)
@@ -8,6 +8,7 @@
 #define IDR_APPLET_PAGE2                132
 #define IDR_SECRET                      133
 #define IDR_APPLET_PAGE3                134
+#define IDR_APPLET_PAGE4                135
 #define IDI_FAILURE                     140
 #define IDI_SUCCESS                     141
 #define IDD_ADD_BROWSE_DOMAIN           142
@@ -30,6 +31,7 @@
 #define IDC_BUTTON2                     1012
 #define IDC_REMOVE_BROWSE_DOMAIN        1012
 #define IDC_ADD_BROWSE_DOMAIN           1013
+#define IDC_POWER_MANAGEMENT            1014
 
 // Next default values for new objects
 // 
@@ -37,7 +39,7 @@
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE        143
 #define _APS_NEXT_COMMAND_VALUE         32771
-#define _APS_NEXT_CONTROL_VALUE         1014
+#define _APS_NEXT_CONTROL_VALUE         1015
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif
index 4a71579c8e453da58986c5c86837e2cb818c23eb..d99c8ab72246f81d20f03601100bc3ca9c5f970c 100755 (executable)
     Change History (most recent first):
 
 $Log: AssemblyInfo.cpp,v $
+Revision 1.6  2009/03/30 20:16:27  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.5  2006/08/14 23:25:43  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -38,8 +42,11 @@ Initial revision
 #include "stdafx.h"
 #include "WinVersRes.h"
 
+using namespace System;
 using namespace System::Reflection;
 using namespace System::Runtime::CompilerServices;
+using namespace System::Runtime::InteropServices;
+using namespace System::Security::Permissions;
 
 //
 // General Information about an assembly is controlled through the following 
@@ -49,9 +56,9 @@ using namespace System::Runtime::CompilerServices;
 [assembly:AssemblyTitleAttribute("dnssd.NET")];
 [assembly:AssemblyDescriptionAttribute(".NET wrapper for DNS-SD services")];
 [assembly:AssemblyConfigurationAttribute("")];
-[assembly:AssemblyCompanyAttribute("Apple Computer, Inc.")];
+[assembly:AssemblyCompanyAttribute("Apple Inc.")];
 [assembly:AssemblyProductAttribute("")];
-[assembly:AssemblyCopyrightAttribute("Apple Computer, Inc.")];
+[assembly:AssemblyCopyrightAttribute("Apple Inc.")];
 [assembly:AssemblyTrademarkAttribute("")];
 [assembly:AssemblyCultureAttribute("")];               
 
@@ -95,3 +102,7 @@ using namespace System::Runtime::CompilerServices;
 [assembly:AssemblyDelaySignAttribute(false)];
 [assembly:AssemblyKeyFileAttribute("dnssd_NET.snk")];
 [assembly:AssemblyKeyNameAttribute("")];
+
+[assembly:ComVisible(false)];
+[assembly:CLSCompliantAttribute(true)];
+[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
index 7fbc319892d74c8c7f21aa68a0be81f7c43d6cc3..ff4647d739041dcc8ecfe9f369c3fc0c6912b6c5 100755 (executable)
     Change History (most recent first):
 
 $Log: Stdafx.h,v $
+Revision 1.6  2009/03/30 20:17:57  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.5  2006/08/14 23:25:43  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -47,3 +51,6 @@ Initial revision
 #using <mscorlib.dll>
 #using <System.dll>
 
+struct _DNSServiceRef_t {};
+struct _DNSRecordRef_t {};
+
index f5ba48623a146145a17665c82cd1645d66de588c..b30699e8b22b1ebb4eafe72c2e5e8f153323c394 100755 (executable)
     Change History (most recent first):
 
 $Log: dnssd_NET.cpp,v $
+Revision 1.11  2009/03/30 20:19:05  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.10  2006/08/14 23:25:43  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -120,7 +124,7 @@ ServiceRef::StartThread()
 
        m_impl->SetupEvents();
 
-       m_thread                =       new Thread(new ThreadStart(this, ProcessingThread));
+       m_thread                =       new Thread(new ThreadStart(this, &Apple::DNSSD::ServiceRef::ProcessingThread));
        m_thread->Name  =       S"DNSService Thread";
        m_thread->IsBackground = true;
        
index d857d4c0c7b3614c2bed2d4e87b4f51239f4e413..98cc63b53e4cabd8b6710767e5aeae12baa5838b 100755 (executable)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="DLL.NET"\r
-       ProjectGUID="{9C6701E2-82B7-44B7-9B5E-3897D9153F79}"\r
-       Keyword="ManagedCProj">\r
+       ProjectGUID="{2A2FFA97-AF60-494F-9384-BBAA283AA3F2}"\r
+       RootNamespace="DLL2NET"\r
+       Keyword="ManagedCProj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
-                       CharacterSet="2"\r
-                       ManagedExtensions="TRUE">\r
+                       CharacterSet="1"\r
+                       ManagedExtensions="4"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                               Description="Generating keypair..."\r
+                               CommandLine="sn -k dnssd_NET.snk"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="../;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;WIN32_LEAN_AND_MEAN"\r
-                               MinimalRebuild="FALSE"\r
-                               BasicRuntimeChecks="0"\r
-                               RuntimeLibrary="1"\r
-                               UsePrecompiledHeader="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;WIN32_LEAN_AND_MEAN"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
                                WarningLevel="3"\r
                                DebugInformationFormat="3"\r
-                               CallingConvention="2"/>\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalOptions="/noentry"\r
-                               AdditionalDependencies="../DLL/Debug/dnssd.lib mscoree.lib ws2_32.lib msvcrtd.lib"\r
+                               AdditionalDependencies="../DLL/$(OutDir)/dnssd.lib ws2_32.lib"\r
                                OutputFile="$(OutDir)\dnssd.NET.dll"\r
                                LinkIncremental="2"\r
-                               AdditionalLibraryDirectories=""\r
-                               GenerateDebugInformation="TRUE"/>\r
+                               GenerateDebugInformation="true"\r
+                               AssemblyDebug="1"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               EmbedManifest="false"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       CharacterSet="1"\r
+                       ManagedExtensions="4"\r
+                       >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                                Description="Generating keypair..."\r
-                               CommandLine="sn -k dnssd_NET.snk"/>\r
+                               CommandLine="sn -k dnssd_NET.snk"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="../;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;WIN32_LEAN_AND_MEAN"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               DebugInformationFormat="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="../DLL/$(OutDir)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)\dnssd.NET.dll"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               AssemblyDebug="1"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               EmbedManifest="false"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
-                       CharacterSet="2"\r
-                       ManagedExtensions="TRUE">\r
+                       CharacterSet="1"\r
+                       ManagedExtensions="4"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                               Description="Generating keypair..."\r
+                               CommandLine="sn -k dnssd_NET.snk"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalOptions="/Zl"\r
                                AdditionalIncludeDirectories="../;../../mDNSShared"\r
                                PreprocessorDefinitions="WIN32;NDEBUG;WIN32_LEAN_AND_MEAN"\r
-                               MinimalRebuild="FALSE"\r
-                               RuntimeLibrary="0"\r
+                               RuntimeLibrary="2"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="3"\r
-                               DebugInformationFormat="3"/>\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalOptions="/noentry"\r
-                               AdditionalDependencies="../DLL/Release/dnssd.lib mscoree.lib ws2_32.lib msvcrt.lib"\r
+                               AdditionalDependencies="../DLL/$(OutDir)/dnssd.lib ws2_32.lib"\r
                                OutputFile="$(OutDir)\dnssd.NET.dll"\r
                                LinkIncremental="1"\r
-                               GenerateDebugInformation="TRUE"\r
-                               ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"/>\r
+                               GenerateDebugInformation="true"\r
+                               TargetMachine="1"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCALinkTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCManifestTool"\r
+                               EmbedManifest="false"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       CharacterSet="1"\r
+                       ManagedExtensions="4"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                                Description="Generating keypair..."\r
-                               CommandLine="sn -k dnssd_NET.snk"/>\r
+                               CommandLine="sn -k dnssd_NET.snk"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories="../;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;WIN32_LEAN_AND_MEAN"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="../DLL/$(OutDir)/dnssd.lib ws2_32.lib"\r
+                               OutputFile="$(OutDir)\dnssd.NET.dll"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               EmbedManifest="false"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
+               <AssemblyReference\r
+                       RelativePath="System.dll"\r
+                       AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"\r
+               />\r
+               <AssemblyReference\r
+                       RelativePath="System.Data.dll"\r
+                       AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"\r
+               />\r
+               <AssemblyReference\r
+                       RelativePath="System.XML.dll"\r
+                       AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"\r
+               />\r
        </References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
-                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
-                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
                        <File\r
-                               RelativePath=".\AssemblyInfo.cpp">\r
+                               RelativePath=".\AssemblyInfo.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\dnssd_NET.cpp">\r
+                               RelativePath=".\dnssd_NET.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\Stdafx.cpp">\r
+                               RelativePath=".\Stdafx.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                        Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
-                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
-                       <File\r
-                               RelativePath=".\dnssd_NET.h">\r
-                       </File>\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
                        <File\r
-                               RelativePath="PString.h">\r
+                               RelativePath=".\dnssd_NET.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\resource.h">\r
+                               RelativePath=".\resource.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\Stdafx.h">\r
+                               RelativePath=".\Stdafx.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
-                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
-                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
                        <File\r
-                               RelativePath="dnssd_NET.ico">\r
+                               RelativePath=".\dnssd_NET.ico"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="dnssd_NET.rc">\r
+                               RelativePath=".\dnssd_NET.rc"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <File\r
-                       RelativePath=".\ReadMe.txt">\r
+                       RelativePath=".\ReadMe.txt"\r
+                       >\r
                </File>\r
        </Files>\r
        <Globals>\r
index 91b3f544a673f73eb0d9e8702d2c7a94164e7d6e..008ad970cc90624917e434e57dcdec858029b6e5 100644 (file)
@@ -17,6 +17,9 @@
 ;      Change History (most recent first):
 ;    
 ; $Log: dnssd.def,v $
+; Revision 1.5  2009/03/30 20:14:27  herscher
+; <rdar://problem/5925472> Current Bonjour code does not compile on Windows
+;
 ; Revision 1.4  2006/09/27 00:46:18  herscher
 ; <rdar://problem/4249761> API: Need DNSServiceGetAddrInfo()
 ;
@@ -58,6 +61,7 @@ EXPORTS
        DNSServiceReconfirmRecord
        DNSServiceNATPortMappingCreate
        DNSServiceGetAddrInfo
+       DNSServiceGetProperty
        TXTRecordCreate
        TXTRecordDeallocate
        TXTRecordSetValue
index eab0f4144f2086d49e2ecd5863783dcc11a4cbcd..22a6e3d9aac87007421382e0163cb234bb822916 100644 (file)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="DLL"\r
        ProjectGUID="{AB581101-18F0-46F6-B56A-83A6B1EA657E}"\r
-       Keyword="Win32Proj">\r
+       RootNamespace="DLL"\r
+       Keyword="Win32Proj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug\"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="../../mDNSCore;../../mDNSShared;../"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DEBUG=1;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="TRUE"\r
-                               ExceptionHandling="FALSE"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DEBUG=1;NOT_HAVE_SA_LEN;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
                                BasicRuntimeChecks="3"\r
-                               SmallerTypeCheck="TRUE"\r
+                               SmallerTypeCheck="true"\r
                                RuntimeLibrary="1"\r
-                               BufferSecurityCheck="TRUE"\r
+                               BufferSecurityCheck="true"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
                                CallingConvention="2"\r
                                CompileAs="0"\r
-                               DisableSpecificWarnings="4127;4204"/>\r
+                               DisableSpecificWarnings="4127;4204"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
                                AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
                                OutputFile="$(OutDir)/dnssd.dll"\r
                                LinkIncremental="2"\r
                                ModuleDefinitionFile="dnssd.def"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/dnssd.pdb"\r
                                SubSystem="2"\r
                                BaseAddress="0x16000000"\r
-                               ImportLibrary="$(IntDir)\dnssd.lib"\r
-                               TargetMachine="1"/>\r
+                               ImportLibrary="$(OutDir)\dnssd.lib"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="../../mDNSCore;../../mDNSShared;../"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DEBUG=1;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;NOT_HAVE_SA_LEN"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
+                               BasicRuntimeChecks="3"\r
+                               SmallerTypeCheck="true"\r
+                               RuntimeLibrary="1"\r
+                               BufferSecurityCheck="true"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                               CompileAs="0"\r
+                               DisableSpecificWarnings="4127;4204"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
+                               OutputFile="$(OutDir)/dnssd.dll"\r
+                               LinkIncremental="2"\r
+                               ModuleDefinitionFile="dnssd.def"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/dnssd.pdb"\r
+                               SubSystem="2"\r
+                               BaseAddress="0x16000000"\r
+                               ImportLibrary="$(OutDir)\dnssd.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                AdditionalIncludeDirectories="../../mDNSCore;../../mDNSShared;../"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;NOT_HAVE_SA_LEN"\r
                                RuntimeLibrary="0"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                                CallingConvention="2"\r
                                CompileAs="0"\r
-                               DisableSpecificWarnings="4127;4204"/>\r
+                               DisableSpecificWarnings="4127;4204"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
                                AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
                                OutputFile="$(OutDir)/dnssd.dll"\r
                                LinkIncremental="1"\r
                                ModuleDefinitionFile="dnssd.def"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
                                BaseAddress="0x16000000"\r
-                               ImportLibrary=".\Release\dnssd.lib"\r
-                               TargetMachine="1"/>\r
+                               ImportLibrary="$(OutDir)\dnssd.lib"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;             mkdir &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)&quot; mkdir &quot;$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)&quot;&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour SDK\include&quot;                      mkdir &quot;$(DSTROOT)\Program Files\Bonjour SDK\include&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                            &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(OutDir)\dnssd.lib&quot;                                                                    &quot;$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(ProjectDir)..\..\mDNSShared\dns_sd.h&quot;                                 &quot;$(DSTROOT)\Program Files\Bonjour SDK\include&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories="../../mDNSCore;../../mDNSShared;../"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;NOT_HAVE_SA_LEN"\r
+                               RuntimeLibrary="0"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                               CompileAs="0"\r
+                               DisableSpecificWarnings="4127;4204"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
+                               OutputFile="$(OutDir)/dnssd.dll"\r
+                               LinkIncremental="1"\r
+                               ModuleDefinitionFile="dnssd.def"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               BaseAddress="0x16000000"\r
+                               ImportLibrary="$(OutDir)\dnssd.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;             mkdir &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)&quot; mkdir &quot;$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)&quot;&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour SDK\include&quot;                      mkdir &quot;$(DSTROOT)\Program Files\Bonjour SDK\include&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                            &quot;$(DSTROOT)\WINDOWS\system32\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(OutDir)\dnssd.lib&quot;                                                                    &quot;$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
                <Filter\r
                        Name="Source Files"\r
                        Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
-                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.c">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\dllmain.c">\r
+                               RelativePath=".\dllmain.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\dnssd.def">\r
+                               RelativePath=".\dnssd.def"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dnssd_clientlib.c">\r
+                               RelativePath="..\..\mDNSShared\dnssd_clientlib.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dnssd_clientstub.c">\r
+                               RelativePath="..\..\mDNSShared\dnssd_clientstub.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dnssd_ipc.c">\r
+                               RelativePath="..\..\mDNSShared\dnssd_ipc.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\GenLinkedList.c">\r
+                               RelativePath="..\..\mDNSShared\GenLinkedList.c"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                        Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
-                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
-                       <File\r
-                               RelativePath="..\..\mDNSShared\CommonServices.h">\r
-                       </File>\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.h">\r
+                               RelativePath="..\..\mDNSShared\CommonServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dns_sd.h">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dnssd_ipc.h">\r
+                               RelativePath="..\..\mDNSShared\dns_sd.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dnssd_sock.h">\r
+                               RelativePath="..\..\mDNSShared\dnssd_ipc.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\GenLinkedList.h">\r
+                               RelativePath="..\..\mDNSShared\GenLinkedList.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\resource.h">\r
+                               RelativePath=".\resource.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
                        Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
-                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
                        <File\r
-                               RelativePath=".\dll.rc">\r
+                               RelativePath=".\dll.rc"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r
diff --git a/mDNSWindows/DLLStub/DLLStub.cpp b/mDNSWindows/DLLStub/DLLStub.cpp
new file mode 100755 (executable)
index 0000000..c39a747
--- /dev/null
@@ -0,0 +1,693 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009, 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 "DLLStub.h"
+
+static int             g_defaultErrorCode = kDNSServiceErr_Unknown;
+static DLLStub g_glueLayer;
+
+
+// ------------------------------------------
+// DLLStub implementation
+// ------------------------------------------
+DLLStub * DLLStub::m_instance;
+
+DLLStub::DLLStub()
+:
+       m_library( LoadLibrary( TEXT( "dnssd.dll" ) ) )
+{
+       m_instance = this;
+}
+
+
+DLLStub::~DLLStub()
+{
+       if ( m_library != NULL )
+       {
+               FreeLibrary( m_library );
+               m_library = NULL;
+       }
+
+       m_instance = NULL;
+}
+
+
+bool
+DLLStub::GetProcAddress( FARPROC * func, LPCSTR lpProcName )
+{ 
+       if ( m_instance && m_instance->m_library )
+       {
+               // Only call ::GetProcAddress if *func is NULL. This allows
+               // the calling code to cache the funcptr value, and we get
+               // some performance benefit.
+
+               if ( *func == NULL )
+               {
+                       *func = ::GetProcAddress( m_instance->m_library, lpProcName );
+               }
+       }
+       else
+       {
+               *func = NULL;
+       }
+
+       return ( *func != NULL );
+}
+
+
+int DNSSD_API
+DNSServiceRefSockFD(DNSServiceRef sdRef)
+{
+       typedef int (DNSSD_API * Func)(DNSServiceRef sdRef);
+       static Func func = NULL;
+       int ret = -1;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+DNSServiceProcessResult(DNSServiceRef sdRef)
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef sdRef);
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef );
+       }
+       
+       return ret;
+}
+
+
+void DNSSD_API
+DNSServiceRefDeallocate(DNSServiceRef sdRef)
+{
+       typedef void (DNSSD_API * Func)(DNSServiceRef sdRef);
+       static Func func = NULL;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               func( sdRef );
+       }
+}
+
+
+DNSServiceErrorType DNSSD_API
+DNSServiceEnumerateDomains
+               (
+               DNSServiceRef                       *sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            interfaceIndex,
+               DNSServiceDomainEnumReply           callBack,
+               void                                *context
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, DNSServiceDomainEnumReply, void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, flags, interfaceIndex, callBack, context );
+       }
+       
+       return ret;
+}
+
+
+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                            port,
+               uint16_t                            txtLen,
+               const void                          *txtRecord,
+               DNSServiceRegisterReply             callBack,
+               void                                *context
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, const char*, const char*, const char*, const char*, uint16_t, uint16_t, const void*, DNSServiceRegisterReply, void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, flags, interfaceIndex, name, regtype, domain, host, port, txtLen, txtRecord, callBack, context );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+DNSServiceAddRecord
+               (
+               DNSServiceRef                       sdRef,
+               DNSRecordRef                        *RecordRef,
+               DNSServiceFlags                     flags,
+               uint16_t                            rrtype,
+               uint16_t                            rdlen,
+               const void                          *rdata,
+               uint32_t                            ttl
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef, DNSRecordRef*, DNSServiceFlags, uint16_t, uint16_t, const void*, uint32_t );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, RecordRef, flags, rrtype, rdlen, rdata, ttl );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+DNSServiceUpdateRecord
+               (
+               DNSServiceRef                       sdRef,
+               DNSRecordRef                        RecordRef,     /* may be NULL */
+               DNSServiceFlags                     flags,
+               uint16_t                            rdlen,
+               const void                          *rdata,
+               uint32_t                            ttl
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef, DNSRecordRef, DNSServiceFlags, uint16_t, const void*, uint32_t );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, RecordRef, flags, rdlen, rdata, ttl );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+DNSServiceRemoveRecord
+               (
+               DNSServiceRef                 sdRef,
+               DNSRecordRef                  RecordRef,
+               DNSServiceFlags               flags
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef, DNSRecordRef, DNSServiceFlags );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, RecordRef, flags );
+       }
+       
+       return ret;
+}
+
+
+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 */
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, const char*, const char*, DNSServiceBrowseReply, void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, flags, interfaceIndex, regtype, domain, callBack, context );
+       }
+       
+       return ret;
+}
+
+
+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 */
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, const char*, const char*, const char*, DNSServiceResolveReply, void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, flags, interfaceIndex, name, regtype, domain, callBack, context );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+DNSServiceConstructFullName
+               (
+               char                            *fullName,
+               const char                      *service,      /* may be NULL */
+               const char                      *regtype,
+               const char                      *domain
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)( char*, const char*, const char*, const char* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( fullName, service, regtype, domain );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+DNSServiceCreateConnection(DNSServiceRef *sdRef)
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)( DNSServiceRef* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef );
+       }
+       
+       return ret;
+}
+
+
+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 */
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef, DNSRecordRef*, DNSServiceFlags, uint32_t, const char*, uint16_t, uint16_t, uint16_t, const void*, uint16_t, DNSServiceRegisterRecordReply, void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, RecordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata, ttl, callBack, context );
+       }
+       
+       return ret;
+}
+
+
+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 */
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, const char*, uint16_t, uint16_t, DNSServiceQueryRecordReply, void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, flags, interfaceIndex, fullname, rrtype, rrclass, callBack, context );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+DNSServiceReconfirmRecord
+               (
+               DNSServiceFlags                    flags,
+               uint32_t                           interfaceIndex,
+               const char                         *fullname,
+               uint16_t                           rrtype,
+               uint16_t                           rrclass,
+               uint16_t                           rdlen,
+               const void                         *rdata
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)( DNSServiceFlags, uint32_t, const char*, uint16_t, uint16_t, uint16_t, const void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata );
+       }
+       
+       return ret;
+}
+
+
+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             */
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, DNSServiceProtocol, uint16_t, uint16_t, uint16_t, DNSServiceNATPortMappingReply, void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, flags, interfaceIndex, protocol, internalPort, externalPort, ttl, callBack, context );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+DNSServiceGetAddrInfo
+               (
+               DNSServiceRef                    *sdRef,
+               DNSServiceFlags                  flags,
+               uint32_t                         interfaceIndex,
+               DNSServiceProtocol               protocol,
+               const char                       *hostname,
+               DNSServiceGetAddrInfoReply       callBack,
+               void                             *context          /* may be NULL */
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, DNSServiceProtocol, const char*, DNSServiceGetAddrInfoReply, void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( sdRef, flags, interfaceIndex, protocol, hostname, callBack, context );
+       }
+       
+       return ret;
+}
+
+
+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 */
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)( const char*, void*, uint32_t* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( property, result, size );
+       }
+       
+       return ret;
+}
+
+
+void DNSSD_API
+TXTRecordCreate
+               (
+               TXTRecordRef     *txtRecord,
+               uint16_t         bufferLen,
+               void             *buffer
+               )
+{
+       typedef void (DNSSD_API * Func)( TXTRecordRef*, uint16_t, void* );
+       static Func func = NULL;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               func( txtRecord, bufferLen, buffer );
+       }
+}
+
+
+void DNSSD_API
+TXTRecordDeallocate
+               (
+               TXTRecordRef     *txtRecord
+               )
+{
+       typedef void (DNSSD_API * Func)( TXTRecordRef* );
+       static Func func = NULL;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               func( txtRecord );
+       }
+}
+
+
+DNSServiceErrorType DNSSD_API
+TXTRecordSetValue
+               (
+               TXTRecordRef     *txtRecord,
+               const char       *key,
+               uint8_t          valueSize,        /* may be zero */
+               const void       *value            /* may be NULL */
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)( TXTRecordRef*, const char*, uint8_t, const void* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( txtRecord, key, valueSize, value );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+TXTRecordRemoveValue
+               (
+               TXTRecordRef     *txtRecord,
+               const char       *key
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)( TXTRecordRef*, const char* );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( txtRecord, key );
+       }
+       
+       return ret;
+}
+
+
+int DNSSD_API
+TXTRecordContainsKey
+               (
+               uint16_t         txtLen,
+               const void       *txtRecord,
+               const char       *key
+               )
+{
+       typedef int (DNSSD_API * Func)( uint16_t, const void*, const char* );
+       static Func func = NULL;
+       int ret = 0;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( txtLen, txtRecord, key );
+       }
+       
+       return ret;
+}
+
+
+uint16_t DNSSD_API
+TXTRecordGetCount
+               (
+               uint16_t         txtLen,
+               const void       *txtRecord
+               )
+{
+       typedef uint16_t (DNSSD_API * Func)( uint16_t, const void* );
+       static Func func = NULL;
+       uint16_t ret = 0;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( txtLen, txtRecord );
+       }
+       
+       return ret;
+}
+
+
+uint16_t DNSSD_API
+TXTRecordGetLength
+               (
+               const TXTRecordRef *txtRecord
+               )
+{
+       typedef uint16_t (DNSSD_API * Func)( const TXTRecordRef* );
+       static Func func = NULL;
+       uint16_t ret = 0;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( txtRecord );
+       }
+       
+       return ret;
+}
+
+
+const void * DNSSD_API
+TXTRecordGetBytesPtr
+               (
+               const TXTRecordRef *txtRecord
+               )
+{
+       typedef const void* (DNSSD_API * Func)( const TXTRecordRef* );
+       static Func func = NULL;
+       const void* ret = NULL;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( txtRecord );
+       }
+       
+       return ret;
+}
+
+
+const void * DNSSD_API
+TXTRecordGetValuePtr
+               (
+               uint16_t         txtLen,
+               const void       *txtRecord,
+               const char       *key,
+               uint8_t          *valueLen
+               )
+{
+       typedef const void* (DNSSD_API * Func)( uint16_t, const void*, const char*, uint8_t* );
+       static Func func = NULL;
+       const void* ret = NULL;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( txtLen, txtRecord, key, valueLen );
+       }
+       
+       return ret;
+}
+
+
+DNSServiceErrorType DNSSD_API
+TXTRecordGetItemAtIndex
+               (
+               uint16_t         txtLen,
+               const void       *txtRecord,
+               uint16_t         itemIndex,
+               uint16_t         keyBufLen,
+               char             *key,
+               uint8_t          *valueLen,
+               const void       **value
+               )
+{
+       typedef DNSServiceErrorType (DNSSD_API * Func)( uint16_t, const void*, uint16_t, uint16_t, char*, uint8_t*, const void** );
+       static Func func = NULL;
+       DNSServiceErrorType ret = g_defaultErrorCode;
+
+       if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
+       {
+               ret = func( txtLen, txtRecord, itemIndex, keyBufLen, key, valueLen, value );
+       }
+       
+       return ret;
+}
\ No newline at end of file
diff --git a/mDNSWindows/DLLStub/DLLStub.h b/mDNSWindows/DLLStub/DLLStub.h
new file mode 100755 (executable)
index 0000000..44f57d1
--- /dev/null
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009, 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 _DLLStub_h
+#define _DLLStub_h
+
+#include <windows.h>
+#include <dns_sd.h>
+
+class DLLStub
+{
+public:
+
+       DLLStub();
+       ~DLLStub();
+
+       static bool
+       GetProcAddress( FARPROC * func, LPCSTR lpProcName );
+
+private:
+
+       static DLLStub  *       m_instance;
+       HMODULE                         m_library;
+};
+
+
+#endif
\ No newline at end of file
diff --git a/mDNSWindows/DLLStub/DLLStub.vcproj b/mDNSWindows/DLLStub/DLLStub.vcproj
new file mode 100755 (executable)
index 0000000..b693b27
--- /dev/null
@@ -0,0 +1,318 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="8.00"\r
+       Name="DLLStub"\r
+       ProjectGUID="{3A2B6325-3053-4236-84BD-AA9BE2E323E5}"\r
+       RootNamespace="DLLStub"\r
+       Keyword="Win32Proj"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="4"\r
+                       UseOfATL="0"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="0"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_LIB;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               MinimalRebuild="false"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)\dnssdStatic.lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="4"\r
+                       UseOfATL="0"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="0"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_LIB;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               MinimalRebuild="false"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)\dnssdStatic.lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="4"\r
+                       UseOfATL="0"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="0"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_LIB;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               RuntimeLibrary="0"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)\dnssdStatic.lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="4"\r
+                       UseOfATL="0"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="0"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_LIB;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               RuntimeLibrary="0"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)\dnssdStatic.lib"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\DLLStub.cpp"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\DLLStub.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
+               </Filter>\r
+               <File\r
+                       RelativePath=".\ReadMe.txt"\r
+                       >\r
+               </File>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/mDNSWindows/DLLX/DLLX.cpp b/mDNSWindows/DLLX/DLLX.cpp
new file mode 100755 (executable)
index 0000000..7cc6c63
--- /dev/null
@@ -0,0 +1,120 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: DLLX.cpp,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+\r
+#include "stdafx.h"\r
+#include "resource.h"\r
+#include "DLLX.h"\r
+#include "dlldatax.h"\r
+#include <DebugServices.h>\r
+\r
+\r
+class CDLLComponentModule : public CAtlDllModuleT< CDLLComponentModule >\r
+{\r
+public :\r
+       DECLARE_LIBID(LIBID_Bonjour)\r
+       DECLARE_REGISTRY_APPID_RESOURCEID(IDR_DLLX, "{56608F9C-223B-4CB6-813D-85EDCCADFB4B}")\r
+};\r
+\r
+CDLLComponentModule _AtlModule;\r
+\r
+\r
+#ifdef _MANAGED\r
+#pragma managed(push, off)\r
+#endif\r
+\r
+// DLL Entry Point\r
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r
+{\r
+       debug_initialize( kDebugOutputTypeWindowsDebugger );
+       debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );\r
+\r
+#ifdef _MERGE_PROXYSTUB\r
+    if (!PrxDllMain(hInstance, dwReason, lpReserved))\r
+        return FALSE;\r
+#endif\r
+       hInstance;\r
+    return _AtlModule.DllMain(dwReason, lpReserved); \r
+}\r
+\r
+#ifdef _MANAGED\r
+#pragma managed(pop)\r
+#endif\r
+\r
+\r
+\r
+\r
+// Used to determine whether the DLL can be unloaded by OLE\r
+STDAPI DllCanUnloadNow(void)\r
+{\r
+#ifdef _MERGE_PROXYSTUB\r
+    HRESULT hr = PrxDllCanUnloadNow();\r
+    if (hr != S_OK)\r
+        return hr;\r
+#endif\r
+    return _AtlModule.DllCanUnloadNow();\r
+}\r
+\r
+\r
+// Returns a class factory to create an object of the requested type\r
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)\r
+{\r
+#ifdef _MERGE_PROXYSTUB\r
+    if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)\r
+        return S_OK;\r
+#endif\r
+    return _AtlModule.DllGetClassObject(rclsid, riid, ppv);\r
+}\r
+\r
+\r
+// DllRegisterServer - Adds entries to the system registry\r
+STDAPI DllRegisterServer(void)\r
+{\r
+    // registers object, typelib and all interfaces in typelib\r
+    HRESULT hr = _AtlModule.DllRegisterServer();\r
+#ifdef _MERGE_PROXYSTUB\r
+    if (FAILED(hr))\r
+        return hr;\r
+    hr = PrxDllRegisterServer();\r
+#endif\r
+       return hr;\r
+}\r
+\r
+\r
+// DllUnregisterServer - Removes entries from the system registry\r
+STDAPI DllUnregisterServer(void)\r
+{\r
+       HRESULT hr = _AtlModule.DllUnregisterServer();\r
+#ifdef _MERGE_PROXYSTUB\r
+    if (FAILED(hr))\r
+        return hr;\r
+    hr = PrxDllRegisterServer();\r
+    if (FAILED(hr))\r
+        return hr;\r
+    hr = PrxDllUnregisterServer();\r
+#endif\r
+       return hr;\r
+}\r
+\r
diff --git a/mDNSWindows/DLLX/DLLX.def b/mDNSWindows/DLLX/DLLX.def
new file mode 100755 (executable)
index 0000000..3029b69
--- /dev/null
@@ -0,0 +1,33 @@
+; -*- Mode: C; tab-width: 4 -*-
+;
+; Copyright (c) 2009 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.
+;
+;   Change History (most recent first):
+;   
+; $Log: DLLX.def,v $
+; Revision 1.1  2009/05/26 04:43:54  herscher
+; <rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+;\r
+;\r
+;\r
+\r
+\r
+LIBRARY      "dnssdX.DLL"\r
+\r
+EXPORTS\r
+       DllCanUnloadNow         PRIVATE\r
+       DllGetClassObject       PRIVATE\r
+       DllRegisterServer       PRIVATE\r
+       DllUnregisterServer     PRIVATE\r
diff --git a/mDNSWindows/DLLX/DLLX.idl b/mDNSWindows/DLLX/DLLX.idl
new file mode 100755 (executable)
index 0000000..05725e8
--- /dev/null
@@ -0,0 +1,309 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: DLLX.idl,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+// This file will be processed by the MIDL tool to\r
+// produce the type library (DLLComponent.tlb) and marshalling code.\r
+\r
+typedef [ uuid(4085DD59-D0E1-4efe-B6EE-DDBF7631B9C0) ]\r
+enum DNSSDFlags\r
+{\r
+       kDNSSDFlagsMoreComing                   = 0x0001,\r
+       kDNSSDFlagsDefault                              = 0x0004,\r
+       kDNSSDFlagsNoAutoRename                 = 0x0008,\r
+       kDNSSDFlagsShared                               = 0x0010,\r
+       kDNSSDFlagsUnique                               = 0x0020,\r
+       kDNSSDFlagsBrowseDomains                = 0x0040,\r
+       kDNSSDFlagsRegistrationDomains  = 0x0080,\r
+       kDNSSDFlagsLongLivedQuery               = 0x0100,\r
+       kDNSSDFlagsAllowRemoteQuery             = 0x0200,\r
+       kDNSSDFlagsForceMulticast               = 0x0400,\r
+       kDNSSDFlagsForce                                = 0x0800,\r
+       kDNSSDFlagsReturnIntermediates  = 0x1000,\r
+       kDNSSDFlagsNonBrowsable                 = 0x2000\r
+} DNSSDFlags;\r
+\r
+\r
+typedef [ uuid(30CDF335-CA52-4b17-AFF2-E83C64C450D4) ]\r
+enum DNSSDAddressFamily\r
+{\r
+       kDNSSDAddressFamily_IPv4 = 0x1,\r
+       kDNSSDAddressFamily_IPv6 = 0x2\r
+} DNSSDAddressFamily;\r
+\r
+\r
+typedef [ uuid(98FB4702-7374-4b16-A8DB-AD35BFB8364D) ]\r
+enum DNSSDProtocol\r
+{\r
+       kDNSSDProtocol_UDP      = 0x10,\r
+       kDNSSDProtocol_TCP      = 0x20\r
+} DNSSDProtocol;\r
+\r
+\r
+typedef [ uuid(72BF3EC3-19BC-47e5-8D95-3B73FF37D893) ]\r
+enum DNSSDRRClass\r
+{\r
+       kDNSSDClass_IN = 1\r
+} DNSSDRRClass;\r
+\r
+\r
+typedef [ uuid(08E362DF-5468-4c9a-AC66-FD4747B917BD) ]\r
+enum DNSSDRRType\r
+{\r
+       kDNSSDType_A         = 1,
+    kDNSSDType_NS        = 2,
+    kDNSSDType_MD        = 3,
+    kDNSSDType_MF        = 4,
+    kDNSSDType_CNAME     = 5,
+    kDNSSDType_SOA       = 6,
+    kDNSSDType_MB        = 7,
+    kDNSSDType_MG        = 8,
+    kDNSSDType_MR        = 9,
+    kDNSSDType_NULL      = 10,
+    kDNSSDType_WKS       = 11,
+    kDNSSDType_PTR       = 12,
+    kDNSSDType_HINFO     = 13,
+    kDNSSDType_MINFO     = 14,
+    kDNSSDType_MX        = 15,
+    kDNSSDType_TXT       = 16,
+    kDNSSDType_RP        = 17,
+    kDNSSDType_AFSDB     = 18,
+    kDNSSDType_X25       = 19,
+    kDNSSDType_ISDN      = 20,
+    kDNSSDType_RT        = 21,
+    kDNSSDType_NSAP      = 22,
+    kDNSSDType_NSAP_PTR  = 23,
+    kDNSSDType_SIG       = 24,
+    kDNSSDType_KEY       = 25,
+    kDNSSDType_PX        = 26,
+    kDNSSDType_GPOS      = 27,
+    kDNSSDType_AAAA      = 28,
+    kDNSSDType_LOC       = 29,
+    kDNSSDType_NXT       = 30,
+    kDNSSDType_EID       = 31,
+    kDNSSDType_NIMLOC    = 32,
+    kDNSSDType_SRV       = 33,
+    kDNSSDType_ATMA      = 34,
+    kDNSSDType_NAPTR     = 35,
+    kDNSSDType_KX        = 36,
+    kDNSSDType_CERT      = 37,
+    kDNSSDType_A6        = 38,
+    kDNSSDType_DNAME     = 39,
+    kDNSSDType_SINK      = 40,
+    kDNSSDType_OPT       = 41,
+    kDNSSDType_APL       = 42,
+    kDNSSDType_DS        = 43,
+    kDNSSDType_SSHFP     = 44,
+    kDNSSDType_IPSECKEY  = 45,
+    kDNSSDType_RRSIG     = 46,
+    kDNSSDType_NSEC      = 47,
+    kDNSSDType_DNSKEY    = 48,
+    kDNSSDType_DHCID     = 49,
+    kDNSSDType_NSEC3     = 50,
+    kDNSSDType_NSEC3PARAM= 51,
+    kDNSSDType_HIP       = 55,
+    kDNSSDType_SPF       = 99,
+    kDNSSDType_UINFO     = 100,
+    kDNSSDType_UID       = 101,
+    kDNSSDType_GID       = 102,
+    kDNSSDType_UNSPEC    = 103,
+    kDNSSDType_TKEY      = 249,
+    kDNSSDType_TSIG      = 250,
+    kDNSSDType_IXFR      = 251,
+    kDNSSDType_AXFR      = 252,
+    kDNSSDType_MAILB     = 253,
+    kDNSSDType_MAILA     = 254,
+    kDNSSDType_ANY       = 255\r
+} DNSSDRRType;\r
+\r
+\r
+typedef [ uuid(3B0059E7-5297-4301-9AAB-1522F31EC8A7) ]\r
+enum DNSSDError
+{
+       kDNSSDError_NoError                   = 0,
+       kDNSSDError_Unknown                   = -65537,
+       kDNSSDError_NoSuchName                = -65538,
+    kDNSSDError_NoMemory                  = -65539,
+    kDNSSDError_BadParam                  = -65540,
+    kDNSSDError_BadReference              = -65541,
+    kDNSSDError_BadState                  = -65542,
+    kDNSSDError_BadFlags                  = -65543,
+    kDNSSDError_Unsupported               = -65544,
+    kDNSSDError_NotInitialized            = -65545,
+    kDNSSDError_AlreadyRegistered         = -65547,
+    kDNSSDError_NameConflict              = -65548,
+    kDNSSDError_Invalid                   = -65549,
+    kDNSSDError_Firewall                  = -65550,
+    kDNSSDError_Incompatible              = -65551,
+    kDNSSDError_BadInterfaceIndex         = -65552,
+    kDNSSDError_Refused                   = -65553,
+    kDNSSDError_NoSuchRecord              = -65554,
+    kDNSSDError_NoAuth                    = -65555,
+    kDNSSDError_NoSuchKey                 = -65556,
+    kDNSSDError_NATTraversal              = -65557,
+    kDNSSDError_DoubleNAT                 = -65558,
+    kDNSSDError_BadTime                   = -65559,
+    kDNSSDError_BadSig                    = -65560,
+    kDNSSDError_BadKey                    = -65561,
+    kDNSSDError_Transient                 = -65562,
+    kDNSSDError_ServiceNotRunning         = -65563,  /* Background daemon not running */
+    kDNSSDError_NATPortMappingUnsupported = -65564,  /* NAT doesn't support NAT-PMP or UPnP */
+    kDNSSDError_NATPortMappingDisabled    = -65565,  /* NAT supports NAT-PMP or UPnP but it's disabled by the administrator */
+    kDNSSDError_NoRouter                  = -65566,  /* No router currently configured (probably no network connectivity) */
+    kDNSSDError_PollingMode               = -65567
+} DNSSDError;\r
+\r
+import "oaidl.idl";\r
+import "ocidl.idl";\r
+\r
+\r
+[\r
+       object,\r
+       uuid(8FA0889C-5973-4FC9-970B-EC15C925D0CE),\r
+       dual,\r
+       nonextensible,\r
+       helpstring("ITXTRecord Interface"),\r
+       pointer_default(unique)\r
+]\r
+interface ITXTRecord : IDispatch{\r
+       [id(1), helpstring("method SetValue")] HRESULT SetValue([in] BSTR key, [in] VARIANT value);\r
+       [id(2), helpstring("method RemoveValue")] HRESULT RemoveValue([in] BSTR key);\r
+       [id(3), helpstring("method ContainsKey")] HRESULT ContainsKey([in] BSTR key, [out,retval] VARIANT_BOOL* retval);\r
+       [id(4), helpstring("method GetValueForKey")] HRESULT GetValueForKey([in] BSTR key, [out,retval] VARIANT* value);\r
+       [id(5), helpstring("method GetCount")] HRESULT GetCount([out,retval] ULONG* count);\r
+       [id(6), helpstring("method GetKeyAtIndex")] HRESULT GetKeyAtIndex([in] ULONG index, [out,retval] BSTR* retval);\r
+       [id(7), helpstring("method GetValueAtIndex")] HRESULT GetValueAtIndex([in] ULONG index, [out,retval] VARIANT* retval);\r
+};\r
+[\r
+       object,\r
+       uuid(9CE603A0-3365-4DA0-86D1-3F780ECBA110),\r
+       dual,\r
+       nonextensible,\r
+       helpstring("IDNSSDRecord Interface"),\r
+       pointer_default(unique)\r
+]\r
+interface IDNSSDRecord : IDispatch{\r
+       [id(1), helpstring("method Update")] HRESULT Update([in] DNSSDFlags flags, [in] VARIANT rdata, [in] ULONG ttl);\r
+       [id(2), helpstring("method Remove")] HRESULT Remove([in] DNSSDFlags flags);\r
+};\r
+[\r
+       object,\r
+       uuid(7FD72324-63E1-45AD-B337-4D525BD98DAD),\r
+       dual,\r
+       nonextensible,\r
+       helpstring("IDNSSDEventManager Interface"),\r
+       pointer_default(unique)\r
+]\r
+interface IDNSSDEventManager : IDispatch{\r
+};\r
+[\r
+       object,\r
+       uuid(29DE265F-8402-474F-833A-D4653B23458F),\r
+       dual,\r
+       nonextensible,\r
+       helpstring("IDNSSDService Interface"),\r
+       pointer_default(unique)\r
+]\r
+interface IDNSSDService : IDispatch{\r
+       [id(1), helpstring("method EnumerateDomains")] HRESULT EnumerateDomains([in] DNSSDFlags flags, [in] ULONG ifIndex, [in] IDNSSDEventManager* eventManager, [out,retval] IDNSSDService** service);\r
+       [id(2), helpstring("method Browse"), local] HRESULT Browse([in] DNSSDFlags flags, [in] ULONG interfaceIndex, [in] BSTR regtype, [in] BSTR domain, [in] IDNSSDEventManager* eventManager, [out,retval] IDNSSDService** sdref);\r
+       [id(3), helpstring("method Resolve")] HRESULT Resolve([in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR serviceName, [in] BSTR regType, [in] BSTR domain, [in] IDNSSDEventManager* eventManager, [out,retval] IDNSSDService** service);\r
+       [id(4), helpstring("method Register")] HRESULT Register([in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR name, [in] BSTR regType, [in] BSTR domain, [in] BSTR host, [in] USHORT port, [in] ITXTRecord* record, [in] IDNSSDEventManager* eventManager, [out,retval] IDNSSDService** service);\r
+       [id(5), helpstring("method QueryRecord")] HRESULT QueryRecord([in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR fullname, [in] DNSSDRRType rrtype, [in] DNSSDRRClass rrclass, [in] IDNSSDEventManager* eventManager, [out,retval] IDNSSDService** service);\r
+       [id(6), helpstring("method RegisterRecord")] HRESULT RegisterRecord([in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR fullname, [in] DNSSDRRType rrtype, [in] DNSSDRRClass rrclass, [in] VARIANT rdata, [in] ULONG ttl, [in] IDNSSDEventManager* eventManager, [out,retval] IDNSSDRecord** record);\r
+       [id(7), helpstring("method AddRecord")] HRESULT AddRecord([in] DNSSDFlags flags, [in] DNSSDRRType rrtype, [in] VARIANT rdata, [in] ULONG ttl, [out,retval] IDNSSDRecord** record);\r
+       [id(8), helpstring("method ReconfirmRecord")] HRESULT ReconfirmRecord([in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR fullname, [in] DNSSDRRType rrtype, [in] DNSSDRRClass rrclass, [in] VARIANT rdata);\r
+       [id(9), helpstring("method GetProperty")] HRESULT GetProperty([in] BSTR prop, [in,out] VARIANT * value );       \r
+       [id(10), helpstring("method GetAddrInfo")] HRESULT GetAddrInfo([in] DNSSDFlags flags, [in] ULONG ifIndex, [in] DNSSDAddressFamily addressFamily, [in] BSTR hostname, [in] IDNSSDEventManager* eventManager, [out,retval] IDNSSDService** service);\r
+       [id(11), helpstring("method NATPortMappingCreate")] HRESULT NATPortMappingCreate([in] DNSSDFlags flags, [in] ULONG ifIndex, [in] DNSSDAddressFamily addressFamily, [in] DNSSDProtocol protocol, [in] USHORT internalPort, [in] USHORT externalPort, [in] ULONG ttl, [in] IDNSSDEventManager* eventManager, [out,retval] IDNSSDService** service);\r
+       [id(12), helpstring("method Stop"), local] HRESULT Stop(void);\r
+};\r
+[\r
+       uuid(18FBED6D-F2B7-4EC8-A4A4-46282E635308),\r
+       version(1.0),\r
+       helpstring("Apple Bonjour Library 1.0")\r
+]\r
+library Bonjour\r
+{\r
+       importlib("stdole2.tlb");\r
+       [\r
+               uuid(21AE8D7F-D5FE-45cf-B632-CFA2C2C6B498),\r
+               helpstring("_IDNSSDEvents Interface")\r
+       ]\r
+       dispinterface _IDNSSDEvents\r
+       {\r
+               properties:\r
+               methods:\r
+               [id(1), helpstring("method DomainFound")] void DomainFound([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR domain);\r
+               [id(2), helpstring("method DomainLost")] void DomainLost([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR domain);\r
+               [id(3), helpstring("method ServiceFound")] void ServiceFound([in] IDNSSDService* browser, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR serviceName, [in] BSTR regType, [in] BSTR domain);\r
+               [id(4), helpstring("method ServiceLost")] void ServiceLost([in] IDNSSDService* browser, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR serviceName, [in] BSTR regType, [in] BSTR domain);\r
+               [id(5), helpstring("method ServiceResolved")] void ServiceResolved([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR fullName, [in] BSTR hostName, [in] USHORT port, [in] ITXTRecord* record);\r
+               [id(6), helpstring("method ServiceRegistered")] void ServiceRegistered([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] BSTR name, [in] BSTR regType, [in] BSTR domain);\r
+               [id(7), helpstring("method QueryRecordAnswered")] void QueryRecordAnswered([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR fullName, [in] DNSSDRRType rrtype, [in] DNSSDRRClass rrclass, [in] VARIANT rdata, [in] ULONG ttl);\r
+               [id(8), helpstring("method RecordRegistered")] void RecordRegistered([in] IDNSSDRecord* record, [in] DNSSDFlags flags);\r
+               [id(9), helpstring("method AddressFound")] void AddressFound([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR hostname, [in] DNSSDAddressFamily addressFamily, [in] BSTR address, [in] ULONG ttl);\r
+               [id(10), helpstring("method MappingCreated")] void MappingCreated([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] ULONG externalAddress, [in] DNSSDAddressFamily addressFamily, [in] DNSSDProtocol protocol, [in] USHORT internalPort, [in] USHORT externalPort, [in] ULONG ttl);\r
+               [id(11), helpstring("method OperationFailed")] void OperationFailed([in] IDNSSDService* service, [in] DNSSDError error);\r
+       };\r
+       [\r
+               uuid(24CD4DE9-FF84-4701-9DC1-9B69E0D1090A),\r
+               helpstring("DNSSDService Class")\r
+       ]\r
+       coclass DNSSDService\r
+       {\r
+               [default] interface IDNSSDService;\r
+       };\r
+       [\r
+               uuid(AFEE063C-05BA-4248-A26E-168477F49734),\r
+               helpstring("TXTRecord Class")\r
+       ]\r
+       coclass TXTRecord\r
+       {\r
+               [default] interface ITXTRecord;\r
+       };\r
+       [\r
+               uuid(5E93C5A9-7516-4259-A67B-41A656F6E01C),\r
+               helpstring("DNSSDRecord Class")\r
+       ]\r
+       coclass DNSSDRecord\r
+       {\r
+               [default] interface IDNSSDRecord;\r
+       };\r
+       [\r
+               uuid(BEEB932A-8D4A-4619-AEFE-A836F988B221),\r
+               helpstring("DNSSDEventManager Class")\r
+       ]\r
+       coclass DNSSDEventManager\r
+       {\r
+               [default] interface IDNSSDEventManager;\r
+               [default, source] dispinterface _IDNSSDEvents;\r
+       };\r
+       enum DNSSDFlags;\r
+       enum DNSSDAddressFamily;\r
+       enum DNSSDProtocol;\r
+       enum DNSSDRRClass;\r
+       enum DNSSDRRType;\r
+       enum DNSSDError;\r
+};\r
diff --git a/mDNSWindows/DLLX/DLLX.rc b/mDNSWindows/DLLX/DLLX.rc
new file mode 100755 (executable)
index 0000000..4299b5a
--- /dev/null
@@ -0,0 +1,126 @@
+// Microsoft Visual C++ generated resource script.\r
+//\r
+#include "resource.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "winres.h"\r
+#include "WinVersRes.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE \r
+BEGIN\r
+    "resource.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE \r
+BEGIN\r
+    "#include ""winres.h""\r\n"\r
+    "#include ""WinVersRes.h""\r\n"\r
+    "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+    "1 TYPELIB ""BonjourLib.tlb""\r\n"\r
+    "\0"\r
+END\r
+\r
+#endif    // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION MASTER_PROD_VERS\r
+ PRODUCTVERSION MASTER_PROD_VERS\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x2L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+    BLOCK "StringFileInfo"\r
+    BEGIN\r
+        BLOCK "040904e4"\r
+        BEGIN\r
+            VALUE "CompanyName", MASTER_COMPANY_NAME\r
+            VALUE "FileDescription", "Bonjour COM Component Library"\r
+            VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+            VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+            VALUE "InternalName", "dnssdX.dll"\r
+            VALUE "OriginalFilename", "dnssdX.dll"\r
+            VALUE "ProductName", MASTER_PROD_NAME\r
+            VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
+        END\r
+    END\r
+    BLOCK "VarFileInfo"\r
+    BEGIN\r
+        VALUE "Translation", 0x409, 1252\r
+    END\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// REGISTRY\r
+//\r
+\r
+IDR_DLLX                       REGISTRY                "DLLX.rgs"\r
+IDR_DNSSDSERVICE        REGISTRY                "DNSSDService.rgs"\r
+IDR_TXTRECORD           REGISTRY                "TXTRecord.rgs"\r
+IDR_DNSSDRECORD         REGISTRY                "DNSSDRecord.rgs"\r
+IDR_DNSSDEVENTMANAGER   REGISTRY                "DNSSDEventManager.rgs"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// String Table\r
+//\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_PROJNAME            "BonjourLib"\r
+END\r
+\r
+#endif    // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+1 TYPELIB "dnssdX.tlb"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif    // not APSTUDIO_INVOKED\r
+\r
diff --git a/mDNSWindows/DLLX/DLLX.rgs b/mDNSWindows/DLLX/DLLX.rgs
new file mode 100755 (executable)
index 0000000..c55ee8d
--- /dev/null
@@ -0,0 +1,11 @@
+HKCR\r
+{\r
+       NoRemove AppID\r
+       {\r
+               '%APPID%' = s 'Bonjour'\r
+               'Bonjour.DLL'\r
+               {\r
+                       val AppID = s '%APPID%'\r
+               }\r
+       }\r
+}\r
diff --git a/mDNSWindows/DLLX/DLLX.vcproj b/mDNSWindows/DLLX/DLLX.vcproj
new file mode 100755 (executable)
index 0000000..04fe58b
--- /dev/null
@@ -0,0 +1,623 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="8.00"\r
+       Name="DLLX"\r
+       ProjectGUID="{78FBFCC5-2873-4AE2-9114-A08082F71124}"\r
+       RootNamespace="DLLX"\r
+       Keyword="AtlProj"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       UseOfATL="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="1"\r
+                               GenerateStublessProxies="true"\r
+                               TypeLibraryName="$(IntDir)/dnssdX.tlb"\r
+                               HeaderFileName="DLLX.h"\r
+                               DLLDataFileName=""\r
+                               InterfaceIdentifierFileName="DLLX_i.c"\r
+                               ProxyFileName="DLLX_p.c"\r
+                               ValidateParameters="false"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL;_MERGE_PROXYSTUB;DEBUG=1;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="..;&quot;$(IntDir)&quot;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               RegisterOutput="true"\r
+                               IgnoreImportLibrary="true"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="ws2_32.lib ../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib"\r
+                               OutputFile="$(OutDir)\dnssdX.dll"\r
+                               LinkIncremental="2"\r
+                               ModuleDefinitionFile=".\DLLX.def"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="2"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       UseOfATL="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                               GenerateStublessProxies="true"\r
+                               TypeLibraryName="$(IntDir)/dnssdX.tlb"\r
+                               HeaderFileName="DLLX.h"\r
+                               DLLDataFileName=""\r
+                               InterfaceIdentifierFileName="DLLX_i.c"\r
+                               ProxyFileName="DLLX_p.c"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL;_MERGE_PROXYSTUB;DEBUG=1;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="..;&quot;$(IntDir)&quot;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               RegisterOutput="true"\r
+                               IgnoreImportLibrary="true"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="ws2_32.lib ../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib"\r
+                               OutputFile="$(OutDir)\dnssdX.dll"\r
+                               LinkIncremental="2"\r
+                               ModuleDefinitionFile=".\DLLX.def"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="2"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       UseOfATL="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="1"\r
+                               GenerateStublessProxies="true"\r
+                               TypeLibraryName="$(IntDir)/dnssdX.tlb"\r
+                               HeaderFileName="DLLX.h"\r
+                               DLLDataFileName=""\r
+                               InterfaceIdentifierFileName="DLLX_i.c"\r
+                               ProxyFileName="DLLX_p.c"\r
+                               ValidateParameters="false"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL;_MERGE_PROXYSTUB;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               RuntimeLibrary="0"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="..;&quot;$(IntDir)&quot;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               RegisterOutput="true"\r
+                               IgnoreImportLibrary="true"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="ws2_32.lib ../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib"\r
+                               OutputFile="$(OutDir)\dnssdX.dll"\r
+                               LinkIncremental="1"\r
+                               ModuleDefinitionFile=".\DLLX.def"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       UseOfATL="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="false"\r
+                               TargetEnvironment="3"\r
+                               GenerateStublessProxies="true"\r
+                               TypeLibraryName="$(IntDir)/dnssdX.tlb"\r
+                               HeaderFileName="DLLX.h"\r
+                               DLLDataFileName=""\r
+                               InterfaceIdentifierFileName="DLLX_i.c"\r
+                               ProxyFileName="DLLX_p.c"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL;_MERGE_PROXYSTUB;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               RuntimeLibrary="0"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                               AdditionalIncludeDirectories="..;&quot;$(IntDir)&quot;"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               RegisterOutput="true"\r
+                               IgnoreImportLibrary="true"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="ws2_32.lib ../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib"\r
+                               OutputFile="$(OutDir)\dnssdX.dll"\r
+                               LinkIncremental="1"\r
+                               ModuleDefinitionFile=".\DLLX.def"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\dlldatax.c"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DLLX.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DLLX.def"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DLLX.idl"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DNSSDEventManager.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DNSSDRecord.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DNSSDService.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\TXTRecord.cpp"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\_IDNSSDEvents_CP.H"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\dlldatax.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DNSSDEventManager.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DNSSDRecord.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DNSSDService.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\Resource.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\stdafx.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\TXTRecord.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\DLLX.rc"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DLLX.rgs"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DNSSDEventManager.rgs"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DNSSDRecord.rgs"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DNSSDService.rgs"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\TXTRecord.rgs"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Generated Files"\r
+                       SourceControlFiles="false"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\DLLX.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DLLX_i.c"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Support Files"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\CommonServices.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\DebugServices.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\DebugServices.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\StringServices.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\StringServices.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/mDNSWindows/DLLX/DNSSD.cpp b/mDNSWindows/DLLX/DNSSD.cpp
new file mode 100755 (executable)
index 0000000..84a8206
--- /dev/null
@@ -0,0 +1,892 @@
+// DNSSD.cpp : Implementation of CDNSSD\r
+\r
+#include "stdafx.h"\r
+#include "DNSSD.h"\r
+#include "DNSSDService.h"\r
+#include "TXTRecord.h"\r
+#include <dns_sd.h>\r
+#include <CommonServices.h>\r
+#include <DebugServices.h>\r
+#include "StringServices.h"\r
+\r
+\r
+// CDNSSD\r
+\r
+STDMETHODIMP CDNSSD::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IBrowseListener* listener, IDNSSDService** browser )\r
+{\r
+       CComObject<CDNSSDService>       *       object          = NULL;\r
+       std::string                                             regtypeUTF8;\r
+       std::string                                             domainUTF8;\r
+       DNSServiceRef                                   sref            = NULL;\r
+       DNSServiceErrorType                             err                     = 0;\r
+       HRESULT                                                 hr                      = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *browser = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( regtype, regtypeUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( domain, domainUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceBrowse( &sref, flags, ifIndex, regtypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceBrowseReply ) &BrowseReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *browser = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IResolveListener* listener, IDNSSDService** service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       std::string                                             serviceNameUTF8;\r
+       std::string                                             regTypeUTF8;\r
+       std::string                                             domainUTF8;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( serviceName, serviceNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( regType, regTypeUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( domain, domainUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceResolve( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDomainListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceEnumerateDomains( &sref, flags, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IRegisterListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       std::string                                             serviceNameUTF8;\r
+       std::string                                             regTypeUTF8;\r
+       std::string                                             domainUTF8;\r
+       std::string                                             hostUTF8;\r
+       const void                                      *       txtRecord               = NULL;\r
+       uint16_t                                                txtLen                  = 0;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( serviceName, serviceNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( regType, regTypeUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( domain, domainUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( host, hostUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       if ( record )\r
+       {\r
+               CComObject< CTXTRecord > * realTXTRecord;\r
+\r
+               realTXTRecord = ( CComObject< CTXTRecord >* ) record;\r
+\r
+               txtRecord       = realTXTRecord->GetBytes();\r
+               txtLen          = realTXTRecord->GetLen();\r
+       }\r
+\r
+       err = DNSServiceRegister( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), hostUTF8.c_str(), port, txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IQueryRecordListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       std::string                                             fullNameUTF8;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( fullname, fullNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceQueryRecord( &sref, flags, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IGetAddrInfoListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       std::string                                             hostNameUTF8;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( hostName, hostNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceGetAddrInfo( &sref, flags, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::CreateConnection(IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object  = NULL;\r
+       DNSServiceRef                                   sref    = NULL;\r
+       DNSServiceErrorType                             err             = 0;\r
+       HRESULT                                                 hr              = 0;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceCreateConnection( &sref );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, INATPortMappingListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       DNSServiceProtocol                              prot                    = 0;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       prot = ( addressFamily | protocol );\r
+\r
+       err = DNSServiceNATPortMappingCreate( &sref, flags, ifIndex, prot, internalPort, externalPort, ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::GetProperty(BSTR prop, VARIANT * value )\r
+{\r
+       std::string                     propUTF8;\r
+       std::vector< BYTE >     byteArray;\r
+       SAFEARRAY               *       psa                     = NULL;\r
+       BYTE                    *       pData           = NULL;\r
+       uint32_t                        elems           = 0;\r
+       DNSServiceErrorType     err                     = 0;\r
+       BOOL                            ok = TRUE;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( prop, propUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       // Setup the byte array\r
+       require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );\r
+       psa = V_ARRAY( value );\r
+       require_action( psa, exit, err = kDNSServiceErr_Unknown );\r
+       require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );\r
+       byteArray.reserve( psa->rgsabound[0].cElements );\r
+       byteArray.assign( byteArray.capacity(), 0 );\r
+       elems = ( uint32_t ) byteArray.capacity();\r
+\r
+       // Call the function and package the return value in the Variant\r
+       err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );\r
+       require_noerr( err, exit );\r
+       ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );\r
+       require_action( ok, exit, err = kDNSSDError_Unknown );\r
+\r
+exit:\r
+\r
+       if ( psa )\r
+       {\r
+               SafeArrayUnaccessData( psa );\r
+               psa = NULL;\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::DomainEnumReply
+    (
+    DNSServiceRef                       sdRef,
+    DNSServiceFlags                     flags,
+    uint32_t                            ifIndex,
+    DNSServiceErrorType                 errorCode,
+    const char                          *replyDomainUTF8,
+    void                                *context
+    )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IDomainListener * listener;\r
+\r
+               listener = ( IDomainListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR replyDomain;\r
+               \r
+                       UTF8ToBSTR( replyDomainUTF8, replyDomain );\r
+\r
+                       if ( flags & kDNSServiceFlagsAdd )\r
+                       {\r
+                               listener->DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );\r
+                       }\r
+                       else\r
+                       {\r
+                               listener->DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       listener->EnumDomainsFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::BrowseReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            ifIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *serviceNameUTF8,
+               const char                          *regTypeUTF8,
+               const char                          *replyDomainUTF8,
+               void                                *context
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IBrowseListener * listener;\r
+\r
+               listener = ( IBrowseListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR        serviceName;\r
+                       CComBSTR        regType;\r
+                       CComBSTR        replyDomain;\r
+               \r
+                       UTF8ToBSTR( serviceNameUTF8, serviceName );\r
+                       UTF8ToBSTR( regTypeUTF8, regType );\r
+                       UTF8ToBSTR( replyDomainUTF8, replyDomain );\r
+\r
+                       if ( flags & kDNSServiceFlagsAdd )\r
+                       {\r
+                               listener->ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );\r
+                       }\r
+                       else\r
+                       {\r
+                               listener->ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       listener->BrowseFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API\r
+CDNSSD::ResolveReply\r
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            ifIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *fullNameUTF8,
+               const char                          *hostNameUTF8,
+               uint16_t                            port,
+               uint16_t                            txtLen,
+               const unsigned char                 *txtRecord,
+               void                                *context\r
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IResolveListener * listener;\r
+\r
+               listener = ( IResolveListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR                                        fullName;\r
+                       CComBSTR                                        hostName;\r
+                       CComBSTR                                        regType;\r
+                       CComBSTR                                        replyDomain;\r
+                       CComObject< CTXTRecord >*       record;\r
+                       BOOL                                            ok;\r
+\r
+                       ok = UTF8ToBSTR( fullNameUTF8, fullName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+                       ok = UTF8ToBSTR( hostNameUTF8, hostName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       try\r
+                       {\r
+                               record = new CComObject<CTXTRecord>();\r
+                       }\r
+                       catch ( ... )\r
+                       {\r
+                               record = NULL;\r
+                       }\r
+\r
+                       require_action( record, exit, err = kDNSServiceErr_NoMemory );\r
+                       record->AddRef();\r
+\r
+                       char buf[ 64 ];\r
+                       sprintf( buf, "txtLen = %d", txtLen );\r
+                       OutputDebugStringA( buf );\r
+\r
+                       if ( txtLen > 0 )\r
+                       {\r
+                               record->SetBytes( txtRecord, txtLen );\r
+                       }\r
+\r
+                       listener->ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, port, record );\r
+               }\r
+               else\r
+               {\r
+                       listener->ResolveFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::RegisterReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               DNSServiceErrorType                 errorCode,
+               const char                          *serviceNameUTF8,
+               const char                          *regTypeUTF8,
+               const char                          *domainUTF8,
+               void                                *context
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IRegisterListener * listener;\r
+\r
+               listener = ( IRegisterListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR                                        serviceName;\r
+                       CComBSTR                                        regType;\r
+                       CComBSTR                                        domain;\r
+                       BOOL                                            ok;\r
+\r
+                       ok = UTF8ToBSTR( serviceNameUTF8, serviceName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+                       ok = UTF8ToBSTR( regTypeUTF8, regType );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+                       ok = UTF8ToBSTR( domainUTF8, domain );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       listener->ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );\r
+               }\r
+               else\r
+               {\r
+                       listener->ServiceRegisterFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::QueryRecordReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            ifIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *fullNameUTF8,
+               uint16_t                            rrtype,
+               uint16_t                            rrclass,
+               uint16_t                            rdlen,
+               const void                          *rdata,
+               uint32_t                            ttl,
+               void                                *context
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IQueryRecordListener * listener;\r
+\r
+               listener = ( IQueryRecordListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR        fullName;\r
+                       VARIANT         var;\r
+                       BOOL            ok;\r
+\r
+                       ok = UTF8ToBSTR( fullNameUTF8, fullName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+                       ok = ByteArrayToVariant( rdata, rdlen, &var );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       listener->QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );\r
+               }\r
+               else\r
+               {\r
+                       listener->QueryRecordFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::GetAddrInfoReply
+               (
+               DNSServiceRef                    sdRef,
+               DNSServiceFlags                  flags,
+               uint32_t                         ifIndex,
+               DNSServiceErrorType              errorCode,
+               const char                       *hostNameUTF8,
+               const struct sockaddr            *rawAddress,
+               uint32_t                         ttl,
+               void                             *context
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IGetAddrInfoListener * listener;\r
+\r
+               listener = ( IGetAddrInfoListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR                        hostName;\r
+                       DWORD                           sockaddrLen;\r
+                       DNSSDAddressFamily      addressFamily;\r
+                       char                            addressUTF8[INET6_ADDRSTRLEN];\r
+                       DWORD                           addressLen = sizeof( addressUTF8 );\r
+                       CComBSTR                        address;\r
+                       BOOL                            ok;\r
+\r
+                       ok = UTF8ToBSTR( hostNameUTF8, hostName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       switch ( rawAddress->sa_family )\r
+                       {\r
+                               case AF_INET:\r
+                               {\r
+                                       addressFamily   = kDNSSDAddressFamily_IPv4;\r
+                                       sockaddrLen             = sizeof( sockaddr_in );\r
+                               }\r
+                               break;\r
+\r
+                               case AF_INET6:\r
+                               {\r
+                                       addressFamily   = kDNSSDAddressFamily_IPv6;\r
+                                       sockaddrLen             = sizeof( sockaddr_in6 );\r
+                               }\r
+                               break;\r
+                       }\r
+\r
+                       err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );\r
+                       require_noerr( err, exit );\r
+                       ok = UTF8ToBSTR( addressUTF8, address );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       listener->GetAddrInfoReply( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );\r
+               }\r
+               else\r
+               {\r
+                       listener->GetAddrInfoFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::NATPortMappingReply
+    (
+    DNSServiceRef                    sdRef,
+    DNSServiceFlags                  flags,
+    uint32_t                         ifIndex,
+    DNSServiceErrorType              errorCode,
+    uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
+    DNSServiceProtocol               protocol,
+    uint16_t                         internalPort,
+    uint16_t                         externalPort,      /* may be different than the requested port     */
+    uint32_t                         ttl,               /* may be different than the requested ttl      */
+    void                             *context
+    )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               INATPortMappingListener * listener;\r
+\r
+               listener = ( INATPortMappingListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       listener->MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), internalPort, externalPort, ttl  );\r
+               }\r
+               else\r
+               {\r
+                       listener->MappingFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
diff --git a/mDNSWindows/DLLX/DNSSDEventManager.cpp b/mDNSWindows/DLLX/DNSSDEventManager.cpp
new file mode 100755 (executable)
index 0000000..af3248c
--- /dev/null
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: DNSSDEventManager.cpp,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#include "stdafx.h"\r
+#include "DNSSDEventManager.h"\r
+\r
+\r
+// CDNSSDEventManager\r
+\r
diff --git a/mDNSWindows/DLLX/DNSSDEventManager.h b/mDNSWindows/DLLX/DNSSDEventManager.h
new file mode 100755 (executable)
index 0000000..3e43b2e
--- /dev/null
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: DNSSDEventManager.h,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#pragma once\r
+#include "resource.h"       // main symbols\r
+\r
+#include "DLLX.h"\r
+#include "_IDNSSDEvents_CP.H"\r
+\r
+\r
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)\r
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."\r
+#endif\r
+\r
+\r
+\r
+// CDNSSDEventManager\r
+\r
+class ATL_NO_VTABLE CDNSSDEventManager :\r
+       public CComObjectRootEx<CComSingleThreadModel>,\r
+       public CComCoClass<CDNSSDEventManager, &CLSID_DNSSDEventManager>,\r
+       public IConnectionPointContainerImpl<CDNSSDEventManager>,\r
+       public CProxy_IDNSSDEvents<CDNSSDEventManager>,\r
+       public IDispatchImpl<IDNSSDEventManager, &IID_IDNSSDEventManager, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>\r
+{\r
+public:\r
+       CDNSSDEventManager()\r
+       {\r
+       }\r
+\r
+DECLARE_REGISTRY_RESOURCEID(IDR_DNSSDEVENTMANAGER)\r
+\r
+\r
+BEGIN_COM_MAP(CDNSSDEventManager)\r
+       COM_INTERFACE_ENTRY(IDNSSDEventManager)\r
+       COM_INTERFACE_ENTRY(IDispatch)\r
+       COM_INTERFACE_ENTRY(IConnectionPointContainer)\r
+END_COM_MAP()\r
+\r
+BEGIN_CONNECTION_POINT_MAP(CDNSSDEventManager)\r
+       CONNECTION_POINT_ENTRY(__uuidof(_IDNSSDEvents))\r
+END_CONNECTION_POINT_MAP()\r
+\r
+\r
+       DECLARE_PROTECT_FINAL_CONSTRUCT()\r
+\r
+       HRESULT FinalConstruct()\r
+       {\r
+               return S_OK;\r
+       }\r
+\r
+       void FinalRelease()\r
+       {\r
+       }\r
+\r
+public:\r
+\r
+};\r
+\r
+OBJECT_ENTRY_AUTO(__uuidof(DNSSDEventManager), CDNSSDEventManager)\r
diff --git a/mDNSWindows/DLLX/DNSSDEventManager.rgs b/mDNSWindows/DLLX/DNSSDEventManager.rgs
new file mode 100755 (executable)
index 0000000..9103512
--- /dev/null
@@ -0,0 +1,27 @@
+HKCR\r
+{\r
+       Bonjour.DNSSDEventManager.1 = s 'DNSSDEventManager Class'\r
+       {\r
+               CLSID = s '{BEEB932A-8D4A-4619-AEFE-A836F988B221}'\r
+       }\r
+       Bonjour.DNSSDEventManager = s 'DNSSDEventManager Class'\r
+       {\r
+               CLSID = s '{BEEB932A-8D4A-4619-AEFE-A836F988B221}'\r
+               CurVer = s 'Bonjour.DNSSDEventManager.1'\r
+       }\r
+       NoRemove CLSID\r
+       {\r
+               ForceRemove {BEEB932A-8D4A-4619-AEFE-A836F988B221} = s 'DNSSDEventManager Class'\r
+               {\r
+                       ProgID = s 'Bonjour.DNSSDEventManager.1'\r
+                       VersionIndependentProgID = s 'Bonjour.DNSSDEventManager'\r
+                       ForceRemove 'Programmable'\r
+                       InprocServer32 = s '%MODULE%'\r
+                       {\r
+                               val ThreadingModel = s 'Apartment'\r
+                       }\r
+                       val AppID = s '%APPID%'\r
+                       'TypeLib' = s '{18FBED6D-F2B7-4EC8-A4A4-46282E635308}'\r
+               }\r
+       }\r
+}\r
diff --git a/mDNSWindows/DLLX/DNSSDRecord.cpp b/mDNSWindows/DLLX/DNSSDRecord.cpp
new file mode 100755 (executable)
index 0000000..37955af
--- /dev/null
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: DNSSDRecord.cpp,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#include "stdafx.h"\r
+#include "DNSSDRecord.h"\r
+#include "StringServices.h"\r
+#include <DebugServices.h>\r
+\r
+\r
+// CDNSSDRecord\r
+\r
+STDMETHODIMP CDNSSDRecord::Update(DNSSDFlags flags, VARIANT rdata, ULONG ttl)\r
+{\r
+       std::vector< BYTE >     byteArray;\r
+       const void              *       byteArrayPtr    = NULL;\r
+       DNSServiceErrorType     err                             = 0;\r
+       HRESULT                         hr                              = 0;\r
+       BOOL                            ok;\r
+\r
+       // Convert the VARIANT\r
+       ok = VariantToByteArray( &rdata, byteArray );\r
+       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       err = DNSServiceUpdateRecord( m_serviceObject->GetSubordRef(), m_rref, flags, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl );\r
+       require_noerr( err, exit );\r
+\r
+exit:\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDRecord::Remove(DNSSDFlags flags)\r
+{\r
+       DNSServiceErrorType     err = 0;\r
+\r
+       err = DNSServiceRemoveRecord( m_serviceObject->GetSubordRef(), m_rref, flags );\r
+       require_noerr( err, exit );\r
+\r
+exit:\r
+\r
+       return err;\r
+}\r
+\r
diff --git a/mDNSWindows/DLLX/DNSSDRecord.h b/mDNSWindows/DLLX/DNSSDRecord.h
new file mode 100755 (executable)
index 0000000..fcf5c74
--- /dev/null
@@ -0,0 +1,108 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: DNSSDRecord.h,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#pragma once\r
+#include "resource.h"       // main symbols\r
+\r
+#include "DLLX.h"\r
+#include "DNSSDService.h"\r
+#include <dns_sd.h>\r
+\r
+\r
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)\r
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."\r
+#endif\r
+\r
+\r
+\r
+// CDNSSDRecord\r
+\r
+class ATL_NO_VTABLE CDNSSDRecord :\r
+       public CComObjectRootEx<CComSingleThreadModel>,\r
+       public CComCoClass<CDNSSDRecord, &CLSID_DNSSDRecord>,\r
+       public IDispatchImpl<IDNSSDRecord, &IID_IDNSSDRecord, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>\r
+{\r
+public:\r
+       CDNSSDRecord()\r
+       {\r
+       }\r
+\r
+DECLARE_REGISTRY_RESOURCEID(IDR_DNSSDRECORD)\r
+\r
+\r
+BEGIN_COM_MAP(CDNSSDRecord)\r
+       COM_INTERFACE_ENTRY(IDNSSDRecord)\r
+       COM_INTERFACE_ENTRY(IDispatch)\r
+END_COM_MAP()\r
+\r
+\r
+\r
+       DECLARE_PROTECT_FINAL_CONSTRUCT()\r
+\r
+       HRESULT FinalConstruct()\r
+       {\r
+               return S_OK;\r
+       }\r
+\r
+       void FinalRelease()\r
+       {\r
+       }\r
+\r
+       inline CDNSSDService*\r
+       GetServiceObject()\r
+       {\r
+               return m_serviceObject;\r
+       }\r
+\r
+       inline void\r
+       SetServiceObject( CDNSSDService * serviceObject )\r
+       {\r
+               m_serviceObject = serviceObject;\r
+       }\r
+\r
+       inline DNSRecordRef\r
+       GetRecordRef()\r
+       {\r
+               return m_rref;\r
+       }\r
+\r
+       inline void\r
+       SetRecordRef( DNSRecordRef rref )\r
+       {\r
+               m_rref = rref;\r
+       }\r
+\r
+public:\r
+\r
+       STDMETHOD(Update)(DNSSDFlags flags, VARIANT rdata, ULONG ttl);\r
+       STDMETHOD(Remove)(DNSSDFlags flags);\r
+\r
+private:\r
+\r
+       CDNSSDService * m_serviceObject;\r
+       DNSRecordRef    m_rref;\r
+};\r
+\r
+OBJECT_ENTRY_AUTO(__uuidof(DNSSDRecord), CDNSSDRecord)\r
diff --git a/mDNSWindows/DLLX/DNSSDRecord.rgs b/mDNSWindows/DLLX/DNSSDRecord.rgs
new file mode 100755 (executable)
index 0000000..ee0a5a2
--- /dev/null
@@ -0,0 +1,27 @@
+HKCR\r
+{\r
+       Bonjour.DNSSDRecord.1 = s 'DNSSDRecord Class'\r
+       {\r
+               CLSID = s '{5E93C5A9-7516-4259-A67B-41A656F6E01C}'\r
+       }\r
+       Bonjour.DNSSDRecord = s 'DNSSDRecord Class'\r
+       {\r
+               CLSID = s '{5E93C5A9-7516-4259-A67B-41A656F6E01C}'\r
+               CurVer = s 'Bonjour.DNSSDRecord.1'\r
+       }\r
+       NoRemove CLSID\r
+       {\r
+               ForceRemove {5E93C5A9-7516-4259-A67B-41A656F6E01C} = s 'DNSSDRecord Class'\r
+               {\r
+                       ProgID = s 'Bonjour.DNSSDRecord.1'\r
+                       VersionIndependentProgID = s 'Bonjour.DNSSDRecord'\r
+                       ForceRemove 'Programmable'\r
+                       InprocServer32 = s '%MODULE%'\r
+                       {\r
+                               val ThreadingModel = s 'Apartment'\r
+                       }\r
+                       val AppID = s '%APPID%'\r
+                       'TypeLib' = s '{18FBED6D-F2B7-4EC8-A4A4-46282E635308}'\r
+               }\r
+       }\r
+}\r
diff --git a/mDNSWindows/DLLX/DNSSDService.cpp b/mDNSWindows/DLLX/DNSSDService.cpp
new file mode 100755 (executable)
index 0000000..219c610
--- /dev/null
@@ -0,0 +1,1106 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: DNSSDService.cpp,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#pragma warning(disable:4995)\r
+\r
+#include "stdafx.h"\r
+#include <strsafe.h>\r
+#include "DNSSDService.h"\r
+#include "DNSSDEventManager.h"\r
+#include "DNSSDRecord.h"\r
+#include "TXTRecord.h"\r
+#include "StringServices.h"\r
+#include <DebugServices.h>\r
+\r
+\r
+#define WM_SOCKET (WM_APP + 100)\r
+\r
+\r
+// CDNSSDService\r
+\r
+BOOL                                           CDNSSDService::m_registeredWindowClass  = FALSE;\r
+HWND                                           CDNSSDService::m_hiddenWindow                   = NULL;\r
+CDNSSDService::SocketMap       CDNSSDService::m_socketMap;\r
+\r
+\r
+HRESULT CDNSSDService::FinalConstruct()\r
+{\r
+       DNSServiceErrorType     err     = 0;\r
+       HRESULT                         hr      = S_OK;\r
+\r
+       m_isPrimary = TRUE;\r
+       err = DNSServiceCreateConnection( &m_primary );\r
+       require_action( !err, exit, hr = E_FAIL );\r
+\r
+       if ( !m_hiddenWindow )\r
+       {\r
+               TCHAR windowClassName[ 256 ];\r
+\r
+               StringCchPrintf( windowClassName, sizeof( windowClassName ) / sizeof( TCHAR ), TEXT( "Bonjour Hidden Window %d" ), GetProcessId( NULL ) );\r
+\r
+               if ( !m_registeredWindowClass )\r
+               {\r
+                       WNDCLASS        wc;\r
+                       ATOM            atom;\r
+\r
+                       wc.style                        = 0;\r
+                       wc.lpfnWndProc          = WndProc;\r
+                       wc.cbClsExtra           = 0;\r
+                       wc.cbWndExtra           = 0;\r
+                       wc.hInstance            = NULL;\r
+                       wc.hIcon                        = NULL;\r
+                       wc.hCursor                      = NULL;\r
+                       wc.hbrBackground        = NULL;\r
+                       wc.lpszMenuName         = NULL;\r
+                       wc.lpszClassName        = windowClassName;\r
+\r
+                       atom = RegisterClass(&wc);\r
+                       require_action( atom != NULL, exit, hr = E_FAIL );\r
+\r
+                       m_registeredWindowClass = TRUE;\r
+               }\r
+\r
+               m_hiddenWindow = CreateWindow( windowClassName, windowClassName, WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandle( NULL ), NULL );\r
+               require_action( m_hiddenWindow != NULL, exit, hr = E_FAIL );\r
+       }\r
+\r
+       err = WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, WM_SOCKET, FD_READ );\r
+       require_action( !err, exit, hr = E_FAIL );\r
+\r
+       m_socketMap[ DNSServiceRefSockFD( m_primary ) ] = this;\r
+\r
+exit:\r
+\r
+       return hr;\r
+}\r
+\r
+\r
+void CDNSSDService::FinalRelease()\r
+{\r
+       dlog( kDebugLevelTrace, "FinalRelease()\n" ); \r
+       Stop();\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object  = NULL;\r
+       DNSServiceRef                                   subord  = NULL;\r
+       DNSServiceErrorType                             err             = 0;\r
+       HRESULT                                                 hr              = 0;\r
+\r
+       check( m_primary );\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       object->AddRef();\r
+\r
+       subord = m_primary;\r
+       err = DNSServiceEnumerateDomains( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetPrimaryRef( m_primary );\r
+       object->SetSubordRef( subord );\r
+       object->SetEventManager( eventManager );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service )\r
+{\r
+       CComObject<CDNSSDService>       *       object          = NULL;\r
+       std::string                                             regtypeUTF8;\r
+       std::string                                             domainUTF8;\r
+       DNSServiceRef                                   subord          = NULL;\r
+       DNSServiceErrorType                             err                     = 0;\r
+       HRESULT                                                 hr                      = 0;\r
+       BOOL                                                    ok;\r
+\r
+       check( m_primary );\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( regtype, regtypeUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( domain, domainUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       object->AddRef();\r
+\r
+       subord = m_primary;\r
+       err = DNSServiceBrowse( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, regtypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, ( DNSServiceBrowseReply ) &BrowseReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetPrimaryRef( m_primary );\r
+       object->SetSubordRef( subord );\r
+       object->SetEventManager( eventManager );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       std::string                                             serviceNameUTF8;\r
+       std::string                                             regTypeUTF8;\r
+       std::string                                             domainUTF8;\r
+       DNSServiceRef                                   subord                  = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       check( m_primary );\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( serviceName, serviceNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( regType, regTypeUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( domain, domainUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       object->AddRef();\r
+\r
+       subord = m_primary;\r
+       err = DNSServiceResolve( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetPrimaryRef( m_primary );\r
+       object->SetSubordRef( subord );\r
+       object->SetEventManager( eventManager );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       std::string                                             serviceNameUTF8;\r
+       std::string                                             regTypeUTF8;\r
+       std::string                                             domainUTF8;\r
+       std::string                                             hostUTF8;\r
+       const void                                      *       txtRecord               = NULL;\r
+       uint16_t                                                txtLen                  = 0;\r
+       DNSServiceRef                                   subord                  = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       check( m_primary );\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( serviceName, serviceNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( regType, regTypeUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( domain, domainUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( host, hostUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       object->AddRef();\r
+\r
+       if ( record )\r
+       {\r
+               CComObject< CTXTRecord > * realTXTRecord;\r
+\r
+               realTXTRecord = ( CComObject< CTXTRecord >* ) record;\r
+\r
+               txtRecord       = realTXTRecord->GetBytes();\r
+               txtLen          = realTXTRecord->GetLen();\r
+       }\r
+\r
+       subord = m_primary;\r
+       err = DNSServiceRegister( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, hostUTF8.c_str(), htons( port ), txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetPrimaryRef( m_primary );\r
+       object->SetSubordRef( subord );\r
+       object->SetEventManager( eventManager );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   subord                  = NULL;\r
+       std::string                                             fullNameUTF8;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       check( m_primary );\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( fullname, fullNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       object->AddRef();\r
+\r
+       subord = m_primary;\r
+       err = DNSServiceQueryRecord( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetPrimaryRef( m_primary );\r
+       object->SetSubordRef( subord );\r
+       object->SetEventManager( eventManager );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::RegisterRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record)\r
+{\r
+       CComObject<CDNSSDRecord>        *       object                  = NULL;\r
+       DNSRecordRef                                    rref                    = NULL;\r
+       std::string                                             fullNameUTF8;\r
+       std::vector< BYTE >                             byteArray;\r
+       const void                                      *       byteArrayPtr    = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       check( m_primary );\r
+\r
+       // Initialize\r
+       *object = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( fullName, fullNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       // Convert the VARIANT\r
+       ok = VariantToByteArray( &rdata, byteArray );\r
+       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDRecord>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceRegisterRecord( m_primary, &rref, flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl, &RegisterRecordReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceObject( this );\r
+       object->SetRecordRef( rref );\r
+       this->SetEventManager( eventManager );\r
+\r
+       *record = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::AddRecord(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record)\r
+{\r
+       CComObject<CDNSSDRecord>        *       object                  = NULL;\r
+       DNSRecordRef                                    rref                    = NULL;\r
+       std::vector< BYTE >                             byteArray;\r
+       const void                                      *       byteArrayPtr    = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       check( m_primary );\r
+\r
+       // Initialize\r
+       *object = NULL;\r
+\r
+       // Convert the VARIANT\r
+       ok = VariantToByteArray( &rdata, byteArray );\r
+       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDRecord>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceAddRecord( m_primary, &rref, flags, rrtype, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceObject( this );\r
+       object->SetRecordRef( rref );\r
+\r
+       *record = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+STDMETHODIMP CDNSSDService::ReconfirmRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata)\r
+{\r
+       std::string                                             fullNameUTF8;\r
+       std::vector< BYTE >                             byteArray;\r
+       const void                                      *       byteArrayPtr    = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( fullName, fullNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       // Convert the VARIANT\r
+       ok = VariantToByteArray( &rdata, byteArray );\r
+       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       err = DNSServiceReconfirmRecord( flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL );\r
+       require_noerr( err, exit );\r
+\r
+exit:\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::GetProperty(BSTR prop, VARIANT * value )\r
+{\r
+       std::string                     propUTF8;\r
+       std::vector< BYTE >     byteArray;\r
+       SAFEARRAY               *       psa                     = NULL;\r
+       BYTE                    *       pData           = NULL;\r
+       uint32_t                        elems           = 0;\r
+       DNSServiceErrorType     err                     = 0;\r
+       BOOL                            ok = TRUE;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( prop, propUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       // Setup the byte array\r
+       require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );\r
+       psa = V_ARRAY( value );\r
+       require_action( psa, exit, err = kDNSServiceErr_Unknown );\r
+       require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );\r
+       byteArray.reserve( psa->rgsabound[0].cElements );\r
+       byteArray.assign( byteArray.capacity(), 0 );\r
+       elems = ( uint32_t ) byteArray.capacity();\r
+\r
+       // Call the function and package the return value in the Variant\r
+       err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );\r
+       require_noerr( err, exit );\r
+       ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );\r
+       require_action( ok, exit, err = kDNSSDError_Unknown );\r
+\r
+exit:\r
+\r
+       if ( psa )\r
+       {\r
+               SafeArrayUnaccessData( psa );\r
+               psa = NULL;\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+STDMETHODIMP CDNSSDService::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IDNSSDEventManager *eventManager, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   subord                  = NULL;\r
+       std::string                                             hostNameUTF8;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       check( m_primary );\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( hostName, hostNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       object->AddRef();\r
+\r
+       subord = m_primary;\r
+       err = DNSServiceGetAddrInfo( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetPrimaryRef( m_primary );\r
+       object->SetSubordRef( subord );\r
+       object->SetEventManager( eventManager );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   subord                  = NULL;\r
+       DNSServiceProtocol                              prot                    = 0;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+\r
+       check( m_primary );\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       object->AddRef();\r
+\r
+       prot = ( addressFamily | protocol );\r
+\r
+       subord = m_primary;\r
+       err = DNSServiceNATPortMappingCreate( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, prot, htons( internalPort ), htons( externalPort ), ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetPrimaryRef( m_primary );\r
+       object->SetSubordRef( subord );\r
+       object->SetEventManager( eventManager );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSDService::Stop(void)\r
+{\r
+       if ( !m_stopped )\r
+       {\r
+               m_stopped = TRUE;\r
+\r
+               dlog( kDebugLevelTrace, "Stop()\n" );\r
+\r
+               if ( m_isPrimary && m_primary )\r
+               {\r
+                       SocketMap::iterator it;\r
+\r
+                       if ( m_hiddenWindow )\r
+                       {\r
+                               WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, 0, 0 );\r
+                       }\r
+\r
+                       it = m_socketMap.find( DNSServiceRefSockFD( m_primary ) );\r
+\r
+                       if ( it != m_socketMap.end() )\r
+                       {\r
+                               m_socketMap.erase( it );\r
+                       }\r
+\r
+                       DNSServiceRefDeallocate( m_primary );\r
+                       m_primary = NULL;\r
+               }\r
+               else if ( m_subord )\r
+               {\r
+                       DNSServiceRefDeallocate( m_subord );\r
+                       m_subord = NULL;\r
+               }\r
+\r
+               if ( m_eventManager != NULL )\r
+               {\r
+                       m_eventManager->Release();\r
+                       m_eventManager = NULL;\r
+               }\r
+       }\r
+\r
+       return S_OK;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSDService::DomainEnumReply
+    (
+    DNSServiceRef                       sdRef,
+    DNSServiceFlags                     flags,
+    uint32_t                            ifIndex,
+    DNSServiceErrorType                 errorCode,
+    const char                          *replyDomainUTF8,
+    void                                *context
+    )\r
+{\r
+       CComObject<CDNSSDService>       * service               = NULL;\r
+       CDNSSDEventManager                      * eventManager  = NULL;\r
+       int err = 0;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( service->ShouldHandleReply( errorCode, eventManager ) )\r
+       {\r
+               CComBSTR replyDomain;\r
+               BOOL ok;\r
+               \r
+               ok = UTF8ToBSTR( replyDomainUTF8, replyDomain );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( flags & kDNSServiceFlagsAdd )\r
+               {\r
+                       eventManager->Fire_DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );\r
+               }\r
+               else\r
+               {\r
+                       eventManager->Fire_DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSDService::BrowseReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            ifIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *serviceNameUTF8,
+               const char                          *regTypeUTF8,
+               const char                          *replyDomainUTF8,
+               void                                *context
+               )\r
+{\r
+       CComObject<CDNSSDService>       * service               = NULL;\r
+       CDNSSDEventManager                      * eventManager  = NULL;\r
+       int err = 0;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( service->ShouldHandleReply( errorCode, eventManager ) )\r
+       {\r
+               CComBSTR        serviceName;\r
+               CComBSTR        regType;\r
+               CComBSTR        replyDomain;\r
+       \r
+               UTF8ToBSTR( serviceNameUTF8, serviceName );\r
+               UTF8ToBSTR( regTypeUTF8, regType );\r
+               UTF8ToBSTR( replyDomainUTF8, replyDomain );\r
+\r
+               if ( flags & kDNSServiceFlagsAdd )\r
+               {\r
+                       eventManager->Fire_ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );\r
+               }\r
+               else\r
+               {\r
+                       eventManager->Fire_ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API\r
+CDNSSDService::ResolveReply\r
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            ifIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *fullNameUTF8,
+               const char                          *hostNameUTF8,
+               uint16_t                            port,
+               uint16_t                            txtLen,
+               const unsigned char                 *txtRecord,
+               void                                *context\r
+               )\r
+{\r
+       CComObject<CDNSSDService>       * service               = NULL;\r
+       CDNSSDEventManager                      * eventManager  = NULL;\r
+       int err = 0;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( service->ShouldHandleReply( errorCode, eventManager ) )\r
+       {\r
+               CComBSTR                                        fullName;\r
+               CComBSTR                                        hostName;\r
+               CComBSTR                                        regType;\r
+               CComBSTR                                        replyDomain;\r
+               CComObject< CTXTRecord >*       record;\r
+               BOOL                                            ok;\r
+\r
+               ok = UTF8ToBSTR( fullNameUTF8, fullName );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+               ok = UTF8ToBSTR( hostNameUTF8, hostName );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               try\r
+               {\r
+                       record = new CComObject<CTXTRecord>();\r
+               }\r
+               catch ( ... )\r
+               {\r
+                       record = NULL;\r
+               }\r
+\r
+               require_action( record, exit, err = kDNSServiceErr_NoMemory );\r
+               record->AddRef();\r
+\r
+               if ( txtLen > 0 )\r
+               {\r
+                       record->SetBytes( txtRecord, txtLen );\r
+               }\r
+\r
+               eventManager->Fire_ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, ntohs( port ), record );\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSDService::RegisterReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               DNSServiceErrorType                 errorCode,
+               const char                          *serviceNameUTF8,
+               const char                          *regTypeUTF8,
+               const char                          *domainUTF8,
+               void                                *context
+               )\r
+{\r
+       CComObject<CDNSSDService>       * service               = NULL;\r
+       CDNSSDEventManager                      * eventManager  = NULL;\r
+       int err = 0;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( service->ShouldHandleReply( errorCode, eventManager ) )\r
+       {\r
+               CComBSTR                                        serviceName;\r
+               CComBSTR                                        regType;\r
+               CComBSTR                                        domain;\r
+               BOOL                                            ok;\r
+\r
+               ok = UTF8ToBSTR( serviceNameUTF8, serviceName );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+               ok = UTF8ToBSTR( regTypeUTF8, regType );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+               ok = UTF8ToBSTR( domainUTF8, domain );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               eventManager->Fire_ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSDService::QueryRecordReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            ifIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *fullNameUTF8,
+               uint16_t                            rrtype,
+               uint16_t                            rrclass,
+               uint16_t                            rdlen,
+               const void                          *rdata,
+               uint32_t                            ttl,
+               void                                *context
+               )\r
+{\r
+       CComObject<CDNSSDService>       * service               = NULL;\r
+       CDNSSDEventManager                      * eventManager  = NULL;\r
+       int err = 0;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( service->ShouldHandleReply( errorCode, eventManager ) )\r
+       {\r
+               CComBSTR        fullName;\r
+               VARIANT         var;\r
+               BOOL            ok;\r
+\r
+               ok = UTF8ToBSTR( fullNameUTF8, fullName );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+               ok = ByteArrayToVariant( rdata, rdlen, &var );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               eventManager->Fire_QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSDService::GetAddrInfoReply
+               (
+               DNSServiceRef                    sdRef,
+               DNSServiceFlags                  flags,
+               uint32_t                         ifIndex,
+               DNSServiceErrorType              errorCode,
+               const char                       *hostNameUTF8,
+               const struct sockaddr            *rawAddress,
+               uint32_t                         ttl,
+               void                             *context
+               )\r
+{\r
+       CComObject<CDNSSDService>       * service               = NULL;\r
+       CDNSSDEventManager                      * eventManager  = NULL;\r
+       int err = 0;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( service->ShouldHandleReply( errorCode, eventManager ) )\r
+       {\r
+               CComBSTR                        hostName;\r
+               DWORD                           sockaddrLen;\r
+               DNSSDAddressFamily      addressFamily;\r
+               char                            addressUTF8[INET6_ADDRSTRLEN];\r
+               DWORD                           addressLen = sizeof( addressUTF8 );\r
+               CComBSTR                        address;\r
+               BOOL                            ok;\r
+\r
+               ok = UTF8ToBSTR( hostNameUTF8, hostName );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               switch ( rawAddress->sa_family )\r
+               {\r
+                       case AF_INET:\r
+                       {\r
+                               addressFamily   = kDNSSDAddressFamily_IPv4;\r
+                               sockaddrLen             = sizeof( sockaddr_in );\r
+                       }\r
+                       break;\r
+\r
+                       case AF_INET6:\r
+                       {\r
+                               addressFamily   = kDNSSDAddressFamily_IPv6;\r
+                               sockaddrLen             = sizeof( sockaddr_in6 );\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );\r
+               require_noerr( err, exit );\r
+               ok = UTF8ToBSTR( addressUTF8, address );\r
+               require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               eventManager->Fire_AddressFound( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSDService::NATPortMappingReply
+    (
+    DNSServiceRef                    sdRef,
+    DNSServiceFlags                  flags,
+    uint32_t                         ifIndex,
+    DNSServiceErrorType              errorCode,
+    uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
+    DNSServiceProtocol               protocol,
+    uint16_t                         internalPort,
+    uint16_t                         externalPort,      /* may be different than the requested port     */
+    uint32_t                         ttl,               /* may be different than the requested ttl      */
+    void                             *context
+    )\r
+{\r
+       CComObject<CDNSSDService>       * service               = NULL;\r
+       CDNSSDEventManager                      * eventManager  = NULL;\r
+       int err = 0;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( service->ShouldHandleReply( errorCode, eventManager ) )\r
+       {\r
+               eventManager->Fire_MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), ntohs( internalPort ), ntohs( externalPort ), ttl  );\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSDService::RegisterRecordReply
+               (
+               DNSServiceRef           sdRef,
+               DNSRecordRef            RecordRef,
+               DNSServiceFlags         flags,
+               DNSServiceErrorType     errorCode,
+               void                            *context
+               )\r
+{\r
+       CComObject<CDNSSDRecord>        * record                = NULL;\r
+       CDNSSDService                           * service               = NULL;\r
+       CDNSSDEventManager                      * eventManager  = NULL;\r
+       int err = 0;\r
+       \r
+       record = ( CComObject< CDNSSDRecord >* ) context;\r
+       require_action( record, exit, err = kDNSServiceErr_Unknown );\r
+       service = record->GetServiceObject();\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( service->ShouldHandleReply( errorCode, eventManager ) )\r
+       {\r
+               eventManager->Fire_RecordRegistered( record, ( DNSSDFlags ) flags );\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+BOOL\r
+CDNSSDService::ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager )\r
+{\r
+       BOOL ok = FALSE;\r
+\r
+       if ( !this->Stopped() )\r
+       {\r
+               eventManager = this->GetEventManager();\r
+               require_action( eventManager, exit, ok = FALSE );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       ok = TRUE;\r
+               }\r
+               else\r
+               {\r
+                       eventManager->Fire_OperationFailed( this, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return ok;\r
+}\r
+\r
+\r
+LRESULT CALLBACK\r
+CDNSSDService::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )\r
+{\r
+       if ( msg == WM_SOCKET )\r
+       {\r
+               SocketMap::iterator it;\r
+                       \r
+               it = m_socketMap.find( ( SOCKET ) wParam );\r
+               check( it != m_socketMap.end() );\r
+\r
+               if ( it != m_socketMap.end() )\r
+               {\r
+                       DNSServiceProcessResult( it->second->m_primary );\r
+               }\r
+       }\r
+\r
+       return DefWindowProc(hWnd, msg, wParam, lParam);;\r
+}\r
diff --git a/mDNSWindows/DLLX/DNSSDService.h b/mDNSWindows/DLLX/DNSSDService.h
new file mode 100755 (executable)
index 0000000..1618a00
--- /dev/null
@@ -0,0 +1,273 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: DNSSDService.h,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#pragma once\r
+#include "resource.h"       // main symbols\r
+\r
+#include "DLLX.h"\r
+#include "DNSSDEventManager.h"\r
+#include <CommonServices.h>\r
+#include <DebugServices.h>\r
+#include <dns_sd.h>\r
+#include <map>\r
+\r
+\r
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)\r
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."\r
+#endif\r
+\r
+\r
+\r
+// CDNSSDService\r
+\r
+class ATL_NO_VTABLE CDNSSDService :\r
+       public CComObjectRootEx<CComSingleThreadModel>,\r
+       public CComCoClass<CDNSSDService, &CLSID_DNSSDService>,\r
+       public IDispatchImpl<IDNSSDService, &IID_IDNSSDService, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>\r
+{\r
+public:\r
+\r
+       typedef CComObjectRootEx<CComSingleThreadModel> Super;\r
+\r
+       CDNSSDService()\r
+       :\r
+               m_isPrimary( FALSE ),\r
+               m_eventManager( NULL ),\r
+               m_stopped( FALSE ),\r
+               m_primary( NULL ),\r
+               m_subord( NULL )\r
+       {\r
+       }\r
+\r
+DECLARE_REGISTRY_RESOURCEID(IDR_DNSSDSERVICE)\r
+\r
+\r
+BEGIN_COM_MAP(CDNSSDService)\r
+       COM_INTERFACE_ENTRY(IDNSSDService)\r
+       COM_INTERFACE_ENTRY(IDispatch)\r
+END_COM_MAP()\r
+\r
+       DECLARE_PROTECT_FINAL_CONSTRUCT()\r
+\r
+       HRESULT\r
+       FinalConstruct();\r
+\r
+       void \r
+       FinalRelease();\r
+\r
+public:\r
+\r
+       inline DNSServiceRef\r
+       GetPrimaryRef()\r
+       {\r
+               return m_primary;\r
+       }\r
+\r
+       inline void\r
+       SetPrimaryRef( DNSServiceRef primary )\r
+       {\r
+               m_primary = primary;\r
+       }\r
+\r
+       inline DNSServiceRef\r
+       GetSubordRef()\r
+       {\r
+               return m_subord;\r
+       }\r
+\r
+       inline void\r
+       SetSubordRef( DNSServiceRef subord )\r
+       {\r
+               m_subord = subord;\r
+       }\r
+\r
+       inline CDNSSDEventManager*\r
+       GetEventManager()\r
+       {\r
+               return m_eventManager;\r
+       }\r
+\r
+       inline void\r
+       SetEventManager( IDNSSDEventManager * eventManager )\r
+       {\r
+               if ( m_eventManager )\r
+               {\r
+                       m_eventManager->Release();\r
+                       m_eventManager = NULL;\r
+               }\r
+\r
+               if ( eventManager )\r
+               {\r
+                       m_eventManager = dynamic_cast< CDNSSDEventManager* >( eventManager );\r
+                       check( m_eventManager );\r
+                       m_eventManager->AddRef();\r
+               }\r
+       }\r
+\r
+       inline BOOL\r
+       Stopped()\r
+       {\r
+               return m_stopped;\r
+       }\r
+\r
+private:\r
+\r
+       static void DNSSD_API
+       DomainEnumReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            ifIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *replyDomain,
+               void                                *context
+               );\r
+\r
+       static void DNSSD_API
+       BrowseReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            interfaceIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *serviceName,
+               const char                          *regtype,
+               const char                          *replyDomain,
+               void                                *context
+               );\r
+\r
+       static void DNSSD_API\r
+       ResolveReply\r
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            interfaceIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *fullname,
+               const char                          *hosttarget,
+               uint16_t                            port,
+               uint16_t                            txtLen,
+               const unsigned char                 *txtRecord,
+               void                                *context\r
+               );\r
+\r
+       static void DNSSD_API
+       RegisterReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               DNSServiceErrorType                 errorCode,
+               const char                          *name,
+               const char                          *regtype,
+               const char                          *domain,
+               void                                *context
+               );\r
+\r
+       static void DNSSD_API
+       QueryRecordReply
+               (
+               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
+               );\r
+\r
+       static void DNSSD_API
+    GetAddrInfoReply
+               (
+               DNSServiceRef                    sdRef,
+               DNSServiceFlags                  flags,
+               uint32_t                         interfaceIndex,
+               DNSServiceErrorType              errorCode,
+               const char                       *hostname,
+               const struct sockaddr            *address,
+               uint32_t                         ttl,
+               void                             *context
+               );\r
+\r
+       static void DNSSD_API
+       NATPortMappingReply
+               (
+               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,
+               uint16_t                         externalPort,      /* may be different than the requested port     */
+               uint32_t                         ttl,               /* may be different than the requested ttl      */
+               void                             *context
+               );\r
+\r
+       static void DNSSD_API
+       RegisterRecordReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSRecordRef                        RecordRef,
+               DNSServiceFlags                     flags,
+               DNSServiceErrorType                 errorCode,
+               void                                *context
+               );\r
+\r
+       inline BOOL\r
+       ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager );\r
+       \r
+       static LRESULT CALLBACK\r
+       WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );\r
+\r
+       typedef std::map< SOCKET, CDNSSDService* > SocketMap;\r
+\r
+       static BOOL                             m_registeredWindowClass;\r
+       static HWND                             m_hiddenWindow;\r
+       static SocketMap                m_socketMap;\r
+       CDNSSDEventManager      *       m_eventManager;\r
+       BOOL                                    m_stopped;\r
+       BOOL                                    m_isPrimary;\r
+       DNSServiceRef                   m_primary;\r
+       DNSServiceRef                   m_subord;\r
+public:\r
+       STDMETHOD(EnumerateDomains)(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service);  \r
+       STDMETHOD(Browse)(DNSSDFlags flags, ULONG interfaceIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** sdref);\r
+       STDMETHOD(Resolve)(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service);\r
+       STDMETHOD(Register)(DNSSDFlags flags, ULONG ifIndex, BSTR name, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service);\r
+       STDMETHOD(QueryRecord)(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service);      \r
+       STDMETHOD(RegisterRecord)(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record);\r
+       STDMETHOD(AddRecord)(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record);\r
+       STDMETHOD(ReconfirmRecord)(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata);\r
+       STDMETHOD(GetProperty)(BSTR prop, VARIANT * value);\r
+       STDMETHOD(GetAddrInfo)(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostname, IDNSSDEventManager *eventManager, IDNSSDService **service);      \r
+       STDMETHOD(NATPortMappingCreate)(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service);\r
+       STDMETHOD(Stop)(void);\r
+};\r
+\r
+OBJECT_ENTRY_AUTO(__uuidof(DNSSDService), CDNSSDService)\r
diff --git a/mDNSWindows/DLLX/DNSSDService.rgs b/mDNSWindows/DLLX/DNSSDService.rgs
new file mode 100755 (executable)
index 0000000..8a84297
--- /dev/null
@@ -0,0 +1,27 @@
+HKCR\r
+{\r
+       Bonjour.DNSSDService.1 = s 'DNSSDService Class'\r
+       {\r
+               CLSID = s '{24CD4DE9-FF84-4701-9DC1-9B69E0D1090A}'\r
+       }\r
+       Bonjour.DNSSDService = s 'DNSSDService Class'\r
+       {\r
+               CLSID = s '{24CD4DE9-FF84-4701-9DC1-9B69E0D1090A}'\r
+               CurVer = s 'Bonjour.DNSSDService.1'\r
+       }\r
+       NoRemove CLSID\r
+       {\r
+               ForceRemove {24CD4DE9-FF84-4701-9DC1-9B69E0D1090A} = s 'DNSSDService Class'\r
+               {\r
+                       ProgID = s 'Bonjour.DNSSDService.1'\r
+                       VersionIndependentProgID = s 'Bonjour.DNSSDService'\r
+                       ForceRemove 'Programmable'\r
+                       InprocServer32 = s '%MODULE%'\r
+                       {\r
+                               val ThreadingModel = s 'Apartment'\r
+                       }\r
+                       val AppID = s '%APPID%'\r
+                       'TypeLib' = s '{18FBED6D-F2B7-4EC8-A4A4-46282E635308}'\r
+               }\r
+       }\r
+}\r
diff --git a/mDNSWindows/DLLX/StringServices.cpp b/mDNSWindows/DLLX/StringServices.cpp
new file mode 100755 (executable)
index 0000000..a9c1d8a
--- /dev/null
@@ -0,0 +1,196 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: StringServices.cpp,v $
+Revision 1.2  2009/06/02 18:43:57  herscher
+<rdar://problem/3948252> Allow component consumers to pass in null strings
+
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#include "StringServices.h"\r
+#include <DebugServices.h>\r
+\r
+\r
+extern BOOL\r
+BSTRToUTF8\r
+       (\r
+       BSTR                    inString,\r
+       std::string     &       outString\r
+       )\r
+{\r
+       USES_CONVERSION;\r
+       \r
+       char    *       utf8String      = NULL;\r
+       OSStatus    err                 = kNoErr;\r
+\r
+       outString = "";
+
+       if ( inString )\r
+       {
+               TCHAR   *       utf16String     = NULL;
+               size_t      size                = 0;
+\r
+               utf16String = OLE2T( inString );\r
+               require_action( utf16String != NULL, exit, err = kUnknownErr );\r
+\r
+               if ( wcslen( utf16String ) > 0 )\r
+               {\r
+                       size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), NULL, 0, NULL, NULL );\r
+                       err = translate_errno( size != 0, GetLastError(), kUnknownErr );\r
+                       require_noerr( err, exit );\r
+\r
+                       try\r
+                       {\r
+                               utf8String = new char[ size + 1 ];\r
+                       }\r
+                       catch ( ... )\r
+                       {\r
+                               utf8String = NULL;\r
+                       }\r
+\r
+                       require_action( utf8String != NULL, exit, err = kNoMemoryErr );\r
+                       size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), utf8String, (int) size, NULL, NULL);\r
+                       err = translate_errno( size != 0, GetLastError(), kUnknownErr );\r
+                       require_noerr( err, exit );\r
+\r
+                       // have to add the trailing 0 because WideCharToMultiByte doesn't do it,\r
+                       // although it does return the correct size\r
+\r
+                       utf8String[size] = '\0';\r
+                       outString = utf8String;\r
+               }
+       }\r
+\r
+exit:\r
+\r
+       if ( utf8String != NULL )\r
+       {\r
+               delete [] utf8String;\r
+       }\r
+\r
+       return ( !err ) ? TRUE : FALSE;\r
+}\r
+\r
+\r
+extern BOOL\r
+UTF8ToBSTR\r
+       (\r
+       const char      *       inString,\r
+       CComBSTR        &       outString\r
+       )\r
+{\r
+       wchar_t *       unicode = NULL;\r
+       OSStatus        err             = 0;\r
+\r
+       if ( inString )\r
+       {
+               int n;
+
+               n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, NULL, 0 );\r
+           \r
+               if ( n > 0 )\r
+               {\r
+                       try\r
+                       {\r
+                               unicode = new wchar_t[ n ];\r
+                       }\r
+                       catch ( ... )\r
+                       {\r
+                               unicode = NULL;\r
+                       }\r
+\r
+                       require_action( unicode, exit, err = ERROR_INSUFFICIENT_BUFFER );\r
+\r
+                       n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, unicode, n );\r
+               }\r
+\r
+               outString = unicode;\r
+       }
+\r
+exit:\r
+\r
+    if ( unicode != NULL )\r
+    {\r
+        delete [] unicode;\r
+       }\r
+\r
+       return ( !err ) ? TRUE : FALSE;\r
+}\r
+\r
+\r
+BOOL\r
+ByteArrayToVariant\r
+       (\r
+       const void      *       inArray,\r
+       size_t                  inArrayLen,\r
+       VARIANT         *       outVariant\r
+       )\r
+{\r
+       LPBYTE                  buf     = NULL;\r
+       HRESULT                 hr      = 0;\r
+       BOOL                    ok      = TRUE;\r
+\r
+       VariantClear( outVariant );\r
+       outVariant->vt          = VT_ARRAY|VT_UI1;\r
+       outVariant->parray      = SafeArrayCreateVector( VT_UI1, 0, ( ULONG ) inArrayLen );\r
+       require_action( outVariant->parray, exit, ok = FALSE );\r
+       hr = SafeArrayAccessData( outVariant->parray, (LPVOID *)&buf );\r
+       require_action( hr == S_OK, exit, ok = FALSE );\r
+       memcpy( buf, inArray, inArrayLen );\r
+       hr = SafeArrayUnaccessData( outVariant->parray );\r
+       require_action( hr == S_OK, exit, ok = FALSE );\r
+\r
+exit:\r
+\r
+       return ok;\r
+}\r
+\r
+\r
+extern BOOL\r
+VariantToByteArray\r
+       (\r
+       VARIANT                         *       inVariant,\r
+       std::vector< BYTE >     &       outArray\r
+       )\r
+{\r
+       SAFEARRAY       *       psa                     = NULL;\r
+       BYTE            *       pData           = NULL;\r
+       ULONG                   cElements       = 0;\r
+       HRESULT                 hr;\r
+       BOOL                    ok = TRUE;\r
+\r
+       require_action( V_VT( inVariant ) == ( VT_ARRAY|VT_UI1 ), exit, ok = FALSE );\r
+       psa = V_ARRAY( inVariant );\r
+       require_action( psa, exit, ok = FALSE );\r
+       require_action( SafeArrayGetDim( psa ) == 1, exit, ok = FALSE );\r
+       hr = SafeArrayAccessData( psa, ( LPVOID* )&pData );\r
+       require_action( hr == S_OK, exit, ok = FALSE );\r
+       cElements = psa->rgsabound[0].cElements;\r
+       outArray.reserve( cElements );\r
+       outArray.assign( cElements, 0 );\r
+       memcpy( &outArray[ 0 ], pData, cElements );\r
+       SafeArrayUnaccessData( psa );\r
+\r
+exit:\r
+\r
+       return ok;\r
+}
\ No newline at end of file
diff --git a/mDNSWindows/DLLX/StringServices.h b/mDNSWindows/DLLX/StringServices.h
new file mode 100755 (executable)
index 0000000..ff6d59b
--- /dev/null
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: StringServices.h,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#ifndef _StringServices_h\r
+#define _StringServices_h\r
+\r
+#include <atlbase.h>\r
+#include <vector>\r
+#include <string>\r
+\r
+\r
+extern BOOL\r
+BSTRToUTF8\r
+       (\r
+       BSTR                    inString,\r
+       std::string     &       outString\r
+       );\r
+\r
+\r
+extern BOOL\r
+UTF8ToBSTR\r
+       (\r
+       const char      *       inString,\r
+       CComBSTR        &       outString\r
+       );\r
+\r
+\r
+extern BOOL\r
+ByteArrayToVariant\r
+       (\r
+       const void      *       inArray,\r
+       size_t                  inArrayLen,\r
+       VARIANT         *       outVariant\r
+       );\r
+\r
+\r
+extern BOOL\r
+VariantToByteArray\r
+       (\r
+       VARIANT                         *       inVariant,\r
+       std::vector< BYTE >     &       outArray\r
+       );\r
+\r
+\r
+#endif
\ No newline at end of file
diff --git a/mDNSWindows/DLLX/TXTRecord.cpp b/mDNSWindows/DLLX/TXTRecord.cpp
new file mode 100755 (executable)
index 0000000..5921654
--- /dev/null
@@ -0,0 +1,206 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: TXTRecord.cpp,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#include "stdafx.h"\r
+#include "TXTRecord.h"\r
+#include "StringServices.h"\r
+#include <DebugServices.h>\r
+\r
+\r
+// CTXTRecord\r
+\r
+\r
+STDMETHODIMP CTXTRecord::SetValue(BSTR key, VARIANT value)\r
+{\r
+       std::string                     keyUTF8;\r
+       ByteArray                       valueArray;\r
+       BOOL                            ok;\r
+       DNSServiceErrorType     err;\r
+       HRESULT                         hr = S_OK;\r
+\r
+       if ( !m_allocated )\r
+       {\r
+               TXTRecordCreate( &m_tref, 0, NULL );\r
+               m_allocated = TRUE;\r
+       }\r
+\r
+       ok = BSTRToUTF8( key, keyUTF8 );\r
+       require_action( ok, exit, hr = S_FALSE );\r
+\r
+       ok = VariantToByteArray( &value, valueArray );\r
+       require_action( ok, exit, hr = S_FALSE );\r
+\r
+       err = TXTRecordSetValue( &m_tref, keyUTF8.c_str(), ( uint8_t ) valueArray.size(), &valueArray[ 0 ] );\r
+       require_action( !err, exit, hr = S_FALSE );\r
+\r
+exit:\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CTXTRecord::RemoveValue(BSTR key)\r
+{\r
+       HRESULT hr = S_OK;\r
+\r
+       if ( m_allocated )\r
+       {\r
+               std::string                     keyUTF8;\r
+               BOOL                            ok;\r
+               DNSServiceErrorType     err;\r
+\r
+               ok = BSTRToUTF8( key, keyUTF8 );\r
+               require_action( ok, exit, hr = S_FALSE );\r
+\r
+               err = TXTRecordRemoveValue( &m_tref, keyUTF8.c_str() );\r
+               require_action( !err, exit, hr = S_FALSE );\r
+       }\r
+\r
+exit:\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CTXTRecord::ContainsKey(BSTR key, VARIANT_BOOL* retval)\r
+{\r
+       std::string keyUTF8;\r
+       int                     ret     = 0;\r
+       HRESULT         err     = S_OK;\r
+\r
+       if ( m_byteArray.size() > 0 )\r
+       {\r
+               BOOL ok;\r
+\r
+               ok = BSTRToUTF8( key, keyUTF8 );\r
+               require_action( ok, exit, err = S_FALSE );\r
+\r
+               ret = TXTRecordContainsKey( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], keyUTF8.c_str() );\r
+       }\r
+\r
+       *retval = ( ret ) ? VARIANT_TRUE : VARIANT_FALSE;\r
+\r
+exit:\r
+\r
+       return err;\r
+}\r
+\r
+STDMETHODIMP CTXTRecord::GetValueForKey(BSTR key, VARIANT* value)\r
+{\r
+       std::string             keyUTF8;\r
+       const void      *       rawValue;\r
+       uint8_t                 rawValueLen;\r
+       BOOL                    ok      = TRUE;\r
+       HRESULT                 hr      = S_OK;\r
+\r
+       VariantClear( value );\r
+\r
+       if ( m_byteArray.size() > 0 )\r
+       {\r
+               ok = BSTRToUTF8( key, keyUTF8 );\r
+               require_action( ok, exit, hr = S_FALSE );\r
+\r
+               rawValue = TXTRecordGetValuePtr( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], keyUTF8.c_str(), &rawValueLen );\r
+\r
+               if ( rawValue )\r
+               {\r
+                       ok = ByteArrayToVariant( rawValue, rawValueLen, value );\r
+                       require_action( ok, exit, hr = S_FALSE );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CTXTRecord::GetCount(ULONG* count)\r
+{\r
+       *count = 0;\r
+\r
+       if ( m_byteArray.size() > 0 )\r
+       {\r
+               *count = TXTRecordGetCount( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ] );\r
+       }\r
+\r
+       return S_OK;\r
+}\r
+\r
+STDMETHODIMP CTXTRecord::GetKeyAtIndex(ULONG index, BSTR* retval)\r
+{\r
+       char                            keyBuf[ 64 ];\r
+       uint8_t                         rawValueLen;\r
+       const void              *       rawValue;\r
+       CComBSTR                        temp;\r
+       DNSServiceErrorType     err;\r
+       BOOL                            ok;\r
+       HRESULT                         hr = S_OK;\r
+\r
+       err = TXTRecordGetItemAtIndex( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], ( uint16_t ) index, sizeof( keyBuf ), keyBuf, &rawValueLen, &rawValue );\r
+       require_action( !err, exit, hr = S_FALSE );\r
+\r
+       ok = UTF8ToBSTR( keyBuf, temp );\r
+       require_action( ok, exit, hr = S_FALSE );\r
+\r
+       *retval = temp;\r
+\r
+exit:\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CTXTRecord::GetValueAtIndex(ULONG index, VARIANT* retval)\r
+{\r
+       char                            keyBuf[ 64 ];\r
+       uint8_t                         rawValueLen;\r
+       const void              *       rawValue;\r
+       CComBSTR                        temp;\r
+       DNSServiceErrorType     err;\r
+       BOOL                            ok;\r
+       HRESULT                         hr = S_OK;\r
+\r
+       err = TXTRecordGetItemAtIndex( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], ( uint16_t ) index, sizeof( keyBuf ), keyBuf, &rawValueLen, &rawValue );\r
+       require_action( !err, exit, hr = S_FALSE );\r
+\r
+       ok = ByteArrayToVariant( rawValue, rawValueLen, retval );\r
+       require_action( ok, exit, hr = S_FALSE );\r
+\r
+exit:\r
+\r
+       return hr;\r
+}\r
+\r
+\r
+void\r
+CTXTRecord::SetBytes\r
+       (\r
+       const unsigned char     *       bytes,\r
+       uint16_t                                len\r
+       )\r
+{\r
+       check ( bytes != NULL );\r
+       check( len );\r
+\r
+       m_byteArray.reserve( len );\r
+       m_byteArray.assign( bytes, bytes + len );\r
+}\r
diff --git a/mDNSWindows/DLLX/TXTRecord.h b/mDNSWindows/DLLX/TXTRecord.h
new file mode 100755 (executable)
index 0000000..f74f8a0
--- /dev/null
@@ -0,0 +1,117 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: TXTRecord.h,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#pragma once\r
+#include "resource.h"       // main symbols\r
+#include "DLLX.h"\r
+#include <vector>\r
+#include <dns_sd.h>\r
+\r
+\r
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)\r
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."\r
+#endif\r
+\r
+\r
+\r
+// CTXTRecord\r
+\r
+class ATL_NO_VTABLE CTXTRecord :\r
+       public CComObjectRootEx<CComSingleThreadModel>,\r
+       public CComCoClass<CTXTRecord, &CLSID_TXTRecord>,\r
+       public IDispatchImpl<ITXTRecord, &IID_ITXTRecord, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>\r
+{\r
+public:\r
+       CTXTRecord()\r
+       :\r
+               m_allocated( FALSE )\r
+       {\r
+       }\r
+\r
+DECLARE_REGISTRY_RESOURCEID(IDR_TXTRECORD)\r
+\r
+\r
+BEGIN_COM_MAP(CTXTRecord)\r
+       COM_INTERFACE_ENTRY(ITXTRecord)\r
+       COM_INTERFACE_ENTRY(IDispatch)\r
+END_COM_MAP()\r
+\r
+\r
+\r
+       DECLARE_PROTECT_FINAL_CONSTRUCT()\r
+\r
+       HRESULT FinalConstruct()\r
+       {\r
+               return S_OK;\r
+       }\r
+\r
+       void FinalRelease()\r
+       {\r
+               if ( m_allocated )\r
+               {\r
+                       TXTRecordDeallocate( &m_tref );\r
+               }\r
+       }\r
+\r
+public:\r
+\r
+       STDMETHOD(SetValue)(BSTR key, VARIANT value);\r
+       STDMETHOD(RemoveValue)(BSTR key);\r
+       STDMETHOD(ContainsKey)(BSTR key, VARIANT_BOOL* retval);\r
+       STDMETHOD(GetValueForKey)(BSTR key, VARIANT* value);\r
+       STDMETHOD(GetCount)(ULONG* count);\r
+       STDMETHOD(GetKeyAtIndex)(ULONG index, BSTR* retval);\r
+       STDMETHOD(GetValueAtIndex)(ULONG index, VARIANT* retval);\r
+\r
+private:\r
+\r
+       typedef std::vector< BYTE > ByteArray;\r
+       ByteArray               m_byteArray;\r
+       BOOL                    m_allocated;\r
+       TXTRecordRef    m_tref;\r
+\r
+public:\r
+\r
+       uint16_t\r
+       GetLen()\r
+       {\r
+               return TXTRecordGetLength( &m_tref );\r
+       }\r
+\r
+       const void*\r
+       GetBytes()\r
+       {\r
+               return TXTRecordGetBytesPtr( &m_tref );\r
+       }\r
+\r
+       void\r
+       SetBytes\r
+               (\r
+               const unsigned char     *       bytes,\r
+               uint16_t                                len\r
+               );\r
+};\r
+\r
+OBJECT_ENTRY_AUTO(__uuidof(TXTRecord), CTXTRecord)\r
diff --git a/mDNSWindows/DLLX/TXTRecord.rgs b/mDNSWindows/DLLX/TXTRecord.rgs
new file mode 100755 (executable)
index 0000000..ce2fe1e
--- /dev/null
@@ -0,0 +1,27 @@
+HKCR\r
+{\r
+       Bonjour.TXTRecord.1 = s 'TXTRecord Class'\r
+       {\r
+               CLSID = s '{AFEE063C-05BA-4248-A26E-168477F49734}'\r
+       }\r
+       Bonjour.TXTRecord = s 'TXTRecord Class'\r
+       {\r
+               CLSID = s '{AFEE063C-05BA-4248-A26E-168477F49734}'\r
+               CurVer = s 'Bonjour.TXTRecord.1'\r
+       }\r
+       NoRemove CLSID\r
+       {\r
+               ForceRemove {AFEE063C-05BA-4248-A26E-168477F49734} = s 'TXTRecord Class'\r
+               {\r
+                       ProgID = s 'Bonjour.TXTRecord.1'\r
+                       VersionIndependentProgID = s 'Bonjour.TXTRecord'\r
+                       ForceRemove 'Programmable'\r
+                       InprocServer32 = s '%MODULE%'\r
+                       {\r
+                               val ThreadingModel = s 'Apartment'\r
+                       }\r
+                       val AppID = s '%APPID%'\r
+                       'TypeLib' = s '{18FBED6D-F2B7-4EC8-A4A4-46282E635308}'\r
+               }\r
+       }\r
+}\r
diff --git a/mDNSWindows/DLLX/_IDNSSDEvents_CP.h b/mDNSWindows/DLLX/_IDNSSDEvents_CP.h
new file mode 100755 (executable)
index 0000000..5c48397
--- /dev/null
@@ -0,0 +1,358 @@
+\r
+// Wizard-generated connection point proxy class\r
+// WARNING: This file may be regenerated by the wizard\r
+\r
+\r
+#pragma once\r
+\r
+template<class T>\r
+class CProxy_IDNSSDEvents :\r
+       public IConnectionPointImpl<T, &__uuidof(_IDNSSDEvents)>\r
+{\r
+public:\r
+       HRESULT Fire_DomainFound( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR domain)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[4];\r
+                               avarParams[3] = service;\r
+                               avarParams[2] = flags;\r
+                               avarParams[1] = ifIndex;\r
+                               avarParams[1].vt = VT_UI4;\r
+                               avarParams[0] = domain;\r
+                               avarParams[0].vt = VT_BSTR;\r
+                               DISPPARAMS params = { avarParams, NULL, 4, 0 };\r
+                               hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_DomainLost( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR domain)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[4];\r
+                               avarParams[3] = service;\r
+                               avarParams[2] = flags;\r
+                               avarParams[1] = ifIndex;\r
+                               avarParams[1].vt = VT_UI4;\r
+                               avarParams[0] = domain;\r
+                               avarParams[0].vt = VT_BSTR;\r
+                               DISPPARAMS params = { avarParams, NULL, 4, 0 };\r
+                               hr = pConnection->Invoke(2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_ServiceFound( IDNSSDService * browser,  DNSSDFlags flags,  ULONG ifIndex,  BSTR serviceName,  BSTR regType,  BSTR domain)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[6];\r
+                               avarParams[5] = browser;\r
+                               avarParams[4] = flags;\r
+                               avarParams[3] = ifIndex;\r
+                               avarParams[3].vt = VT_UI4;\r
+                               avarParams[2] = serviceName;\r
+                               avarParams[2].vt = VT_BSTR;\r
+                               avarParams[1] = regType;\r
+                               avarParams[1].vt = VT_BSTR;\r
+                               avarParams[0] = domain;\r
+                               avarParams[0].vt = VT_BSTR;\r
+                               DISPPARAMS params = { avarParams, NULL, 6, 0 };\r
+                               hr = pConnection->Invoke(3, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_ServiceLost( IDNSSDService * browser,  DNSSDFlags flags,  ULONG ifIndex,  BSTR serviceName,  BSTR regType,  BSTR domain)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[6];\r
+                               avarParams[5] = browser;\r
+                               avarParams[4] = flags;\r
+                               avarParams[3] = ifIndex;\r
+                               avarParams[3].vt = VT_UI4;\r
+                               avarParams[2] = serviceName;\r
+                               avarParams[2].vt = VT_BSTR;\r
+                               avarParams[1] = regType;\r
+                               avarParams[1].vt = VT_BSTR;\r
+                               avarParams[0] = domain;\r
+                               avarParams[0].vt = VT_BSTR;\r
+                               DISPPARAMS params = { avarParams, NULL, 6, 0 };\r
+                               hr = pConnection->Invoke(4, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_ServiceResolved( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR fullName,  BSTR hostName,  USHORT port,  ITXTRecord * record)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[7];\r
+                               avarParams[6] = service;\r
+                               avarParams[5] = flags;\r
+                               avarParams[4] = ifIndex;\r
+                               avarParams[4].vt = VT_UI4;\r
+                               avarParams[3] = fullName;\r
+                               avarParams[3].vt = VT_BSTR;\r
+                               avarParams[2] = hostName;\r
+                               avarParams[2].vt = VT_BSTR;\r
+                               avarParams[1] = port;\r
+                               avarParams[1].vt = VT_UI2;\r
+                               avarParams[0] = record;\r
+                               DISPPARAMS params = { avarParams, NULL, 7, 0 };\r
+                               hr = pConnection->Invoke(5, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_ServiceRegistered( IDNSSDService * service,  DNSSDFlags flags,  BSTR name,  BSTR regType,  BSTR domain)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[5];\r
+                               avarParams[4] = service;\r
+                               avarParams[3] = flags;\r
+                               avarParams[2] = name;\r
+                               avarParams[2].vt = VT_BSTR;\r
+                               avarParams[1] = regType;\r
+                               avarParams[1].vt = VT_BSTR;\r
+                               avarParams[0] = domain;\r
+                               avarParams[0].vt = VT_BSTR;\r
+                               DISPPARAMS params = { avarParams, NULL, 5, 0 };\r
+                               hr = pConnection->Invoke(6, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_QueryRecordAnswered( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR fullName,  DNSSDRRType rrtype,  DNSSDRRClass rrclass,  VARIANT rdata,  ULONG ttl)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[8];\r
+                               avarParams[7] = service;\r
+                               avarParams[6] = flags;\r
+                               avarParams[5] = ifIndex;\r
+                               avarParams[5].vt = VT_UI4;\r
+                               avarParams[4] = fullName;\r
+                               avarParams[4].vt = VT_BSTR;\r
+                               avarParams[3] = rrtype;\r
+                               avarParams[2] = rrclass;\r
+                               avarParams[1] = rdata;\r
+                               avarParams[0] = ttl;\r
+                               avarParams[0].vt = VT_UI4;\r
+                               DISPPARAMS params = { avarParams, NULL, 8, 0 };\r
+                               hr = pConnection->Invoke(7, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_RecordRegistered( IDNSSDRecord * record,  DNSSDFlags flags)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[2];\r
+                               avarParams[1] = record;\r
+                               avarParams[0] = flags;\r
+                               DISPPARAMS params = { avarParams, NULL, 2, 0 };\r
+                               hr = pConnection->Invoke(8, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_AddressFound( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR hostname,  DNSSDAddressFamily addressFamily,  BSTR address,  ULONG ttl)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[7];\r
+                               avarParams[6] = service;\r
+                               avarParams[5] = flags;\r
+                               avarParams[4] = ifIndex;\r
+                               avarParams[4].vt = VT_UI4;\r
+                               avarParams[3] = hostname;\r
+                               avarParams[3].vt = VT_BSTR;\r
+                               avarParams[2] = addressFamily;\r
+                               avarParams[1] = address;\r
+                               avarParams[1].vt = VT_BSTR;\r
+                               avarParams[0] = ttl;\r
+                               avarParams[0].vt = VT_UI4;\r
+                               DISPPARAMS params = { avarParams, NULL, 7, 0 };\r
+                               hr = pConnection->Invoke(9, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_MappingCreated( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  ULONG externalAddress,  DNSSDAddressFamily addressFamily,  DNSSDProtocol protocol,  USHORT internalPort,  USHORT externalPort,  ULONG ttl)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[9];\r
+                               avarParams[8] = service;\r
+                               avarParams[7] = flags;\r
+                               avarParams[6] = ifIndex;\r
+                               avarParams[6].vt = VT_UI4;\r
+                               avarParams[5] = externalAddress;\r
+                               avarParams[5].vt = VT_UI4;\r
+                               avarParams[4] = addressFamily;\r
+                               avarParams[3] = protocol;\r
+                               avarParams[2] = internalPort;\r
+                               avarParams[2].vt = VT_UI2;\r
+                               avarParams[1] = externalPort;\r
+                               avarParams[1].vt = VT_UI2;\r
+                               avarParams[0] = ttl;\r
+                               avarParams[0].vt = VT_UI4;\r
+                               DISPPARAMS params = { avarParams, NULL, 9, 0 };\r
+                               hr = pConnection->Invoke(10, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+       HRESULT Fire_OperationFailed( IDNSSDService * service,  DNSSDError error)\r
+       {\r
+               HRESULT hr = S_OK;\r
+               T * pThis = static_cast<T *>(this);\r
+               int cConnections = m_vec.GetSize();\r
+\r
+               for (int iConnection = 0; iConnection < cConnections; iConnection++)\r
+               {\r
+                       pThis->Lock();\r
+                       CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);\r
+                       pThis->Unlock();\r
+\r
+                       IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);\r
+\r
+                       if (pConnection)\r
+                       {\r
+                               CComVariant avarParams[2];\r
+                               avarParams[1] = service;\r
+                               avarParams[0] = error;\r
+                               DISPPARAMS params = { avarParams, NULL, 2, 0 };\r
+                               hr = pConnection->Invoke(11, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);\r
+                       }\r
+               }\r
+               return hr;\r
+       }\r
+};\r
+\r
diff --git a/mDNSWindows/DLLX/dlldatax.c b/mDNSWindows/DLLX/dlldatax.c
new file mode 100755 (executable)
index 0000000..d2508e8
--- /dev/null
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-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.
+
+    Change History (most recent first):
+    
+$Log: dlldatax.c,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#ifdef _MERGE_PROXYSTUB // merge proxy stub DLL\r
+\r
+#define REGISTER_PROXY_DLL //DllRegisterServer, etc.\r
+\r
+#define _WIN32_WINNT 0x0500    //for WinNT 4.0 or Win95 with DCOM\r
+#define USE_STUBLESS_PROXY     //defined only with MIDL switch /Oicf\r
+\r
+#pragma comment(lib, "rpcns4.lib")\r
+#pragma comment(lib, "rpcrt4.lib")\r
+\r
+#define ENTRY_PREFIX   Prx\r
+\r
+#include "dlldata.c"\r
+#include "DLLX_p.c"\r
+\r
+#endif //_MERGE_PROXYSTUB\r
diff --git a/mDNSWindows/DLLX/dlldatax.h b/mDNSWindows/DLLX/dlldatax.h
new file mode 100755 (executable)
index 0000000..093d8f1
--- /dev/null
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-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.
+
+    Change History (most recent first):
+    
+$Log: dlldatax.h,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#pragma once\r
+\r
+#ifdef _MERGE_PROXYSTUB\r
+\r
+extern "C" \r
+{\r
+BOOL WINAPI PrxDllMain(HINSTANCE hInstance, DWORD dwReason, \r
+       LPVOID lpReserved);\r
+STDAPI PrxDllCanUnloadNow(void);\r
+STDAPI PrxDllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv);\r
+STDAPI PrxDllRegisterServer(void);\r
+STDAPI PrxDllUnregisterServer(void);\r
+}\r
+\r
+#endif\r
diff --git a/mDNSWindows/DLLX/resource.h b/mDNSWindows/DLLX/resource.h
new file mode 100755 (executable)
index 0000000..5613187
--- /dev/null
@@ -0,0 +1,30 @@
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by DLLX.rc\r
+//\r
+#define IDS_PROJNAME                    100\r
+#define IDR_DLLX                               101\r
+#define IDR_DNSSD                       102\r
+#define IDR_DNSSDSERVICE                103\r
+#define IDR_BROWSELISTENER              104\r
+#define IDR_RESOLVELISTENER             105\r
+#define IDR_TXTRECORD                   106\r
+#define IDR_ENUMERATEDOMAINSLISTENER    107\r
+#define IDR_REGISTERLISTENER            108\r
+#define IDR_QUERYRECORDLISTENER         109\r
+#define IDR_GETADDRINFOLISTENER         110\r
+#define IDR_DNSSDRECORD                 111\r
+#define IDR_REGISTERRECORDLISTENER      112\r
+#define IDR_NATPORTMAPPINGLISTENER      113\r
+#define IDR_DNSSDEVENTMANAGER           114\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE        201\r
+#define _APS_NEXT_COMMAND_VALUE         32768\r
+#define _APS_NEXT_CONTROL_VALUE         201\r
+#define _APS_NEXT_SYMED_VALUE           115\r
+#endif\r
+#endif\r
diff --git a/mDNSWindows/DLLX/stdafx.h b/mDNSWindows/DLLX/stdafx.h
new file mode 100755 (executable)
index 0000000..fdde090
--- /dev/null
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2009 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.
+
+    Change History (most recent first):
+    
+$Log: stdafx.h,v $
+Revision 1.1  2009/05/26 04:43:54  herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#pragma once\r
+\r
+#ifndef STRICT\r
+#define STRICT\r
+#endif\r
+\r
+// Modify the following defines if you have to target a platform prior to the ones specified below.\r
+// Refer to MSDN for the latest info on corresponding values for different platforms.\r
+#ifndef WINVER                         // Allow use of features specific to Windows XP or later.\r
+#define WINVER 0x0501          // Change this to the appropriate value to target other versions of Windows.\r
+#endif\r
+\r
+#ifndef _WIN32_WINNT           // Allow use of features specific to Windows XP or later.                   \r
+#define _WIN32_WINNT 0x0501    // Change this to the appropriate value to target other versions of Windows.\r
+#endif                                         \r
+\r
+#ifndef _WIN32_WINDOWS         // Allow use of features specific to Windows 98 or later.\r
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.\r
+#endif\r
+\r
+#ifndef _WIN32_IE                      // Allow use of features specific to IE 6.0 or later.\r
+#define _WIN32_IE 0x0600       // Change this to the appropriate value to target other versions of IE.\r
+#endif\r
+\r
+#define _ATL_APARTMENT_THREADED\r
+#define _ATL_NO_AUTOMATIC_NAMESPACE\r
+\r
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS     // some CString constructors will be explicit\r
+\r
+\r
+#include "resource.h"\r
+#include <atlbase.h>\r
+#include <atlcom.h>\r
+\r
+using namespace ATL;
\ No newline at end of file
index 641349dda8ed8ea4b68625129914135d1e1e14ff..4a49fdfeedd71ba33cc13b45fbb6a1886dca60a9 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: AboutDialog.cpp,v $
+Revision 1.4  2008/10/23 22:33:26  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
 Revision 1.3  2006/08/14 23:25:49  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -75,7 +78,7 @@ AboutDialog::AboutDialog(CWnd* pParent /*=NULL*/)
        : CDialog(AboutDialog::IDD, pParent)
 {
        //{{AFX_DATA_INIT(AboutDialog)
-               // NOTE: the ClassWizard will add member initialization here
+               // Note: the ClassWizard will add member initialization here
        //}}AFX_DATA_INIT
 }
 
@@ -97,6 +100,6 @@ void AboutDialog::DoDataExchange(CDataExchange* pDX)
 {
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(AboutDialog)
-               // NOTE: the ClassWizard will add DDX and DDV calls here
+               // Note: the ClassWizard will add DDX and DDV calls here
        //}}AFX_DATA_MAP
 }
index 98f4103349c29a9b21a8c3857e24fef7bee728a4..e4869ca02588044e6e9c9e75b8b48f7b52491755 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: AboutDialog.h,v $
+Revision 1.4  2008/10/23 22:33:26  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
 Revision 1.3  2006/08/14 23:25:49  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -69,7 +72,7 @@ class AboutDialog : public CDialog
                
                //{{AFX_DATA(AboutDialog)
                enum { IDD = IDD_ABOUT_DIALOG };
-                       // NOTE: the ClassWizard will add data members here
+                       // Note: the ClassWizard will add data members here
                //}}AFX_DATA
                
                // ClassWizard generated virtual function overrides
index f917ce8a062d1f97056e8216f6b27d1de9cbc430..486d46bf79ac7ea5c3bcd6ea1460910d35231220 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: ChooserDialog.cpp,v $
+Revision 1.5  2008/10/23 22:33:26  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
 Revision 1.4  2006/08/14 23:25:49  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -387,7 +390,7 @@ ChooserDialog::ChooserDialog( CWnd *inParent )
        : CDialog( ChooserDialog::IDD, inParent)
 {
        //{{AFX_DATA_INIT(ChooserDialog)
-               // NOTE: the ClassWizard will add member initialization here
+               // Note: the ClassWizard will add member initialization here
        //}}AFX_DATA_INIT
        
        // Load menu accelerator table.
index 01fa3a003342fba98e69ce161276dc733438c81d..5472b47d51c4dd6cb908820d29dc680cd2e70ff2 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: BrowserDialog.cpp,v $
+Revision 1.4  2008/10/23 22:33:26  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
 Revision 1.3  2006/08/14 23:25:55  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -87,7 +90,7 @@ BrowserDialog::BrowserDialog( CWnd *inParent )
        : CDialog( BrowserDialog::IDD, inParent )
 {
        //{{AFX_DATA_INIT(BrowserDialog)
-               // NOTE: the ClassWizard will add member initialization here
+               // Note: the ClassWizard will add member initialization here
        //}}AFX_DATA_INIT
        
        // Note that LoadIcon does not require a subsequent DestroyIcon in Win32.
index a846ec983cc5bb9c92d566372527494f0affbdc0..593175dc186570a9452cabb3b96298f78f47436a 100755 (executable)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="Java"\r
        ProjectGUID="{9CE2568A-3170-41C6-9F20-A0188A9EC114}"\r
-       Keyword="MakeFileProj">\r
+       Keyword="MakeFileProj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
                        OutputDirectory="Debug"\r
                        IntermediateDirectory="Debug"\r
-                       ConfigurationType="0">\r
+                       ConfigurationType="0"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       >\r
                        <Tool\r
                                Name="VCNMakeTool"\r
                                BuildCommandLine="nmake /f makefile DEBUG=1"\r
                                ReBuildCommandLine="nmake /f makefile DEBUG=1"\r
-                               CleanCommandLine="nmake /f makefile DEBUG=1 clean"/>\r
+                               CleanCommandLine="nmake /f makefile DEBUG=1 clean"\r
+                               Output=""\r
+                               PreprocessorDefinitions=""\r
+                               IncludeSearchPath=""\r
+                               ForcedIncludes=""\r
+                               AssemblySearchPath=""\r
+                               ForcedUsingAssemblies=""\r
+                               CompileAsManaged=""\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
                        OutputDirectory="Release"\r
                        IntermediateDirectory="Release"\r
-                       ConfigurationType="0">\r
+                       ConfigurationType="0"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       >\r
+                       <Tool\r
+                               Name="VCNMakeTool"\r
+                               BuildCommandLine="nmake /f makefile"\r
+                               ReBuildCommandLine="nmake /f makefile"\r
+                               CleanCommandLine="nmake /f makefile clean"\r
+                               Output=""\r
+                               PreprocessorDefinitions=""\r
+                               IncludeSearchPath=""\r
+                               ForcedIncludes=""\r
+                               AssemblySearchPath=""\r
+                               ForcedUsingAssemblies=""\r
+                               CompileAsManaged=""\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="0"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       >\r
+                       <Tool\r
+                               Name="VCNMakeTool"\r
+                               BuildCommandLine="nmake /f makefile DEBUG=1"\r
+                               ReBuildCommandLine="nmake /f makefile DEBUG=1"\r
+                               CleanCommandLine="nmake /f makefile DEBUG=1 clean"\r
+                               Output=""\r
+                               PreprocessorDefinitions=""\r
+                               IncludeSearchPath=""\r
+                               ForcedIncludes=""\r
+                               AssemblySearchPath=""\r
+                               ForcedUsingAssemblies=""\r
+                               CompileAsManaged=""\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="0"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       >\r
                        <Tool\r
                                Name="VCNMakeTool"\r
                                BuildCommandLine="nmake /f makefile"\r
                                ReBuildCommandLine="nmake /f makefile"\r
-                               CleanCommandLine="nmake /f makefile clean"/>\r
+                               CleanCommandLine="nmake /f makefile clean"\r
+                               Output=""\r
+                               PreprocessorDefinitions=""\r
+                               IncludeSearchPath=""\r
+                               ForcedIncludes=""\r
+                               AssemblySearchPath=""\r
+                               ForcedUsingAssemblies=""\r
+                               CompileAsManaged=""\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
index 99a79877d696c18a97240ef989e58fc6bd37c45c..768b51f9102fe5c41ac0e2d40f9b560b391dedfe 100644 (file)
 # limitations under the License.
 #
 # $Log: makefile,v $
+# Revision 1.10  2009/03/30 20:22:43  herscher
+# <rdar://problem/5925472> Current Bonjour code does not compile on Windows
+# Update LIBDIR to work with new build directory structure
+# Create postbuild rules for new buildtrain
+#
 # Revision 1.9  2006/08/14 23:26:04  cheshire
 # Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 #
@@ -89,13 +94,13 @@ CFLAGS_DEBUG = -Zi -DMDNS_DEBUGMSGS=2
 OBJDIR = objects\debug
 BUILDDIR = build\debug
 INSTALLDIR = root\"Program Files"\Bonjour
-LIBDIR = ..\DLL\Debug
+LIBDIR = ..\DLL\Win32\Debug
 !else
 CFLAGS_DEBUG = -Os -DMDNS_DEBUGMSGS=0 
 OBJDIR = objects\prod
 BUILDDIR = build\prod
 INSTALLDIR = root\"Program Files"\Bonjour
-LIBDIR = ..\DLL\Release
+LIBDIR = ..\DLL\Win32\Release
 !endif
 
 CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_DEBUG)
@@ -113,7 +118,13 @@ setup:
        @if not exist $(BUILDDIR)       mkdir $(BUILDDIR)
 
 postbuild:
-       @if not exist root                                              mkdir root
+       @if not "%RC_XBS%"=="YES" GOTO CONT
+       @if not exist "$(DSTROOT)\WINDOWS\system32\Win32"       mkdir "$(DSTROOT)\WINDOWS\system32\Win32"
+       @if not exist "$(DSTROOT)\Program Files\Bonjour\Win32"  mkdir "$(DSTROOT)\Program Files\Bonjour\Win32"
+       @copy $(BUILDDIR)\jdns_sd.dll "$(DSTROOT)\WINDOWS\system32\Win32"
+       @copy $(BUILDDIR)\dns_sd.jar  "$(DSTROOT)\Program Files\Bonjour\Win32"
+       @:CONT
+       @if not exist root                                      mkdir root
        @if not exist root\"Program Files"      mkdir root\"Program Files"
        @if not exist $(INSTALLDIR)                     mkdir $(INSTALLDIR)
        copy $(BUILDDIR)\dns_sd.jar $(INSTALLDIR)
@@ -137,14 +148,14 @@ JARCONTENTS =     $(OBJDIR)\com\apple\dnssd\DNSSDService.class \
                                $(OBJDIR)\com\apple\dnssd\DNSRecord.class \
                                $(OBJDIR)\com\apple\dnssd\TXTRecord.class \
                                $(OBJDIR)\com\apple\dnssd\DNSSDRegistration.class \
+                               $(OBJDIR)\com\apple\dnssd\DNSSDRecordRegistrar.class \
                                $(OBJDIR)\com\apple\dnssd\BaseListener.class \
                                $(OBJDIR)\com\apple\dnssd\BrowseListener.class \
                                $(OBJDIR)\com\apple\dnssd\ResolveListener.class \
                                $(OBJDIR)\com\apple\dnssd\RegisterListener.class \
+                               $(OBJDIR)\com\apple\dnssd\RegisterRecordListener.class \
                                $(OBJDIR)\com\apple\dnssd\QueryListener.class \
                                $(OBJDIR)\com\apple\dnssd\DomainListener.class \
-                               $(OBJDIR)\com\apple\dnssd\DNSSDRecordRegistrar.class \
-                               $(OBJDIR)\com\apple\dnssd\RegisterRecordListener.class \
                                $(OBJDIR)\com\apple\dnssd\DNSSD.class
 
 $(BUILDDIR)\dns_sd.jar: $(JARCONTENTS)
index f42620a0083283e6394cb276cc9ef2a7d76bbca6..bed3203771a83f9f09c3f9b02b1814daf4b7fcf2 100644 (file)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="NSPTool"\r
        ProjectGUID="{208B3A9F-1CA0-4D1D-9D6C-C61616F94705}"\r
-       Keyword="Win32Proj">\r
+       Keyword="Win32Proj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories=".;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="TRUE"\r
-                               ExceptionHandling="FALSE"\r
+                               AdditionalIncludeDirectories=".;..;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
                                BasicRuntimeChecks="3"\r
-                               SmallerTypeCheck="TRUE"\r
+                               SmallerTypeCheck="true"\r
                                RuntimeLibrary="1"\r
-                               BufferSecurityCheck="TRUE"\r
-                               EnableFunctionLevelLinking="FALSE"\r
+                               BufferSecurityCheck="true"\r
+                               EnableFunctionLevelLinking="false"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="4"\r
-                               CallingConvention="0"/>\r
+                               CallingConvention="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="..\"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
                                OutputFile="$(OutDir)/NSPTool.exe"\r
                                LinkIncremental="2"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/NSPTool.pdb"\r
                                SubSystem="1"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories=".;..;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
+                               BasicRuntimeChecks="3"\r
+                               SmallerTypeCheck="true"\r
+                               RuntimeLibrary="1"\r
+                               BufferSecurityCheck="true"\r
+                               EnableFunctionLevelLinking="false"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="..\"/>\r
+                               AdditionalIncludeDirectories="..\"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
+                               OutputFile="$(OutDir)/NSPTool.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/NSPTool.pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories=".;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"\r
+                               AdditionalIncludeDirectories=".;..;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"\r
                                RuntimeLibrary="0"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="3"/>\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="..\"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
                                OutputFile="$(OutDir)/NSPTool.exe"\r
                                LinkIncremental="1"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
                                SubSystem="1"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories=".;..;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"\r
+                               RuntimeLibrary="0"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="..\"/>\r
+                               AdditionalIncludeDirectories="..\"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
+                               OutputFile="$(OutDir)/NSPTool.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
                <Filter\r
                        Name="Source Files"\r
                        Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
-                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.c">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\NSPTool.c">\r
+                               RelativePath=".\NSPTool.c"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                        Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
-                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\CommonServices.h">\r
+                               RelativePath="..\..\mDNSShared\CommonServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.h">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\resource.h">\r
+                               RelativePath=".\resource.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
                        Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
-                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
                        <File\r
-                               RelativePath=".\NSPTool.rc">\r
+                               RelativePath=".\NSPTool.rc"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r
index c86b7ec2175d9abef046147405de312292933715..47b910dcae5eabfd7fa9a7f2b43f9473e2f69bf4 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: RegNames.h,v $
+Revision 1.5  2009/03/30 21:47:35  herscher
+Fix file corruption during previous checkin
+
 Revision 1.3  2006/08/14 23:25:20  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -35,7 +38,10 @@ Consolidates all registry key names and can safely be included in any component
 
 #if defined(UNICODE)
 
-#      define kServiceParametersNode                           L"SOFTWARE\\Apple Computer, Inc.\\Bonjour"
+#      define kServiceParametersSoftware                       L"SOFTWARE"
+#      define kServiceParametersAppleComputer          L"Apple Computer, Inc."
+#      define kServiceParametersBonjour                        L"Bonjour"
+#      define kServiceParametersNode                           L"SOFTWARE\\Apple Inc.\\Bonjour"
 #      define kServiceName                                                     L"Bonjour Service"
 #      define kServiceDynDNSBrowseDomains                      L"BrowseDomains"
 #      define kServiceDynDNSHostNames                          L"HostNames"
@@ -49,7 +55,10 @@ Consolidates all registry key names and can safely be included in any component
 
 # else
 
-#      define kServiceParametersNode                           "SOFTWARE\\Apple Computer, Inc.\\Bonjour"
+#      define kServiceParametersSoftware                       "SOFTWARE"
+#      define kServiceParametersAppleComputer          "Apple Computer, Inc."
+#      define kServiceParametersBonjour                        "Bonjour"
+#      define kServiceParametersNode                           "SOFTWARE\\Apple Inc.\\Bonjour"
 #      define kServiceName                                                     "Bonjour Service"
 #      define kServiceDynDNSBrowseDomains                      "BrowseDomains"
 #      define kServiceDynDNSHostNames                          "HostNames"
diff --git a/mDNSWindows/Secret.c b/mDNSWindows/Secret.c
new file mode 100644 (file)
index 0000000..4c12d15
--- /dev/null
@@ -0,0 +1,348 @@
+/* -*- 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.
+
+    Change History (most recent first):
+    
+$Log: Secret.c,v $
+Revision 1.2  2009/06/25 21:11:52  herscher
+Fix compilation error when building Control Panel.
+
+Revision 1.1  2009/06/22 23:25:04  herscher
+<rdar://problem/5265747> ControlPanel doesn't display key and password in dialog box. Refactor Lsa calls into Secret.h and Secret.c, which is used by both the ControlPanel and mDNSResponder system service.
+
+
+*/
+
+#include "Secret.h"
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#include <process.h>
+#include <ntsecapi.h>
+#include <lm.h>
+#include "DebugServices.h"
+
+
+mDNSlocal OSStatus MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input );
+mDNSlocal OSStatus MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input );
+
+
+BOOL
+LsaGetSecret( const char * inDomain, char * outDomain, unsigned outDomainLength, char * outKey, unsigned outKeyLength, char * outSecret, unsigned outSecretLength )
+{
+       PLSA_UNICODE_STRING             domainLSA;
+       PLSA_UNICODE_STRING             keyLSA;
+       PLSA_UNICODE_STRING             secretLSA;
+       size_t                                  i;
+       size_t                                  dlen;
+       LSA_OBJECT_ATTRIBUTES   attrs;
+       LSA_HANDLE                              handle = NULL;
+       NTSTATUS                                res;
+       OSStatus                                err;
+
+       check( inDomain );
+       check( outDomain );
+       check( outKey );
+       check( outSecret );
+
+       // Initialize
+
+       domainLSA       = NULL;
+       keyLSA          = NULL;
+       secretLSA       = NULL;
+
+       // If there isn't a trailing dot, add one because the mDNSResponder
+       // presents names with the trailing dot.
+
+       strcpy_s( outDomain, outDomainLength, inDomain );
+       dlen = strlen( outDomain );
+       
+       if ( outDomain[ dlen - 1 ] != '.' )
+       {
+               outDomain[ dlen ] = '.';
+               outDomain[ dlen + 1 ] = '\0';
+       }
+
+       // Canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
+
+       dlen = strlen( outDomain );
+       for ( i = 0; i < dlen; i++ )
+       {
+               outDomain[i] = (char) tolower( outDomain[i] );  // canonicalize -> lower case
+       }
+
+       // attrs are reserved, so initialize to zeroes.
+
+       ZeroMemory( &attrs, sizeof( attrs ) );
+
+       // Get a handle to the Policy object on the local system
+
+       res = LsaOpenPolicy( NULL, &attrs, POLICY_GET_PRIVATE_INFORMATION, &handle );
+       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+       require_noerr( err, exit );
+
+       // Get the encrypted data
+
+       domainLSA = ( PLSA_UNICODE_STRING ) malloc( sizeof( LSA_UNICODE_STRING ) );
+       require_action( domainLSA != NULL, exit, err = mStatus_NoMemoryErr );
+       err = MakeLsaStringFromUTF8String( domainLSA, outDomain );
+       require_noerr( err, exit );
+
+       // Retrieve the key
+
+       res = LsaRetrievePrivateData( handle, domainLSA, &keyLSA );
+       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+       require_noerr_quiet( err, exit );
+
+       // <rdar://problem/4192119> Lsa secrets use a flat naming space.  Therefore, we will prepend "$" to the keyname to
+       // make sure it doesn't conflict with a zone name.
+       
+       // Strip off the "$" prefix.
+
+       err = MakeUTF8StringFromLsaString( outKey, outKeyLength, keyLSA );
+       require_noerr( err, exit );
+       require_action( outKey[0] == '$', exit, err = kUnknownErr );
+       memcpy( outKey, outKey + 1, strlen( outKey ) );
+
+       // Retrieve the secret
+
+       res = LsaRetrievePrivateData( handle, keyLSA, &secretLSA );
+       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+       require_noerr_quiet( err, exit );
+
+       // Convert the secret to UTF8 string
+
+       err = MakeUTF8StringFromLsaString( outSecret, outSecretLength, secretLSA );
+       require_noerr( err, exit );
+
+exit:
+
+       if ( domainLSA != NULL )
+       {
+               if ( domainLSA->Buffer != NULL )
+               {
+                       free( domainLSA->Buffer );
+               }
+
+               free( domainLSA );
+       }
+
+       if ( keyLSA != NULL )
+       {
+               LsaFreeMemory( keyLSA );
+       }
+
+       if ( secretLSA != NULL )
+       {
+               LsaFreeMemory( secretLSA );
+       }
+
+       if ( handle )
+       {
+               LsaClose( handle );
+               handle = NULL;
+       }
+
+       return ( !err ) ? TRUE : FALSE;
+}
+
+
+mDNSBool
+LsaSetSecret( const char * inDomain, const char * inKey, const char * inSecret )
+{
+       size_t                                  inDomainLength;
+       size_t                                  inKeyLength;
+       char                                    domain[ 1024 ];
+       char                                    key[ 1024 ];
+       LSA_OBJECT_ATTRIBUTES   attrs;
+       LSA_HANDLE                              handle = NULL;
+       NTSTATUS                                res;
+       LSA_UNICODE_STRING              lucZoneName;
+       LSA_UNICODE_STRING              lucKeyName;
+       LSA_UNICODE_STRING              lucSecretName;
+       BOOL                                    ok = TRUE;
+       OSStatus                                err;
+
+       require_action( inDomain != NULL, exit, ok = FALSE );
+       require_action( inKey != NULL, exit, ok = FALSE );
+       require_action( inSecret != NULL, exit, ok = FALSE );
+
+       inDomainLength = strlen( inDomain );
+       require_action( ( inDomainLength > 0 ) && ( inDomainLength < sizeof( domain ) ), exit, ok = FALSE );
+
+       inKeyLength = strlen( inKey );
+       require_action( ( inKeyLength > 0 ) && ( inKeyLength < ( sizeof( key ) - 1 ) ), exit, ok = FALSE );
+
+       // If there isn't a trailing dot, add one because the mDNSResponder
+       // presents names with the trailing dot.
+
+       ZeroMemory( domain, sizeof( domain ) );
+       strcpy_s( domain, sizeof( domain ), inDomain );
+
+       if ( domain[ strlen( domain ) - 1 ] != '.' )
+       {
+               domain[ strlen( domain ) - 1 ] = '.';
+       }
+
+       // <rdar://problem/4192119>
+       //
+       // Prepend "$" to the key name, so that there will
+       // be no conflict between the zone name and the key
+       // name
+
+       ZeroMemory( key, sizeof( key ) );
+       key[ 0 ] = '$';
+       strcpy_s( key + 1, sizeof( key ) - 1, inKey );
+
+       if ( key[ strlen( key ) - 1 ] != '.' )
+       {
+               key[ strlen( key ) - 1 ] = '.';
+       }
+
+       // attrs are reserved, so initialize to zeroes.
+
+       ZeroMemory( &attrs, sizeof( attrs ) );
+
+       // Get a handle to the Policy object on the local system
+
+       res = LsaOpenPolicy( NULL, &attrs, POLICY_ALL_ACCESS, &handle );
+       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+       require_noerr( err, exit );
+
+       // Intializing PLSA_UNICODE_STRING structures
+
+       ok = MakeLsaStringFromUTF8String( &lucZoneName, domain );
+       err = translate_errno( ok, errno_compat(), kUnknownErr );
+       require_noerr( err, exit );
+       ok = MakeLsaStringFromUTF8String( &lucKeyName, key );
+       err = translate_errno( ok, errno_compat(), kUnknownErr );
+       require_noerr( err, exit );
+
+       ok = MakeLsaStringFromUTF8String( &lucSecretName, inSecret );
+       err = translate_errno( ok, errno_compat(), kUnknownErr );
+       require_noerr( err, exit );
+
+       // Store the private data.
+
+       res = LsaStorePrivateData( handle, &lucZoneName, &lucKeyName );
+       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+       require_noerr( err, exit );
+
+       res = LsaStorePrivateData( handle, &lucKeyName, &lucSecretName );
+       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+       require_noerr( err, exit );
+
+exit:
+
+       if ( handle )
+       {
+               LsaClose( handle );
+               handle = NULL;
+       }
+
+       return ok;
+}
+
+
+//===========================================================================================================================
+//     MakeLsaStringFromUTF8String
+//===========================================================================================================================
+
+mDNSlocal OSStatus
+MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input )
+{
+       int                     size;
+       OSStatus        err;
+       
+       check( input );
+       check( output );
+
+       output->Buffer = NULL;
+
+       size = MultiByteToWideChar( CP_UTF8, 0, input, -1, NULL, 0 );
+       err = translate_errno( size > 0, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       output->Length = (USHORT)( size * sizeof( wchar_t ) );
+       output->Buffer = (PWCHAR) malloc( output->Length );
+       require_action( output->Buffer, exit, err = mStatus_NoMemoryErr );
+       size = MultiByteToWideChar( CP_UTF8, 0, input, -1, output->Buffer, size );
+       err = translate_errno( size > 0, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       // We're going to subtrace one wchar_t from the size, because we didn't
+       // include it when we encoded the string
+
+       output->MaximumLength = output->Length;
+       output->Length          -= sizeof( wchar_t );
+       
+exit:
+
+       if ( err && output->Buffer )
+       {
+               free( output->Buffer );
+               output->Buffer = NULL;
+       }
+
+       return( err );
+}
+
+
+
+//===========================================================================================================================
+//     MakeUTF8StringFromLsaString
+//===========================================================================================================================
+
+mDNSlocal OSStatus
+MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input )
+{
+       size_t          size;
+       OSStatus        err = kNoErr;
+
+       // The Length field of this structure holds the number of bytes,
+       // but WideCharToMultiByte expects the number of wchar_t's. So
+       // we divide by sizeof(wchar_t) to get the correct number.
+
+       size = (size_t) WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), NULL, 0, NULL, NULL);
+       err = translate_errno( size != 0, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+       
+       // Ensure that we have enough space (Add one for trailing '\0')
+
+       require_action( ( size + 1 ) <= len, exit, err = mStatus_NoMemoryErr );
+
+       // Convert the string
+
+       size = (size_t) WideCharToMultiByte( CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), output, (int) size, NULL, NULL); 
+       err = translate_errno( size != 0, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       // have to add the trailing 0 because WideCharToMultiByte doesn't do it,
+       // although it does return the correct size
+
+       output[size] = '\0';
+
+exit:
+
+       return err;
+}
+
diff --git a/mDNSWindows/Secret.h b/mDNSWindows/Secret.h
new file mode 100644 (file)
index 0000000..a117f09
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*- 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.
+
+    Change History (most recent first):
+    
+$Log: Secret.h,v $
+Revision 1.2  2009/06/25 21:11:52  herscher
+Fix compilation error when building Control Panel.
+
+Revision 1.1  2009/06/22 23:25:04  herscher
+<rdar://problem/5265747> ControlPanel doesn't display key and password in dialog box. Refactor Lsa calls into Secret.h and Secret.c, which is used by both the ControlPanel and mDNSResponder system service.
+
+
+*/
+
+#ifndef _Secret_h
+#define _Secret_h
+
+#include "mDNSEmbeddedAPI.h"
+
+
+#if defined(__cplusplus )
+extern "C" {
+#endif
+
+
+extern mDNSBool
+LsaGetSecret( const char * inDomain, char * outDomain, unsigned outDomainLength, char * outKey, unsigned outKeyLength, char * outSecret, unsigned outSecretLength );
+
+
+extern mDNSBool
+LsaSetSecret( const char * inDomain, const char * inKey, const char * inSecret );
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif
\ No newline at end of file
index 79019daceff5b1abd1b5a80c22bf65abe8191941..4f1ad49426892dc6c7d7e554bea62526c167631a 100755 (executable)
     Change History (most recent first):
     
 $Log: Firewall.cpp,v $
+Revision 1.6  2009/04/24 04:55:26  herscher
+<rdar://problem/3496833> Advertise SMB file sharing via Bonjour
+
+Revision 1.5  2009/03/30 20:39:29  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5712486> Put in extra defensive checks to prevent NULL pointer dereferencing crash
+<rdar://problem/5187308> Move build train to Visual Studio 2005
+
 Revision 1.4  2006/08/14 23:26:07  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -39,10 +47,6 @@ Wrapper for Windows Firewall API code
 #endif
 
 
-#if !defined(_WSPIAPI_COUNTOF)
-#      define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
-#endif
-
 #include "Firewall.h"
 #include <windows.h>
 #include <crtdbg.h>
@@ -71,12 +75,12 @@ mDNSFirewallInitialize(OUT INetFwProfile ** fwProfile)
        // call will fail on anything other than XP SP2
 
        err = CoCreateInstance( __uuidof(NetFwMgr), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwMgr), (void**)&fwMgr );
-       require(SUCCEEDED(err), exit);
+       require(SUCCEEDED(err) && ( fwMgr != NULL ), exit);
 
        // Use the reference to get the local firewall policy
 
        err = fwMgr->get_LocalPolicy(&fwPolicy);
-       require(SUCCEEDED(err), exit);
+       require(SUCCEEDED(err) && ( fwPolicy != NULL ), exit);
 
        // Use the reference to get the extant profile. Empirical evidence
        // suggests that there is the potential for a race condition when a system
@@ -156,16 +160,16 @@ mDNSFirewallAppIsEnabled
        // Get the list of authorized applications
 
        err = fwProfile->get_AuthorizedApplications(&fwApps);
-       require(SUCCEEDED(err), exit);
+       require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
 
     fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
-       require_action(SysStringLen(fwBstrProcessImageFileName) > 0, exit, err = kNoMemoryErr);
+       require_action( ( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
 
        // Look for us
 
     err = fwApps->Item(fwBstrProcessImageFileName, &fwApp);
        
-    if (SUCCEEDED(err))
+    if (SUCCEEDED(err) && ( fwApp != NULL ) )
     {
         // It's listed, but is it enabled?
 
@@ -186,7 +190,10 @@ exit:
 
        // Deallocate the BSTR
 
-    SysFreeString(fwBstrProcessImageFileName);
+       if ( fwBstrProcessImageFileName != NULL )
+       {
+               SysFreeString(fwBstrProcessImageFileName);
+       }
 
        // Release the COM objects
 
@@ -234,15 +241,15 @@ mDNSFirewallAddApp
                // Get the list of authorized applications
 
         err = fwProfile->get_AuthorizedApplications(&fwApps);
-               require(SUCCEEDED(err), exit);
+               require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
 
         // Create an instance of an authorized application.
 
                err = CoCreateInstance( __uuidof(NetFwAuthorizedApplication), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwAuthorizedApplication), (void**)&fwApp );
-               require(SUCCEEDED(err), exit);
+               require(SUCCEEDED(err) && ( fwApp != NULL ), exit);
 
         fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
-               require_action(SysStringLen(fwBstrProcessImageFileName) > 0, exit, err = kNoMemoryErr);
+               require_action(( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
 
                // Set the executable file name
 
@@ -250,7 +257,7 @@ mDNSFirewallAddApp
                require(SUCCEEDED(err), exit);
 
                fwBstrName = SysAllocString(fwName);
-               require_action(SysStringLen(fwBstrName) > 0, exit, err = kNoMemoryErr);
+               require_action( ( fwBstrName != NULL ) && ( SysStringLen(fwBstrName) > 0 ), exit, err = kNoMemoryErr);
 
                // Set the friendly name
 
@@ -269,8 +276,15 @@ exit:
 
        // Deallocate the BSTR objects
 
-    SysFreeString(fwBstrName);
-    SysFreeString(fwBstrProcessImageFileName);
+       if ( fwBstrName != NULL )
+       {
+               SysFreeString(fwBstrName);
+       }
+
+       if ( fwBstrProcessImageFileName != NULL )
+       {
+               SysFreeString(fwBstrProcessImageFileName);
+       }
 
     // Release the COM objects
 
@@ -285,6 +299,57 @@ exit:
     }
 
     return err;
+}\r
+\r
+\r
+static OSStatus\r
+mDNSFirewallIsFileAndPrintSharingEnabled\r
+       (\r
+       IN INetFwProfile        * fwProfile,\r
+       OUT BOOL                        * fwServiceEnabled\r
+       )\r
+{\r
+    VARIANT_BOOL fwEnabled;\r
+    INetFwService* fwService = NULL;\r
+    INetFwServices* fwServices = NULL;\r
+       OSStatus err = S_OK;\r
+\r
+    _ASSERT(fwProfile != NULL);\r
+    _ASSERT(fwServiceEnabled != NULL);\r
+\r
+    *fwServiceEnabled = FALSE;\r
+\r
+    // Retrieve the globally open ports collection.\r
+    err = fwProfile->get_Services(&fwServices);\r
+       require( SUCCEEDED( err ), exit );\r
+\r
+    // Attempt to retrieve the globally open port.\r
+    err = fwServices->Item(NET_FW_SERVICE_FILE_AND_PRINT, &fwService);\r
+       require( SUCCEEDED( err ), exit );\r
+       \r
+       // Find out if the globally open port is enabled.\r
+    err = fwService->get_Enabled(&fwEnabled);\r
+       require( SUCCEEDED( err ), exit );\r
+       if (fwEnabled != VARIANT_FALSE)\r
+       {\r
+               *fwServiceEnabled = TRUE;\r
+       }\r
+\r
+exit:\r
+\r
+    // Release the globally open port.\r
+    if (fwService != NULL)\r
+    {\r
+        fwService->Release();\r
+    }\r
+\r
+    // Release the globally open ports collection.\r
+    if (fwServices != NULL)\r
+    {\r
+        fwServices->Release();\r
+    }\r
+\r
+    return err;\r
 }
 
 
@@ -315,7 +380,7 @@ mDNSAddToFirewall
        // Connect to the firewall
 
        err = mDNSFirewallInitialize(&fwProfile);
-       require_noerr(err, exit);
+       require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
 
        // Add us to the list of exempt programs
 
@@ -326,7 +391,10 @@ exit:
 
        // Disconnect from the firewall
 
-       mDNSFirewallCleanup(fwProfile);
+       if ( fwProfile != NULL )
+       {
+               mDNSFirewallCleanup(fwProfile);
+       }
 
        // De-initialize COM
 
@@ -337,3 +405,52 @@ exit:
 
        return err;
 }
+
+
+BOOL
+mDNSIsFileAndPrintSharingEnabled()
+{
+       INetFwProfile   *       fwProfile                                       = NULL;
+       HRESULT                         comInit                                         = E_FAIL;
+       BOOL                            enabled                                         = FALSE;
+       OSStatus                        err                                                     = kNoErr;
+
+       // Initialize COM.
+
+       comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
+
+       // Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
+       // initialized with a different mode.
+
+       if (comInit != RPC_E_CHANGED_MODE)
+       {
+               err = comInit;
+               require(SUCCEEDED(err), exit);
+       }
+
+       // Connect to the firewall
+
+       err = mDNSFirewallInitialize(&fwProfile);
+       require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
+
+       err = mDNSFirewallIsFileAndPrintSharingEnabled( fwProfile, &enabled );
+       require_noerr( err, exit );
+
+exit:
+
+       // Disconnect from the firewall
+
+       if ( fwProfile != NULL )
+       {
+               mDNSFirewallCleanup(fwProfile);
+       }
+
+       // De-initialize COM
+
+       if (SUCCEEDED(comInit))
+    {
+        CoUninitialize();
+    }
+
+       return enabled;
+}
index e84a93044affd62722a81c7198c9ef0e707e6cdf..155ac9af594ab9bcdc51f7c634b8cca84318ffc7 100755 (executable)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: Firewall.h,v $
+Revision 1.3  2009/04/24 04:55:26  herscher
+<rdar://problem/3496833> Advertise SMB file sharing via Bonjour
+
 Revision 1.2  2006/08/14 23:26:07  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -71,6 +74,10 @@ mDNSAddToFirewall
                );
 
 
+BOOL
+mDNSIsFileAndPrintSharingEnabled();
+
+
 
 
 
index dfe06d1efad4dc3b4667e906093e096ef0cc2f3a..8671e0b9f47a22e7ecead318a66a934fe767fbf3 100644 (file)
     Change History (most recent first):
     
 $Log: Service.c,v $
+Revision 1.46  2009/06/05 18:28:24  herscher
+<rdar://problem/6125087> mDNSResponder should be able to identify VPN adapters generically
+<rdar://problem/6885843> WIN7: Bonjour removes the default gateway entry and thereby breaks network connectivity
+
+Revision 1.45  2009/04/30 20:07:51  mcguire
+<rdar://problem/6822674> Support multiple UDSs from launchd
+
+Revision 1.44  2009/03/30 20:41:36  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/6330821> Bonjour for Windows incompatible w/Juniper Network Connect. Do a substring search for "Juniper" in the description field
+ of the network adapter.
+<rdar://problem/6122028> Bonjour for Windows incompatible w/Cisco AnyConnect VPN Client
+<rdar://problem/5652098> Bonjour for Windows incompatible w/Juniper Network Connect. Update the adapter name per info received from Juniper
+<rdar://problem/5781566> Core: Default Gateway set to 0.0.0.0 on Vista causes ARP flood
+<rdar://problem/5991983> Change the registry values from Apple Computer, Inc. to Apple Inc.
+<rdar://problem/5301328> wchar/sizeof mismatch in CheckFirewall()
+
+Revision 1.43  2009/01/13 05:31:35  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
 Revision 1.42  2007/02/14 01:58:19  cheshire
 <rdar://problem/4995831> Don't delete Unix Domain Socket on exit if we didn't create it on startup
 
@@ -168,6 +188,8 @@ mDNSResponder Windows Service. Provides global Bonjour support with an IPC inter
 
 #include       <stdio.h>
 #include       <stdlib.h>
+#include       <stdarg.h>
+#include       <stddef.h>
 
 
 #include       "CommonServices.h"
@@ -188,10 +210,17 @@ mDNSResponder Windows Service. Provides global Bonjour support with an IPC inter
        #include        <mswsock.h>
        #include        <process.h>
        #include        <ipExport.h>
+       #include        <ws2def.h>
+       #include        <ws2ipdef.h>
        #include        <iphlpapi.h>
+       #include        <netioapi.h>
        #include        <iptypes.h>
 #endif
 
+#ifndef HeapEnableTerminationOnCorruption
+#      define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS)1
+#endif
+
 #if 0
 #pragma mark == Constants ==
 #endif
@@ -205,6 +234,9 @@ mDNSResponder Windows Service. Provides global Bonjour support with an IPC inter
 #define        kServiceDependencies                            TEXT("Tcpip\0\0")
 #define        kDNSServiceCacheEntryCountDefault       512
 #define kRetryFirewallPeriod                           30 * 1000
+#define kDefValueSize                                          MAX_PATH + 1
+#define kZeroIndex                                                     0
+#define kDefaultRouteMetric                                    399
 
 #define RR_CACHE_SIZE 500
 static CacheEntity gRRCache[RR_CACHE_SIZE];
@@ -292,8 +324,12 @@ static void                        CoreCallback(mDNS * const inMDNS, mStatus result);
 static void                    HostDescriptionChanged(mDNS * const inMDNS);
 static OSStatus                GetRouteDestination(DWORD * ifIndex, DWORD * address);
 static OSStatus                SetLLRoute( mDNS * const inMDNS );
-static bool                    HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr );
+static bool                    HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr, unsigned long metric );
 static bool                    IsValidAddress( const char * addr );
+static bool                    IsNortelVPN( IP_ADAPTER_INFO * pAdapter );
+static bool                    IsJuniperVPN( IP_ADAPTER_INFO * pAdapter );
+static bool                    IsCiscoVPN( IP_ADAPTER_INFO * pAdapter );
+static const char * strnistr( const char * string, const char * subString, size_t max );
 
 #if defined(UNICODE)
 #      define StrLen(X)        wcslen(X)
@@ -337,6 +373,12 @@ DEBUG_LOCAL HANDLE                                         gStopEvent                              = NULL;
 DEBUG_LOCAL CRITICAL_SECTION                   gEventSourceLock;
 DEBUG_LOCAL GenLinkedList                              gEventSources;
 DEBUG_LOCAL BOOL                                               gRetryFirewall                  = FALSE;
+DEBUG_LOCAL DWORD                                              gOSMajorVersion;
+DEBUG_LOCAL DWORD                                              gOSMinorVersion;
+
+typedef DWORD ( WINAPI * GetIpInterfaceEntryFunctionPtr )( PMIB_IPINTERFACE_ROW );
+mDNSlocal HMODULE                                                              gIPHelperLibraryInstance                = NULL;
+mDNSlocal GetIpInterfaceEntryFunctionPtr               gGetIpInterfaceEntryFunctionPtr = NULL;
 
 
 #if 0
@@ -356,6 +398,8 @@ int __cdecl main( int argc, char *argv[] )
        BOOL                    ok;
        BOOL                    start;
        int                             i;
+
+       HeapSetInformation( NULL, HeapEnableTerminationOnCorruption, NULL, 0 );
        
        debug_initialize( kDebugOutputTypeMetaConsole );
        debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
@@ -798,7 +842,7 @@ static OSStatus CheckFirewall()
 
                // Get a full path to the executable
 
-               size = GetModuleFileNameW( NULL, fullPath, sizeof( fullPath ) );
+               size = GetModuleFileNameW( NULL, fullPath, MAX_PATH );
                err = translate_errno( size > 0, (OSStatus) GetLastError(), kPathErr );
                require_noerr( err, exit );
 
@@ -1164,16 +1208,22 @@ static OSStatus ServiceRun( int argc, LPTSTR argv[] )
        
        initialized = FALSE;
        
-       // Initialize the service-specific stuff and mark the service as running.
+       // <rdar://problem/5727548> Make the service as running before we call ServiceSpecificInitialize. We've
+       // had reports that some machines with McAfee firewall installed cause a problem with iTunes installation.
+       // We think that the firewall product is interferring with code in ServiceSpecificInitialize. So as a
+       // simple workaround, we'll mark us as running *before* we call ServiceSpecificInitialize. This will unblock
+       // any installers that are waiting for our state to change.
+
+       gServiceStatus.dwCurrentState = SERVICE_RUNNING;
+       ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
+       check_translated_errno( ok, GetLastError(), kParamErr );
+
+       // Initialize the service-specific stuff
        
        err = ServiceSpecificInitialize( argc, argv );
        require_noerr( err, exit );
        initialized = TRUE;
        
-       gServiceStatus.dwCurrentState = SERVICE_RUNNING;
-       ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
-       check_translated_errno( ok, GetLastError(), kParamErr );
-       
        err = CheckFirewall();
        check_noerr( err );
 
@@ -1232,13 +1282,15 @@ static void     ServiceStop( void )
 
 static OSStatus        ServiceSpecificInitialize( int argc, LPTSTR argv[] )
 {
-       OSStatus                                                err;
+       OSVERSIONINFO osInfo;
+       OSStatus err;
+       BOOL ok;
        
        DEBUG_UNUSED( argc );
        DEBUG_UNUSED( argv );
        
-       memset( &gMDNSRecord, 0, sizeof gMDNSRecord);
-       memset( &gPlatformStorage, 0, sizeof gPlatformStorage);
+       mDNSPlatformMemZero( &gMDNSRecord, sizeof gMDNSRecord);
+       mDNSPlatformMemZero( &gPlatformStorage, sizeof gPlatformStorage);
 
        gPlatformStorage.idleThreadCallback = udsIdle;
        gPlatformStorage.hostDescriptionChangedCallback = HostDescriptionChanged;
@@ -1252,19 +1304,20 @@ static OSStatus ServiceSpecificInitialize( int argc, LPTSTR argv[] )
        err = mDNS_Init( &gMDNSRecord, &gPlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses, CoreCallback, mDNS_Init_NoInitCallbackContext); 
        require_noerr( err, exit);
 
-       err = udsserver_init(dnssd_InvalidSocket);
+       err = udsserver_init(mDNSNULL, 0);
        require_noerr( err, exit);
 
        //
-       // <rdar://problem/4096464> Don't call SetLLRoute on loopback
-       // 
-       // Otherwise, set a route to link local addresses (169.254.0.0)
+       // Get the version of Windows that we're running on
        //
+       osInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+       ok = GetVersionEx( &osInfo );
+       err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+       gOSMajorVersion = osInfo.dwMajorVersion;
+       gOSMinorVersion = osInfo.dwMinorVersion;
 
-       if ( gServiceManageLLRouting && !gPlatformStorage.registeredLoopback4 )
-       {
-               SetLLRoute( &gMDNSRecord );
-       }
+       SetLLRoute( &gMDNSRecord );
 
 exit:
        if( err != kNoErr )
@@ -1346,7 +1399,7 @@ static void       ServiceSpecificFinalize( int argc, LPTSTR argv[] )
        //
        // give a chance for the udsserver code to clean up
        //
-       udsserver_exit(dnssd_InvalidSocket);
+       udsserver_exit();
 
        //
        // and finally close down the mDNSCore
@@ -1357,6 +1410,18 @@ static void      ServiceSpecificFinalize( int argc, LPTSTR argv[] )
        // clean up the event sources mutex...no one should be using it now
        //
        DeleteCriticalSection(&gEventSourceLock);
+
+       //
+       // clean up loaded library
+       //
+
+       if( gIPHelperLibraryInstance )
+       {
+               gGetIpInterfaceEntryFunctionPtr = NULL;
+               
+               FreeLibrary( gIPHelperLibraryInstance );
+               gIPHelperLibraryInstance = NULL;
+       }
 }
 
 
@@ -1365,16 +1430,7 @@ CoreCallback(mDNS * const inMDNS, mStatus status)
 {
        if (status == mStatus_ConfigChanged)
        {
-               //
-               // <rdar://problem/4096464> Don't call SetLLRoute on loopback
-               // 
-               // Otherwise, set a route to link local addresses (169.254.0.0)
-               //
-
-               if ( gServiceManageLLRouting && !inMDNS->p->registeredLoopback4 )
-               {
-                       SetLLRoute( inMDNS );
-               }
+               SetLLRoute( inMDNS );
        }
 }
 
@@ -1465,7 +1521,7 @@ udsSocketThread(LPVOID inParam)
                //
                if (result == WAIT_OBJECT_0)
                {
-                       source->callback(source->context);
+                       source->callback( (int) source->sock, 0, source->context);
                }
                //
                // close event
@@ -1477,7 +1533,7 @@ udsSocketThread(LPVOID inParam)
                        // so we'll go in here and it will clean up for us
                        //
                        shutdown(source->sock, 2);
-                       source->callback(source->context);
+                       source->callback( (int) source->sock, 0, source->context);
 
                        break;
                }
@@ -1525,7 +1581,7 @@ udsSupportAddFDToEventLoop( SocketRef fd, udsEventCallback callback, void *conte
 
        newSource = malloc(sizeof(Win32EventSource));
        require_action( newSource, exit, err = mStatus_NoMemoryErr );
-       memset(newSource, 0, sizeof(Win32EventSource));
+       mDNSPlatformMemZero(newSource, sizeof(Win32EventSource));
 
        newSource->flags        = 0;
        newSource->sock         = (SOCKET) fd;
@@ -1783,7 +1839,7 @@ EventSourceUnlock()
 //===========================================================================================================================
 
 static bool
-HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr )
+HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr, unsigned long metric )
 {
        PMIB_IPFORWARDTABLE     pIpForwardTable = NULL;
        DWORD                           dwSize                  = 0;
@@ -1815,7 +1871,7 @@ HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr )
        //
        for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
        {
-               if ( pIpForwardTable->table[i].dwForwardDest == addr )
+               if ( ( pIpForwardTable->table[i].dwForwardDest == addr ) && ( !metric || ( pIpForwardTable->table[i].dwForwardMetric1 == metric ) ) )
                {
                        memcpy( rowExtant, &(pIpForwardTable->table[i]), sizeof(*rowExtant) );
                        found = true;
@@ -1846,124 +1902,128 @@ IsValidAddress( const char * addr )
 
 
 //===========================================================================================================================
-//     SetLLRoute
+//     GetAdditionalMetric
 //===========================================================================================================================
 
-static OSStatus
-SetLLRoute( mDNS * const inMDNS )
+static ULONG
+GetAdditionalMetric( DWORD ifIndex )
 {
-       DWORD                           ifIndex;
-       MIB_IPFORWARDROW        rowExtant;
-       bool                            addRoute;
-       MIB_IPFORWARDROW        row;
-       OSStatus                        err;
+       ULONG metric = 0;
 
-       ZeroMemory(&row, sizeof(row));
-
-       err = GetRouteDestination(&ifIndex, &row.dwForwardNextHop);
-       require_noerr( err, exit );
-       row.dwForwardDest               = inet_addr(kLLNetworkAddr);
-       row.dwForwardIfIndex    = ifIndex;
-       row.dwForwardMask               = inet_addr(kLLNetworkAddrMask);
-       row.dwForwardType               = 3;
-       row.dwForwardProto              = MIB_IPPROTO_NETMGMT;
-       row.dwForwardAge                = 0;
-       row.dwForwardPolicy             = 0;
-       row.dwForwardMetric1    = 30;
-       row.dwForwardMetric2    = (DWORD) - 1;
-       row.dwForwardMetric3    = (DWORD) - 1;
-       row.dwForwardMetric4    = (DWORD) - 1;
-       row.dwForwardMetric5    = (DWORD) - 1;
-
-       addRoute = true;
-
-       //
-       // check to make sure we don't already have a route
-       //
-       if ( HaveRoute( &rowExtant, inet_addr( kLLNetworkAddr ) ) )
+       if( !gIPHelperLibraryInstance )
        {
-               //
-               // set the age to 0 so that we can do a memcmp.
-               //
-               rowExtant.dwForwardAge = 0;
+               gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
 
-               //
-               // check to see if this route is the same as our route
-               //
-               if (memcmp(&row, &rowExtant, sizeof(row)) != 0)
-               {
-                       //
-                       // if it isn't then delete this entry
-                       //
-                       DeleteIpForwardEntry(&rowExtant);
-               }
-               else
-               {
-                       //
-                       // else it is, so we don't want to create another route
-                       //
-                       addRoute = false;
+               gGetIpInterfaceEntryFunctionPtr = 
+                               (GetIpInterfaceEntryFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetIpInterfaceEntry" );
+
+               if( !gGetIpInterfaceEntryFunctionPtr )
+               {               
+                       BOOL ok;
+                               
+                       ok = FreeLibrary( gIPHelperLibraryInstance );
+                       check_translated_errno( ok, GetLastError(), kUnknownErr );
+                       gIPHelperLibraryInstance = NULL;
                }
        }
 
-       if (addRoute && row.dwForwardNextHop)
+       if ( gGetIpInterfaceEntryFunctionPtr )
        {
-               err = CreateIpForwardEntry(&row);
+               MIB_IPINTERFACE_ROW row;
+               DWORD err;
 
+               ZeroMemory( &row, sizeof( MIB_IPINTERFACE_ROW ) );
+               row.Family = AF_INET;
+               row.InterfaceIndex = ifIndex;
+               err = gGetIpInterfaceEntryFunctionPtr( &row );
                require_noerr( err, exit );
+               metric = row.Metric + 256;
        }
 
+exit:
+
+       return metric;
+}
+
+
+//===========================================================================================================================
+//     SetLLRoute
+//===========================================================================================================================
+
+static OSStatus
+SetLLRoute( mDNS * const inMDNS )
+{
+       OSStatus err = kNoErr;
+
+       DEBUG_UNUSED( inMDNS );
+
        //
-       // Now we want to see if we should install a default route for this interface.
-       // We want to do this if the following are true:
-       //
-       // 1. This interface has a link-local address
-       // 2. This is the only IPv4 interface
+       // <rdar://problem/4096464> Don't call SetLLRoute on loopback
+       // <rdar://problem/6885843> Default route on Windows 7 breaks network connectivity
+       // 
+       // Don't mess w/ the routing table on Vista and later OSes, as 
+       // they have a permanent route to link-local addresses. Otherwise,
+       // set a route to link local addresses (169.254.0.0)
        //
-
-       if ( ( row.dwForwardNextHop & 0xFFFF ) == row.dwForwardDest )
+       if ( ( gOSMajorVersion < 6 ) && gServiceManageLLRouting && !gPlatformStorage.registeredLoopback4 )
        {
-               mDNSInterfaceData       *       ifd;
-               int                                             numLinkLocalInterfaces  = 0;
-               int                                             numInterfaces                   = 0;
-       
-               for ( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
-               {
-                       if ( ifd->defaultAddr.type == mDNSAddrType_IPv4 )
-                       {
-                               numInterfaces++;
+               DWORD                           ifIndex;
+               MIB_IPFORWARDROW        rowExtant;
+               bool                            addRoute;
+               MIB_IPFORWARDROW        row;
 
-                               if ( ( ifd->interfaceInfo.ip.ip.v4.b[0] == 169 ) && ( ifd->interfaceInfo.ip.ip.v4.b[1] == 254 ) )
-                               {
-                                       numLinkLocalInterfaces++;
-                               }
-                       }
-               }
+               ZeroMemory(&row, sizeof(row));
 
-               row.dwForwardDest               = 0;
+               err = GetRouteDestination(&ifIndex, &row.dwForwardNextHop);
+               require_noerr( err, exit );
+               row.dwForwardDest               = inet_addr(kLLNetworkAddr);
                row.dwForwardIfIndex    = ifIndex;
-               row.dwForwardMask               = 0;
+               row.dwForwardMask               = inet_addr(kLLNetworkAddrMask);
                row.dwForwardType               = 3;
                row.dwForwardProto              = MIB_IPPROTO_NETMGMT;
                row.dwForwardAge                = 0;
                row.dwForwardPolicy             = 0;
-               row.dwForwardMetric1    = 20;
+               row.dwForwardMetric1    = 20 + GetAdditionalMetric( ifIndex );
                row.dwForwardMetric2    = (DWORD) - 1;
                row.dwForwardMetric3    = (DWORD) - 1;
                row.dwForwardMetric4    = (DWORD) - 1;
                row.dwForwardMetric5    = (DWORD) - 1;
-               
-               if ( numInterfaces == numLinkLocalInterfaces )
+
+               addRoute = true;
+
+               //
+               // check to make sure we don't already have a route
+               //
+               if ( HaveRoute( &rowExtant, inet_addr( kLLNetworkAddr ), 0 ) )
                {
-                       if ( !HaveRoute( &row, 0 ) )
+                       //
+                       // set the age to 0 so that we can do a memcmp.
+                       //
+                       rowExtant.dwForwardAge = 0;
+
+                       //
+                       // check to see if this route is the same as our route
+                       //
+                       if (memcmp(&row, &rowExtant, sizeof(row)) != 0)
                        {
-                               err = CreateIpForwardEntry(&row);
-                               require_noerr( err, exit );
+                               //
+                               // if it isn't then delete this entry
+                               //
+                               DeleteIpForwardEntry(&rowExtant);
+                       }
+                       else
+                       {
+                               //
+                               // else it is, so we don't want to create another route
+                               //
+                               addRoute = false;
                        }
                }
-               else
+
+               if (addRoute && row.dwForwardNextHop)
                {
-                       DeleteIpForwardEntry( &row );
+                       err = CreateIpForwardEntry(&row);
+                       check_noerr( err );
                }
        }
 
@@ -2019,25 +2079,19 @@ GetRouteDestination(DWORD * ifIndex, DWORD * address)
        err                     =       kUnknownErr;
                        
        // <rdar://problem/3718122>
+       // <rdar://problem/5652098>
        //
-       // Look for the Nortel VPN virtual interface.  This interface
-       // is identified by it's unique MAC address: 44-45-53-54-42-00
+       // Look for the Nortel VPN virtual interface, along with Juniper virtual interface.
        //
-       // If the interface is active (i.e., has a non-zero IP Address),
+       // If these interfaces are active (i.e., has a non-zero IP Address),
        // then we want to disable routing table modifications.
 
        while (pAdapter)
        {
-               if ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) &&
-                   (pAdapter->AddressLength == 6) &&
-                   (pAdapter->Address[0] == 0x44) &&
-                   (pAdapter->Address[1] == 0x45) &&
-                   (pAdapter->Address[2] == 0x53) &&
-                   (pAdapter->Address[3] == 0x54) &&
-                   (pAdapter->Address[4] == 0x42) &&
-                   (pAdapter->Address[5] == 0x00) &&
-                       (inet_addr( pAdapter->IpAddressList.IpAddress.String ) != 0))
+               if ( ( IsNortelVPN( pAdapter ) || IsJuniperVPN( pAdapter ) || IsCiscoVPN( pAdapter ) ) &&
+                        ( inet_addr( pAdapter->IpAddressList.IpAddress.String ) != 0 ) )
                {
+                       dlog( kDebugLevelTrace, DEBUG_NAME "disabling routing table management due to VPN incompatibility" );
                        goto exit;
                }
 
@@ -2089,3 +2143,89 @@ exit:
 
        return( err );
 }
+
+
+static bool
+IsNortelVPN( IP_ADAPTER_INFO * pAdapter )
+{
+       return ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) &&
+                   (pAdapter->AddressLength == 6) &&
+                   (pAdapter->Address[0] == 0x44) &&
+                   (pAdapter->Address[1] == 0x45) &&
+                   (pAdapter->Address[2] == 0x53) &&
+                   (pAdapter->Address[3] == 0x54) &&
+                   (pAdapter->Address[4] == 0x42) &&
+                       (pAdapter->Address[5] == 0x00)) ? true : false;
+}
+
+
+static bool
+IsJuniperVPN( IP_ADAPTER_INFO * pAdapter )
+{      
+       return ( strnistr( pAdapter->Description, "Juniper", sizeof( pAdapter->Description  ) ) != NULL ) ? true : false;
+}
+
+
+static bool
+IsCiscoVPN( IP_ADAPTER_INFO * pAdapter )
+{
+       return ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) &&
+                   (pAdapter->AddressLength == 6) &&
+                   (pAdapter->Address[0] == 0x00) &&
+                   (pAdapter->Address[1] == 0x05) &&
+                   (pAdapter->Address[2] == 0x9a) &&
+                   (pAdapter->Address[3] == 0x3c) &&
+                   (pAdapter->Address[4] == 0x7a) &&
+                       (pAdapter->Address[5] == 0x00)) ? true : false;
+}
+
+
+static const char *
+strnistr( const char * string, const char * subString, size_t max )
+{
+       size_t       subStringLen;
+       size_t       offset;
+       size_t       maxOffset;
+       size_t       stringLen;
+       const char * pPos;
+
+       if ( ( string == NULL ) || ( subString == NULL ) )
+       {
+               return string;
+       }
+
+       stringLen = ( max > strlen( string ) ) ? strlen( string ) : max;
+
+       if ( stringLen == 0 )
+       {
+               return NULL;
+       }
+       
+       subStringLen = strlen( subString );
+
+       if ( subStringLen == 0 )
+       {
+               return string;
+       }
+
+       if ( subStringLen > stringLen )
+       {
+               return NULL;
+       }
+
+       maxOffset = stringLen - subStringLen;
+       pPos      = string;
+
+       for ( offset = 0; offset <= maxOffset; offset++ )
+       {
+               if ( _strnicmp( pPos, subString, subStringLen ) == 0 )
+               {
+                       return pPos;
+               }
+
+               pPos++;
+       }
+
+       return NULL;
+}
+
index e25dc6e08a7e769e6e5e75223d655f36e97ea50d..d16d01706c0d857e370e9335f829ef7e4ce7bfcd 100644 (file)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="mDNSResponder"\r
        ProjectGUID="{C1D98254-BA27-4427-A3BE-A68CA2CC5F69}"\r
-       Keyword="Win32Proj">\r
+       Keyword="Win32Proj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0500;DEBUG=1;MDNS_DEBUGMSGS=0;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="TRUE"\r
-                               ExceptionHandling="FALSE"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;&quot;C:/Program Files/Microsoft SDKs/Windows/v6.1/Include&quot;"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;DEBUG=1;MDNS_DEBUGMSGS=0;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_LEGACY_NAT_TRAVERSAL_"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
                                BasicRuntimeChecks="3"\r
-                               SmallerTypeCheck="TRUE"\r
+                               SmallerTypeCheck="true"\r
                                RuntimeLibrary="1"\r
-                               BufferSecurityCheck="TRUE"\r
+                               BufferSecurityCheck="true"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="4"\r
-                               CallingConvention="2"/>\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                               DisableSpecificWarnings="4127"\r
+                               ShowIncludes="false"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="ws2_32.lib iphlpapi.lib crypt32.lib"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="ws2_32.lib iphlpapi.lib crypt32.lib netapi32.lib"\r
                                OutputFile="$(OutDir)/mDNSResponder.exe"\r
                                LinkIncremental="2"\r
-                               IgnoreAllDefaultLibraries="FALSE"\r
-                               GenerateDebugInformation="TRUE"\r
+                               IgnoreAllDefaultLibraries="false"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/mDNSResponder.pdb"\r
                                SubSystem="1"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\mDNSResponder.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;&quot;C:/Program Files/Microsoft SDKs/Windows/v6.1/Include&quot;"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;DEBUG=1;MDNS_DEBUGMSGS=0;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_LEGACY_NAT_TRAVERSAL_"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
+                               BasicRuntimeChecks="3"\r
+                               SmallerTypeCheck="true"\r
+                               RuntimeLibrary="1"\r
+                               BufferSecurityCheck="true"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                               DisableSpecificWarnings="4127"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="ws2_32.lib iphlpapi.lib crypt32.lib netapi32.lib"\r
+                               OutputFile="$(OutDir)/mDNSResponder.exe"\r
+                               LinkIncremental="2"\r
+                               IgnoreAllDefaultLibraries="false"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/mDNSResponder.pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="17"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCALinkTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\mDNSResponder64.manifest"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0500;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;&quot;C:/Program Files/Microsoft SDKs/Windows/v6.1/Include&quot;"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_LEGACY_NAT_TRAVERSAL_"\r
                                RuntimeLibrary="0"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="3"/>\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               DisableSpecificWarnings="4127"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="ws2_32.lib iphlpapi.lib netapi32.lib"\r
                                OutputFile="$(OutDir)/mDNSResponder.exe"\r
                                LinkIncremental="1"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
                                SubSystem="1"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\mDNSResponder.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                  &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;&quot;C:/Program Files/Microsoft SDKs/Windows/v6.1/Include&quot;"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;_LEGACY_NAT_TRAVERSAL_"\r
+                               RuntimeLibrary="0"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               DisableSpecificWarnings="4127"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="ws2_32.lib iphlpapi.lib netapi32.lib"\r
+                               OutputFile="$(OutDir)/mDNSResponder.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                               AdditionalManifestFiles="res\mDNSResponder64.manifest"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                  &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
                <Filter\r
                        Name="Source Files"\r
                        Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
-                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\DebugServices.c"\r
+                               >\r
+                       </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.c">\r
+                               RelativePath="..\..\mDNSCore\DNSCommon.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\DNSCommon.c">\r
+                               RelativePath="..\..\mDNSCore\DNSDigest.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\DNSDigest.c">\r
+                               RelativePath="..\..\mDNSShared\dnssd_ipc.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dnssd_ipc.c">\r
+                               RelativePath="Firewall.cpp"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="Firewall.cpp">\r
+                               RelativePath="..\..\mDNSShared\GenLinkedList.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\GenLinkedList.c">\r
+                               RelativePath="..\..\mDNSMacOSX\LegacyNATTraversal.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\mDNS.c">\r
+                               RelativePath="..\..\mDNSCore\mDNS.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\mDNSDebug.c">\r
+                               RelativePath="..\..\mDNSShared\mDNSDebug.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\mDNSWin32.c">\r
+                               RelativePath="..\mDNSWin32.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\VPCDetect.cpp">\r
+                               RelativePath="..\Secret.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\Service.c">\r
+                               RelativePath=".\Service.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\uDNS.c">\r
+                               RelativePath="..\..\mDNSCore\uDNS.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\uds_daemon.c">\r
+                               RelativePath="..\..\mDNSShared\uds_daemon.c"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                        Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
-                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\CommonServices.h">\r
+                               RelativePath="..\..\mDNSShared\CommonServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.h">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\DNSCommon.h">\r
+                               RelativePath="..\..\mDNSCore\DNSCommon.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dnssd_ipc.h">\r
+                               RelativePath="..\..\mDNSShared\dnssd_ipc.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\GenLinkedList.h">\r
+                               RelativePath="..\..\mDNSShared\GenLinkedList.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\mDNSDebug.h">\r
+                               RelativePath="..\..\mDNSCore\mDNSDebug.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\mDNSEmbeddedAPI.h">\r
+                               RelativePath="..\..\mDNSCore\mDNSEmbeddedAPI.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\mDNSWin32.h">\r
+                               RelativePath="..\mDNSWin32.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\VPCDetect.h">\r
+                               RelativePath=".\Resource.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\Resource.h">\r
+                               RelativePath="..\Secret.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\uDNS.h">\r
+                               RelativePath="..\..\mDNSCore\uDNS.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\uds_daemon.h">\r
+                               RelativePath="..\..\mDNSShared\uds_daemon.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
                        Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
-                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
                        <File\r
-                               RelativePath=".\Service.rc">\r
+                               RelativePath=".\Service.rc"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r
diff --git a/mDNSWindows/SystemService/res/mDNSResponder.manifest b/mDNSWindows/SystemService/res/mDNSResponder.manifest
new file mode 100644 (file)
index 0000000..7275854
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+       <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Apple.Bonjour.mDNSResponder" type="win32"/>
+       <description>Enables hardware devices and software services to automatically configure themselves and advertise their presence on the network.</description>
+       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+               <security>
+                       <requestedPrivileges>
+                               <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
+                       </requestedPrivileges>
+               </security>
+       </trustInfo>
+</assembly>
diff --git a/mDNSWindows/SystemService/res/mDNSResponder64.manifest b/mDNSWindows/SystemService/res/mDNSResponder64.manifest
new file mode 100644 (file)
index 0000000..13b3998
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+       <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Apple.Bonjour.ControlPanel" type="win32"/>
+       <description>Enables hardware devices and software services to automatically configure themselves and advertise their presence on the network.</description>
+       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+               <security>
+                       <requestedPrivileges>
+                               <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
+                       </requestedPrivileges>
+               </security>
+       </trustInfo>
+</assembly>
index 654b07a5b074e8ad8f1081a7c137a950b657b30c..b3b5551a94e996fef6efdca691ccc09ccc7abff9 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: WinServices.cpp,v $
+Revision 1.3  2009/06/22 23:25:04  herscher
+<rdar://problem/5265747> ControlPanel doesn't display key and password in dialog box. Refactor Lsa calls into Secret.h and Secret.c, which is used by both the ControlPanel and mDNSResponder system service.
+
 Revision 1.2  2006/08/14 23:25:20  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -27,6 +30,7 @@ First checked in
 */
 
 #include "WinServices.h"
+#include <DebugServices.h>
 
 
 //===========================================================================================================================
@@ -75,3 +79,29 @@ exit:
        }
        return( err );
 }
+
+
+//===========================================================================================================================
+//     UTF8StringToStringObject
+//===========================================================================================================================
+
+OSStatus
+StringObjectToUTF8String( CString &inObject, char* outUTF8, size_t outUTF8Len )
+{
+    OSStatus err = kNoErr;
+
+       memset( outUTF8, 0, outUTF8Len );
+
+       if ( inObject.GetLength() > 0 )
+    {
+               size_t size;
+
+               size = (size_t) WideCharToMultiByte( CP_UTF8, 0, inObject.GetBuffer(), inObject.GetLength(), outUTF8, (int) outUTF8Len, NULL, NULL);
+        err = translate_errno( size != 0, GetLastError(), kUnknownErr );
+        require_noerr( err, exit );
+    }
+
+exit:
+
+       return err;
+}
index 9d9db91d4bba5059893a66938eaaaf5dc6edd770..8909cd1a4472d94572b64ffce11cbca8a504c687 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: WinServices.h,v $
+Revision 1.3  2009/06/22 23:25:05  herscher
+<rdar://problem/5265747> ControlPanel doesn't display key and password in dialog box. Refactor Lsa calls into Secret.h and Secret.c, which is used by both the ControlPanel and mDNSResponder system service.
+
 Revision 1.2  2006/08/14 23:25:21  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -41,4 +44,5 @@ First checked in
 #include "CommonServices.h"
 
 
-OSStatus       UTF8StringToStringObject( const char *inUTF8, CString &inObject );
+OSStatus       UTF8StringToStringObject( const char *inUTF8, CString &outObject );
+OSStatus       StringObjectToUTF8String( CString &inObject, char* outUTF8, size_t outUTF8Len );
index 8c436e0fcd380a42e748276fb2582e107805fb67..b155515a05775ba9efa2ce24878170d2ef4faaa1 100644 (file)
     Change History (most recent first):
 
 $Log: WinVersRes.h,v $
+Revision 1.61  2009/06/30 17:37:32  herscher
+Bump to 2.0.0.5
+
+Revision 1.60  2009/06/15 18:03:41  herscher
+Bump to version 2.0.0.4
+
+Revision 1.59  2009/05/27 20:14:35  herscher
+Bump version to 2.0.0.3
+
+Revision 1.58  2009/05/26 21:13:35  herscher
+Bump to version 2.0.0.2
+
+Revision 1.57  2009/04/28 20:12:15  herscher
+Bump version to 2.0.0.1
+
+Revision 1.56  2009/04/02 22:04:43  herscher
+Bump to version 2.0.0.0
+
 Revision 1.55  2007/04/27 20:34:31  herscher
 <rdar://problem/5159673> mDNS: Company name needs to be changed to Apple Inc.
 
@@ -193,12 +211,12 @@ First checked in.
 #define MASTER_COMPANY_NAME   "Apple Inc."
 
 // Define the product version for mDNSResponder on Windows
-#define MASTER_PROD_VERS               1,0,3,1
-#define MASTER_PROD_VERS_STR   "1,0,3,1"
-#define MASTER_PROD_VERS_STR2  "1.0.3.1"
-#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.3.1"
+#define MASTER_PROD_VERS               2,0,0,5
+#define MASTER_PROD_VERS_STR   "2,0,0,5"
+#define MASTER_PROD_VERS_STR2  "2.0.0.5"
+#define MASTER_PROD_VERS_STR3 "Explorer Plugin 2.0.0.5"
 
 // Define the legal copyright
-#define MASTER_LEGAL_COPYRIGHT "Copyright (C) 2003-2007 Apple Inc."
+#define MASTER_LEGAL_COPYRIGHT "Copyright (C) 2003-2009 Apple Inc."
 
 #endif // WINRESVERS_H
index 953ef202f9821faeebd0fa584139750e85c15623..0edb6ff67251660e6ff85569a615f922eeeeea10 100755 (executable)
@@ -92,8 +92,8 @@ unsigned char ISOCODES[] = {
 4, 6, 'd','a', 0 , 0 , 0 , 0 ,
 4, 11, 'f','i', 0 , 0 , 0 , 0 ,
 4, 18, 'k','o', 0 , 0 , 0 , 0 ,
-4, 20, 'n','o', 0 , 0 , 0 , 0 ,
-8, 20, 'n','o', 0 , 0 , 0 , 0 ,
+4, 20, 'n','b', 0 , 0 , 0 , 0 ,
+8, 20, 'n','b', 0 , 0 , 0 , 0 ,
 4, 22, 'p','t', 0 , 0 , 0 , 0 ,
 4, 29, 's','v', 0 , 0 , 0 , 0 ,
 8, 29, 's','v', 0 , 0 , 0 , 0 ,
index 1cb1f6466bfecb946de6c96bba939b68b6ce39aa..8f1283f85b818ccbfc157a7469d0c41e2e80471f 100755 (executable)
     Change History (most recent first):
     
 $Log: mDNSWin32.c,v $
+Revision 1.142  2009/06/25 21:11:02  herscher
+<rdar://problem/7003607> Platform layer doesn't correctly initialize the port field of TCP and UDP socket structures.
+
+Revision 1.141  2009/06/22 23:25:05  herscher
+<rdar://problem/5265747> ControlPanel doesn't display key and password in dialog box. Refactor Lsa calls into Secret.h and Secret.c, which is used by both the ControlPanel and mDNSResponder system service.
+
+Revision 1.140  2009/04/24 04:55:26  herscher
+<rdar://problem/3496833> Advertise SMB file sharing via Bonjour
+
+Revision 1.139  2009/04/01 20:06:31  herscher
+<rdar://problem/5629676> Corrupt computer name string used
+
+Revision 1.138  2009/04/01 19:31:54  herscher
+Remove extraneous printf
+
+Revision 1.137  2009/04/01 17:50:15  mcguire
+cleanup mDNSRandom
+
+Revision 1.136  2009/03/30 20:53:10  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8.
+<rdar://problem/6145992> Reduce sleep from 3 seconds to 2 seconds
+<rdar://problem/6145992> Bonjour Service sometimes only gets a IPv6 link-local address after a network changed event
+<rdar://problem/6145913> Bonjour For Windows doesn't show IPv4 loopback intermittently when no network interfaces are active
+<rdar://problem/6143633> Bonjour service does not publish ANY IPv6 address on Windows Vista
+<rdar://problem/6136296> Bonjour 105A6: mDNSResponder is crashing on startup
+<rdar://problem/6127927> B4Windows: uDNS: Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+<rdar://problem/5270738> Remove Virtual PC check from mDNSResponder code
+
+Revision 1.135  2009/01/13 05:31:35  mkrochma
+<rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
+
+Revision 1.134  2008/10/23 22:33:25  cheshire
+Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
+
+Revision 1.133  2008/10/22 17:19:57  cheshire
+Don't need to define BPF_fd any more (it's now per-interface, not global)
+
+Revision 1.132  2008/10/03 23:34:08  cheshire
+Added skeleton definition of mDNSPlatformSendRawPacket
+
+Revision 1.131  2008/10/03 18:25:18  cheshire
+Instead of calling "m->MainCallback" function pointer directly, call mDNSCore routine "mDNS_ConfigChanged(m);"
+
 Revision 1.130  2007/11/16 18:53:56  cheshire
 TCPSocketFlags needs to be first field of TCPSocket_struct
 
@@ -114,8 +158,9 @@ Revision 1.106  2006/02/26 19:31:05  herscher
 
 #include       "CommonServices.h"
 #include       "DebugServices.h"
-#include       "VPCDetect.h"
+#include       "Firewall.h"
 #include       "RegNames.h"
+#include       "Secret.h"
 #include       <dns_sd.h>
 
 #include       <Iphlpapi.h>
@@ -123,10 +168,11 @@ Revision 1.106  2006/02/26 19:31:05  herscher
        #include        <mswsock.h>
        #include        <process.h>
        #include        <ntsecapi.h>
+       #include        <lm.h>
 #endif
 
 #include       "mDNSEmbeddedAPI.h"
-
+#include       "DNSCommon.h"
 #include       "mDNSWin32.h"
 
 #if 0
@@ -156,18 +202,19 @@ Revision 1.106  2006/02/26 19:31:05  herscher
 #define kWaitListComputerDescriptionEvent                      ( WAIT_OBJECT_0 + 3 )
 #define kWaitListTCPIPEvent                                                    ( WAIT_OBJECT_0 + 4 )
 #define kWaitListDynDNSEvent                                           ( WAIT_OBJECT_0 + 5 )
-#define        kWaitListFixedItemCount                                         6 + MDNS_WINDOWS_ENABLE_IPV4 + MDNS_WINDOWS_ENABLE_IPV6
+#define kWaitListFileShareEvent                                                ( WAIT_OBJECT_0 + 6 )
+#define kWaitListFirewallEvent                                         ( WAIT_OBJECT_0 + 7 )
+#define        kWaitListFixedItemCount                                         8 + MDNS_WINDOWS_ENABLE_IPV4 + MDNS_WINDOWS_ENABLE_IPV6
 
 #define kRegistryMaxKeyLength                                          255
+#define kRegistryMaxValueName                                          16383
 
 #if( !TARGET_OS_WINDOWS_CE )
        static GUID                                                                             kWSARecvMsgGUID = WSAID_WSARECVMSG;
 #endif
 
 #define kIPv6IfIndexBase                                                       (10000000L)
-
-#define kRetryVPCRate                                                          (-100000000)
-#define kRetryVPCMax                                                           (10)
+#define SMBPortAsNumber                                                                445
 
 
 #if 0
@@ -191,20 +238,24 @@ mDNSlocal mStatus                 SetupSocket( mDNS * const inMDNS, const struct sockaddr *inA
 mDNSlocal mStatus                      SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort );
 mDNSlocal mStatus                      SetupNotifications( mDNS * const inMDNS );
 mDNSlocal mStatus                      TearDownNotifications( mDNS * const inMDNS );
-mDNSlocal mStatus           SetupRetryVPCCheck( mDNS * const inMDNS );
-mDNSlocal mStatus           TearDownRetryVPCCheck( mDNS * const inMDNS );
 
 mDNSlocal mStatus                      SetupThread( mDNS * const inMDNS );
 mDNSlocal mStatus                      TearDownThread( const mDNS * const inMDNS );
 mDNSlocal unsigned WINAPI      ProcessingThread( LPVOID inParam );
 mDNSlocal mStatus                      ProcessingThreadInitialize( mDNS * const inMDNS );
 mDNSlocal mStatus                      ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **outWaitList, int *outWaitListCount );
-mDNSlocal void                         ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *inIFD, SocketRef inSock );
+mDNSlocal void                         ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *inIFD, UDPSocket * inUDPSocket, SocketRef inSock );
 mDNSlocal void                         ProcessingThreadInterfaceListChanged( mDNS *inMDNS );
 mDNSlocal void                         ProcessingThreadComputerDescriptionChanged( mDNS * inMDNS );
 mDNSlocal void                         ProcessingThreadTCPIPConfigChanged( mDNS * inMDNS );
 mDNSlocal void                         ProcessingThreadDynDNSConfigChanged( mDNS * inMDNS );
-mDNSlocal void              ProcessingThreadRetryVPCCheck( mDNS * inMDNS );
+mDNSlocal void                         ProcessingThreadFileShareChanged( mDNS * inMDNS );
+mDNSlocal void                         ProcessingThreadFirewallChanged( mDNS * inMDNS );
+mDNSlocal OSStatus                     GetWindowsVersionString( char *inBuffer, size_t inBufferSize );
+
+mDNSlocal int                          getifaddrs( struct ifaddrs **outAddrs );
+mDNSlocal void                         freeifaddrs( struct ifaddrs *inAddrs );
+
 
 
 // Platform Accessors
@@ -231,21 +282,24 @@ struct TCPSocket_struct
        TCPSocket *                     next;
 };
 
+struct UDPSocket_struct
+{
+       mDNSIPPort                                      port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
+       SocketRef                                       sock;
+       HANDLE                                          readEvent;
+       mDNSAddr                                        dstAddr;
+       LPFN_WSARECVMSG                         recvMsgPtr;
+       struct UDPSocket_struct *       next;
+};
 
-mDNSexport mStatus     mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID );
-mDNSexport mStatus     mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo );
 
-// Utilities
 
-typedef struct PolyString PolyString;
 
-struct PolyString
-{
-       domainname                      m_dname;
-       char                            m_utf8[256];
-       PLSA_UNICODE_STRING     m_lsa;
-};
 
+mDNSexport mStatus     mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID );
+mDNSexport mStatus     mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo );
+
+// Utilities
 
 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
        mDNSlocal int   getifaddrs_ipv6( struct ifaddrs **outAddrs );
@@ -269,10 +323,18 @@ mDNSlocal mStatus                 RegQueryString( HKEY key, LPCSTR param, LPSTR * string, DWOR
 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 OSStatus                     MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input );
-mDNSlocal OSStatus                     MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input );
 mDNSlocal void                         FreeTCPSocket( TCPSocket *sock );
+mDNSlocal void                         FreeUDPSocket( 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 m );
+mDNSlocal void                         SetDomainSecret( mDNS * const m, const domainname * inDomain );
+mDNSlocal void                         CheckFileShares( mDNS * const m );
 
 #ifdef __cplusplus
        }
@@ -290,6 +352,8 @@ mDNSlocal mDNS_PlatformSupport      gMDNSPlatformSupport;
 mDNSs32                                                        mDNSPlatformOneSecond = 0;
 mDNSlocal TCPSocket *          gTCPConnectionList              = NULL;
 mDNSlocal int                                  gTCPConnections                 = 0;
+mDNSlocal UDPSocket *                          gUDPSocketList                  = NULL;
+mDNSlocal int                                          gUDPSockets                             = 0;
 mDNSlocal BOOL                                 gWaitListChanged                = FALSE;
 
 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
@@ -307,6 +371,35 @@ mDNSlocal BOOL                                     gWaitListChanged                = FALSE;
 
 #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;
+
+
 #if 0
 #pragma mark -
 #pragma mark == Platform Support ==
@@ -331,7 +424,7 @@ mDNSexport mStatus  mDNSPlatformInit( mDNS * const inMDNS )
        // 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.
        
-       memset( &gMDNSPlatformSupport, 0, sizeof( gMDNSPlatformSupport ) );
+       mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) );
        if( !inMDNS->p ) inMDNS->p                              = &gMDNSPlatformSupport;
        inMDNS->p->interfaceListChangedSocket   = kInvalidSocketRef;
        mDNSPlatformOneSecond                                   = 1000;         // Use milliseconds as the quantum of time
@@ -361,12 +454,6 @@ mDNSexport mStatus mDNSPlatformInit( mDNS * const inMDNS )
        inMDNS->HISoftware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HISoftware.c[ 1 ] );
        dlog( kDebugLevelInfo, DEBUG_NAME "HISoftware: %#s\n", inMDNS->HISoftware.c );
 #endif
-
-       // Bookkeeping
-
-       inMDNS->p->vpcCheckCount                        = 0;
-       inMDNS->p->vpcCheckEvent                        = NULL;
-       inMDNS->p->timersCount                          = 0;
        
        // Set up the IPv4 unicast socket
 
@@ -462,10 +549,19 @@ mDNSexport mStatus        mDNSPlatformInit( mDNS * const inMDNS )
        
        err = SetupThread( inMDNS );
        require_noerr( err, exit );
+
+       // Notify core of domain secret keys
+
+       SetDomainSecrets( inMDNS );
        
        // Success!
-       
+
        mDNSCoreInitComplete( inMDNS, err );
+
+       // See if we need to advertise file sharing
+
+       inMDNS->p->smbRegistered = mDNSfalse;
+       CheckFileShares( inMDNS );
        
 exit:
        if( err )
@@ -495,9 +591,6 @@ mDNSexport void     mDNSPlatformClose( mDNS * const inMDNS )
        err = TearDownInterfaceList( inMDNS );
        check_noerr( err );
        check( !inMDNS->p->inactiveInterfaceList );
-
-       err = TearDownRetryVPCCheck( inMDNS );
-       check_noerr( err );
                
        err = TearDownSynchronizationObjects( inMDNS );
        check_noerr( err );
@@ -544,93 +637,34 @@ mDNSexport void   mDNSPlatformClose( mDNS * const inMDNS )
        }
 #endif
 
-       WSACleanup();
-       
-       dlog( kDebugLevelTrace, DEBUG_NAME "platform close done\n" );
-}
-
-//===========================================================================================================================
-//     mDNSPlatformSendUDP
-//===========================================================================================================================
-
-mDNSexport mStatus
-       mDNSPlatformSendUDP( 
-               const mDNS * const                      inMDNS, 
-               const void * const              inMsg, 
-               const mDNSu8 * const            inMsgEnd, 
-               mDNSInterfaceID                         inInterfaceID, 
-               const mDNSAddr *                        inDstIP, 
-               mDNSIPPort                                      inDstPort )
-{
-       SOCKET                                          sendingsocket = INVALID_SOCKET;
-       mStatus                                         err = mStatus_NoError;
-       mDNSInterfaceData *                     ifd = (mDNSInterfaceData*) inInterfaceID;
-       struct sockaddr_storage         addr;
-       int                                                     n;
-       
-       DEBUG_USE_ONLY( inMDNS );
-       
-       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 : inMDNS->p->unicastSock4;
-       }
-       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 : inMDNS->p->unicastSock6;
-       }
-       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))
+       if ( g_hAAPI32 )
        {
-               n = sendto( sendingsocket, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
-               err = translate_errno( n > 0, errno_compat(), kWriteErr );
+               // Release any resources
 
-               if ( err )
+               if ( g_hProvider && g_lpCryptReleaseContext )
                {
-                       // 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 );
-                       }
+                       ( 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();
        
-exit:
-       return( err );
+       dlog( kDebugLevelTrace, DEBUG_NAME "platform close done\n" );
 }
 
+
 //===========================================================================================================================
 //     mDNSPlatformLock
 //===========================================================================================================================
@@ -758,12 +792,82 @@ mDNSexport void   mDNSPlatformMemFree( void *inMem )
 }
 
 //===========================================================================================================================
-//     mDNSPlatformRandomSeed
+//     mDNSPlatformRandomNumber
 //===========================================================================================================================
 
-mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
+mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
 {
-       return( GetTickCount() );
+       mDNSu32         randomNumber = 0;
+       BOOL            bResult;
+       OSStatus        err = 0;
+
+       if ( !g_hAAPI32 )
+       {
+               g_hAAPI32 = LoadLibrary( TEXT("AdvAPI32.dll") );
+               err = translate_errno( g_hAAPI32 != NULL, GetLastError(), mStatus_UnknownErr );
+               require_noerr( err, exit );
+       }
+
+       // Function Pointer: CryptAcquireContext
+
+       if ( !g_lpCryptAcquireContext )
+       {
+               g_lpCryptAcquireContext = ( fnCryptAcquireContext )
+#ifdef UNICODE
+                       ( GetProcAddress( g_hAAPI32, "CryptAcquireContextW" ) );
+#else
+                       ( GetProcAddress( g_hAAPI32, "CryptAcquireContextA" ) );
+#endif
+               err = translate_errno( g_lpCryptAcquireContext != NULL, GetLastError(), mStatus_UnknownErr );
+               require_noerr( err, exit );
+       }
+
+       // Function Pointer: CryptReleaseContext
+
+       if ( !g_lpCryptReleaseContext )
+       {
+               g_lpCryptReleaseContext = ( fnCryptReleaseContext )
+         ( GetProcAddress( g_hAAPI32, "CryptReleaseContext" ) );
+               err = translate_errno( g_lpCryptReleaseContext != NULL, GetLastError(), mStatus_UnknownErr );
+               require_noerr( err, exit );
+       }
+      
+       // Function Pointer: CryptGenRandom
+
+       if ( !g_lpCryptGenRandom )
+       {
+               g_lpCryptGenRandom = ( fnCryptGenRandom )
+          ( GetProcAddress( g_hAAPI32, "CryptGenRandom" ) );
+               err = translate_errno( g_lpCryptGenRandom != NULL, GetLastError(), mStatus_UnknownErr );
+               require_noerr( err, exit );
+       }
+
+       // Setup
+
+       if ( !g_hProvider )
+       {
+               bResult = (*g_lpCryptAcquireContext)( &g_hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET );
+
+               if ( !bResult )
+               {
+                       bResult =  ( *g_lpCryptAcquireContext)( &g_hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET );
+                       err = translate_errno( bResult, GetLastError(), mStatus_UnknownErr );
+                       require_noerr( err, exit );
+               }
+       }
+
+       bResult = (*g_lpCryptGenRandom)( g_hProvider, sizeof( randomNumber ), ( BYTE* ) &randomNumber );
+       err = translate_errno( bResult, GetLastError(), mStatus_UnknownErr );
+       require_noerr( err, exit );
+
+exit:
+
+       if ( err )
+       {
+               randomNumber = rand();
+       }
+
+       return randomNumber;
 }
 
 //===========================================================================================================================
@@ -965,12 +1069,12 @@ mDNSPlatformTCPSocket
 
        sock = (TCPSocket *) malloc( sizeof( TCPSocket ) );
        require_action( sock, exit, err = mStatus_NoMemoryErr );
-       memset( sock, 0, sizeof( TCPSocket ) );
+       mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
 
        sock->fd                = INVALID_SOCKET;
        sock->flags             = flags;
 
-       bzero(&saddr, sizeof(saddr));
+       mDNSPlatformMemZero(&saddr, sizeof(saddr));
        saddr.sin_family                = AF_INET;
        saddr.sin_addr.s_addr   = htonl( INADDR_ANY );
        saddr.sin_port                  = port->NotAnInteger;
@@ -981,6 +1085,12 @@ mDNSPlatformTCPSocket
        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 );
@@ -989,7 +1099,7 @@ mDNSPlatformTCPSocket
 
        // Get port number
 
-       memset( &saddr, 0, sizeof( saddr ) );
+       mDNSPlatformMemZero( &saddr, sizeof( saddr ) );
        len = sizeof( saddr );
 
        err = getsockname( sock->fd, ( struct sockaddr* ) &saddr, &len );
@@ -1040,7 +1150,7 @@ mDNSPlatformTCPConnect
        sock->callback = inCallback;
        sock->context = inContext;
 
-       bzero(&saddr, sizeof(saddr));
+       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));
@@ -1088,7 +1198,7 @@ mDNSexport TCPSocket *mDNSPlatformTCPAccept( TCPSocketFlags flags, int fd )
        sock = malloc( sizeof( TCPSocket ) );
        require_action( sock, exit, err = mStatus_NoMemoryErr );
        
-       memset( sock, 0, sizeof( *sock ) );
+       mDNSPlatformMemZero( sock, sizeof( *sock ) );
 
        sock->fd        = fd;
        sock->flags = flags;
@@ -1202,193 +1312,303 @@ mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock )
     return ( int ) sock->fd;
     }
 
+       
 //===========================================================================================================================
 //     mDNSPlatformUDPSocket
 //===========================================================================================================================
 
-mDNSexport UDPSocket *mDNSPlatformUDPSocket
-       (
-       mDNS    *       const m,
-       mDNSIPPort                port
-       )
+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 = (struct UDPSocket_struct*) malloc( sizeof( struct UDPSocket_struct ) );
+       require_action( sock, exit, err = mStatus_NoMemoryErr );
+       memset( sock, 0, sizeof( struct UDPSocket_struct ) );
+
+       // Create the socket
+
+       sock->recvMsgPtr        = m->p->unicastSock4RecvMsgPtr;
+       sock->dstAddr           = m->p->unicastSock4DestAddr;
+       sock->sock                      = INVALID_SOCKET;
+
+       // Try at most 10000 times to get a unique random port
+
+       for (i=0; i<10000; i++)
        {
-       DEBUG_UNUSED( m );
-       DEBUG_UNUSED( port );
+               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(0xC000 + mDNSRandom(0x3FFF));
+               }
+
+               saddr.sin_port = port.NotAnInteger;
+
+        err = SetupSocket(m, ( struct sockaddr* ) &saddr, port, &sock->sock );
+        if (!err) break;
+       }
+
+       require_noerr( err, exit );
+
+       // Set the port
+
+       sock->port = port;
+
+       // Set it up with Windows Eventing
+
+       sock->readEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+       err = translate_errno( sock->readEvent, GetLastError(), mStatus_UnknownErr );
+       require_noerr( err, exit );
+       err = WSAEventSelect( sock->sock, sock->readEvent, FD_READ );
+       require_noerr( err, exit );
+
+       // Bookkeeping
+
+       sock->next                      = gUDPSocketList;
+       gUDPSocketList          = sock;
+       gUDPSockets++;
+       gWaitListChanged        = TRUE;
+
+exit:
 
-       return NULL;
+       if ( err )
+       {
+               if ( sock )
+               {
+                       FreeUDPSocket( sock );
+                       sock = NULL;
+               }
        }
+
+       return sock;
+}
        
 //===========================================================================================================================
 //     mDNSPlatformUDPClose
 //===========================================================================================================================
        
 mDNSexport void mDNSPlatformUDPClose( UDPSocket *sock )
+{
+       UDPSocket       *       current  = gUDPSocketList;
+       UDPSocket       *       last = NULL;
+
+       while ( current )
        {
-       DEBUG_UNUSED( sock );
-       }
-               
+               if ( current == sock )
+               {
+                       if ( last == NULL )
+                       {
+                               gUDPSocketList = sock->next;
+                       }
+                       else
+                       {
+                               last->next = sock->next;
+                       }
 
-//===========================================================================================================================
-//     mDNSPlatformTLSSetupCerts
-//===========================================================================================================================
+                       FreeUDPSocket( sock );
 
-mDNSexport mStatus
-mDNSPlatformTLSSetupCerts(void)
-{
-       return mStatus_UnsupportedErr;
+                       gUDPSockets--;
+                       gWaitListChanged = TRUE;
+
+                       break;
+               }
+
+               last    = current;
+               current = current->next;
+       }
 }
 
+
 //===========================================================================================================================
-//     mDNSPlatformTLSTearDownCerts
+//     mDNSPlatformSendUDP
 //===========================================================================================================================
 
-mDNSexport void
-mDNSPlatformTLSTearDownCerts(void)
+mDNSexport mStatus
+       mDNSPlatformSendUDP( 
+               const mDNS * const                      inMDNS, 
+               const void * const              inMsg, 
+               const mDNSu8 * const            inMsgEnd, 
+               mDNSInterfaceID                         inInterfaceID, 
+               UDPSocket *                                     inSrcSocket,
+               const mDNSAddr *                        inDstIP, 
+               mDNSIPPort                                      inDstPort )
 {
-}
-
-//===========================================================================================================================
-//     mDNSPlatformSetDNSConfig
-//===========================================================================================================================
+       SOCKET                                          sendingsocket = INVALID_SOCKET;
+       mStatus                                         err = mStatus_NoError;
+       mDNSInterfaceData *                     ifd = (mDNSInterfaceData*) inInterfaceID;
+       struct sockaddr_storage         addr;
+       int                                                     n;
+       
+       DEBUG_USE_ONLY( inMDNS );
+       
+       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 : inMDNS->p->unicastSock4;
 
-mDNSlocal void SetDNSServers( mDNS *const m );
-mDNSlocal void SetSearchDomainList( void );
+               if (inSrcSocket) { sendingsocket = inSrcSocket->sock; debugf("mDNSPlatformSendUDP using port %d, static port %d, sock %d", mDNSVal16(inSrcSocket->port), inMDNS->p->unicastSock4, 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 : inMDNS->p->unicastSock6;
+       }
+       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 );
 
-void
-mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **browseDomains)
-{
-       LPSTR           name = NULL;
-       char            subKeyName[kRegistryMaxKeyLength + 1];
-       DWORD           cSubKeys = 0;
-       DWORD           cbMaxSubKey;
-       DWORD           cchMaxClass;
-       DWORD           dwSize;
-       DWORD           enabled;
-       HKEY            key;
-       HKEY            subKey = NULL;
-       domainname      dname;
-       DWORD           i;
-       OSStatus        err;
+               if ( err )
+               {
+                       // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
 
-       if (setservers) SetDNSServers(m);
-       if (setsearch) SetSearchDomainList();
+                       if ( !mDNSAddressIsAllDNSLinkGroup( inDstIP ) && ( WSAGetLastError() == WSAEHOSTDOWN || WSAGetLastError() == WSAENETDOWN || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAENETUNREACH ) )
+                       {
+                               err = mStatus_TransientErr;
+                       }
+                       else
+                       {
+                               require_noerr( err, exit );
+                       }
+               }
+       }
+       
+exit:
+       return( err );
+}
 
-       // Initialize
 
-       fqdn->c[0] = '\0';
+mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
+       {
+       DEBUG_UNUSED( m );
+       DEBUG_UNUSED( InterfaceID );
+       }
 
-       *browseDomains = NULL;
+//===========================================================================================================================
+//     mDNSPlatformSendRawPacket
+//===========================================================================================================================
        
-       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 )
+mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
        {
-               if ( !MakeDomainNameFromDNSNameString( fqdn, name ) || !fqdn->c[0] )
-               {
-                       dlog( kDebugLevelError, "bad DDNS host name in registry: %s", name[0] ? name : "(unknown)");
-               }
+       DEBUG_UNUSED( msg );
+       DEBUG_UNUSED( end );
+       DEBUG_UNUSED( InterfaceID );
        }
 
-       if ( key )
+mDNSexport void mDNSPlatformReceiveRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
        {
-               RegCloseKey( key );
-               key = NULL;
+       DEBUG_UNUSED( msg );
+       DEBUG_UNUSED( end );
+       DEBUG_UNUSED( InterfaceID );
        }
 
-       if ( name )
+mDNSexport void mDNSPlatformSetLocalARP( const mDNSv4Addr * const tpa, const mDNSEthAddr * const tha, mDNSInterfaceID InterfaceID )
        {
-               free( name );
-               name = NULL;
+       DEBUG_UNUSED( tpa );
+       DEBUG_UNUSED( tha );
+       DEBUG_UNUSED( InterfaceID );
        }
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains, &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 );
+mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
+       {
+       fprintf( stderr, msg );
+       }
 
-       for ( i = 0; i < cSubKeys; i++)
+mDNSexport void mDNSPlatformWriteLogMsg( const char * ident, const char * msg, int flags )
        {
-               DWORD enabled;
+       DEBUG_UNUSED( ident );
+       DEBUG_UNUSED( msg );
+       DEBUG_UNUSED( flags );
+       }
 
-               dwSize = kRegistryMaxKeyLength;
-            
-               err = RegEnumKeyExA( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
+mDNSexport void mDNSPlatformSourceAddrForDest( mDNSAddr * const src, const mDNSAddr * const dst )
+       {
+       DEBUG_UNUSED( src );
+       DEBUG_UNUSED( dst );
+       }
 
-               if ( !err )
-               {
-                       err = RegOpenKeyExA( key, subKeyName, 0, KEY_READ, &subKey );
-                       require_noerr( err, exit );
+//===========================================================================================================================
+//     mDNSPlatformTLSSetupCerts
+//===========================================================================================================================
 
-                       dwSize = sizeof( DWORD );
-                       err = RegQueryValueExA( subKey, "Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+mDNSexport mStatus
+mDNSPlatformTLSSetupCerts(void)
+{
+       return mStatus_UnsupportedErr;
+}
 
-                       if ( !err && ( subKeyName[0] != '\0' ) && enabled )
-                       {
-                               if ( !MakeDomainNameFromDNSNameString( &dname, subKeyName ) || !dname.c[0] )
-                               {
-                                       dlog( kDebugLevelError, "bad DDNS browse domain in registry: %s", subKeyName[0] ? subKeyName : "(unknown)");
-                               }
-                               else
-                               {
-                                       DNameListElem * browseDomain = (DNameListElem*) malloc( sizeof( DNameListElem ) );
-                                       require_action( browseDomain, exit, err = mStatus_NoMemoryErr );
-                                       
-                                       AssignDomainName(&browseDomain->name, &dname);
-                                       browseDomain->next = *browseDomains;
+//===========================================================================================================================
+//     mDNSPlatformTLSTearDownCerts
+//===========================================================================================================================
 
-                                       *browseDomains = browseDomain;
-                               }
-                       }
+mDNSexport void
+mDNSPlatformTLSTearDownCerts(void)
+{
+}
 
-                       RegCloseKey( subKey );
-                       subKey = NULL;
-       }
-       }
+//===========================================================================================================================
+//     mDNSPlatformSetDNSConfig
+//===========================================================================================================================
 
-       if ( key )
-       {
-               RegCloseKey( key );
-               key = NULL;
-       }
+mDNSlocal void SetDNSServers( mDNS *const m );
+mDNSlocal void SetSearchDomainList( void );
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains, &key );
-       require_noerr( err, exit );
+mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **regDomains, DNameListElem **browseDomains)
+{
+       if (setservers) SetDNSServers(m);
+       if (setsearch) SetSearchDomainList();
        
-       err = RegQueryString( key, "", &name, &dwSize, &enabled );
-       if ( !err && ( name[0] != '\0' ) && enabled )
-       {
-               *RegDomains = (DNameListElem*) malloc( sizeof( DNameListElem ) );
-               if (!*RegDomains) dlog( kDebugLevelError, "No memory");
-               else
-               {
-                       (*RegDomains)->next = mDNSNULL;
-                       if ( !MakeDomainNameFromDNSNameString( &(*RegDomains)->name, name ) || (*RegDomains)->name.c[0] )
-                       {
-                               dlog( kDebugLevelError, "bad DDNS registration domain in registry: %s", name[0] ? name : "(unknown)");
-                       }
-               }
-       }
-
-exit:
-
-       if ( subKey )
+       if ( fqdn )
        {
-               RegCloseKey( subKey );
+               GetDDNSFQDN( fqdn );
        }
 
-       if ( key )
+       if ( browseDomains )
        {
-               RegCloseKey( key );
+               GetDDNSDomains( browseDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains );
        }
 
-       if ( name )
+       if ( regDomains )
        {
-               free( name );
+               GetDDNSDomains( regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
        }
 }
 
@@ -1398,9 +1618,10 @@ exit:
 //===========================================================================================================================
 
 mDNSexport void
-mDNSPlatformDynDNSHostNameStatusChanged(domainname *const dname, mStatus status)
+mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
 {
        char            uname[MAX_ESCAPED_DOMAIN_NAME];
+       BYTE            bStatus;
        LPCTSTR         name;
        HKEY            key = NULL;
        mStatus         err;
@@ -1422,8 +1643,8 @@ mDNSPlatformDynDNSHostNameStatusChanged(domainname *const dname, mStatus status)
        err = RegCreateKey( HKEY_LOCAL_MACHINE, name, &key );
        require_noerr( err, exit );
 
-       status = ( status ) ? 0 : 1;
-       err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &status, sizeof(DWORD) );
+       bStatus = ( status ) ? 0 : 1;
+       err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &bStatus, sizeof(DWORD) );
        require_noerr( err, exit );
 
 exit:
@@ -1442,115 +1663,39 @@ exit:
 //===========================================================================================================================
 
 // This routine needs to be called whenever the system secrets database changes.
-// Right now I call it from ProcessingThreadDynDNSConfigChanged, which may or may not be sufficient.
-// Also, it needs to call mDNS_SetSecretForDomain() for *every* configured DNS domain/secret pair
-// in the database, not just inDomain (the inDomain parameter should be deleted).
+// We call it from ProcessingThreadDynDNSConfigChanged and mDNSPlatformInit
 
 mDNSlocal void
-SetDomainSecrets( mDNS * const m, const domainname * inDomain )
+SetDomainSecrets( mDNS * const m )
 {
-       PolyString                              domain;
-       PolyString                              key;
-       PolyString                              secret;
-       size_t                                  i;
-       size_t                                  dlen;
-       LSA_OBJECT_ATTRIBUTES   attrs;
-       LSA_HANDLE                              handle = NULL;
-       NTSTATUS                                res;
-       OSStatus                                err;
-
-       // Initialize PolyStrings
-
-       domain.m_lsa    = NULL;
-       key.m_lsa               = NULL;
-       secret.m_lsa    = NULL;
-
-       // canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
-       
-       ConvertDomainNameToCString( inDomain, domain.m_utf8 );
-       dlen = strlen( domain.m_utf8 );
-       for ( i = 0; i < dlen; i++ )
-       {
-               domain.m_utf8[i] = (char) tolower( domain.m_utf8[i] );  // canonicalize -> lower case
-       }
-
-       MakeDomainNameFromDNSNameString( &domain.m_dname, domain.m_utf8 );
-
-       // attrs are reserved, so initialize to zeroes.
-
-       ZeroMemory( &attrs, sizeof( attrs ) );
+       DomainAuthInfo *ptr;
+       domainname              fqdn;
+       DNameListElem * regDomains = NULL;
 
-       // Get a handle to the Policy object on the local system
-
-       res = LsaOpenPolicy( NULL, &attrs, POLICY_GET_PRIVATE_INFORMATION, &handle );
-       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-       require_noerr( err, exit );
-
-       // Get the encrypted data
-
-       domain.m_lsa = ( PLSA_UNICODE_STRING) malloc( sizeof( LSA_UNICODE_STRING ) );
-       require_action( domain.m_lsa != NULL, exit, err = mStatus_NoMemoryErr );
-       err = MakeLsaStringFromUTF8String( domain.m_lsa, domain.m_utf8 );
-       require_noerr( err, exit );
-
-       // Retrieve the key
-
-       res = LsaRetrievePrivateData( handle, domain.m_lsa, &key.m_lsa );
-       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-       require_noerr_quiet( err, exit );
-
-       // <rdar://problem/4192119> Lsa secrets use a flat naming space.  Therefore, we will prepend "$" to the keyname to
-       // make sure it doesn't conflict with a zone name.
-       
-       // Convert the key to a domainname.  Strip off the "$" prefix.
-
-       err = MakeUTF8StringFromLsaString( key.m_utf8, sizeof( key.m_utf8 ), key.m_lsa );
-       require_noerr( err, exit );
-       require_action( key.m_utf8[0] == '$', exit, err = kUnknownErr );
-       MakeDomainNameFromDNSNameString( &key.m_dname, key.m_utf8 + 1 );
-
-       // Retrieve the secret
-
-       res = LsaRetrievePrivateData( handle, key.m_lsa, &secret.m_lsa );
-       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-       require_noerr_quiet( err, exit );
+       // 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.
        
-       // Convert the secret to UTF8 string
-
-       err = MakeUTF8StringFromLsaString( secret.m_utf8, sizeof( secret.m_utf8 ), secret.m_lsa );
-       require_noerr( err, exit );
-
-       // And finally, tell the core about this secret
-
-       debugf("Setting shared secret for zone %s with key %##s", domain.m_utf8, key.m_dname.c);
-       mDNS_SetSecretForDomain( m, &domain.m_dname, &key.m_dname, secret.m_utf8, mDNSfalse );
-
-exit:
-
-       if ( domain.m_lsa != NULL )
-       {
-               if ( domain.m_lsa->Buffer != NULL )
-               {
-                       free( domain.m_lsa->Buffer );
-               }
+       for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
+               ptr->deltime = NonZeroTime(m->timenow + mDNSPlatformOneSecond*10);
 
-               free( domain.m_lsa );
-       }
+       GetDDNSFQDN( &fqdn );
 
-       if ( key.m_lsa != NULL )
+       if ( fqdn.c[ 0 ] )
        {
-               LsaFreeMemory( key.m_lsa );
+               SetDomainSecret( m, &fqdn );
        }
 
-       if ( secret.m_lsa != NULL )
-       {
-               LsaFreeMemory( secret.m_lsa );
-       }
+       GetDDNSDomains( &regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
 
-       if ( handle )
+       while ( regDomains )
        {
-               LsaClose( handle );
-               handle = NULL;
+               DNameListElem * current = regDomains;
+               SetDomainSecret( m, &current->name );
+               regDomains = regDomains->next;
+               free( current );
        }
 }
 
@@ -1567,8 +1712,8 @@ SetSearchDomainList( void )
 {
        char                    *       searchList      = NULL;
        DWORD                           searchListLen;
-       DNameListElem   *       head = NULL;
-       DNameListElem   *       current = NULL;
+       //DNameListElem *       head = NULL;
+       //DNameListElem *       current = NULL;
        char                    *       tok;
        HKEY                            key;
        mStatus                         err;
@@ -1638,7 +1783,7 @@ SetReverseMapSearchDomainList( void )
                ifa = ifa->ifa_next;
        }
 
-exit:
+       return;
 }
 
 
@@ -1718,7 +1863,7 @@ SetDNSServers( mDNS *const m )
        {
                mDNSAddr addr;
                err = StringToAddress( &addr, ipAddr->IpAddress.String );
-               if ( !err ) mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, addr, UnicastDNSPort);
+               if ( !err ) mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, &addr, UnicastDNSPort);
        }
 
 exit:
@@ -1742,7 +1887,6 @@ exit:
 mDNSlocal void
 SetDomainFromDHCP( void )
 {
-       DNameListElem   *       head            = NULL;
        int                                     i                       = 0;
        IP_ADAPTER_INFO *       pAdapterInfo;
        IP_ADAPTER_INFO *       pAdapter;
@@ -1750,7 +1894,6 @@ SetDomainFromDHCP( void )
        DWORD                           index;
        HKEY                            key = NULL;
        LPSTR                           domain = NULL;
-       domainname                      dname;
        DWORD                           dwSize;
        mStatus                         err = mStatus_NoError;
 
@@ -2041,14 +2184,12 @@ mDNSlocal mStatus       TearDownSynchronizationObjects( mDNS * const inMDNS )
 mDNSlocal mStatus      SetupNiceName( mDNS * const inMDNS )
 {
        mStatus         err = 0;
-       char            tempString[ 256 ];
        char            utf8[ 256 ];
        
        check( inMDNS );
        
        // Set up the nice name.
-       tempString[ 0 ] = '\0';
-       utf8[0]                 = '\0';
+       utf8[0] = '\0';
 
        // First try and open the registry key that contains the computer description value
        if (inMDNS->p->descKey == NULL)
@@ -2086,16 +2227,17 @@ mDNSlocal mStatus       SetupNiceName( mDNS * const inMDNS )
        // if we can't find it in the registry, then use the hostname of the machine
        if ( err || ( utf8[ 0 ] == '\0' ) )
        {
-               DWORD tempStringLen = sizeof( tempString );
+               TCHAR hostname[256];
+               DWORD hostnameLen = sizeof( hostname ) / sizeof( TCHAR );
                BOOL  ok;
 
-               ok = GetComputerNameExA( ComputerNamePhysicalDnsHostname, tempString, &tempStringLen );
+               ok = GetComputerNameExW( ComputerNamePhysicalDnsHostname, hostname, &hostnameLen );
                err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
                check_noerr( err );
                
                if( !err )
                {
-                       err = WindowsLatin1toUTF8( tempString, utf8, sizeof( utf8 ) );
+                       err = TCHARtoUTF8( hostname, utf8, sizeof( utf8 ) );
                }
 
                if ( err )
@@ -2121,7 +2263,6 @@ mDNSlocal mStatus SetupNiceName( mDNS * const inMDNS )
        return( err );
 }
 
-
 //===========================================================================================================================
 //     SetupHostName
 //===========================================================================================================================
@@ -2554,17 +2695,9 @@ mDNSlocal mStatus        SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI
                #if( !TARGET_OS_WINDOWS_CE )
                {
                        DWORD size;
-
-                       // If we are running inside VPC, then we won't use WSARecvMsg because it will give us bogus information due to
-                       // a bug in VPC itself.
                        
-                       err = inMDNS->p->inVirtualPC;
-
-                       if ( !err )
-                       {
-                               err = WSAIoctl( sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ),
+                       err = WSAIoctl( sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ),
                                        &ifd->wsaRecvMsgFunctionPtr, sizeof( ifd->wsaRecvMsgFunctionPtr ), &size, NULL, NULL );
-                       }
 
                        if ( err )
                        {
@@ -2599,7 +2732,7 @@ mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI
        err = SockAddrToMDNSAddr( inIFA->ifa_netmask, &ifd->interfaceInfo.mask, NULL );
        require_noerr( err, exit );
        
-       ifd->interfaceInfo.Advertise = inMDNS->AdvertiseLocalAddresses;
+       ifd->interfaceInfo.Advertise = ( mDNSu8 ) inMDNS->AdvertiseLocalAddresses;
        
        err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, mDNSfalse );
        require_noerr( err, exit );
@@ -2715,7 +2848,7 @@ mDNSlocal mStatus SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAdd
                // Bind the socket to the desired port
                
                ipv4.NotAnInteger       = ( (const struct sockaddr_in *) inAddr )->sin_addr.s_addr;
-               memset( &sa4, 0, sizeof( sa4 ) );
+               mDNSPlatformMemZero( &sa4, sizeof( sa4 ) );
                sa4.sin_family          = AF_INET;
                sa4.sin_port            = port.NotAnInteger;
                sa4.sin_addr.s_addr     = ipv4.NotAnInteger;
@@ -2774,7 +2907,7 @@ mDNSlocal mStatus SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAdd
                
                // Bind the socket to the desired port
                
-               memset( &sa6, 0, sizeof( sa6 ) );
+               mDNSPlatformMemZero( &sa6, sizeof( sa6 ) );
                sa6.sin6_family         = AF_INET6;
                sa6.sin6_port           = port.NotAnInteger;
                sa6.sin6_flowinfo       = 0;
@@ -2978,17 +3111,51 @@ mDNSlocal mStatus       SetupNotifications( mDNS * const inMDNS )
        err = RegNotifyChangeKeyValue(inMDNS->p->ddnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->ddnsChangedEvent, TRUE);
        require_noerr( err, exit );
 
-exit:
-       if( err )
-       {
-               TearDownNotifications( inMDNS );
-       }
-       return( err );
-}
+       // This will catch all changes to file sharing
 
-//===========================================================================================================================
-//     TearDownNotifications
-//===========================================================================================================================
+       inMDNS->p->fileShareEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+       err = translate_errno( inMDNS->p->fileShareEvent, (mStatus) GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\Shares"), &inMDNS->p->fileShareKey );
+       require_noerr( err, exit );
+
+       err = RegNotifyChangeKeyValue(inMDNS->p->fileShareKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->fileShareEvent, TRUE);
+       require_noerr( err, exit );
+
+       // This will catch changes to the Windows firewall
+
+       inMDNS->p->firewallEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+       err = translate_errno( inMDNS->p->firewallEvent, (mStatus) GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       // Just to make sure that initialization doesn't fail on some old OS
+       // that doesn't have this key, we'll only add the notification if
+       // the key exists.
+
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\FirewallRules"), &inMDNS->p->firewallKey );
+       
+       if ( !err )
+       {
+               err = RegNotifyChangeKeyValue(inMDNS->p->firewallKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->firewallEvent, TRUE);
+               require_noerr( err, exit );
+       }
+       else
+       {
+               err = mStatus_NoError;
+       }
+
+exit:
+       if( err )
+       {
+               TearDownNotifications( inMDNS );
+       }
+       return( err );
+}
+
+//===========================================================================================================================
+//     TearDownNotifications
+//===========================================================================================================================
 
 mDNSlocal mStatus      TearDownNotifications( mDNS * const inMDNS )
 {
@@ -3028,64 +3195,31 @@ mDNSlocal mStatus       TearDownNotifications( mDNS * const inMDNS )
                inMDNS->p->ddnsKey = NULL;
        }
 
-       return( mStatus_NoError );
-}
-
-
-//===========================================================================================================================
-//     SetupRetryVPCCheck
-//===========================================================================================================================
-
-mDNSlocal mStatus
-SetupRetryVPCCheck( mDNS * const inMDNS )
-{
-    LARGE_INTEGER      liDueTime;
-       BOOL                    ok;
-       mStatus                 err;
-
-       dlog( kDebugLevelTrace, DEBUG_NAME "setting up retry VirtualPC check\n" );
-    
-       liDueTime.QuadPart = kRetryVPCRate;
-
-    // Create a waitable timer.
-    
-       inMDNS->p->vpcCheckEvent = CreateWaitableTimer( NULL, TRUE, TEXT( "VPCCheckTimer" ) );
-       err = translate_errno( inMDNS->p->vpcCheckEvent, (mStatus) GetLastError(), kUnknownErr );
-       require_noerr( err, exit );
-
-    // Set a timer to wait for 10 seconds.
-    
-       ok = SetWaitableTimer( inMDNS->p->vpcCheckEvent, &liDueTime, 0, NULL, NULL, 0 );
-       err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-       require_noerr( err, exit );
-
-       inMDNS->p->timersCount++;
-
-exit:
-
-       return err;
-}
-
-
-//===========================================================================================================================
-//     TearDownRetryVPCCheck
-//===========================================================================================================================
+       if ( inMDNS->p->fileShareEvent != NULL )
+       {
+               CloseHandle( inMDNS->p->fileShareEvent );
+               inMDNS->p->fileShareEvent = NULL;
+       }
 
-mDNSlocal mStatus
-TearDownRetryVPCCheck( mDNS * const inMDNS )
-{
-       dlog( kDebugLevelTrace, DEBUG_NAME "tearing down retry VirtualPC check\n" );
+       if ( inMDNS->p->fileShareKey != NULL )
+       {
+               RegCloseKey( inMDNS->p->fileShareKey );
+               inMDNS->p->fileShareKey = NULL;
+       }
 
-       if ( inMDNS->p->vpcCheckEvent )
+       if ( inMDNS->p->firewallEvent != NULL )
        {
-               CancelWaitableTimer( inMDNS->p->vpcCheckEvent );
-               CloseHandle( inMDNS->p->vpcCheckEvent );
+               CloseHandle( inMDNS->p->firewallEvent );
+               inMDNS->p->firewallEvent = NULL;
+       }
 
-               inMDNS->p->vpcCheckEvent = NULL;
-               inMDNS->p->timersCount--;
+       if ( inMDNS->p->firewallKey != NULL )
+       {
+               RegCloseKey( inMDNS->p->firewallKey );
+               inMDNS->p->firewallKey = NULL;
        }
 
-       return ( mStatus_NoError );
+       return( mStatus_NoError );
 }
 
 
@@ -3241,6 +3375,16 @@ mDNSlocal unsigned WINAPI        ProcessingThread( LPVOID inParam )
                                }
                                else if( result == kWaitListInterfaceListChangedEvent )
                                {
+                                       // It would be nice to come up with a more elegant solution to this, but it seems that
+                                       // GetAdaptersAddresses doesn't always stay in sync after network changed events.  So as
+                                       // as a simple workaround, we'll pause for a couple of seconds before processing the change.
+
+                                       // We arrived at 2 secs by trial and error. We could reproduce the problem after sleeping
+                                       // for 500 msec and 750 msec, but couldn't after sleeping for 1 sec.  We added another
+                                       // second on top of that to account for machine load or some other exigency.
+
+                                       Sleep( 2000 );
+
                                        // Interface list changed event. Break out of the inner loop to re-setup the wait list.
                                        
                                        ProcessingThreadInterfaceListChanged( m );
@@ -3277,6 +3421,21 @@ mDNSlocal unsigned WINAPI        ProcessingThread( LPVOID inParam )
                                        ProcessingThreadDynDNSConfigChanged( m );
                                        break;
                                }
+                               else if ( result == kWaitListFileShareEvent )
+                               {
+                                       //
+                                       // File sharing changed
+                                       //
+                                       ProcessingThreadFileShareChanged( m );
+                                       break;
+                               }
+                               else if ( result == kWaitListFirewallEvent )
+                               {
+                                       //
+                                       // Firewall configuration changed
+                                       //
+                                       ProcessingThreadFirewallChanged( m );
+                               }
                                else
                                {
                                        int             waitItemIndex;
@@ -3286,26 +3445,21 @@ mDNSlocal unsigned WINAPI       ProcessingThread( LPVOID inParam )
                                        waitItemIndex = (int)( ( (int) result ) - WAIT_OBJECT_0 );
                                        dlog( kDebugLevelChatty, DEBUG_NAME "socket data available on socket index %d\n", waitItemIndex );
                                        check( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) );
+
                                        if( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) )
                                        {
                                                HANDLE                                  signaledObject;
                                                int                                             n = 0;
                                                mDNSInterfaceData       *       ifd;
                                                TCPSocket *                     tcd;
+                                               UDPSocket *                     sock;
                                                
                                                signaledObject = waitList[ waitItemIndex ];
        
-                                               if ( m->p->vpcCheckEvent == signaledObject )
-                                               {
-                                                       ProcessingThreadRetryVPCCheck( m );
-                                                       ++n;
-
-                                                       break;
-                                               }
 #if ( MDNS_WINDOWS_ENABLE_IPV4 )
                                                if ( m->p->unicastSock4ReadEvent == signaledObject )
                                                {
-                                                       ProcessingThreadProcessPacket( m, NULL, m->p->unicastSock4 );
+                                                       ProcessingThreadProcessPacket( m, NULL, NULL, m->p->unicastSock4 );
                                                        ++n;
                                                }
 #endif
@@ -3313,7 +3467,7 @@ mDNSlocal unsigned WINAPI ProcessingThread( LPVOID inParam )
 #if ( MDNS_WINDOWS_ENABLE_IPV6 )
                                                if ( m->p->unicastSock6ReadEvent == signaledObject )
                                                {
-                                                       ProcessingThreadProcessPacket( m, NULL, m->p->unicastSock6 );
+                                                       ProcessingThreadProcessPacket( m, NULL, NULL, m->p->unicastSock6 );
                                                        ++n;
                                                }
 #endif
@@ -3322,7 +3476,7 @@ mDNSlocal unsigned WINAPI ProcessingThread( LPVOID inParam )
                                                {
                                                        if( ifd->readPendingEvent == signaledObject )
                                                        {
-                                                               ProcessingThreadProcessPacket( m, ifd, ifd->sock );
+                                                               ProcessingThreadProcessPacket( m, ifd, NULL, ifd->sock );
                                                                ++n;
                                                        }
                                                }
@@ -3347,6 +3501,18 @@ mDNSlocal unsigned WINAPI        ProcessingThread( LPVOID inParam )
                                                        }
                                                }
        
+                                               for ( sock = gUDPSocketList; sock; sock = sock->next )
+                                               {
+                                                       if ( sock->readEvent == signaledObject )
+                                                       {
+                                                               ProcessingThreadProcessPacket( m, NULL, sock, sock->sock );
+       
+                                                               ++n;
+       
+                                                               break;
+                                                       }
+                                               }
+
                                                check( n > 0 );
                                        }
                                        else
@@ -3400,14 +3566,6 @@ mDNSlocal mStatus ProcessingThreadInitialize( mDNS * const inMDNS )
        
        inMDNS->p->threadID = GetCurrentThreadId();
 
-       err = IsVPCRunning( &inMDNS->p->inVirtualPC );
-
-       if ( err )
-       {
-               TearDownRetryVPCCheck( inMDNS );
-               SetupRetryVPCCheck( inMDNS );
-       }
-
        err = SetupInterfaceList( inMDNS );
        require_noerr( err, exit );
 
@@ -3419,7 +3577,6 @@ exit:
        if( err )
        {
                TearDownInterfaceList( inMDNS );
-               TearDownRetryVPCCheck( inMDNS );
        }
        inMDNS->p->initStatus = err;
        
@@ -3440,6 +3597,7 @@ mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o
        HANDLE *                                waitItemPtr;
        mDNSInterfaceData       *       ifd;
        TCPSocket *                     tcd;
+       UDPSocket *                     sock;
        
        dlog( kDebugLevelTrace, DEBUG_NAME "thread setting up wait list\n" );
        check( inMDNS );
@@ -3449,7 +3607,7 @@ mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o
        
        // Allocate an array to hold all the objects to wait on.
        
-       waitListCount = kWaitListFixedItemCount + inMDNS->p->timersCount + inMDNS->p->interfaceCount + gTCPConnections;
+       waitListCount = kWaitListFixedItemCount + inMDNS->p->interfaceCount + gTCPConnections + gUDPSockets;
        waitList = (HANDLE *) malloc( waitListCount * sizeof( *waitList ) );
        require_action( waitList, exit, err = mStatus_NoMemoryErr );
        waitItemPtr = waitList;
@@ -3462,13 +3620,8 @@ mDNSlocal mStatus        ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o
        *waitItemPtr++ = inMDNS->p->descChangedEvent;
        *waitItemPtr++ = inMDNS->p->tcpipChangedEvent;
        *waitItemPtr++ = inMDNS->p->ddnsChangedEvent;
-
-       // Add timers
-
-       if ( inMDNS->p->vpcCheckEvent )
-       {
-               *waitItemPtr++ = inMDNS->p->vpcCheckEvent;
-       }
+       *waitItemPtr++ = inMDNS->p->fileShareEvent;
+       *waitItemPtr++ = inMDNS->p->firewallEvent;
        
        // Append all the dynamic wait items to the list.
 #if ( MDNS_WINDOWS_ENABLE_IPV4 )
@@ -3489,6 +3642,11 @@ mDNSlocal mStatus        ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o
                *waitItemPtr++ = tcd->pendingEvent;
        }
 
+       for ( sock = gUDPSocketList; sock; sock = sock->next )
+       {
+               *waitItemPtr++ = sock->readEvent;
+       }
+
        check( (int)( waitItemPtr - waitList ) == waitListCount );
        
        *outWaitList            = waitList;
@@ -3509,7 +3667,7 @@ exit:
 //     ProcessingThreadProcessPacket
 //===========================================================================================================================
 
-mDNSlocal void ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *inIFD, SocketRef inSock )
+mDNSlocal void ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *inIFD, UDPSocket * inUDPSocket, SocketRef inSock )
 {
        OSStatus                                        err;
        const mDNSInterfaceID           iid = inIFD ? inIFD->interfaceInfo.InterfaceID : NULL;
@@ -3536,18 +3694,25 @@ mDNSlocal void  ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *i
                dstPort         = MulticastDNSPort;
                ttl                     = 255;
        }
+       else if ( inUDPSocket )
+       {
+               recvMsgPtr      = inUDPSocket->recvMsgPtr;
+               dstAddr         = inUDPSocket->dstAddr;
+               dstPort         = inUDPSocket->port;
+               ttl                     = 255;
+       }
        else if ( inSock == inMDNS->p->unicastSock4 )
        {
                recvMsgPtr      = inMDNS->p->unicastSock4RecvMsgPtr;
                dstAddr         = inMDNS->p->unicastSock4DestAddr;
-               dstPort         = zeroIPPort;
+               dstPort         = inMDNS->UnicastPort4;
                ttl                     = 255;
        }
        else if ( inSock == inMDNS->p->unicastSock6 )
        {
                recvMsgPtr      = inMDNS->p->unicastSock6RecvMsgPtr;
                dstAddr         = inMDNS->p->unicastSock6DestAddr;
-               dstPort         = zeroIPPort;
+               dstPort         = inMDNS->UnicastPort6;
                ttl                     = 255;
        }
        else
@@ -3578,7 +3743,7 @@ mDNSlocal void    ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *i
                msg.dwFlags                     = 0;
                                
                err = recvMsgPtr( inSock, &msg, &size, NULL, NULL );
-               err = translate_errno( err == 0, (OSStatus) GetLastError(), kUnknownErr );
+               err = translate_errno( err == 0, (OSStatus) WSAGetLastError(), kUnknownErr );
                require_noerr( err, exit );
                n = (int) size;
                
@@ -3682,14 +3847,11 @@ mDNSlocal void  ProcessingThreadInterfaceListChanged( mDNS *inMDNS )
        
        // Inform clients of the change.
        
-       if( inMDNS->MainCallback )
-       {
-               inMDNS->MainCallback( inMDNS, mStatus_ConfigChanged );
-       }
+       mDNS_ConfigChanged(inMDNS);
        
        // Force mDNS to update.
        
-       mDNSCoreMachineSleep( inMDNS, mDNSfalse );
+       mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this
 }
 
 
@@ -3781,39 +3943,46 @@ mDNSlocal void  ProcessingThreadDynDNSConfigChanged( mDNS *inMDNS )
 
 
 //===========================================================================================================================
-//     ProcessingThreadRetryVPCCheck
+//     ProcessingThreadFileShareChanged
 //===========================================================================================================================
-
-mDNSlocal void
-ProcessingThreadRetryVPCCheck( mDNS * inMDNS )
+mDNSlocal void ProcessingThreadFileShareChanged( mDNS *inMDNS )
 {
-       mStatus err = mStatus_NoError;
-
-       dlog( kDebugLevelTrace, DEBUG_NAME "in ProcessingThreadRetryVPCCheck\n" );
+       mStatus err;
        
-       TearDownRetryVPCCheck( inMDNS );
+       dlog( kDebugLevelInfo, DEBUG_NAME "File shares has changed\n" );
+       check( inMDNS );
+
+       CheckFileShares( inMDNS );
+
+       // and reset the event handler
        
-       if ( inMDNS->p->vpcCheckCount < kRetryVPCMax )
+       if ((inMDNS->p->fileShareKey != NULL) && (inMDNS->p->fileShareEvent))
        {
-               inMDNS->p->vpcCheckCount++;
+               err = RegNotifyChangeKeyValue(inMDNS->p->fileShareKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->fileShareEvent, TRUE);
+               check_noerr( err );
+       }
+}
 
-               err = IsVPCRunning( &inMDNS->p->inVirtualPC );
-               require_noerr( err, exit );
+
+//===========================================================================================================================
+//     ProcessingThreadFileShareChanged
+//===========================================================================================================================
+mDNSlocal void ProcessingThreadFirewallChanged( mDNS *inMDNS )
+{
+       mStatus err;
        
-               if ( inMDNS->p->inVirtualPC )
-               {
-                       ProcessingThreadInterfaceListChanged( inMDNS );
-               }
-       }
+       dlog( kDebugLevelInfo, DEBUG_NAME "Firewall has changed\n" );
+       check( inMDNS );
 
-exit:
+       CheckFileShares( inMDNS );
 
-       if ( err )
+       // and reset the event handler
+       
+       if ((inMDNS->p->firewallKey != NULL) && (inMDNS->p->firewallEvent))
        {
-               SetupRetryVPCCheck( inMDNS );
+               err = RegNotifyChangeKeyValue(inMDNS->p->firewallKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->firewallEvent, TRUE);
+               check_noerr( err );
        }
-
-       return; 
 }
 
 
@@ -3856,8 +4025,9 @@ mDNSlocal int     getifaddrs( struct ifaddrs **outAddrs )
        
        // 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
-       
-       if( !gGetAdaptersAddressesFunctionPtr || ( ( err = getifaddrs_ipv6( outAddrs ) ) != mStatus_NoError ) )
+       // <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 );
@@ -3983,10 +4153,33 @@ mDNSlocal int   getifaddrs_ipv6( struct ifaddrs **outAddrs )
                        int                                             prefixIndex;
                        IP_ADAPTER_PREFIX *             prefix;
                        ULONG                                   prefixLength;
+                       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 );
                        
@@ -4050,7 +4243,7 @@ mDNSlocal int     getifaddrs_ipv6( struct ifaddrs **outAddrs )
                        prefixLength = 0;
                        for( prefixIndex = 0, prefix = firstPrefix; prefix; ++prefixIndex, prefix = prefix->Next )
                        {
-                               if( prefixIndex == addrIndex )
+                               if( ( prefix->Address.lpSockaddr->sa_family == family ) && ( prefixIndex == addrIndex ) )
                                {
                                        check_string( prefix->Address.lpSockaddr->sa_family == family, "addr family != netmask family" );
                                        prefixLength = prefix->PrefixLength;
@@ -4063,25 +4256,10 @@ mDNSlocal int   getifaddrs_ipv6( struct ifaddrs **outAddrs )
                                {
                                        struct sockaddr_in * sa4;
                                        
-                                       require_action( prefixLength <= 32, exit, err = ERROR_INVALID_DATA );
-                                       
                                        sa4 = (struct sockaddr_in *) calloc( 1, sizeof( *sa4 ) );
                                        require_action( sa4, exit, err = WSAENOBUFS );
-                                       
                                        sa4->sin_family = AF_INET;
-                                       
-                                       if ( prefixLength != 0 )
-                                       {
-                                               sa4->sin_addr.s_addr = htonl( 0xFFFFFFFFU << ( 32 - prefixLength ) );
-                                       }
-                                       else
-                                       {
-                                               uint32_t index;
-
-                                               dlog( kDebugLevelWarning, DEBUG_NAME "%s: IPv4 prefixLength is 0\n", __ROUTINE__ );
-                                               err = AddressToIndexAndMask( ifa->ifa_addr, &index, (struct sockaddr*) sa4 );
-                                               require_noerr( err, exit );
-                                       }
+                                       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;
@@ -4206,12 +4384,27 @@ mDNSlocal int   getifaddrs_ipv4( struct ifaddrs **outAddrs )
        
        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 );
                
@@ -4240,14 +4433,14 @@ mDNSlocal int   getifaddrs_ipv4( struct ifaddrs **outAddrs )
                        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;
-                       require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
-                       err = AddressToIndexAndMask( ifa->ifa_addr, &ifa->ifa_extra.index, ifa->ifa_netmask );
-                       require_noerr( err, exit );
+                       ( ( struct sockaddr_in* ) ifa->ifa_netmask )->sin_addr = netmask.sin_addr;
+                       ifa->ifa_extra.index = ifIndex;
                }
                else
                {
@@ -4315,7 +4508,7 @@ mDNSlocal int     getifaddrs_ce( struct ifaddrs **outAddrs )
        // Call WSAIoctl with SIO_ADDRESS_LIST_QUERY and pass a null buffer. This call will fail, but the size needed to 
        // for the request will be filled in. Once we know the size, allocate a buffer to hold the entire list.
        //
-       // NOTE: Due to a bug in Windows CE, the size returned by WSAIoctl is not enough so double it as a workaround.
+       // Note: Due to a bug in Windows CE, the size returned by WSAIoctl is not enough so double it as a workaround.
        
        size = 0;
        WSAIoctl( sock, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0, &size, NULL, NULL );
@@ -4333,7 +4526,7 @@ mDNSlocal int     getifaddrs_ce( struct ifaddrs **outAddrs )
        
        // Process the raw interface list and build a linked list of interfaces.
        //
-       // NOTE: Due to a bug in Windows CE, the iAddressCount field is always 0 so use 1 in that case.
+       // Note: Due to a bug in Windows CE, the iAddressCount field is always 0 so use 1 in that case.
        
        n = addressList->iAddressCount;
        if( n == 0 )
@@ -4551,6 +4744,7 @@ AddressToIndexAndMask( struct sockaddr * addr, uint32_t * ifIndex, struct sockad
        }
 
        require_noerr( err, exit );
+       err = mStatus_UnknownErr;
 
        for ( i = 0; i < pIPAddrTable->dwNumEntries; i++ )
        {
@@ -4591,7 +4785,7 @@ mDNSlocal mDNSBool        CanReceiveUnicast( void )
        ok = IsValidSocket( sock );
        if( ok )
        {
-               memset( &addr, 0, sizeof( addr ) );
+               mDNSPlatformMemZero( &addr, sizeof( addr ) );
                addr.sin_family                 = AF_INET;
                addr.sin_port                   = MulticastDNSPort.NotAnInteger;
                addr.sin_addr.s_addr    = htonl( INADDR_ANY );
@@ -4923,135 +5117,326 @@ exit:
 
 
 //===========================================================================================================================
-//     ConvertUTF8ToLsaString
+//     FreeTCPConnectionData
 //===========================================================================================================================
 
-mDNSlocal OSStatus
-MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input )
+mDNSlocal void
+FreeTCPSocket( TCPSocket *sock )
+{
+       check( sock );
+
+       if ( sock->pendingEvent )
+       {
+               CloseHandle( sock->pendingEvent );
+       }
+
+       if ( sock->fd != INVALID_SOCKET )
+       {
+               closesocket( sock->fd );
+       }
+
+       free( sock );
+}
+
+
+//===========================================================================================================================
+//  FreeUDPSocket
+//===========================================================================================================================
+
+mDNSlocal void
+FreeUDPSocket( UDPSocket * sock )
 {
-       int                     size;
+    check( sock );
+
+    if ( sock->readEvent )
+    {
+        CloseHandle( sock->readEvent );
+    }
+
+    if ( sock->sock != INVALID_SOCKET )
+    {
+        closesocket( sock->sock );
+    }
+
+    free( sock );
+}
+
+//===========================================================================================================================
+//     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( input );
-       check( output );
 
-       output->Buffer = NULL;
+       check( fqdn );
 
-       size = MultiByteToWideChar( CP_UTF8, 0, input, -1, NULL, 0 );
-       err = translate_errno( size > 0, GetLastError(), kUnknownErr );
-       require_noerr( err, exit );
+       // Initialize
+
+       fqdn->c[0] = '\0';
 
-       output->Length = (USHORT)( size * sizeof( wchar_t ) );
-       output->Buffer = (PWCHAR) malloc( output->Length );
-       require_action( output->Buffer, exit, err = mStatus_NoMemoryErr );
-       size = MultiByteToWideChar( CP_UTF8, 0, input, -1, output->Buffer, size );
-       err = translate_errno( size > 0, GetLastError(), kUnknownErr );
+       // Get info from Bonjour registry key
+
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSHostNames, &key );
        require_noerr( err, exit );
 
-       // We're going to subtrace one wchar_t from the size, because we didn't
-       // include it when we encoded the string
+       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)");
+               }
+       }
 
-       output->MaximumLength = output->Length;
-       output->Length          -= sizeof( wchar_t );
-       
 exit:
 
-       if ( err && output->Buffer )
+       if ( key )
        {
-               free( output->Buffer );
-               output->Buffer = NULL;
+               RegCloseKey( key );
+               key = NULL;
        }
 
-       return( err );
+       if ( name )
+       {
+               free( name );
+               name = NULL;
+       }
 }
 
 
-//===========================================================================================================================
-//     ConvertLsaStringToUTF8
-//===========================================================================================================================
-
-mDNSlocal OSStatus
-MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input )
+#ifdef UNICODE
+mDNSlocal void GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey )
+#else
+mDNSlocal void GetDDNSConfig( DNameListElem ** domains, LPCSTR lpSubKey )
+#endif
 {
-       size_t          size;
-       OSStatus        err = kNoErr;
+       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;
 
-       // The Length field of this structure holds the number of bytes,
-       // but WideCharToMultiByte expects the number of wchar_t's. So
-       // we divide by sizeof(wchar_t) to get the correct number.
+       check( domains );
 
-       size = (size_t) WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), NULL, 0, NULL, NULL);
-       err = translate_errno( size != 0, GetLastError(), kUnknownErr );
-       require_noerr( err, exit );
-       
-       // Ensure that we have enough space (Add one for trailing '\0')
+       // Initialize
 
-       require_action( ( size + 1 ) <= len, exit, err = mStatus_NoMemoryErr );
+       *domains = NULL;
 
-       // Convert the string
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, lpSubKey, &key );
+       require_noerr( err, exit );
 
-       size = (size_t) WideCharToMultiByte( CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), output, (int) size, NULL, NULL); 
-       err = translate_errno( size != 0, GetLastError(), kUnknownErr );
+       // Get information about this node
+
+       err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
        require_noerr( err, exit );
 
-       // have to add the trailing 0 because WideCharToMultiByte doesn't do it,
-       // although it does return the correct size
+       for ( i = 0; i < cSubKeys; i++)
+       {
+               DWORD enabled;
 
-       output[size] = '\0';
+               dwSize = kRegistryMaxKeyLength;
+        
+               err = RegEnumKeyExA( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
 
-exit:
+               if ( !err )
+               {
+                       err = RegOpenKeyExA( key, subKeyName, 0, KEY_READ, &subKey );
+                       require_noerr( err, exit );
 
-       return err;
-}
+                       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;
+                               }
+                       }
 
-//===========================================================================================================================
-//     FreeTCPConnectionData
-//===========================================================================================================================
+                       RegCloseKey( subKey );
+                       subKey = NULL;
+               }
+       }
 
-mDNSlocal void
-FreeTCPSocket( TCPSocket *sock )
-{
-       check( sock );
+exit:
 
-       if ( sock->pendingEvent )
+       if ( subKey )
        {
-               CloseHandle( sock->pendingEvent );
+               RegCloseKey( subKey );
        }
 
-       if ( sock->fd != INVALID_SOCKET )
+       if ( key )
        {
-               closesocket( sock->fd );
+               RegCloseKey( key );
        }
-
-       free( sock );
 }
 
-//===========================================================================================================================
-//     SetupAddr
-//===========================================================================================================================
 
-mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
+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 ) ) )
        {
-       if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
+               domainname domain;
+               domainname key;
 
-       if (sa->sa_family == AF_INET)
+               // 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)
                {
-               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);
+                       ptr = (DomainAuthInfo*)malloc(sizeof(DomainAuthInfo));
+                       require_action( ptr, exit, err = mStatus_NoMemoryErr );
                }
 
-       if (sa->sa_family == AF_INET6)
+               err = mDNS_SetSecretForDomain(m, ptr, &domain, &key, outSecret, mDNSfalse );
+               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
+CheckFileShares( mDNS * const m )
+{
+       PSHARE_INFO_1   bufPtr = ( PSHARE_INFO_1 ) NULL;
+       DWORD                   entriesRead = 0;
+       DWORD                   totalEntries = 0;
+       DWORD                   resume = 0;
+       mDNSBool                enabled = mDNSfalse;
+       NET_API_STATUS  res;
+       mStatus                 err;
+
+       check( m );
+
+       if ( mDNSIsFileAndPrintSharingEnabled() )
+       {
+               dlog( kDebugLevelTrace, DEBUG_NAME "file and print sharing is enabled\n" );
+
+               res = NetShareEnum( NULL, 1, ( LPBYTE* )&bufPtr, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resume );
+
+               if ( ( res == ERROR_SUCCESS ) || ( res == ERROR_MORE_DATA ) )
                {
-               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);
+                       PSHARE_INFO_1 p = bufPtr;
+                       DWORD i;
+
+                       for( i = 0; i <= totalEntries; 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 ) )
+                               {
+                                       enabled = mDNStrue;
+                                       break;
+                               }
+
+                               p++;
+                       }
+
+                       NetApiBufferFree( bufPtr );
+                       bufPtr = NULL;
                }
+       }
 
-       LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
-       return(mStatus_Invalid);
+       if ( enabled && !m->p->smbRegistered )
+       {
+               domainname              type;
+               domainname              domain;
+               mDNSIPPort              port = { { SMBPortAsNumber >> 8, SMBPortAsNumber & 0xFF } };
+               mDNSInterfaceID iid = mDNSPlatformInterfaceIDfromInterfaceIndex( m, 0 );
+
+               dlog( kDebugLevelTrace, DEBUG_NAME "registering smb type\n" );
+               
+               MakeDomainNameFromDNSNameString(&type, "_smb._tcp" );
+               MakeDomainNameFromDNSNameString(&domain, "local.");
+
+               err = mDNS_RegisterService( m, &m->p->smbSRS, &m->nicelabel, &type, &domain, NULL, port, NULL, 0, NULL, 0, iid, /* callback */ NULL, /* context */ NULL);
+               require_noerr( err, exit );
+
+               m->p->smbRegistered = mDNStrue;
+       }
+       else if ( !enabled && m->p->smbRegistered )
+       {
+               dlog( kDebugLevelTrace, DEBUG_NAME "deregistering smb type\n" );
+               
+               err = mDNS_DeregisterService( m, &m->p->smbSRS );
+               require_noerr( err, exit );
+
+               m->p->smbRegistered = mDNSfalse;
        }
+
+exit:
+
+       return;
+}
index 04be2cec2ea7c35e6be43dc50a51883ed442ff9e..c85f2fefa476090313b2907571312a233c0f9021 100755 (executable)
     Change History (most recent first):
     
 $Log: mDNSWin32.h,v $
+Revision 1.28  2009/04/24 04:55:26  herscher
+<rdar://problem/3496833> Advertise SMB file sharing via Bonjour
+
+Revision 1.27  2009/03/30 20:45:52  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/6127927> B4Windows: uDNS: Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
+Remove VirtualPC workaround
+
 Revision 1.26  2006/08/14 23:25:21  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -199,16 +207,18 @@ struct    mDNS_PlatformSupport_struct
        HANDLE                                          descChangedEvent;       // Computer description changed event
        HANDLE                                          tcpipChangedEvent;      // TCP/IP config changed
        HANDLE                                          ddnsChangedEvent;       // DynDNS config changed
+       HANDLE                                          fileShareEvent;         // File Sharing changed
+       HANDLE                                          firewallEvent;          // Firewall changed
        HANDLE                                          wakeupEvent;
        HANDLE                                          initEvent;
-       HANDLE                                          vpcCheckEvent;          // Timer handle to check if we're running in Virtual PC
-       int                                                     vpcCheckCount;
        HKEY                                            descKey;
        HKEY                                            tcpipKey;
        HKEY                                            ddnsKey;
+       HKEY                                            fileShareKey;
+       HKEY                                            firewallKey;
+       mDNSBool                                        smbRegistered;
+       ServiceRecordSet                        smbSRS;
        mStatus                                         initStatus;
-       mDNSBool                                        inVirtualPC;
-       int                                                     timersCount;
        mDNSBool                                        registeredLoopback4;
        SocketRef                                       interfaceListChangedSocket;
        int                                                     interfaceCount;
@@ -257,32 +267,6 @@ struct ifaddrs
 };
 
 
-//---------------------------------------------------------------------------------------------------------------------------
-/*!    @function       GetWindowsVersionString
-
-       @abstract       Stores Windows version information in the string passed in (inBuffer)
-*/
-
-OSStatus       GetWindowsVersionString( char *inBuffer, size_t inBufferSize );
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!    @function       getifaddrs
-
-       @abstract       Builds a linked list of interfaces. Caller must free using freeifaddrs if successful.
-*/
-
-int    getifaddrs( struct ifaddrs **outAddrs );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!    @function       freeifaddrs
-
-       @abstract       Frees a linked list of interfaces built with getifaddrs.
-*/
-
-void   freeifaddrs( struct ifaddrs *inAddrs );
-
-
 #ifdef __cplusplus
        }
 #endif
index db0d802f9188411cb586f0329514c80b62ed895e..8173b0d665dda5652ca413ef214eb556a5825fd1 100644 (file)
     Change History (most recent first):
     
 $Log: mdnsNSP.c,v $
+Revision 1.22  2009/03/30 20:34:51  herscher
+<rdar://problem/5925472> Current Bonjour code does not compile on Windows
+<rdar://problem/5914160> Eliminate use of GetNextLabel in mdnsNSP
+
+Revision 1.21  2008/07/16 01:25:10  cheshire
+<rdar://problem/5914160> Eliminate use of GetNextLabel in mdnsNSP
+
 Revision 1.20  2006/08/14 23:26:10  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -96,6 +103,7 @@ mDNS NameSpace Provider (NSP). Hooks into the Windows name resolution system to
 #include       <stdlib.h>
 #include       <string.h>
 
+#include       "ClientCommon.h"
 #include       "CommonServices.h"
 #include       "DebugServices.h"
 
@@ -115,6 +123,8 @@ mDNS NameSpace Provider (NSP). Hooks into the Windows name resolution system to
 #define snprintf _snprintf
 #endif
 
+#define MAX_LABELS 128
+
 #if 0
 #pragma mark == Structures ==
 #endif
@@ -284,7 +294,6 @@ DEBUG_LOCAL OSStatus        HostsFileOpen( HostsFile ** self, const char * fname );
 DEBUG_LOCAL OSStatus   HostsFileClose( HostsFile * self );
 DEBUG_LOCAL void               HostsFileInfoFree( HostsFileInfo * info );
 DEBUG_LOCAL OSStatus   HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo );
-DEBUG_LOCAL const char * GetNextLabel( const char *cstr, char label[64] );
 DEBUG_LOCAL DWORD              GetScopeId( DWORD ifIndex );
 
 #ifdef ENABLE_REVERSE_LOOKUP
@@ -391,7 +400,7 @@ STDAPI      DllRegisterServer( void )
 
        WSCUnInstallNameSpace( &gNSPGUID );
 
-       err = GetModuleFileNameW( gInstance, path, sizeof( path ) );
+       err = GetModuleFileNameW( gInstance, path, MAX_PATH );
        err = translate_errno( err != 0, errno_compat(), kUnknownErr );
        require_noerr( err, exit );
 
@@ -654,7 +663,7 @@ DEBUG_LOCAL int WSPAPI
                char                    translated[ kDNSServiceMaxDomainName ];
                int                             n;
                int                             labels          = 0;
-               const char      *       label[128];
+               const char      *       label[MAX_LABELS];
                char                    text[64];
 
                n = WideCharToMultiByte( CP_UTF8, 0, name, -1, translated, sizeof( translated ), NULL, NULL );
@@ -664,9 +673,12 @@ DEBUG_LOCAL int WSPAPI
 
                // Don't resolve multi-label name
 
+               // <rdar://problem/5914160> Eliminate use of GetNextLabel in mdnsNSP
+               // Add checks for GetNextLabel returning NULL, individual labels being greater than
+               // 64 bytes, and the number of labels being greater than MAX_LABELS
                replyDomain = translated;
 
-               while ( *replyDomain )
+               while (replyDomain && *replyDomain && labels < MAX_LABELS)
                {
                        label[labels++] = replyDomain;
                        replyDomain             = GetNextLabel(replyDomain, text);
@@ -682,7 +694,7 @@ DEBUG_LOCAL int WSPAPI
                require_action( InHostsTable( translated ) == FALSE, exit, err = WSASERVICE_NOT_FOUND );
        }
 
-       // The name ends in .local ( and isn't in the hosts table ), {8,9,A,B}.E.F.ip6.arpa, or .254.169.in-addr.arpa so start the resolve operation. Lazy initialize DNS-SD if needed.
+       // The name ends in .local ( and isn't in the hosts table ), .0.8.e.f.ip6.arpa, or .254.169.in-addr.arpa so start the resolve operation. Lazy initialize DNS-SD if needed.
                
        NSPLock();
        
@@ -2319,37 +2331,6 @@ exit:
 }
 
 
-//===========================================================================================================================
-//     GetNextLabel
-//===========================================================================================================================
-DEBUG_LOCAL const char*
-GetNextLabel(const char *cstr, char label[64])
-{
-       char *ptr = label;
-       while (*cstr && *cstr != '.')                                                           // While we have characters in the label...
-               {
-               char c = *cstr++;
-               if (c == '\\')
-                       {
-                       c = *cstr++;
-                       if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
-                               {
-                               int v0 = cstr[-1] - '0';                                                // then interpret as three-digit decimal
-                               int v1 = cstr[ 0] - '0';
-                               int v2 = cstr[ 1] - '0';
-                               int val = v0 * 100 + v1 * 10 + v2;
-                               if (val <= 255) { c = (char)val; cstr += 2; }   // If valid three-digit decimal value, use it
-                               }
-                       }
-               *ptr++ = c;
-               if (ptr >= label+64) return(NULL);
-               }
-       if (*cstr) cstr++;                                                                                      // Skip over the trailing dot (if present)
-       *ptr++ = 0;
-       return(cstr);
-}
-
-
 #ifdef ENABLE_REVERSE_LOOKUP
 //===========================================================================================================================
 //     IsReverseLookup
@@ -2361,6 +2342,7 @@ IsReverseLookup( LPCWSTR name, size_t size )
        LPCWSTR         p;
        OSStatus        err = kNoErr;
 
+       // IPv6LL Reverse-mapping domains are {8,9,A,B}.E.F.ip6.arpa
        require_action_quiet( size > sizeof_string( ".0.8.e.f.ip6.arpa" ), exit, err = WSASERVICE_NOT_FOUND );
  
        p = name + ( size - 1 );
index f10b4bce03bf407d054b12ffef28a6e6007b2691..1d6f563fbc902850a8704a9917089de0b2f69f72 100644 (file)
 <?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.10"\r
+       Version="8.00"\r
        Name="mdnsNSP"\r
        ProjectGUID="{F4F15529-F0EB-402F-8662-73C5797EE557}"\r
-       Keyword="Win32Proj">\r
+       Keyword="Win32Proj"\r
+       >\r
        <Platforms>\r
                <Platform\r
-                       Name="Win32"/>\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
        </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug"\r
-                       IntermediateDirectory=".\Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories=".;../;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;NSP_EXPORTS;DEBUG;WIN32_LEAN_AND_MEAN"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="TRUE"\r
-                               ExceptionHandling="FALSE"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSShared;../../Clients"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;NSP_EXPORTS;DEBUG;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
                                BasicRuntimeChecks="3"\r
-                               SmallerTypeCheck="TRUE"\r
+                               SmallerTypeCheck="true"\r
                                RuntimeLibrary="1"\r
-                               BufferSecurityCheck="TRUE"\r
+                               BufferSecurityCheck="true"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
-                               DebugInformationFormat="4"\r
-                               CallingConvention="2"/>\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../DLL/Debug/dnssd.lib ws2_32.lib iphlpapi.lib shlwapi.lib"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib iphlpapi.lib shlwapi.lib"\r
                                OutputFile="$(OutDir)/mdnsNSP.dll"\r
                                LinkIncremental="2"\r
                                ModuleDefinitionFile="mdnsNSP.def"\r
                                DelayLoadDLLs="dnssd.dll"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/mdnsNSP.pdb"\r
                                SubSystem="2"\r
-                               BaseAddress="0x16080000"\r
+                               BaseAddress="0x64000000"\r
                                ImportLibrary="$(OutDir)/mdnsNSP.lib"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSShared;../../Clients"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;NSP_EXPORTS;DEBUG;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
+                               BasicRuntimeChecks="3"\r
+                               SmallerTypeCheck="true"\r
+                               RuntimeLibrary="1"\r
+                               BufferSecurityCheck="true"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib iphlpapi.lib shlwapi.lib"\r
+                               OutputFile="$(OutDir)/mdnsNSP.dll"\r
+                               LinkIncremental="2"\r
+                               ModuleDefinitionFile="mdnsNSP.def"\r
+                               DelayLoadDLLs="dnssd.dll"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/mdnsNSP.pdb"\r
+                               SubSystem="2"\r
+                               BaseAddress="0x64000000"\r
+                               ImportLibrary="$(OutDir)/mdnsNSP.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
-                       CharacterSet="2">\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories=".;../;../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_WINDOWS;_USRDLL;NSP_EXPORTS;WIN32_LEAN_AND_MEAN"\r
-                               StringPooling="TRUE"\r
-                               MinimalRebuild="TRUE"\r
-                               ExceptionHandling="FALSE"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSShared;../../Clients"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;_USRDLL;NSP_EXPORTS;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
                                BasicRuntimeChecks="0"\r
-                               SmallerTypeCheck="FALSE"\r
+                               SmallerTypeCheck="false"\r
                                RuntimeLibrary="0"\r
                                UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
-                               CallingConvention="2"/>\r
+                               CallingConvention="2"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
                        <Tool\r
-                               Name="VCCustomBuildTool"/>\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../DLL/Release/dnssd.lib ws2_32.lib iphlpapi.lib shlwapi.lib"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib iphlpapi.lib shlwapi.lib"\r
                                OutputFile="$(OutDir)/mdnsNSP.dll"\r
                                LinkIncremental="1"\r
                                ModuleDefinitionFile="mdnsNSP.def"\r
                                DelayLoadDLLs="dnssd.dll"\r
-                               GenerateDebugInformation="TRUE"\r
+                               GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
                                SubSystem="2"\r
                                OptimizeReferences="0"\r
                                EnableCOMDATFolding="0"\r
-                               BaseAddress="0x16080000"\r
+                               BaseAddress="0x64000000"\r
                                ImportLibrary="$(IntDir)/mdnsNSP.lib"\r
-                               TargetMachine="1"/>\r
+                               TargetMachine="1"\r
+                       />\r
                        <Tool\r
-                               Name="VCMIDLTool"/>\r
+                               Name="VCALinkTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPostBuildEventTool"/>\r
+                               Name="VCManifestTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCPreLinkEventTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                  &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSShared;../../Clients"\r
+                               PreprocessorDefinitions="WIN32;_WINDOWS;_USRDLL;NSP_EXPORTS;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+                               StringPooling="true"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
+                               BasicRuntimeChecks="0"\r
+                               SmallerTypeCheck="false"\r
+                               RuntimeLibrary="0"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerListingLocation="$(IntDir)\"\r
+                               WarningLevel="4"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                               CallingConvention="2"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
-                               AdditionalIncludeDirectories="../"/>\r
+                               AdditionalIncludeDirectories="../"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+                               AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib iphlpapi.lib shlwapi.lib"\r
+                               OutputFile="$(OutDir)/mdnsNSP.dll"\r
+                               LinkIncremental="1"\r
+                               ModuleDefinitionFile="mdnsNSP.def"\r
+                               DelayLoadDLLs="dnssd.dll"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="0"\r
+                               EnableCOMDATFolding="0"\r
+                               BaseAddress="0x64000000"\r
+                               ImportLibrary="$(IntDir)/mdnsNSP.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCXMLDataGeneratorTool"/>\r
+                               Name="VCBscMakeTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCWebDeploymentTool"/>\r
+                               Name="VCFxCopTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCManagedWrapperGeneratorTool"/>\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
                        <Tool\r
-                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="if not &quot;%RC_XBS%&quot; == &quot;YES&quot; goto END&#x0D;&#x0A;if not exist &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;   mkdir &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;xcopy /I/Y &quot;$(TargetPath)&quot;                                                                  &quot;$(DSTROOT)\Program Files\Bonjour\$(PlatformName)&quot;&#x0D;&#x0A;:END&#x0D;&#x0A;"\r
+                       />\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
                <Filter\r
                        Name="Source Files"\r
                        Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
-                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\..\Clients\ClientCommon.c"\r
+                               >\r
+                       </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.c">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\mdnsNSP.c">\r
+                               RelativePath=".\mdnsNSP.c"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\mdnsNSP.def">\r
+                               RelativePath=".\mdnsNSP.def"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                        Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
-                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\..\Clients\ClientCommon.h"\r
+                               >\r
+                       </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\CommonServices.h">\r
+                               RelativePath="..\..\mDNSShared\CommonServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\DebugServices.h">\r
+                               RelativePath="..\..\mDNSShared\DebugServices.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\..\mDNSShared\dns_sd.h">\r
+                               RelativePath="..\..\..\mDNSShared\dns_sd.h"\r
+                               >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\resource.h">\r
+                               RelativePath=".\resource.h"\r
+                               >\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
                        Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
-                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
                        <File\r
-                               RelativePath=".\mdnsNSP.rc">\r
+                               RelativePath=".\mdnsNSP.rc"\r
+                               >\r
                        </File>\r
                </Filter>\r
        </Files>\r