* 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: BonjourExample.cpp,v $
-Revision 1.2 2006/08/14 23:23:57 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2005/05/20 22:01:01 bradley
-Bonjour for Windows example code to browse for HTTP services and deliver via Window messages.
-
-*/
+ */
#include "stdafx.h"
* 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.cpp,v $
-Revision 1.2 2006/08/14 23:23:57 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2005/05/20 22:01:02 bradley
-Bonjour for Windows example code to browse for HTTP services and deliver via Window messages.
-
-*/
+ */
// Standard source file to build the pre-compiled header.
* 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.2 2006/08/14 23:23:57 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2005/05/20 22:01:02 bradley
-Bonjour for Windows example code to browse for HTTP services and deliver via Window messages.
-
-*/
+ */
// Standard Windows pre-compiled header file.
* 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
* 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]);
--- /dev/null
+// 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 "afxres.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 ""afxres.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "\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 1,0,0,0\r
+ PRODUCTVERSION 1,0,0,0\r
+ FILEFLAGSMASK 0x17L\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x1L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", "Apple Inc."\r
+ VALUE "FileDescription", "Bonjour Console Utility"\r
+ VALUE "FileVersion", "1.0.0.0"\r
+ VALUE "InternalName", "dns-sd.exe"\r
+ VALUE "LegalCopyright", "Copyright (C) 2010 Apple Inc."\r
+ VALUE "OriginalFilename", "dns-sd.exe"\r
+ VALUE "ProductName", "Bonjour"\r
+ VALUE "ProductVersion", "1.0.0.0"\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x409, 1200\r
+ END\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
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="8.00"\r
+ Name="dns-sd"\r
+ ProjectGUID="{AA230639-E115-4A44-AA5A-44A61235BA50}"\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="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
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="$(BONJOUR_SDK_HOME)/Include"\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="0"\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
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+ AdditionalDependencies=""$(BONJOUR_SDK_HOME)/Lib/$(PlatformName)/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="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="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="$(BONJOUR_SDK_HOME)/Include"\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="0"\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
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+ AdditionalDependencies=""$(BONJOUR_SDK_HOME)/Lib/$(PlatformName)/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="VCALinkTool"\r
+ />\r
+ <Tool\r
+ Name="VCManifestTool"\r
+ AdditionalManifestFiles="DNS-SD64.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|Win32"\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
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="1"\r
+ OmitFramePointers="true"\r
+ AdditionalIncludeDirectories="$(BONJOUR_SDK_HOME)/Include"\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
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+ AdditionalDependencies=""$(BONJOUR_SDK_HOME)/Lib/$(PlatformName)/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="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
+ CommandLine=""\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="$(BONJOUR_SDK_HOME)/Include"\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
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
+ AdditionalDependencies=""$(BONJOUR_SDK_HOME)/Lib/$(PlatformName)/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="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=""\r
+ />\r
+ </Configuration>\r
+ </Configurations>\r
+ <References>\r
+ </References>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\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
+ >\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\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
+ >\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
+ >\r
+ <File\r
+ RelativePath="dns-sd.rc"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\WINDOWS\system32\$(PlatformName)" mkdir "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
xcopy /I/Y "$(ProjectDir)..\dns-sd.c" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
:END
"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\WINDOWS\system32\$(PlatformName)" mkdir "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\DNSServiceBrowser" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\DNSServiceBrowser"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\SimpleChat" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\SimpleChat"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\DNSServiceBrowser" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\DNSServiceBrowser"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\DNSServiceBrowser\My Project" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\DNSServiceBrowser\My Project"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\SimpleChat" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\SimpleChat"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
xcopy /I/Y "$(ProjectDir)..\dns-sd.c" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
xcopy /I/Y "$(ProjectDir)..\ClientCommon.c" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
xcopy /I/Y "$(ProjectDir)..\ClientCommon.h" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
xcopy /I/Y "$(ProjectDir)resource.h" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
xcopy /I/Y "$(ProjectDir)DNS-SD.manifest" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
xcopy /I/Y "$(ProjectDir)DNS-SD64.manifest" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
xcopy /I/Y "$(ProjectDir)dns-sd.sdk.rc" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
move /Y "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C\dns-sd.sdk.rc" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C\dns-sd.rc"
xcopy /I/Y "$(ProjectDir)dns-sd.sdk.vcproj" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C"
move /Y "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C\dns-sd.sdk.vcproj" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\C\dns-sd.vcproj"
xcopy /I/Y "$(ProjectDir)..\DNSServiceBrowser.NET\App.ico" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\DNSServiceBrowser"
xcopy /I/Y "$(ProjectDir)..\DNSServiceBrowser.NET\AssemblyInfo.cs" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\DNSServiceBrowser"
xcopy /I/Y "$(ProjectDir)..\DNSServiceBrowser.NET\DNSServiceBrowser.NET.csproj" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\DNSServiceBrowser"
xcopy /I/Y "$(ProjectDir)..\DNSServiceBrowser.NET\DNSServiceBrowser.cs" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\DNSServiceBrowser"
xcopy /I/Y "$(ProjectDir)..\DNSServiceBrowser.NET\DNSServiceBrowser.resx" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\DNSServiceBrowser"
xcopy /I/Y "$(ProjectDir)..\SimpleChat.NET\App.ico" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\SimpleChat"
xcopy /I/Y "$(ProjectDir)..\SimpleChat.NET\AssemblyInfo.cs" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\SimpleChat"
xcopy /I/Y "$(ProjectDir)..\SimpleChat.NET\SimpleChat.NET.csproj" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\SimpleChat"
xcopy /I/Y "$(ProjectDir)..\SimpleChat.NET\SimpleChat.cs" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\SimpleChat"
xcopy /I/Y "$(ProjectDir)..\SimpleChat.NET\SimpleChat.resx" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\CS\SimpleChat"
xcopy /I/Y "$(ProjectDir)..\DNSServiceBrowser.VB\DNSServiceBrowser.Designer.vb" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\DNSServiceBrowser"
xcopy /I/Y "$(ProjectDir)..\DNSServiceBrowser.VB\DNSServiceBrowser.VB.vbproj" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\DNSServiceBrowser"
xcopy /I/Y "$(ProjectDir)..\DNSServiceBrowser.VB\DNSServiceBrowser.resx" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\DNSServiceBrowser"
xcopy /I/Y "$(ProjectDir)..\DNSServiceBrowser.VB\DNSServiceBrowser.vb" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\DNSServiceBrowser"
xcopy /E/Y "$(ProjectDir)..\DNSServiceBrowser.VB\My Project" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\DNSServiceBrowser\My Project"
xcopy /E/Y "$(ProjectDir)..\SimpleChat.VB" "$(DSTROOT)\Program Files\Bonjour SDK\Samples\VB\SimpleChat"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
* See the License for the specific language governing permissions and\r
* limitations under the License.\r
-\r
- Change History (most recent first):\r
- \r
-$Log: AssemblyInfo.cs,v $
-Revision 1.2 2006/08/14 23:23:58 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2004/07/19 07:54:24 shersche
-Initial revision
-\r
-\r
-*/\r
+ */\r
\r
using System.Reflection;\r
using System.Runtime.CompilerServices;\r
* 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: 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
-
-Revision 1.6 2005/02/10 22:35:06 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.5 2004/09/21 16:26:58 shersche
-Check to make sure browse list selected item is not null before resolving
-Submitted by: prepin@gmail.com
-
-Revision 1.4 2004/09/13 19:38:17 shersche
-Changed code to reflect namespace and type changes to dnssd.NET library
-
-Revision 1.3 2004/09/11 00:38:14 shersche
-DNSService APIs now assume port in host format. Check for null text record in resolve callback.
-
-Revision 1.2 2004/07/22 23:15:25 shersche
-Fix service names for teleport, tftp, and bootps
-
-Revision 1.1 2004/07/19 07:54:24 shersche
-Initial revision
-
-
-
-*/
+ */
using System;
using System.Drawing;
+'\r
+' Copyright (c) 2010 Apple Inc. All rights reserved.\r
+'\r
+' Licensed under the Apache License, Version 2.0 (the "License");\r
+' you may not use this file except in compliance with the License.\r
+' You may obtain a copy of the License at\r
+' \r
+' http://www.apache.org/licenses/LICENSE-2.0\r
+' \r
+' Unless required by applicable law or agreed to in writing, software\r
+' distributed under the License is distributed on an "AS IS" BASIS,\r
+' WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+' See the License for the specific language governing permissions and\r
+' limitations under the License.\r
+'\r
+\r
Public Class DNSServiceBrowser\r
Public WithEvents MyEventManager As New Bonjour.DNSSDEventManager\r
\r
* 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: DNSServiceBrowser.m,v $
-Revision 1.35 2006/11/27 08:27:49 mkrochma
-Fix a crashing bug
-
-Revision 1.34 2006/11/24 05:41:07 mkrochma
-More cleanup and more service types
-
-Revision 1.33 2006/11/24 01:34:24 mkrochma
-Display interface index and query for IPv6 addresses even when there's no IPv4
-
-Revision 1.32 2006/11/24 00:25:31 mkrochma
-<rdar://problem/4084652> Tools: DNS Service Browser contains some bugs
-
-Revision 1.31 2006/08/14 23:23:55 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.30 2005/01/27 17:46:16 cheshire
-Added comment
-
-Revision 1.29 2004/06/04 20:58:36 cheshire
-Move DNSServiceBrowser from mDNSMacOSX directory to Clients directory
-
-Revision 1.28 2004/05/18 23:51:26 cheshire
-Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
-
-Revision 1.27 2003/11/19 18:49:48 rpantos
-<rdar://problem/3282283> couple of little tweaks to previous checkin
-
-Revision 1.26 2003/11/07 19:35:20 rpantos
-<rdar://problem/3282283> Display multiple IP addresses. Connect using host rather than IP addr.
-
-Revision 1.25 2003/10/29 05:16:54 rpantos
-Checkpoint: transition from DNSServiceDiscovery.h to dns_sd.h
-
-Revision 1.24 2003/10/28 02:25:45 rpantos
-<rdar://problem/3282283> Cancel pending resolve when focus changes or service disappears.
-
-Revision 1.23 2003/10/28 01:29:15 rpantos
-<rdar://problem/3282283> Restructure a bit to make arrow keys work & views behave better.
-
-Revision 1.22 2003/10/28 01:23:27 rpantos
-<rdar://problem/3282283> Bail if mDNS cannot be initialized at startup.
-
-Revision 1.21 2003/10/28 01:19:45 rpantos
-<rdar://problem/3282283> Do not put a trailing '.' on service names. Handle PATH for HTTP txtRecords.
-
-Revision 1.20 2003/10/28 01:13:49 rpantos
-<rdar://problem/3282283> Remove filter when displaying browse results.
-
-Revision 1.19 2003/10/28 01:10:14 rpantos
-<rdar://problem/3282283> Change 'compare' to 'caseInsensitiveCompare' to fix sort order.
-
-Revision 1.18 2003/08/12 19:55:07 cheshire
-Update to APSL 2.0
-
-*/
+ */
#import <Cocoa/Cocoa.h>
#include <sys/types.h>
} else if (interface == kDNSServiceInterfaceIndexLocalOnly) {
// Only available locally on this machine.
strlcpy(interfaceName, "local", IF_NAMESIZE);
+ } else if (interface == kDNSServiceInterfaceIndexP2P) {
+ // Peer-to-peer.
+ strlcpy(interfaceName, "p2p", IF_NAMESIZE);
} else {
// Converts interface index to interface name.
if_indextoname(interface, interfaceName);
* 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: DNSServiceReg.m,v $
-Revision 1.16 2006/08/14 23:23:55 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.15 2004/06/05 02:01:08 cheshire
-Move DNSServiceRegistration from mDNSMacOSX directory to Clients directory
-
-Revision 1.14 2004/03/04 19:20:23 cheshire
-Remove invalid UTF-8 character
-
-Revision 1.13 2003/08/12 19:55:07 cheshire
-Update to APSL 2.0
-
*/
#include "dns_sd.h"
* 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: ClassFactory.cpp,v $
-Revision 1.3 2006/08/14 23:24:00 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
*/
#include "StdAfx.h"
* 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: ClassFactory.h,v $
-Revision 1.3 2006/08/14 23:24:00 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#ifndef __CLASS_FACTORY__
#define __CLASS_FACTORY__
* 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: 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
-
-Revision 1.3 2004/07/26 05:44:08 shersche
-remove extraneous debug statement
-
-Revision 1.2 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#include "StdAfx.h"
* 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: 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
-
-Revision 1.2 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#ifndef __EXPLORER_BAR__
#define __EXPLORER_BAR__
* 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: 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
-
-Revision 1.21 2005/04/06 01:13:07 shersche
-<rdar://problem/4066195> Use the product icon instead of globe icon for 'About' link.
-
-Revision 1.20 2005/03/18 02:43:02 shersche
-<rdar://problem/4046443> Use standard IE website icon for 'About Bonjour', only using globe icon if standard icon cannot be loaded
-
-Revision 1.19 2005/03/16 03:46:27 shersche
-<rdar://problem/4045657> Use Bonjour icon for all discovered sites
-
-Revision 1.18 2005/02/26 01:24:05 shersche
-Remove display lines in tree control
-
-Revision 1.17 2005/02/25 19:57:30 shersche
-<rdar://problem/4023323> Remove FTP browsing from plugin
-
-Revision 1.16 2005/02/08 23:31:06 shersche
-Move "About ..." item underneath WebSites, change icons for discovered sites and "About ..." item
-
-Revision 1.15 2005/01/27 22:38:27 shersche
-add About item to tree list
-
-Revision 1.14 2005/01/25 17:55:39 shersche
-<rdar://problem/3911084> Get bitmaps from non-localizable resource module
-Bug #: 3911084
-
-Revision 1.13 2005/01/06 21:13:09 shersche
-<rdar://problem/3796779> Handle kDNSServiceErr_Firewall return codes
-Bug #: 3796779
-
-Revision 1.12 2004/10/26 00:56:03 cheshire
-Use "#if 0" instead of commenting out code
-
-Revision 1.11 2004/10/18 23:49:17 shersche
-<rdar://problem/3841564> Remove trailing dot from hostname, because some flavors of Windows have difficulty parsing hostnames with a trailing dot.
-Bug #: 3841564
-
-Revision 1.10 2004/09/02 02:18:58 cheshire
-Minor textual cleanup to improve readability
-
-Revision 1.9 2004/09/02 02:11:56 cheshire
-<rdar://problem/3783611> Fix incorrect testing of MoreComing flag
-
-Revision 1.8 2004/07/26 05:47:31 shersche
-use TXTRecord APIs, fix bug in locating service to be removed
-
-Revision 1.7 2004/07/22 16:08:20 shersche
-clean up debug print statements, re-enable code inadvertently commented out
-
-Revision 1.6 2004/07/22 05:27:20 shersche
-<rdar://problem/3735827> Check to make sure error isn't WSAEWOULDBLOCK when canceling browse
-Bug #: 3735827
-
-Revision 1.5 2004/07/20 06:49:18 shersche
-clean up socket handling code
-
-Revision 1.4 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.3 2004/06/27 14:59:59 shersche
-reference count service info to handle multi-homed hosts
-
-Revision 1.2 2004/06/23 16:09:34 shersche
-Add the resolve DNSServiceRef to list of extant refs. This fixes the "doesn't resolve when double clicking" problem
-
-Submitted by: Scott Herscher
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.5 2004/04/15 01:00:05 bradley
-Removed support for automatically querying for A/AAAA records when resolving names. Platforms
-without .local name resolving support will need to manually query for A/AAAA records as needed.
-
-Revision 1.4 2004/04/09 21:03:15 bradley
-Changed port numbers to use network byte order for consistency with other platforms.
-
-Revision 1.3 2004/04/08 09:43:43 bradley
-Changed callback calling conventions to __stdcall so they can be used with C# delegates.
-
-Revision 1.2 2004/02/21 04:36:19 bradley
-Enable dot local name lookups now that the NSP is being installed.
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#include "StdAfx.h"
ServiceHandlerEntry * e;
+ s.LoadString( IDS_ABOUT );
+ m_about = mTree.InsertItem( s, 0, 0 );
+
// Web Site Handler
e = new ServiceHandlerEntry;
e->needsLogin = false;
mServiceHandlers.Add( e );
- s.LoadString( IDS_ABOUT );
- m_about = mTree.InsertItem( s, 0, 0 );
-
err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
require_noerr( err, exit );
m_serviceRefs.push_back(e->ref);
+#if defined( _BROWSE_FOR_HTTPS_ )
+ e = new ServiceHandlerEntry;
+ check( e );
+ e->type = "_https._tcp";
+ e->urlScheme = "https://";
+ e->ref = NULL;
+ e->obj = this;
+ e->needsLogin = false;
+ mServiceHandlers.Add( e );
+
+ err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
+ require_noerr( err, exit );
+
+ err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(e->ref), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE);
+ require_noerr( err, exit );
+
+ m_serviceRefs.push_back(e->ref);
+#endif
+
m_imageList.Create( 16, 16, ILC_MASK | ILC_COLOR16, 2, 0);
bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_LOGO ) ) );
* 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: 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
-
-Revision 1.7 2005/02/25 19:57:30 shersche
-<rdar://problem/4023323> Remove FTP browsing from plugin
-
-Revision 1.6 2005/01/27 22:27:03 shersche
-Add m_about member for "About ..." tree item
-
-Revision 1.5 2004/07/26 05:47:31 shersche
-use TXTRecord APIs, fix bug in locating service to be removed
-
-Revision 1.4 2004/07/20 06:49:18 shersche
-clean up socket handling code
-
-Revision 1.3 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.2 2004/06/27 14:59:59 shersche
-reference count service info to handle multi-homed hosts
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.3 2004/04/15 01:00:05 bradley
-Removed support for automatically querying for A/AAAA records when resolving names. Platforms
-without .local name resolving support will need to manually query for A/AAAA records as needed.
-
-Revision 1.2 2004/04/08 09:43:43 bradley
-Changed callback calling conventions to __stdcall so they can be used with C# delegates.
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#ifndef __EXPLORER_BAR_WINDOW__
#define __EXPLORER_BAR_WINDOW__
* 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: 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
-
-Revision 1.8 2005/06/30 18:01:54 shersche
-<rdar://problem/4130635> Cause IE to rebuild cache so we don't have to reboot following an install.
-
-Revision 1.7 2005/02/23 02:00:45 shersche
-<rdar://problem/4014479> Delete all the registry entries when component is unregistered
-
-Revision 1.6 2005/01/25 17:56:45 shersche
-<rdar://problem/3911084> Load resource DLLs, get icons and bitmaps from resource DLLs
-Bug #: 3911084
-
-Revision 1.5 2004/09/15 10:33:54 shersche
-<rdar://problem/3721611> Install XP toolbar button (8 bit mask) if running on XP platform, otherwise install 1 bit mask toolbar button
-Bug #: 3721611
-
-Revision 1.4 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.3 2004/06/26 14:12:07 shersche
-Register the toolbar button
-
-Revision 1.2 2004/06/24 20:09:39 shersche
-Change text
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#include "StdAfx.h"
; See the License for the specific language governing permissions and
; limitations under the License.
;
-; Change History (most recent first):
-;
-; $Log: ExplorerPlugin.def,v $
-; Revision 1.3 2006/08/14 23:24:00 cheshire
-; Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-;
-; Revision 1.2 2004/07/13 21:24:21 rpantos
-; Fix for <rdar://problem/3701120>.
-;
-; Revision 1.1 2004/06/18 04:34:59 rpantos
-; Move to Clients from mDNSWindows
-;
-; Revision 1.1 2004/01/30 03:01:56 bradley
-; Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-;
-;
LIBRARY ExplorerPlugin
* 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: 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
-
-Revision 1.3 2005/01/25 18:35:38 shersche
-Declare APIs for obtaining handles to resource modules
-
-Revision 1.2 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#pragma once
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
:END
"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
:END
"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\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
+ IDC_LEGAL,92,31,123,50,0\r
END\r
\r
\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj"
:END"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources\en.lproj"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources\en.lproj"
:END"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources\en.lproj"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources"
:END"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\ExplorerPlugin.Resources"
:END"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ExplorerPlugin.Resources"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\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=".\about.bmp"\r
>\r
</File>\r
<File\r
- RelativePath=".\about.bmp"\r
+ RelativePath="res\about.bmp"\r
>\r
</File>\r
<File\r
>\r
</File>\r
<File\r
- RelativePath="res\logo.bmp"\r
+ RelativePath=".\logo.bmp"\r
>\r
</File>\r
<File\r
- RelativePath=".\logo.bmp"\r
+ RelativePath="res\logo.bmp"\r
>\r
</File>\r
<File\r
* 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: LoginDialog.cpp,v $
-Revision 1.3 2006/08/14 23:24:00 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#include <assert.h>
#include <stdlib.h>
* 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: LoginDialog.h,v $
-Revision 1.3 2006/08/14 23:24:00 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#ifndef __LOGIN_DIALOG__
#define __LOGIN_DIALOG__
* 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):
-
*/
// Include the core resources
* 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.cpp,v $
-Revision 1.3 2006/08/14 23:24:00 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#include "StdAfx.h"
* 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.4 2006/08/14 23:24:00 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2005/10/19 19:50:34 herscher
-Workaround a bug in the latest Microsoft Platform SDK when compiling C++ files that include (directly or indirectly) <WspiApi.h>
-
-Revision 1.2 2004/07/13 21:24:21 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:34:59 rpantos
-Move to Clients from mDNSWindows
-
-Revision 1.1 2004/01/30 03:01:56 bradley
-Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
-
-*/
+ */
#ifndef __STDAFX__
#define __STDAFX__
--- /dev/null
+/* -*- 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.
+ */
+
+#include "CDNSSDService.h"
+#include "nsThreadUtils.h"
+#include "nsIEventTarget.h"
+#include "private/pprio.h"
+#include <string>
+#include <stdio.h>
+
+
+NS_IMPL_ISUPPORTS2(CDNSSDService, IDNSSDService, nsIRunnable)
+
+CDNSSDService::CDNSSDService()
+:
+ m_master( 1 ),
+ m_threadPool( NULL ),
+ m_mainRef( NULL ),
+ m_subRef( NULL ),
+ m_listener( NULL ),
+ m_fileDesc( NULL ),
+ m_job( NULL )
+{
+ nsresult err;
+
+ if ( DNSServiceCreateConnection( &m_mainRef ) != kDNSServiceErr_NoError )
+ {
+ err = NS_ERROR_FAILURE;
+ goto exit;
+ }
+
+ if ( ( m_fileDesc = PR_ImportTCPSocket( DNSServiceRefSockFD( m_mainRef ) ) ) == NULL )
+ {
+ err = NS_ERROR_FAILURE;
+ goto exit;
+ }
+
+ if ( ( m_threadPool = PR_CreateThreadPool( 1, 1, 8192 ) ) == NULL )
+ {
+ err = NS_ERROR_FAILURE;
+ goto exit;
+ }
+
+ err = SetupNotifications();
+
+exit:
+
+ if ( err != NS_OK )
+ {
+ Cleanup();
+ }
+}
+
+
+CDNSSDService::CDNSSDService( DNSServiceRef ref, nsISupports * listener )
+:
+ m_master( 0 ),
+ m_threadPool( NULL ),
+ m_mainRef( ref ),
+ m_subRef( ref ),
+ m_listener( listener ),
+ m_fileDesc( NULL ),
+ m_job( NULL )
+{
+}
+
+
+CDNSSDService::~CDNSSDService()
+{
+ Cleanup();
+}
+
+
+void
+CDNSSDService::Cleanup()
+{
+ if ( m_master )
+ {
+ if ( m_job )
+ {
+ PR_CancelJob( m_job );
+ m_job = NULL;
+ }
+
+ if ( m_threadPool != NULL )
+ {
+ PR_ShutdownThreadPool( m_threadPool );
+ m_threadPool = NULL;
+ }
+
+ if ( m_fileDesc != NULL )
+ {
+ PR_Close( m_fileDesc );
+ m_fileDesc = NULL;
+ }
+
+ if ( m_mainRef )
+ {
+ DNSServiceRefDeallocate( m_mainRef );
+ m_mainRef = NULL;
+ }
+ }
+ else
+ {
+ if ( m_subRef )
+ {
+ DNSServiceRefDeallocate( m_subRef );
+ m_subRef = NULL;
+ }
+ }
+}
+
+
+nsresult
+CDNSSDService::SetupNotifications()
+{
+ NS_PRECONDITION( m_threadPool != NULL, "m_threadPool is NULL" );
+ NS_PRECONDITION( m_fileDesc != NULL, "m_fileDesc is NULL" );
+ NS_PRECONDITION( m_job == NULL, "m_job is not NULL" );
+
+ m_iod.socket = m_fileDesc;
+ m_iod.timeout = PR_INTERVAL_MAX;
+ m_job = PR_QueueJob_Read( m_threadPool, &m_iod, Read, this, PR_FALSE );
+ return ( m_job ) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+
+/* IDNSSDService browse (in long interfaceIndex, in AString regtype, in AString domain, in IDNSSDBrowseListener listener); */
+NS_IMETHODIMP
+CDNSSDService::Browse(PRInt32 interfaceIndex, const nsAString & regtype, const nsAString & domain, IDNSSDBrowseListener *listener, IDNSSDService **_retval NS_OUTPARAM)
+{
+ CDNSSDService * service = NULL;
+ DNSServiceErrorType dnsErr = 0;
+ nsresult err = 0;
+
+ *_retval = NULL;
+
+ if ( !m_mainRef )
+ {
+ err = NS_ERROR_NOT_AVAILABLE;
+ goto exit;
+ }
+
+ try
+ {
+ service = new CDNSSDService( m_mainRef, listener );
+ }
+ catch ( ... )
+ {
+ service = NULL;
+ }
+
+ if ( service == NULL )
+ {
+ err = NS_ERROR_FAILURE;
+ goto exit;
+ }
+
+ dnsErr = DNSServiceBrowse( &service->m_subRef, kDNSServiceFlagsShareConnection, interfaceIndex, NS_ConvertUTF16toUTF8( regtype ).get(), NS_ConvertUTF16toUTF8( domain ).get(), ( DNSServiceBrowseReply ) BrowseReply, service );
+
+ if ( dnsErr != kDNSServiceErr_NoError )
+ {
+ err = NS_ERROR_FAILURE;
+ goto exit;
+ }
+
+ listener->AddRef();
+ service->AddRef();
+ *_retval = service;
+ err = NS_OK;
+
+exit:
+
+ if ( err && service )
+ {
+ delete service;
+ service = NULL;
+ }
+
+ return err;
+}
+
+
+/* IDNSSDService resolve (in long interfaceIndex, in AString name, in AString regtype, in AString domain, in IDNSSDResolveListener listener); */
+NS_IMETHODIMP
+CDNSSDService::Resolve(PRInt32 interfaceIndex, const nsAString & name, const nsAString & regtype, const nsAString & domain, IDNSSDResolveListener *listener, IDNSSDService **_retval NS_OUTPARAM)
+{
+ CDNSSDService * service;
+ DNSServiceErrorType dnsErr;
+ nsresult err;
+
+ *_retval = NULL;
+
+ if ( !m_mainRef )
+ {
+ err = NS_ERROR_NOT_AVAILABLE;
+ goto exit;
+ }
+
+ try
+ {
+ service = new CDNSSDService( m_mainRef, listener );
+ }
+ catch ( ... )
+ {
+ service = NULL;
+ }
+
+ if ( service == NULL )
+ {
+ err = NS_ERROR_FAILURE;
+ goto exit;
+ }
+
+ dnsErr = DNSServiceResolve( &service->m_subRef, kDNSServiceFlagsShareConnection, interfaceIndex, NS_ConvertUTF16toUTF8( name ).get(), NS_ConvertUTF16toUTF8( regtype ).get(), NS_ConvertUTF16toUTF8( domain ).get(), ( DNSServiceResolveReply ) ResolveReply, service );
+
+ if ( dnsErr != kDNSServiceErr_NoError )
+ {
+ err = NS_ERROR_FAILURE;
+ goto exit;
+ }
+
+ listener->AddRef();
+ service->AddRef();
+ *_retval = service;
+ err = NS_OK;
+
+exit:
+
+ if ( err && service )
+ {
+ delete service;
+ service = NULL;
+ }
+
+ return err;
+}
+
+
+/* void stop (); */
+NS_IMETHODIMP
+CDNSSDService::Stop()
+{
+ if ( m_subRef )
+ {
+ DNSServiceRefDeallocate( m_subRef );
+ m_subRef = NULL;
+ }
+
+ return NS_OK;
+}
+
+
+void
+CDNSSDService::Read( void * arg )
+{
+ NS_PRECONDITION( arg != NULL, "arg is NULL" );
+
+ NS_DispatchToMainThread( ( CDNSSDService* ) arg );
+}
+
+
+NS_IMETHODIMP
+CDNSSDService::Run()
+{
+ nsresult err = NS_OK;
+
+ NS_PRECONDITION( m_mainRef != NULL, "m_mainRef is NULL" );
+
+ m_job = NULL;
+
+ if ( PR_Available( m_fileDesc ) > 0 )
+ {
+ if ( DNSServiceProcessResult( m_mainRef ) != kDNSServiceErr_NoError )
+ {
+ err = NS_ERROR_FAILURE;
+ }
+ }
+
+ if ( !err )
+ {
+ err = SetupNotifications();
+ }
+
+ return err;
+}
+
+
+void DNSSD_API
+CDNSSDService::BrowseReply
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char * serviceName,
+ const char * regtype,
+ const char * replyDomain,
+ void * context
+ )
+{
+ CDNSSDService * self = ( CDNSSDService* ) context;
+
+ // This should never be NULL, but let's be defensive.
+
+ if ( self != NULL )
+ {
+ IDNSSDBrowseListener * listener = ( IDNSSDBrowseListener* ) self->m_listener;
+
+ // Same for this
+
+ if ( listener != NULL )
+ {
+ listener->OnBrowse( self, ( flags & kDNSServiceFlagsAdd ) ? PR_TRUE : PR_FALSE, interfaceIndex, errorCode, NS_ConvertUTF8toUTF16( serviceName ), NS_ConvertUTF8toUTF16( regtype ), NS_ConvertUTF8toUTF16( replyDomain ) );
+ }
+ }
+}
+
+
+void DNSSD_API
+CDNSSDService::ResolveReply
+ (
+ 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
+ )
+{
+ CDNSSDService * self = ( CDNSSDService* ) context;
+
+ // This should never be NULL, but let's be defensive.
+
+ if ( self != NULL )
+ {
+ IDNSSDResolveListener * listener = ( IDNSSDResolveListener* ) self->m_listener;
+
+ // Same for this
+
+ if ( listener != NULL )
+ {
+ std::string path = "";
+ const void * value = NULL;
+ uint8_t valueLen = 0;
+
+ value = TXTRecordGetValuePtr( txtLen, txtRecord, "path", &valueLen );
+
+ if ( value && valueLen )
+ {
+ char * temp;
+
+ temp = new char[ valueLen + 2 ];
+
+ if ( temp )
+ {
+ char * dst = temp;
+
+ memset( temp, 0, valueLen + 2 );
+
+ if ( ( ( char* ) value )[ 0 ] != '/' )
+ {
+ *dst++ = '/';
+ }
+
+ memcpy( dst, value, valueLen );
+ path = temp;
+ delete [] temp;
+ }
+ }
+
+ listener->OnResolve( self, interfaceIndex, errorCode, NS_ConvertUTF8toUTF16( fullname ), NS_ConvertUTF8toUTF16( hosttarget ) , ntohs( port ), NS_ConvertUTF8toUTF16( path.c_str() ) );
+ }
+ }
+}
+
--- /dev/null
+/* -*- 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.
+ */
+
+
+#ifndef _CDNSSDSERVICE_H
+#define _CDNSSDSERVICE_H
+
+#include "IDNSSDService.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIThread.h"
+#include "nsIRunnable.h"
+#include "prtpool.h"
+#include <dns_sd.h>
+#include <stdio.h>
+#include <string>
+
+
+#define CDNSSDSERVICE_CONTRACTID "@apple.com/DNSSDService;1"
+#define CDNSSDSERVICE_CLASSNAME "CDNSSDService"
+#define CDNSSDSERVICE_CID { 0x944ED267, 0x465A, 0x4989, { 0x82, 0x72, 0x7E, 0xE9, 0x28, 0x6C, 0x99, 0xA5 } }
+
+
+/* Header file */
+class CDNSSDService : public IDNSSDService, nsIRunnable
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_IDNSSDSERVICE
+ NS_DECL_NSIRUNNABLE
+
+ CDNSSDService();
+ CDNSSDService( DNSServiceRef mainRef, nsISupports * listener );
+
+ virtual ~CDNSSDService();
+
+private:
+
+ 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
+ );
+
+ static void DNSSD_API
+ ResolveReply
+ (
+ 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
+ );
+
+ static void
+ Read
+ (
+ void * arg
+ );
+
+ nsresult
+ SetupNotifications();
+
+ void
+ Cleanup();
+
+ char m_master;
+ PRThreadPool * m_threadPool;
+ DNSServiceRef m_mainRef;
+ DNSServiceRef m_subRef;
+ nsISupports * m_listener;
+ PRFileDesc * m_fileDesc;
+ PRJobIoDesc m_iod;
+ PRJob * m_job;
+};
+
+
+#endif
--- /dev/null
+/* -*- 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.
+ */
+
+#include "nsIGenericFactory.h"
+#include "CDNSSDService.h"
+
+NS_COM_GLUE nsresult
+NS_NewGenericModule2(nsModuleInfo const *info, nsIModule* *result);
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(CDNSSDService)
+
+static nsModuleComponentInfo components[] =
+{
+ {
+ CDNSSDSERVICE_CLASSNAME,
+ CDNSSDSERVICE_CID,
+ CDNSSDSERVICE_CONTRACTID,
+ CDNSSDServiceConstructor,
+ }
+};
+
+NS_IMPL_NSGETMODULE("CDNSSDServiceModule", components)
+
--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 9.00\r
+# Visual Studio 2005\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNSSDService", "DNSSDService.vcproj", "{7826EA27-D4CC-4FAA-AD23-DF813823227B}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Debug|Win32 = Debug|Win32\r
+ Release|Win32 = Release|Win32\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Debug|Win32.ActiveCfg = Debug|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Debug|Win32.Build.0 = Debug|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Release|Win32.ActiveCfg = Release|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Release|Win32.Build.0 = Release|Win32\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+#include "WinVersRes.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "#include ""WinVersRes.h""\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MASTER_PROD_VERS
+ PRODUCTVERSION MASTER_PROD_VERS
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", MASTER_COMPANY_NAME
+ VALUE "FileDescription", "Firefox Extension Library"
+ VALUE "FileVersion", MASTER_PROD_VERS_STR
+ VALUE "InternalName", "DNSSDService.dll"
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT
+ VALUE "OriginalFilename", "DNSSDService.dll"
+ VALUE "ProductName", MASTER_PROD_NAME
+ VALUE "ProductVersion", MASTER_PROD_VERS_STR
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="8.00"\r
+ Name="FirefoxExtension"\r
+ ProjectGUID="{7826EA27-D4CC-4FAA-AD23-DF813823227B}"\r
+ >\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"\r
+ />\r
+ </Platforms>\r
+ <ToolFiles>\r
+ </ToolFiles>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ ConfigurationType="2"\r
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
+ UseOfMFC="0"\r
+ ATLMinimizesCRunTimeLibraryUsage="false"\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="true"\r
+ SuppressStartupBanner="true"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName=".\$(OutDir)\DNSSDService.tlb"\r
+ HeaderFileName=""\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="1"\r
+ AdditionalIncludeDirectories="..\..\mDNSShared;"$(SRCROOT)\AppleInternal\XULRunner\include\xpcom";"$(SRCROOT)\AppleInternal\XULRunner\include\nspr";"$(SRCROOT)\AppleInternal\XULRunner\include\string";"$(SRCROOT)\AppleInternal\XULRunner\include\pref";"$(SRCROOT)\AppleInternal\XULRunner\sdk\include""\r
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;DNSSDSERVICE_EXPORTS;XP_WIN;XP_WIN32"\r
+ StringPooling="true"\r
+ RuntimeLibrary="0"\r
+ EnableFunctionLevelLinking="true"\r
+ PrecompiledHeaderFile=""\r
+ AssemblerListingLocation="$(IntDir)\"\r
+ ObjectFile="$(IntDir)\"\r
+ ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
+ WarningLevel="3"\r
+ SuppressStartupBanner="true"\r
+ ForcedIncludeFiles=""\r
+ />\r
+ <Tool\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="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+ AdditionalDependencies="$(SRCROOT)\AppleInternal\XULRunner\lib\nspr4.lib $(SRCROOT)\AppleInternal\XULRunner\lib\xpcom.lib $(SRCROOT)\AppleInternal\XULRunner\lib\xpcomglue_s.lib ws2_32.lib ../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib"\r
+ OutputFile="$(OutDir)\DNSSDService.dll"\r
+ LinkIncremental="1"\r
+ SuppressStartupBanner="true"\r
+ AdditionalLibraryDirectories=""\r
+ ProgramDatabaseFile=".\$(OutDir)/DNSSDService.pdb"\r
+ ImportLibrary=".\$(OutDir)/DNSSDService.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
+ SuppressStartupBanner="true"\r
+ OutputFile=".\$(OutDir)\DNSSDService.bsc"\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="xcopy /I/Y $(PlatformName)\$(ConfigurationName)\DNSSDService.dll extension\platform\WINNT\components
if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\FirefoxExtension" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\FirefoxExtension"
xcopy /E/I/Y "extension" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\FirefoxExtension"
:END
"\r
+ />\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ ConfigurationType="2"\r
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
+ UseOfMFC="0"\r
+ ATLMinimizesCRunTimeLibraryUsage="false"\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="true"\r
+ SuppressStartupBanner="true"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName=".\$(OutDir)\DNSSDService.tlb"\r
+ HeaderFileName=""\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="..\..\mDNSShared;"$(SRCROOT)\AppleInternal\XULRunner\include\xpcom";"$(SRCROOT)\AppleInternal\XULRunner\include\nspr";"$(SRCROOT)\AppleInternal\XULRunner\include\string";"$(SRCROOT)\AppleInternal\XULRunner\include\pref";"$(SRCROOT)\AppleInternal\XULRunner\sdk\include""\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DNSSDSERVICE_EXPORTS;XP_WIN;XP_WIN32"\r
+ MinimalRebuild="true"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="1"\r
+ PrecompiledHeaderFile=""\r
+ AssemblerListingLocation="$(IntDir)\"\r
+ ObjectFile="$(IntDir)\"\r
+ ProgramDataBaseFileName="$(IntDir)\vc80.pdb"\r
+ WarningLevel="3"\r
+ SuppressStartupBanner="true"\r
+ DebugInformationFormat="3"\r
+ ForcedIncludeFiles=""\r
+ />\r
+ <Tool\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="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
+ AdditionalDependencies="$(SRCROOT)\AppleInternal\XULRunner\lib\nspr4.lib $(SRCROOT)\AppleInternal\XULRunner\lib\xpcom.lib $(SRCROOT)\AppleInternal\XULRunner\lib\xpcomglue_s.lib ws2_32.lib ../../mDNSWindows/DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib"\r
+ OutputFile="$(OutDir)\DNSSDService.dll"\r
+ LinkIncremental="2"\r
+ SuppressStartupBanner="true"\r
+ AdditionalLibraryDirectories=""\r
+ GenerateDebugInformation="true"\r
+ ProgramDatabaseFile=".\$(OutDir)\DNSSDService.pdb"\r
+ ImportLibrary=".\$(OutDir)/DNSSDService.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
+ SuppressStartupBanner="true"\r
+ OutputFile=".\$(OutDir)\DNSSDService.bsc"\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="xcopy /I/Y $(PlatformName)\$(ConfigurationName)\DNSSDService.dll extension\platform\WINNT\components"\r
+ />\r
+ </Configuration>\r
+ </Configurations>\r
+ <References>\r
+ </References>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+ >\r
+ <File\r
+ RelativePath=".\CDNSSDService.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\CDNSSDServiceModule.cpp"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl"\r
+ >\r
+ <File\r
+ RelativePath=".\CDNSSDService.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\IDNSSDService.h"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="IDL"\r
+ Filter="idl"\r
+ >\r
+ <File\r
+ RelativePath=".\IDNSSDService.idl"\r
+ >\r
+ <FileConfiguration\r
+ Name="Release|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ />\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Debug|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ />\r
+ </FileConfiguration>\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+ >\r
+ <File\r
+ RelativePath=".\FirefoxExtension.rc"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+/*\r
+ * DO NOT EDIT. THIS FILE IS GENERATED FROM IDNSSDService.idl\r
+ */\r
+\r
+#ifndef __gen_IDNSSDService_h__\r
+#define __gen_IDNSSDService_h__\r
+\r
+\r
+#ifndef __gen_nsISupports_h__\r
+#include "nsISupports.h"\r
+#endif\r
+\r
+/* For IDL files that don't want to include root IDL files. */\r
+#ifndef NS_NO_VTABLE\r
+#define NS_NO_VTABLE\r
+#endif\r
+class IDNSSDService; /* forward declaration */\r
+\r
+\r
+/* starting interface: IDNSSDBrowseListener */\r
+#define IDNSSDBROWSELISTENER_IID_STR "27346495-a1ed-458a-a5bc-587df9a26b4f"\r
+\r
+#define IDNSSDBROWSELISTENER_IID \\r
+ {0x27346495, 0xa1ed, 0x458a, \\r
+ { 0xa5, 0xbc, 0x58, 0x7d, 0xf9, 0xa2, 0x6b, 0x4f }}\r
+\r
+class NS_NO_VTABLE NS_SCRIPTABLE IDNSSDBrowseListener : public nsISupports {\r
+ public: \r
+\r
+ NS_DECLARE_STATIC_IID_ACCESSOR(IDNSSDBROWSELISTENER_IID)\r
+\r
+ /* void onBrowse (in IDNSSDService service, in boolean add, in long interfaceIndex, in long error, in AString serviceName, in AString regtype, in AString domain); */\r
+ NS_SCRIPTABLE NS_IMETHOD OnBrowse(IDNSSDService *service, PRBool add, PRInt32 interfaceIndex, PRInt32 error, const nsAString & serviceName, const nsAString & regtype, const nsAString & domain) = 0;\r
+\r
+};\r
+\r
+ NS_DEFINE_STATIC_IID_ACCESSOR(IDNSSDBrowseListener, IDNSSDBROWSELISTENER_IID)\r
+\r
+/* Use this macro when declaring classes that implement this interface. */\r
+#define NS_DECL_IDNSSDBROWSELISTENER \\r
+ NS_SCRIPTABLE NS_IMETHOD OnBrowse(IDNSSDService *service, PRBool add, PRInt32 interfaceIndex, PRInt32 error, const nsAString & serviceName, const nsAString & regtype, const nsAString & domain); \r
+\r
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */\r
+#define NS_FORWARD_IDNSSDBROWSELISTENER(_to) \\r
+ NS_SCRIPTABLE NS_IMETHOD OnBrowse(IDNSSDService *service, PRBool add, PRInt32 interfaceIndex, PRInt32 error, const nsAString & serviceName, const nsAString & regtype, const nsAString & domain) { return _to OnBrowse(service, add, interfaceIndex, error, serviceName, regtype, domain); } \r
+\r
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */\r
+#define NS_FORWARD_SAFE_IDNSSDBROWSELISTENER(_to) \\r
+ NS_SCRIPTABLE NS_IMETHOD OnBrowse(IDNSSDService *service, PRBool add, PRInt32 interfaceIndex, PRInt32 error, const nsAString & serviceName, const nsAString & regtype, const nsAString & domain) { return !_to ? NS_ERROR_NULL_POINTER : _to->OnBrowse(service, add, interfaceIndex, error, serviceName, regtype, domain); } \r
+\r
+#if 0\r
+/* Use the code below as a template for the implementation class for this interface. */\r
+\r
+/* Header file */\r
+class _MYCLASS_ : public IDNSSDBrowseListener\r
+{\r
+public:\r
+ NS_DECL_ISUPPORTS\r
+ NS_DECL_IDNSSDBROWSELISTENER\r
+\r
+ _MYCLASS_();\r
+\r
+private:\r
+ ~_MYCLASS_();\r
+\r
+protected:\r
+ /* additional members */\r
+};\r
+\r
+/* Implementation file */\r
+NS_IMPL_ISUPPORTS1(_MYCLASS_, IDNSSDBrowseListener)\r
+\r
+_MYCLASS_::_MYCLASS_()\r
+{\r
+ /* member initializers and constructor code */\r
+}\r
+\r
+_MYCLASS_::~_MYCLASS_()\r
+{\r
+ /* destructor code */\r
+}\r
+\r
+/* void onBrowse (in IDNSSDService service, in boolean add, in long interfaceIndex, in long error, in AString serviceName, in AString regtype, in AString domain); */\r
+NS_IMETHODIMP _MYCLASS_::OnBrowse(IDNSSDService *service, PRBool add, PRInt32 interfaceIndex, PRInt32 error, const nsAString & serviceName, const nsAString & regtype, const nsAString & domain)\r
+{\r
+ return NS_ERROR_NOT_IMPLEMENTED;\r
+}\r
+\r
+/* End of implementation class template. */\r
+#endif\r
+\r
+\r
+/* starting interface: IDNSSDResolveListener */\r
+#define IDNSSDRESOLVELISTENER_IID_STR "6620e18f-47f3-47c6-941f-126a5fd4fcf7"\r
+\r
+#define IDNSSDRESOLVELISTENER_IID \\r
+ {0x6620e18f, 0x47f3, 0x47c6, \\r
+ { 0x94, 0x1f, 0x12, 0x6a, 0x5f, 0xd4, 0xfc, 0xf7 }}\r
+\r
+class NS_NO_VTABLE NS_SCRIPTABLE IDNSSDResolveListener : public nsISupports {\r
+ public: \r
+\r
+ NS_DECLARE_STATIC_IID_ACCESSOR(IDNSSDRESOLVELISTENER_IID)\r
+\r
+ /* void onResolve (in IDNSSDService service, in long interfaceIndex, in long error, in AString fullname, in AString host, in short port, in AString path); */\r
+ NS_SCRIPTABLE NS_IMETHOD OnResolve(IDNSSDService *service, PRInt32 interfaceIndex, PRInt32 error, const nsAString & fullname, const nsAString & host, PRInt16 port, const nsAString & path) = 0;\r
+\r
+};\r
+\r
+ NS_DEFINE_STATIC_IID_ACCESSOR(IDNSSDResolveListener, IDNSSDRESOLVELISTENER_IID)\r
+\r
+/* Use this macro when declaring classes that implement this interface. */\r
+#define NS_DECL_IDNSSDRESOLVELISTENER \\r
+ NS_SCRIPTABLE NS_IMETHOD OnResolve(IDNSSDService *service, PRInt32 interfaceIndex, PRInt32 error, const nsAString & fullname, const nsAString & host, PRInt16 port, const nsAString & path); \r
+\r
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */\r
+#define NS_FORWARD_IDNSSDRESOLVELISTENER(_to) \\r
+ NS_SCRIPTABLE NS_IMETHOD OnResolve(IDNSSDService *service, PRInt32 interfaceIndex, PRInt32 error, const nsAString & fullname, const nsAString & host, PRInt16 port, const nsAString & path) { return _to OnResolve(service, interfaceIndex, error, fullname, host, port, path); } \r
+\r
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */\r
+#define NS_FORWARD_SAFE_IDNSSDRESOLVELISTENER(_to) \\r
+ NS_SCRIPTABLE NS_IMETHOD OnResolve(IDNSSDService *service, PRInt32 interfaceIndex, PRInt32 error, const nsAString & fullname, const nsAString & host, PRInt16 port, const nsAString & path) { return !_to ? NS_ERROR_NULL_POINTER : _to->OnResolve(service, interfaceIndex, error, fullname, host, port, path); } \r
+\r
+#if 0\r
+/* Use the code below as a template for the implementation class for this interface. */\r
+\r
+/* Header file */\r
+class _MYCLASS_ : public IDNSSDResolveListener\r
+{\r
+public:\r
+ NS_DECL_ISUPPORTS\r
+ NS_DECL_IDNSSDRESOLVELISTENER\r
+\r
+ _MYCLASS_();\r
+\r
+private:\r
+ ~_MYCLASS_();\r
+\r
+protected:\r
+ /* additional members */\r
+};\r
+\r
+/* Implementation file */\r
+NS_IMPL_ISUPPORTS1(_MYCLASS_, IDNSSDResolveListener)\r
+\r
+_MYCLASS_::_MYCLASS_()\r
+{\r
+ /* member initializers and constructor code */\r
+}\r
+\r
+_MYCLASS_::~_MYCLASS_()\r
+{\r
+ /* destructor code */\r
+}\r
+\r
+/* void onResolve (in IDNSSDService service, in long interfaceIndex, in long error, in AString fullname, in AString host, in short port, in AString path); */\r
+NS_IMETHODIMP _MYCLASS_::OnResolve(IDNSSDService *service, PRInt32 interfaceIndex, PRInt32 error, const nsAString & fullname, const nsAString & host, PRInt16 port, const nsAString & path)\r
+{\r
+ return NS_ERROR_NOT_IMPLEMENTED;\r
+}\r
+\r
+/* End of implementation class template. */\r
+#endif\r
+\r
+\r
+/* starting interface: IDNSSDService */\r
+#define IDNSSDSERVICE_IID_STR "3a3539ff-f8d8-40b4-8d02-5ea73c51fa12"\r
+\r
+#define IDNSSDSERVICE_IID \\r
+ {0x3a3539ff, 0xf8d8, 0x40b4, \\r
+ { 0x8d, 0x02, 0x5e, 0xa7, 0x3c, 0x51, 0xfa, 0x12 }}\r
+\r
+class NS_NO_VTABLE NS_SCRIPTABLE IDNSSDService : public nsISupports {\r
+ public: \r
+\r
+ NS_DECLARE_STATIC_IID_ACCESSOR(IDNSSDSERVICE_IID)\r
+\r
+ /* IDNSSDService browse (in long interfaceIndex, in AString regtype, in AString domain, in IDNSSDBrowseListener listener); */\r
+ NS_SCRIPTABLE NS_IMETHOD Browse(PRInt32 interfaceIndex, const nsAString & regtype, const nsAString & domain, IDNSSDBrowseListener *listener, IDNSSDService **_retval NS_OUTPARAM) = 0;\r
+\r
+ /* IDNSSDService resolve (in long interfaceIndex, in AString name, in AString regtype, in AString domain, in IDNSSDResolveListener listener); */\r
+ NS_SCRIPTABLE NS_IMETHOD Resolve(PRInt32 interfaceIndex, const nsAString & name, const nsAString & regtype, const nsAString & domain, IDNSSDResolveListener *listener, IDNSSDService **_retval NS_OUTPARAM) = 0;\r
+\r
+ /* void stop (); */\r
+ NS_SCRIPTABLE NS_IMETHOD Stop(void) = 0;\r
+\r
+};\r
+\r
+ NS_DEFINE_STATIC_IID_ACCESSOR(IDNSSDService, IDNSSDSERVICE_IID)\r
+\r
+/* Use this macro when declaring classes that implement this interface. */\r
+#define NS_DECL_IDNSSDSERVICE \\r
+ NS_SCRIPTABLE NS_IMETHOD Browse(PRInt32 interfaceIndex, const nsAString & regtype, const nsAString & domain, IDNSSDBrowseListener *listener, IDNSSDService **_retval NS_OUTPARAM); \\r
+ NS_SCRIPTABLE NS_IMETHOD Resolve(PRInt32 interfaceIndex, const nsAString & name, const nsAString & regtype, const nsAString & domain, IDNSSDResolveListener *listener, IDNSSDService **_retval NS_OUTPARAM); \\r
+ NS_SCRIPTABLE NS_IMETHOD Stop(void); \r
+\r
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */\r
+#define NS_FORWARD_IDNSSDSERVICE(_to) \\r
+ NS_SCRIPTABLE NS_IMETHOD Browse(PRInt32 interfaceIndex, const nsAString & regtype, const nsAString & domain, IDNSSDBrowseListener *listener, IDNSSDService **_retval NS_OUTPARAM) { return _to Browse(interfaceIndex, regtype, domain, listener, _retval); } \\r
+ NS_SCRIPTABLE NS_IMETHOD Resolve(PRInt32 interfaceIndex, const nsAString & name, const nsAString & regtype, const nsAString & domain, IDNSSDResolveListener *listener, IDNSSDService **_retval NS_OUTPARAM) { return _to Resolve(interfaceIndex, name, regtype, domain, listener, _retval); } \\r
+ NS_SCRIPTABLE NS_IMETHOD Stop(void) { return _to Stop(); } \r
+\r
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */\r
+#define NS_FORWARD_SAFE_IDNSSDSERVICE(_to) \\r
+ NS_SCRIPTABLE NS_IMETHOD Browse(PRInt32 interfaceIndex, const nsAString & regtype, const nsAString & domain, IDNSSDBrowseListener *listener, IDNSSDService **_retval NS_OUTPARAM) { return !_to ? NS_ERROR_NULL_POINTER : _to->Browse(interfaceIndex, regtype, domain, listener, _retval); } \\r
+ NS_SCRIPTABLE NS_IMETHOD Resolve(PRInt32 interfaceIndex, const nsAString & name, const nsAString & regtype, const nsAString & domain, IDNSSDResolveListener *listener, IDNSSDService **_retval NS_OUTPARAM) { return !_to ? NS_ERROR_NULL_POINTER : _to->Resolve(interfaceIndex, name, regtype, domain, listener, _retval); } \\r
+ NS_SCRIPTABLE NS_IMETHOD Stop(void) { return !_to ? NS_ERROR_NULL_POINTER : _to->Stop(); } \r
+\r
+#if 0\r
+/* Use the code below as a template for the implementation class for this interface. */\r
+\r
+/* Header file */\r
+class _MYCLASS_ : public IDNSSDService\r
+{\r
+public:\r
+ NS_DECL_ISUPPORTS\r
+ NS_DECL_IDNSSDSERVICE\r
+\r
+ _MYCLASS_();\r
+\r
+private:\r
+ ~_MYCLASS_();\r
+\r
+protected:\r
+ /* additional members */\r
+};\r
+\r
+/* Implementation file */\r
+NS_IMPL_ISUPPORTS1(_MYCLASS_, IDNSSDService)\r
+\r
+_MYCLASS_::_MYCLASS_()\r
+{\r
+ /* member initializers and constructor code */\r
+}\r
+\r
+_MYCLASS_::~_MYCLASS_()\r
+{\r
+ /* destructor code */\r
+}\r
+\r
+/* IDNSSDService browse (in long interfaceIndex, in AString regtype, in AString domain, in IDNSSDBrowseListener listener); */\r
+NS_IMETHODIMP _MYCLASS_::Browse(PRInt32 interfaceIndex, const nsAString & regtype, const nsAString & domain, IDNSSDBrowseListener *listener, IDNSSDService **_retval NS_OUTPARAM)\r
+{\r
+ return NS_ERROR_NOT_IMPLEMENTED;\r
+}\r
+\r
+/* IDNSSDService resolve (in long interfaceIndex, in AString name, in AString regtype, in AString domain, in IDNSSDResolveListener listener); */\r
+NS_IMETHODIMP _MYCLASS_::Resolve(PRInt32 interfaceIndex, const nsAString & name, const nsAString & regtype, const nsAString & domain, IDNSSDResolveListener *listener, IDNSSDService **_retval NS_OUTPARAM)\r
+{\r
+ return NS_ERROR_NOT_IMPLEMENTED;\r
+}\r
+\r
+/* void stop (); */\r
+NS_IMETHODIMP _MYCLASS_::Stop()\r
+{\r
+ return NS_ERROR_NOT_IMPLEMENTED;\r
+}\r
+\r
+/* End of implementation class template. */\r
+#endif\r
+\r
+\r
+#endif /* __gen_IDNSSDService_h__ */\r
--- /dev/null
+/* -*- Mode: C; tab-width: 4 -*-\r
+ *\r
+ * Copyright (c) 2009 Apple Computer, Inc. All rights reserved.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "nsISupports.idl"\r
+\r
+interface IDNSSDService;\r
+\r
+\r
+[scriptable, function, uuid(27346495-A1ED-458A-A5BC-587DF9A26B4F)]\r
+interface IDNSSDBrowseListener : nsISupports\r
+{\r
+ void\r
+ onBrowse( in IDNSSDService service, in boolean add, in long interfaceIndex, in long error, in AString serviceName, in AString regtype, in AString domain );\r
+};\r
+\r
+\r
+[scriptable, function, uuid(6620E18F-47F3-47C6-941F-126A5FD4FCF7)]\r
+interface IDNSSDResolveListener : nsISupports\r
+{\r
+ void\r
+ onResolve( in IDNSSDService service, in long interfaceIndex, in long error, in AString fullname, in AString host, in short port, in AString path );\r
+};\r
+\r
+\r
+[scriptable, uuid(3A3539FF-F8D8-40B4-8D02-5EA73C51FA12)]\r
+interface IDNSSDService : nsISupports\r
+{\r
+ IDNSSDService\r
+ browse( in long interfaceIndex, in AString regtype, in AString domain, in IDNSSDBrowseListener listener );\r
+\r
+ IDNSSDService\r
+ resolve( in long interfaceIndex, in AString name, in AString regtype, in AString domain, in IDNSSDResolveListener listener );\r
+\r
+ void\r
+ stop();\r
+};\r
--- /dev/null
+content bonjour4firefox content/
+locale bonjour4firefox en-US locale/en-US/
+skin bonjour4firefox classic/1.0 skin/
+skin bonjour4firefox classic/1.0 skin-darwin/ os=darwin
+overlay chrome://browser/content/browser.xul chrome://bonjour4firefox/content/browserOverlay.xul
+style chrome://global/content/customizeToolbar.xul chrome://bonjour4firefox/skin/overlay.css
--- /dev/null
+tree.sidebar-placesTree treechildren::-moz-tree-row(selected)
+{
+ background-color: #6f81a9;
+ background-image: url("chrome://browser/skin/places/selected-gradient.png");
+ background-repeat: repeat-x;
+ background-position: bottom left;
+ border-top: 1px solid #979797;
+}
+
+
+tree.sidebar-placesTree treechildren::-moz-tree-separator
+{
+ border-top: 1px solid #505d6d;
+ margin: 0 10px;
+}
+
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
+<?xml-stylesheet href="browseList.css"?>
+<!DOCTYPE page SYSTEM "chrome://bonjour4firefox/locale/bonjour4firefox.dtd">
+ <page
+ orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ style="background-color: transparent !important; -moz-appearance: none !important;"
+ onload="BonjourBrowser.init()"
+ onunload="BonjourBrowser.cleanup()">
+
+
+ <menupopup id="targetmenu">
+ <menuitem label="&bonjour4firefoxSidebarOpenDefault.label;" value="current"/>
+ <menuitem label="&bonjour4firefoxSidebarOpenTab.label;" value="tab"/>
+ <menuitem label="&bonjour4firefoxSidebarOpenWindow.label;" value="window"/>
+ </menupopup>
+
+ <tree id="treeBrowseList" flex="1" class="sidebar-placesTree" hidecolumnpicker="true">
+ <treecols hide="true">
+ <treecol id="title" flex="1" primary="true" hideheader="true"/>
+ </treecols>
+
+ <treechildren class="sidebar-placesTreechildren" context="targetmenu" flex="1" id="treeChildrenBrowseList">
+ <treeitem>
+ <treerow>
+ <treecell src="chrome://bonjour4firefox/content/bonjour4firefox.png" label="About Bonjour"/>
+ </treerow>
+ </treeitem>
+ </treechildren>
+ </tree>
+
+ <script><![CDATA[
+
+ var BonjourBrowser =
+ {
+ Service: null,
+ Browse: null,
+ BrowseListener: null,
+ Resolve: null,
+ ResolveListener: null,
+
+ init: function()
+ {
+ document.getElementById("treeChildrenBrowseList").addEventListener( "click", this.listListener, false );
+
+ try
+ {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ const cid = "@apple.com/DNSSDService;1";
+ Service = Components.classes[cid].createInstance();
+ Service = Service.QueryInterface(Components.interfaces.IDNSSDService);
+ }
+ catch (err)
+ {
+ alert(err);
+ return;
+ }
+
+ BrowseListener = this.browseListener;
+ ResolveListener = this.resolveListener;
+
+ try
+ {
+ Browse = Service.browse(0, "_http._tcp", "", BrowseListener );
+ }
+ catch ( err )
+ {
+ alert( err );
+ return;
+ }
+ },
+
+ cleanup: function()
+ {
+ if ( Browse != null )
+ {
+ Browse.stop();
+ Browse = null;
+ }
+ },
+
+
+ browseListener: function( service, add, interfaceIndex, error, serviceName, regtype, domain )
+ {
+ if ( error == 0 )
+ {
+ // First see if we can look this guy up
+
+ var treeView = document.getElementById( 'treeChildrenBrowseList' );
+ var treeItem = null;
+
+ for ( i = 1; i < treeView.childNodes.length; i++ )
+ {
+ var ti = treeView.childNodes[ i ];
+ var tr = ti.childNodes[ 0 ];
+ var tc = tr.childNodes[ 0 ];
+
+ if ( tc.getAttribute( 'label' ) == serviceName )
+ {
+ treeItem = ti;
+ break;
+ }
+ }
+
+ if ( add )
+ {
+ // If we've already seen this guy, then bump up his reference count
+
+ if ( treeItem )
+ {
+ var refcnt = treeItem.getUserData( 'refcnt' );
+ refcnt++;
+ }
+ else
+ {
+ var newTreeItem = document.createElement('treeitem');
+ var newTreeRow = document.createElement('treerow');
+ newTreeRow.setAttribute( 'properties', 'bonjourRow' );
+ var newTreeCell = document.createElement('treecell');
+ newTreeCell.setAttribute( 'label', serviceName );
+ newTreeCell.setAttribute( 'src', 'chrome://bonjour4firefox/content/bonjour4firefox.png' );
+
+ newTreeItem.appendChild( newTreeRow );
+ newTreeRow.appendChild( newTreeCell );
+ newTreeItem.setUserData( 'interfaceIndex', interfaceIndex, null );
+ newTreeItem.setUserData( 'serviceName', serviceName, null );
+ newTreeItem.setUserData( 'regtype', regtype, null );
+ newTreeItem.setUserData( 'domain', domain, null );
+ newTreeItem.setUserData( 'refcnt', 1, null );
+
+ // Insert in alphabetical order
+
+ var insertBefore = null;
+
+ for ( i = 1; i < treeView.childNodes.length; i++ )
+ {
+ var ti = treeView.childNodes[ i ];
+ var tr = ti.childNodes[ 0 ];
+ var tc = tr.childNodes[ 0 ];
+
+ if ( serviceName.toLowerCase() < tc.getAttribute( 'label' ).toLowerCase() )
+ {
+ insertBefore = ti;
+ break;
+ }
+ }
+
+ if ( insertBefore != null )
+ {
+ treeView.insertBefore( newTreeItem, insertBefore );
+ }
+ else
+ {
+ treeView.appendChild( newTreeItem );
+ }
+ }
+ }
+ else if ( treeItem )
+ {
+ var refcnt = treeItem.getUserData( 'refcnt' );
+
+ if ( --refcnt == 0 )
+ {
+ treeView.removeChild( treeItem );
+ }
+ }
+ }
+ else
+ {
+ alert( 'There was an error browsing for websites: ' + error );
+ }
+ },
+
+ listListener: function( event )
+ {
+ var treeBrowseList = document.getElementById( 'treeBrowseList' );
+
+ if ( treeBrowseList.currentIndex == 0 )
+ {
+ window._content.location="http://www.apple.com/bonjour";
+ }
+ else
+ {
+ var item = treeBrowseList.view.getItemAtIndex(treeBrowseList.currentIndex);
+
+ var interfaceIndex = item.getUserData("interfaceIndex");
+ var serviceName = item.getUserData("serviceName");
+ var regtype = item.getUserData("regtype");
+ var domain = item.getUserData("domain");
+
+ try
+ {
+ Resolve = Service.resolve( interfaceIndex, serviceName, regtype, domain, ResolveListener );
+ }
+ catch ( err )
+ {
+ alert( err );
+ return;
+ }
+ }
+ },
+
+ resolveListener: function( service, interfaceIndex, error, fullname, host, port, path )
+ {
+ if ( error == 0 )
+ {
+ window._content.location='http://' + host + ':' + port + path;
+ }
+ else
+ {
+ alert( 'There was an error resolving ' + fullname );
+ }
+
+ Resolve.stop();
+ },
+ };
+
+ ]]></script>
+</page>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://bonjour4firefox/skin/overlay.css" type="text/css"?>
+<!DOCTYPE overlay SYSTEM "chrome://bonjour4firefox/locale/bonjour4firefox.dtd">
+<overlay id="bonjour4firefox-overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="overlay.js"/>
+ <stringbundleset id="stringbundleset">
+ <stringbundle id="bonjour4firefox-strings" src="chrome://bonjour4firefox/locale/bonjour4firefox.properties"/>
+ </stringbundleset>
+
+ <menupopup id="viewSidebarMenu">
+ <menuitem observes="viewBonjour4FirefoxSidebar"/>
+ </menupopup>
+
+ <toolbarpalette id="BrowserToolbarPalette">
+ <toolbarbutton id="bonjour4firefox-toolbar-button"
+ label="&bonjour4firefoxToolbar.label;"
+ tooltiptext="&bonjour4firefoxToolbar.tooltip;"
+ oncommand="toggleSidebar('viewBonjour4FirefoxSidebar');"
+ class="toolbarbutton-1 chromeclass-toolbar-additional"/>
+ </toolbarpalette>
+
+ <broadcasterset id="mainBroadcasterSet">
+ <broadcaster id="viewBonjour4FirefoxSidebar"
+ autoCheck="false"
+ label="Bonjour"
+ type="checkbox" group="sidebar"
+ sidebarurl="chrome://bonjour4firefox/content/bonjour4firefox.xul"
+ sidebartitle="&bonjour4firefox.label;"
+ oncommand="toggleSidebar('viewBonjour4FirefoxSidebar');"/>
+ </broadcasterset>
+</overlay>
--- /dev/null
+var bonjour4firefox =
+{
+ onLoad: function()
+ {
+ // initialization code
+ this.initialized = true;
+ this.strings = document.getElementById("bonjour4firefox-strings");
+ },
+ onMenuItemCommand: function(e)
+ {
+ var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
+ promptService.alert(window, this.strings.getString("helloMessageTitle"), this.strings.getString("helloMessage"));
+ },
+ onToolbarButtonCommand: function(e)
+ {
+ // just reuse the function above. you can change this, obviously!
+ bonjour4firefox.onMenuItemCommand(e);
+ }
+};
+
+window.addEventListener("load", function(e) { bonjour4firefox.onLoad(e); }, false);
--- /dev/null
+// See http://kb.mozillazine.org/Localize_extension_descriptions
+pref("extensions.bonjour4firefox@apple.com.description", "chrome://bonjour4firefox/locale/bonjour4firefox.properties");
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>bonjour4firefox@apple.com</em:id>
+ <em:name>Bonjour Extension for Firefox</em:name>
+ <em:version>1.0</em:version>
+ <em:creator>Apple Inc.</em:creator>
+ <em:description>Bonjour Browsing Extension for Firefox</em:description>
+ <em:iconURL>chrome://bonjour4firefox/content/bonjour4firefox.png</em:iconURL>
+ <em:targetApplication>
+ <Description>
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- firefox -->
+ <em:minVersion>3.5</em:minVersion>
+ <em:maxVersion>3.6.*</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ </Description>
+</RDF>
--- /dev/null
+<!ENTITY bonjour4firefox.label "Bonjour">
+<!ENTITY bonjour4firefoxToolbar.label "Bonjour">
+<!ENTITY bonjour4firefoxToolbar.tooltip "Display Bonjour enabled websites">
+<!ENTITY bonjour4firefoxSidebarOpenDefault.label "Open in current window">
+<!ENTITY bonjour4firefoxSidebarOpenTab.label "Open in new tab">
+<!ENTITY bonjour4firefoxSidebarOpenWindow.label "Open in new window">
--- /dev/null
+helloMessage=Hello World!
+helloMessageTitle=Hello
+prefMessage=Int Pref Value: %d
+extensions.bonjour4firefox.description=Bonjour Browsing Extension for Firefox
--- /dev/null
+This extension was generated by the Extension Wizard at
+http://ted.mielczarek.org/code/mozilla/extensionwiz/ .
+This extension is compatible only with Firefox 1.5 and
+above. Most of the files in this package are based on
+the 'helloworld' extension from the Mozillazine Knowledge Base.
+
+You can build an XPI for installation by running the
+build.sh script located in this folder. For development
+you should do the following:
+ 1. Unzip the entire contents of this package to somewhere,
+ e.g, c:\dev or /home/user/dev
+ 2. Put the full path to the folder (e.g. c:\dev\bonjour4firefox on
+ Windows, /home/user/dev/bonjour4firefox on Linux) in a file named
+ bonjour4firefox@apple.com and copy that file to
+ [your profile folder]\extensions\
+ 3. Restart Firefox.
+
+For more information, see the Mozillazine Knowledge Base:
+http://kb.mozillazine.org/Getting_started_with_extension_development
+
+-Ted Mielczarek <ted.mielczarek@gmail.com>
--- /dev/null
+#bonjour4firefox-hello
+{
+ color: red ! important;
+}
+#bonjour4firefox-toolbar-button
+{
+ list-style-image: url("chrome://bonjour4firefox/skin/toolbar-button.png");
+ -moz-image-region: rect(0px 36px 23px 0px);
+}
+#bonjour4firefox-toolbar-button[disabled="true"]
+{
+ -moz-image-region: rect(23px 36px 46px 0px);
+}
+#bonjour4firefox-toolbar-button:hover:active
+{
+ -moz-image-region: rect(46px 36px 69px 0px);
+}
--- /dev/null
+#bonjour4firefox-hello
+{
+ color: black ! important;
+}
+#bonjour4firefox-toolbar-button
+{
+ list-style-image: url("chrome://bonjour4firefox/skin/toolbar-button.png");
+ -moz-image-region: rect(0px 24px 24px 0px);
+}
+#bonjour4firefox-toolbar-button:hover
+{
+ -moz-image-region: rect(24px 24px 48px 0px);
+}
+[iconsize="small"] #bonjour4firefox-toolbar-button
+{
+ -moz-image-region: rect( 0px 40px 16px 24px);
+}
+[iconsize="small"] #bonjour4firefox-toolbar-button:hover
+{
+ -moz-image-region: rect(24px 40px 40px 24px);
+}
--- /dev/null
+Building the Bonjour Firefox Extension on Windows
+
+There is a Visual Studio 2005 project file that will build the extension correctly as long as the Visual Studio environment is setup correctly. This code was built against the 1.9 version of the XULRunner SDK. The Visual Studio environment should be modified to add the include and lib paths of the XULRunner SDK. Specifically, the following include paths should be added to VC++ include directories:
+
+…\xulrunner-sdk\include\xpcom
+…\xulrunner-sdk\include\nspr
+…\xulrunner-sdk\include\string
+…\xulrunner-sdk\include\pref
+…\xulrunner-sdk\sdk\include
+
+The following path should be added to VC++ lib directories:
+
+…\xulrunner-sdk\lib
+
+After the code has been built, it can be installed like any other Firefox extension. Please consult Firefox extension documentation for more information on how to package and install Firefox extensions.
+
--- /dev/null
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by FirefoxExtension.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_WMDMLOGGER 101
+#define IDS_LOG_SEV_INFO 201
+#define IDS_LOG_SEV_WARN 202
+#define IDS_LOG_SEV_ERROR 203
+#define IDS_LOG_DATETIME 204
+#define IDS_LOG_SRCNAME 205
+#define IDS_DEF_LOGFILE 301
+#define IDS_DEF_MAXSIZE 302
+#define IDS_DEF_SHRINKTOSIZE 303
+#define IDS_DEF_LOGENABLED 304
+#define IDS_MUTEX_TIMEOUT 401
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
* 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: DNSSDUnitTest.java,v $
-Revision 1.6 2006/08/14 23:24:07 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.5 2006/06/20 23:01:58 rpantos
-<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
-
-Revision 1.4 2004/08/04 01:07:43 rpantos
-Update unit test for <rdar://problems/3731579&3731582>.
-
-Revision 1.3 2004/05/26 01:41:58 cheshire
-Pass proper flags to DNSSD.enumerateDomains
-
-Revision 1.2 2004/04/30 21:53:34 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
- DNSSDUnitTest is a simple program that exercises parts of the DNSSD API.
+ *
+ * DNSSDUnitTest is a simple program that exercises parts of the DNSSD API.
*/
import com.apple.dnssd.*;
# See the License for the specific language governing permissions and
# 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
-#
-# Revision 1.10 2006/09/21 00:56:37 cheshire
-# <rdar://problem/4245577> Need 64-bit version of dns-sd command-line tool
-# Add in missing "build/" in targets line for builds other than OS X
-#
-# Revision 1.9 2006/09/18 18:55:39 cheshire
-# <rdar://problem/4245577> Need 64-bit version of dns-sd command-line tool
-#
-# Revision 1.8 2006/08/14 23:23:55 cheshire
-# Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-#
-# Revision 1.7 2006/01/06 01:06:17 cheshire
-# <rdar://problem/3978979> Compile library and client programs in one pass
-#
-# Revision 1.6 2004/09/24 21:15:26 cheshire
-# <rdar://problem/3724985> Library "libmdns" misnamed; should be "libdns_sd"
-#
-# Revision 1.5 2004/09/02 17:32:45 cheshire
-# Look for headers in ../mDNSShared before we go to /usr/include
-#
-# Revision 1.4 2004/05/21 17:25:56 cheshire
-# Fixes to make sample client work on Linux
-#
-# Revision 1.3 2004/03/12 08:05:32 cheshire
-# Add a "make clean" target
-#
-# Revision 1.2 2004/02/11 20:59:26 cheshire
-# Fix Makefile so it creates the "build" directory if necessary
-#
-# Revision 1.1 2004/02/06 03:19:09 cheshire
-# Check in code to make command-line "dns-sd" testing tool
-#
-#
# Notes:
# $@ means "The file name of the target of the rule"
# $< means "The name of the first prerequisite"
* 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: FirstPage.cpp,v $
-Revision 1.6 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.5 2005/07/07 17:53:20 shersche
-Fix problems associated with the CUPS printer workaround fix.
-
-Revision 1.4 2005/03/16 01:41:29 shersche
-<rdar://problem/3989644> Remove info icon from first page
-
-Revision 1.3 2005/01/25 08:58:08 shersche
-<rdar://problem/3911084> Load icons at run-time from resource DLLs
-Bug #: 3911084
-
-Revision 1.2 2004/07/13 20:15:04 shersche
-<rdar://problem/3726363> Load large font name from resource
-Bug #: 3726363
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#include "stdafx.h"
#include "PrinterSetupWizardApp.h"
* 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: FirstPage.h,v $
-Revision 1.3 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/07/07 17:53:20 shersche
-Fix problems associated with the CUPS printer workaround fix.
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#pragma once
#include "afxwin.h"
* 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.8 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.7 2005/07/07 17:53:20 shersche
-Fix problems associated with the CUPS printer workaround fix.
-
-Revision 1.6 2005/02/08 21:45:06 shersche
-<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
-
-Revision 1.5 2005/01/06 08:17:08 shersche
-Display the selected protocol ("Raw", "LPR", "IPP") rather than the port name
-
-Revision 1.4 2004/07/13 20:15:04 shersche
-<rdar://problem/3726363> Load large font name from resource
-Bug #: 3726363
-
-Revision 1.3 2004/07/12 06:59:03 shersche
-<rdar://problem/3723695> Use resource strings for Yes/No
-Bug #: 3723695
-
-Revision 1.2 2004/06/26 23:27:12 shersche
-support for installing multiple printers of the same name
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#include "stdafx.h"
#include "PrinterSetupWizardApp.h"
#include "PrinterSetupWizardSheet.h"
#include "FourthPage.h"
+#if !defined( PBS_MARQUEE )
+# define PBS_MARQUEE 0x08
+#endif
+
+#if !defined( PBM_SETMARQUEE )
+# define PBM_SETMARQUEE WM_USER + 10
+#endif
+
+
// CFourthPage dialog
OSStatus
CFourthPage::OnInitPage()
{
- return kNoErr;
+ CWnd * window;
+ OSStatus err = kNoErr;
+
+ window = GetDlgItem( IDC_INSTALLING );
+ require_action( window, exit, err = kUnknownErr );
+ window->ShowWindow( SW_HIDE );
+
+ window = GetDlgItem( IDC_PROGRESS );
+ require_action( window, exit, err = kUnknownErr );
+ SetWindowLong( *window, GWL_STYLE, GetWindowLong( *window, GWL_STYLE ) | PBS_MARQUEE );
+ SetWindowLongPtr( *window, GWL_STYLE, GetWindowLongPtr( *window, GWL_STYLE ) | PBS_MARQUEE );
+ window->SendMessage( ( UINT ) PBM_SETMARQUEE, ( WPARAM ) FALSE,( LPARAM ) 35 );
+ window->ShowWindow( SW_HIDE );
+
+exit:
+
+ return err;
}
return CPropertyPage::OnKillActive();
}
+
+
+BOOL
+CFourthPage::StartActivityIndicator()
+{
+ CWnd * window;
+ BOOL ok = TRUE;
+
+ window = GetDlgItem( IDC_COMPLETE1 );
+ require_action( window, exit, ok = FALSE );
+ window->ShowWindow( SW_HIDE );
+
+ window = GetDlgItem( IDC_COMPLETE2 );
+ require_action( window, exit, ok = FALSE );
+ window->ShowWindow( SW_HIDE );
+
+ window = GetDlgItem( IDC_INSTALLING );
+ require_action( window, exit, ok = FALSE );
+ window->ShowWindow( SW_SHOW );
+
+ window = GetDlgItem( IDC_PROGRESS );
+ require_action( window, exit, ok = FALSE );
+ window->SendMessage( ( UINT ) PBM_SETMARQUEE, ( WPARAM ) TRUE,( LPARAM ) 50 );
+ window->ShowWindow( SW_SHOW );
+
+exit:
+
+ return ok;
+}
+
+
+BOOL
+CFourthPage::StopActivityIndicator()
+{
+ CWnd * window;
+ BOOL ok = TRUE;
+
+ window = GetDlgItem( IDC_INSTALLING );
+ require_action( window, exit, ok = FALSE );
+ window->ShowWindow( SW_HIDE );
+
+ window = GetDlgItem( IDC_PROGRESS );
+ require_action( window, exit, ok = FALSE );
+ window->SendMessage( ( UINT ) PBM_SETMARQUEE, ( WPARAM ) FALSE,( LPARAM ) 35 );
+ window->ShowWindow( SW_HIDE );
+
+exit:
+
+ return ok;
+}
* 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.4 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2005/07/07 17:53:20 shersche
-Fix problems associated with the CUPS printer workaround fix.
-
-Revision 1.2 2005/01/06 08:17:08 shersche
-Display the selected protocol ("Raw", "LPR", "IPP") rather than the port name
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#pragma once
#include "afxwin.h"
virtual BOOL OnSetActive();
virtual BOOL OnKillActive();
+ BOOL StartActivityIndicator();
+ BOOL StopActivityIndicator();
+
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
* 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"
* 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
\r
// Icon with lowest ID value placed first to ensure application icon\r
// remains consistent on all systems.\r
-IDR_MAINFRAME ICON "res\\Print.ico"\r
+IDR_MAINFRAME ICON "res\\NetworkPrinter.ico"\r
\r
/////////////////////////////////////////////////////////////////////////////\r
//\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
:END
"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
:END
"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\r
RelativePath="res\NetworkPrinter.ico"\r
>\r
</File>\r
- <File\r
- RelativePath="res\Print.ico"\r
- >\r
- </File>\r
<File\r
RelativePath="res\PrinterSetupWizard.manifest"\r
>\r
* 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: 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
-
-Revision 1.8 2005/04/13 17:43:39 shersche
-<rdar://problem/4081448> Change "PrinterWizard.dll" to "PrinterWizardResources.dll"
-
-Revision 1.7 2005/02/15 07:50:09 shersche
-<rdar://problem/4007151> Update name
-
-Revision 1.6 2005/02/10 22:35:10 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.5 2005/01/25 18:30:02 shersche
-Fix call to PathForResource() by passing in NULL as first parameter.
-
-Revision 1.4 2005/01/25 08:54:41 shersche
-<rdar://problem/3911084> Load resource DLLs at startup.
-Bug #: 3911084
-
-Revision 1.3 2004/07/13 21:24:23 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.2 2004/06/24 20:12:08 shersche
-Clean up source code
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#include "stdafx.h"
#include "PrinterSetupWizardApp.h"
* 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: PrinterSetupWizardApp.h,v $
-Revision 1.3 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/01/25 08:52:55 shersche
-<rdar://problem/3911084> Add APIs to return localizable and non-localizable resource DLL handles
-Bug #: 3911084
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#pragma once
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,180,171,8\r
- LTEXT "To change these settings, click Back.",IDC_STATIC,116,190,171,8\r
+ LTEXT "To complete the installation, click Finish.",IDC_COMPLETE1,116,180,171,8\r
+ LTEXT "To change these settings, click Back.",IDC_COMPLETE2,116,190,171,8\r
+ LTEXT "Please wait a few moments while the Bonjour Printer Wizard installs the printer.",IDC_INSTALLING,116,170,171,31\r
+ CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,116,190,165,8\r
END\r
\r
IDD_DIALOG1 DIALOGEX 0, 0, 265, 130\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj"
:END"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources\en.lproj"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources\en.lproj"
:END"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources\en.lproj"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\r
\r
// Icon with lowest ID value placed first to ensure application icon\r
// remains consistent on all systems.\r
-IDR_MAINFRAME ICON "res\\Print.ico"\r
+IDR_MAINFRAME ICON "res\\NetworkPrinter.ico"\r
IDI_INFO ICON "res\\Info.ico"\r
IDI_PRINTER ICON "res\\NetworkPrinter.ico"\r
\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources"
:END"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)\PrinterWizard.Resources"
:END"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour Print Services\$(PlatformName)\PrinterWizard.Resources"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\r
RelativePath=".\res\NetworkPrinter.ico"\r
>\r
</File>\r
- <File\r
- RelativePath=".\res\Print.ico"\r
- >\r
- </File>\r
<File\r
RelativePath=".\res\Printer.bmp"\r
>\r
</File>\r
- <File\r
- RelativePath=".\res\Printer.ico"\r
- >\r
- </File>\r
- <File\r
- RelativePath=".\res\Printer2.ico"\r
- >\r
- </File>\r
- <File\r
- RelativePath="res\PrinterSetupWizard.ico"\r
- >\r
- </File>\r
<File\r
RelativePath="PrinterSetupWizardRes.rc"\r
>\r
* 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: 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
-
-Revision 1.34 2005/10/05 17:32:51 herscher
-<rdar://problem/4141221> Use a case insensitive compare operation to check whether a printer with the same name has already been installed.
-
-Revision 1.33 2005/07/11 20:17:15 shersche
-<rdar://problem/4124524> UI fixes associated with CUPS printer workaround fix.
-
-Revision 1.32 2005/07/07 17:53:20 shersche
-Fix problems associated with the CUPS printer workaround fix.
-
-Revision 1.31 2005/06/30 18:02:54 shersche
-<rdar://problem/4124524> Workaround for Mac OS X Printer Sharing bug
-
-Revision 1.30 2005/04/13 17:46:22 shersche
-<rdar://problem/4082122> Generic PCL not selected when printers advertise multiple text records
-
-Revision 1.29 2005/02/14 20:48:37 shersche
-<rdar://problem/4003710> Default pdl key to "application/postscript"
-
-Revision 1.28 2005/02/14 20:37:53 shersche
-<rdar://problem/4003944> Populate comment field with the model name that users see in the wizard UI.
-
-Revision 1.27 2005/02/09 05:04:03 shersche
-<rdar://problem/3946587> Use TXTRecordGetValuePtr() API in ParseTextRecord
-
-Revision 1.26 2005/02/08 21:45:06 shersche
-<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
-
-Revision 1.25 2005/02/08 18:54:17 shersche
-<rdar://problem/3987680> Default queue name is "lp" when rp key is not specified.
-
-Revision 1.24 2005/02/01 02:15:55 shersche
-<rdar://problem/3946587> Use TXTRecord parsing APIs in ParseTextRecord
-
-Revision 1.23 2005/01/31 23:54:30 shersche
-<rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
-
-Revision 1.22 2005/01/25 18:49:43 shersche
-Get icon resources from resource DLL
-
-Revision 1.21 2005/01/10 01:09:32 shersche
-Use the "note" key to populate pLocation field when setting up printer
-
-Revision 1.20 2005/01/03 19:05:01 shersche
-Store pointer to instance of wizard sheet so that print driver install thread sends a window message to the correct window
-
-Revision 1.19 2004/12/31 07:23:53 shersche
-Don't modify the button setting in SetSelectedPrinter()
-
-Revision 1.18 2004/12/29 18:53:38 shersche
-<rdar://problem/3725106>
-<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
-Bug #: 3725106, 3737413
-
-Revision 1.17 2004/10/12 18:02:53 shersche
-<rdar://problem/3764873> Escape '/', '@', '"' characters in printui command.
-Bug #: 3764873
-
-Revision 1.16 2004/09/13 21:27:22 shersche
-<rdar://problem/3796483> Pass the moreComing flag to OnAddPrinter and OnRemovePrinter callbacks
-Bug #: 3796483
-
-Revision 1.15 2004/09/11 05:59:06 shersche
-<rdar://problem/3785766> Fix code that generates unique printer names based on currently installed printers
-Bug #: 3785766
-
-Revision 1.14 2004/09/02 01:57:58 cheshire
-<rdar://problem/3783611> Fix incorrect testing of MoreComing flag
-
-Revision 1.13 2004/07/26 21:06:29 shersche
-<rdar://problem/3739200> Removing trailing '.' in hostname
-Bug #: 3739200
-
-Revision 1.12 2004/07/13 21:24:23 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.11 2004/06/28 00:51:47 shersche
-Move call to EnumPrinters out of browse callback into standalone function
-
-Revision 1.10 2004/06/27 23:06:47 shersche
-code cleanup, make sure EnumPrinters returns non-zero value
-
-Revision 1.9 2004/06/27 15:49:31 shersche
-clean up some cruft in the printer browsing code
-
-Revision 1.8 2004/06/27 08:04:51 shersche
-copy selected printer to prevent printer being deleted out from under
-
-Revision 1.7 2004/06/26 23:27:12 shersche
-support for installing multiple printers of the same name
-
-Revision 1.6 2004/06/26 21:22:39 shersche
-handle spaces in file names
-
-Revision 1.5 2004/06/26 03:19:57 shersche
-clean up warning messages
-
-Submitted by: herscher
-
-Revision 1.4 2004/06/25 02:26:52 shersche
-Normalize key fields in text record entries
-Submitted by: herscher
-
-Revision 1.3 2004/06/24 20:12:07 shersche
-Clean up source code
-Submitted by: herscher
-
-Revision 1.2 2004/06/23 17:58:21 shersche
-<rdar://problem/3701837> eliminated memory leaks on exit
-<rdar://problem/3701926> installation of a printer that is already installed results in a no-op
-Bug #: 3701837, 3701926
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#include "stdafx.h"
#include "PrinterSetupWizardApp.h"
#include <winspool.h>
#include <tcpxcv.h>
#include <string>
+#include <shlwapi.h>
// unreachable code
#pragma warning(disable:4702)
# include <process.h>
#endif
+
+#if defined( UNICODE ) || defined( _UNICODE )
+# define GetEnv _wgetenv
+#else
+# define GetEnv getenv
+#endif
+
+static TCHAR*
+g_printerDriverFiles[] = // Printer driver files
+{
+ TEXT( "ps5ui.dll" ),
+ TEXT( "pscript.hlp" ),
+ TEXT( "pscript.ntf" ),
+ TEXT( "pscript5.dll" ),
+ TEXT( "cups6.ini" ),
+ TEXT( "cupsui6.dll" ),
+ TEXT( "cupsps6.dll" )
+};
+
+
// Private Messages
#define WM_SOCKET_EVENT ( WM_USER + 0x100 )
#define WM_PROCESS_EVENT ( WM_USER + 0x101 )
+\r
+
+static BOOL\r
+Is64BitWindows()\r
+{\r
+#if defined(_WIN64)\r
+ return TRUE; // 64-bit programs run only on Win64\r
+#else\r
+ typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)( HANDLE, PBOOL );\r
+ LPFN_ISWOW64PROCESS fnIsWow64Process;\r
+ BOOL bIsWow64 = FALSE;\r
+\r
+ fnIsWow64Process = ( LPFN_ISWOW64PROCESS ) GetProcAddress( GetModuleHandle( TEXT( "kernel32" ) ), "IsWow64Process" );\r
+ \r
+ if ( fnIsWow64Process != NULL )\r
+ {\r
+ BOOL ok;\r
+\r
+ ok = fnIsWow64Process( GetCurrentProcess(), &bIsWow64 );\r
+\r
+ if ( !ok )\r
+ {\r
+ bIsWow64 = FALSE;\r
+ }\r
+ }\r
+\r
+ return bIsWow64;\r
+#endif\r
+}\r
// CPrinterSetupWizardSheet
CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
{
Logger log;
- Service * service;
+ CUPSLibrary cupsLib;
+ Service * service = NULL;
BOOL ok;
OSStatus err = 0;
service = printer->services.front();
check( service );
- //
- // if the driver isn't installed, then install it
- //
-
- if ( !printer->driverInstalled )
+ if ( printer->isCUPSPrinter && cupsLib.IsInstalled() )
+ {
+ err = InstallPrinterCUPS( printer, service, cupsLib );
+ require_noerr( err, exit );
+ }
+ else
{
- DWORD dwResult;
- HANDLE hThread;
- unsigned threadID;
-
- m_driverThreadFinished = false;
-
- //
- // create the thread
- //
- hThread = (HANDLE) _beginthreadex_compat( NULL, 0, InstallDriverThread, printer, 0, &threadID );
- err = translate_errno( hThread, (OSStatus) GetLastError(), kUnknownErr );
- require_noerr_with_log( log, "_beginthreadex_compat()", err, exit );
-
//
- // go modal
+ // if the driver isn't installed, then install it
//
- while (!m_driverThreadFinished)
+
+ if ( !printer->driverInstalled )
{
- MSG msg;
-
- GetMessage( &msg, m_hWnd, 0, 0 );
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
+ DWORD dwResult;
+ HANDLE hThread;
+ unsigned threadID;
- //
- // Wait until child process exits.
- //
- dwResult = WaitForSingleObject( hThread, INFINITE );
- err = translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr );
- require_noerr_with_log( log, "WaitForSingleObject()", err, exit );
+ m_driverThreadFinished = false;
+
+ //
+ // create the thread
+ //
+ hThread = (HANDLE) _beginthreadex_compat( NULL, 0, InstallDriverThread, printer, 0, &threadID );
+ err = translate_errno( hThread, (OSStatus) GetLastError(), kUnknownErr );
+ require_noerr_with_log( log, "_beginthreadex_compat()", err, exit );
+
+ //
+ // go modal
+ //
+ while (!m_driverThreadFinished)
+ {
+ MSG msg;
+
+ GetMessage( &msg, m_hWnd, 0, 0 );
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
- //
- // check the return value of thread
- //
- require_noerr_with_log( log, "thread exit code", m_driverThreadExitCode, exit );
+ //
+ // Wait until child process exits.
+ //
+ dwResult = WaitForSingleObject( hThread, INFINITE );
+ err = translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr );
+ require_noerr_with_log( log, "WaitForSingleObject()", err, exit );
- //
- // now we know that the driver was successfully installed
- //
- printer->driverInstalled = true;
- }
+ //
+ // check the return value of thread
+ //
+ require_noerr_with_log( log, "thread exit code", m_driverThreadExitCode, exit );
- if ( service->type == kPDLServiceType )
- {
- 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, log );
- require_noerr_with_log( log, "InstallPrinterPDLAndLPR()", err, exit );
- }
- else if ( service->type == kIPPServiceType )
- {
- err = InstallPrinterIPP( printer, service, log );
- require_noerr_with_log( log, "InstallPrinterIPP()", err, exit );
- }
- else
- {
- require_action_with_log( log, ( service->type == kPDLServiceType ) || ( service->type == kLPRServiceType ) || ( service->type == kIPPServiceType ), exit, err = kUnknownErr );
+ //
+ // now we know that the driver was successfully installed
+ //
+ printer->driverInstalled = true;
+ }
+
+ if ( service->type == kPDLServiceType )
+ {
+ err = InstallPrinterPort( printer, service, PROTOCOL_RAWTCP_TYPE, log );
+ require_noerr_with_log( log, "InstallPrinterPort()", err, exit );
+ err = InstallPrinterPDLAndLPR( printer, service, log );
+ require_noerr_with_log( log, "InstallPrinterPDLAndLPR()", err, exit );
+ }
+ else if ( service->type == kLPRServiceType )
+ {
+ err = InstallPrinterPort( printer, service, PROTOCOL_LPR_TYPE, log );
+ require_noerr_with_log( log, "InstallPrinterPort()", err, exit );
+ err = InstallPrinterPDLAndLPR( printer, service, log );
+ require_noerr_with_log( log, "InstallPrinterPDLAndLPR()", err, exit );
+ }
+ else if ( service->type == kIPPServiceType )
+ {
+ // There's no need to install a printer port for IPP printers, because
+ // the call to AddPrinter() will do that for us.
+
+ err = InstallPrinterIPP( printer, service, log );
+ require_noerr_with_log( log, "InstallPrinterIPP()", err, exit );
+ }
+ else
+ {
+ require_action_with_log( log, ( service->type == kPDLServiceType ) || ( service->type == kLPRServiceType ) || ( service->type == kIPPServiceType ), exit, err = kUnknownErr );
+ }
}
printer->installed = true;
OSStatus
-CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * service, DWORD protocol, Logger & log )
+CPrinterSetupWizardSheet::InstallPrinterPort( Printer * printer, Service * service, DWORD protocol, Logger & log )
{
PRINTER_DEFAULTS printerDefaults = { NULL, NULL, SERVER_ACCESS_ADMINISTER };
+ PORT_DATA_1 portData;
DWORD dwStatus;
DWORD cbInputData = 100;
PBYTE pOutputData = NULL;
DWORD cbOutputNeeded = 0;
- PORT_DATA_1 portData;
- PRINTER_INFO_2 pInfo;
HANDLE hXcv = NULL;
- HANDLE hPrinter = NULL;
Queue * q;
BOOL ok;
OSStatus err;
- check(printer != NULL);
- check(printer->installed == false);
+ ZeroMemory(&portData, sizeof(PORT_DATA_1));
+
+ require_action_with_log( log, wcslen(printer->portName) < sizeof_array(portData.sztPortName), exit, err = kSizeErr );
+ wcscpy_s(portData.sztPortName, printer->portName);
q = service->queues.front();
check( q );
}
require_action_with_log( log, pOutputData, exit, err = kNoMemoryErr );
-
- //
- // setup the port
- //
- ZeroMemory(&portData, sizeof(PORT_DATA_1));
-
- 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.dwProtocol = protocol;
portData.cbSize = sizeof PORT_DATA_1;
portData.dwReserved = 0L;
-
+
require_action_with_log( log, wcslen(q->name) < sizeof_array(portData.sztQueue), exit, err = kSizeErr );
wcscpy_s(portData.sztQueue, q->name);
err = translate_errno( ok, errno_compat(), kUnknownErr );
require_noerr_with_log( log, "XcvData()", err, exit );
+exit:
+
+ if (hXcv != NULL)
+ {
+ ClosePrinter(hXcv);
+ }
+
+ if (pOutputData != NULL)
+ {
+ delete [] pOutputData;
+ }
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * service, Logger & log )
+{
+ PRINTER_INFO_2 pInfo;
+ HANDLE hPrinter = NULL;
+ Queue * q;
+ OSStatus err;
+
+ check(printer != NULL);
+ check(printer->installed == false);
+
+ q = service->queues.front();
+ check( q );
+
//
// add the printer
//
ClosePrinter(hPrinter);
}
- if (hXcv != NULL)
- {
- ClosePrinter(hXcv);
- }
-
- if (pOutputData != NULL)
- {
- delete [] pOutputData;
- }
-
return err;
}
}
+OSStatus
+CPrinterSetupWizardSheet::InstallPrinterCUPS(Printer * printer, Service * service, CUPSLibrary & cupsLib )
+{
+ OSStatus err = kNoErr;
+
+ check( printer );
+ check( service );
+ check( cupsLib.IsInstalled() );
+
+ err = InstallPrinterCUPS( printer, service, cupsLib, TEXT( "Windows NT x86" ) );
+ require_noerr( err, exit );
+
+ if ( Is64BitWindows() )
+ {
+ err = InstallPrinterCUPS( printer, service, cupsLib, TEXT( "Windows x64" ) );
+ require_noerr( err, exit );
+ }
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::InstallPrinterCUPS(Printer * printer, Service * service, CUPSLibrary & cupsLib, TCHAR * env )
+{
+
+ Queue * q;
+ CString ppdfile; // PPD file for printer drivers
+ TCHAR driverdir[1024]; // Directory for driver files
+ DWORD needed; // Bytes needed
+ DRIVER_INFO_3 driverinfo; // Driver information
+ PRINTER_INFO_2 printerinfo; // Printer information
+ HANDLE printerHandle = NULL; // Handle to printer
+ CString filename; // Driver filename
+ CString dependentFiles; // List of dependent files
+ CString portName; // Port Name
+ int bytes; // Bytes copied
+ TCHAR datadir[ MAX_PATH ]; // Driver files location
+ CFile in; // Input file
+ CFile out; // Output file
+ void * http; // Connection to server
+ char buffer[4096]; // Copy/error buffer
+ CString platform;
+ char hostname[ 1024 ];
+ CString dest;
+ char destANSI[ 1024 ];
+ int i;
+ DWORD num;
+ OSStatus err = 0;
+ BOOL ok;
+
+ check( printer );
+ check( service );
+ check( cupsLib.IsInstalled() );
+ check( env );
+
+ // What do we do here for multiple queues?
+ q = service->queues.front();
+ require_action( q != NULL, exit, err = kUnknownErr );
+
+ num = GetModuleFileName( NULL, datadir, MAX_PATH );
+ err = translate_errno( num > 0, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+ ok = PathRemoveFileSpec( datadir );
+ require_action( ok, exit, err = kUnknownErr );
+
+ ok = GetPrinterDriverDirectory(NULL, env, 1, ( LPBYTE ) driverdir, sizeof( driverdir ), &needed );
+ err = translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ platform = env;
+ platform = platform.Right( 3 );
+
+ // Append the supported banner pages to the PPD file...
+ err = StringObjectToUTF8String( service->hostname, hostname, sizeof( hostname ) );
+ require_noerr( err, exit );
+ http = cupsLib.httpConnectEncrypt( hostname, service->portNumber, cupsLib.cupsEncryption() );
+ err = translate_errno( http != NULL, errno, kUnknownErr );
+ require_noerr( err, exit );
+
+ if ( ( service->portNumber == 443 ) || ( cupsLib.cupsEncryption() >= HTTP_ENCRYPT_REQUIRED ) )
+ {
+ // This forces the use the https: URLs below...
+ cupsLib.cupsSetEncryption( HTTP_ENCRYPT_ALWAYS );
+ }
+
+ // Strip the leading "printers/" or "classes/" from the beginning
+ // of the name
+
+ dest = q->name;
+ dest.Replace( TEXT( "printers/" ), TEXT( "" ) );
+ dest.Replace( TEXT( "classes/" ), TEXT( "" ) );
+
+ err = StringObjectToUTF8String( dest, destANSI, sizeof( destANSI ) );
+ require_noerr( err, exit );
+
+ // Get the PPD file...
+ for ( i = 0; i < 10; i++ )
+ {
+ char ppdfileANSI[ 1024 ];
+
+ if ( cupsLib.cupsAdminCreateWindowsPPD( http, destANSI, ppdfileANSI, sizeof( ppdfileANSI ) ) )
+ {
+ err = UTF8StringToStringObject( ppdfileANSI, ppdfile );
+ require_noerr( err, exit );
+ break;
+ }
+ }
+
+ err = translate_errno( i < 10, errno, kUnknownErr );
+ require_noerr( err, exit );
+
+ // Copy the PPD file to the Windows driver directory...
+ filename.Format( TEXT( "%s/%s.ppd" ), driverdir, dest );
+
+ ok = in.Open( ppdfile, CFile::modeRead | CFile::typeBinary );
+ translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ ok = out.Open( filename, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary );
+ translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ while ( ( bytes = in.Read( buffer, sizeof(buffer) ) ) > 0 )
+ {
+ out.Write(buffer, bytes );
+ }
+
+ in.Close();
+ out.Close();
+
+ // Cleanup temp file...
+ CFile::Remove( ppdfile );
+
+ // Copy the driver files to the driver directory...
+ for ( i = 0; i < ( sizeof( g_printerDriverFiles ) / sizeof( g_printerDriverFiles[0] ) ); i++ )
+ {
+ filename.Format( TEXT( "%s/drivers/%s/%s" ), datadir, platform, g_printerDriverFiles[i]);
+
+ ok = in.Open(filename, CFile::modeRead | CFile::typeBinary );
+ err = translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ filename.Format( TEXT( "%s/%s" ), driverdir, g_printerDriverFiles[i] );
+ ok = out.Open(filename, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary );
+ err = translate_errno( ok, errno, kUnknownErr );
+
+ while ( ( bytes = in.Read(buffer, sizeof( buffer ) ) ) > 0 )
+ {
+ out.Write( buffer, bytes );
+ }
+
+ in.Close();
+ out.Close();
+ }
+
+ // Do the Windows system calls needed to add the printer driver...
+ filename.Format( TEXT( "%s.ppd" ), dest);
+ dependentFiles.Format( TEXT( "pscript5.dll%c" ) TEXT( "%s.ppd%c" ) TEXT( "ps5ui.dll%c" ) TEXT( "pscript.hlp%c" ) TEXT( "pscript.ntf%c" ) TEXT( "cups6.ini%c" ) TEXT( "cupsps6.dll%c" ) TEXT( "cupsui6.dll%c" ), 0, dest, 0, 0, 0, 0, 0, 0, 0);
+
+ driverinfo.cVersion = 3;
+ driverinfo.pName = printer->actualName.GetBuffer();
+ driverinfo.pEnvironment = env;
+ driverinfo.pDriverPath = TEXT( "pscript5.dll" );
+ driverinfo.pDataFile = filename.GetBuffer();
+ driverinfo.pConfigFile = TEXT( "ps5ui.dll" );
+ driverinfo.pHelpFile = TEXT( "pscript.hlp" );
+ driverinfo.pDependentFiles = dependentFiles.GetBuffer();
+ driverinfo.pMonitorName = NULL;
+ driverinfo.pDefaultDataType = TEXT( "raw" );
+
+ ok = AddPrinterDriverEx(NULL, 3, (LPBYTE) &driverinfo, APD_COPY_ALL_FILES );
+ err = translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ // See if the printer has already been added?
+ if ( OpenPrinter( printer->actualName.GetBuffer(), &printerHandle, NULL ) )
+ {
+ // Printer already exists, so we are done now...
+ goto exit;
+ }
+
+ // Add the printer using the HTTP/IPP port...
+ portName.Format( TEXT( "%s://%s:%d/printers/%s" ), cupsLib.cupsEncryption() == HTTP_ENCRYPT_ALWAYS ? TEXT( "https" ) : TEXT( "http" ), service->hostname.GetBuffer(), service->portNumber, dest );
+
+ memset(&printerinfo, 0, sizeof(printerinfo));
+ printerinfo.pPrinterName = printer->actualName.GetBuffer();
+ printerinfo.pPortName = portName.GetBuffer();
+ printerinfo.pDriverName = printer->actualName.GetBuffer();
+ printerinfo.Attributes = PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL;
+ printerinfo.pComment = q->description.GetBuffer();
+ printerinfo.pLocation = q->location.GetBuffer();
+ printerinfo.pPrintProcessor = TEXT( "winprint" );
+
+ printerHandle = AddPrinter( NULL, 2, (LPBYTE) &printerinfo );
+ err = translate_errno( printerHandle, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+exit:
+
+ if ( printerHandle != NULL )
+ {
+ ClosePrinter( printerHandle );
+ printerHandle = NULL;
+ }
+
+ return err;
+}
+
BEGIN_MESSAGE_MAP(CPrinterSetupWizardSheet, CPropertySheet)
ON_MESSAGE( WM_SOCKET_EVENT, OnSocketEvent )
ON_MESSAGE( WM_PROCESS_EVENT, OnProcessEvent )
BOOL CPrinterSetupWizardSheet::OnInitDialog()
{
OSStatus err;
-
+
CPropertySheet::OnInitDialog();
err = StartBrowse();
void
CPrinterSetupWizardSheet::OnOK()
{
+ CWnd * window;
+ OSStatus err;
+
check ( m_selectedPrinter != NULL );
SetWizardButtons( PSWIZB_DISABLEDFINISH );
- if ( InstallPrinter( m_selectedPrinter ) != kNoErr )
+ window = GetDlgItem( IDCANCEL );
+
+ if ( window )
+ {
+ window->EnableWindow( FALSE );
+ }
+
+ m_pgFourth.StartActivityIndicator();
+
+ err = InstallPrinter( m_selectedPrinter );
+
+ m_pgFourth.StopActivityIndicator();
+
+ if ( err != kNoErr )
{
CString caption;
CString message;
caption.LoadString(IDS_INSTALL_ERROR_CAPTION);
+ caption.AppendFormat( TEXT( " (%d)" ), err );
message.LoadString(IDS_INSTALL_ERROR_MESSAGE);
-
MessageBox(message, caption, MB_OK|MB_ICONEXCLAMATION);
}
OSStatus err = kNoErr;
require_noerr( inErrorCode, exit );
-
+
self = reinterpret_cast <CPrinterSetupWizardSheet*>( inContext );
require_quiet( self, exit );
if ( inFlags & kDNSServiceFlagsAdd )
{
- if (printer == NULL)
- {
- // If not, then create a new one
+ BOOL newPrinter = FALSE;
+ if ( !printer )
+ {
printer = self->OnAddPrinter( inInterfaceIndex, inName, inType, inDomain, moreComing );
require_action( printer, exit, err = kUnknownErr );
+ newPrinter = TRUE;
+ }
+
+ // If we're looking at the browse list on page 2, then we need to call
+ // CPage2::OnAddPrinter() regardless of whether we've seen the printer
+ // or not because the moreComing flag might have changed from a previous
+ // call. If we only call CPage2::OnAddPrinter() when there's a new printer,
+ // we might not correctly update our UI, so if we've seen the printer before,
+ // call OnAddPrinter with a NULL parameter.
+
+ if ( self->GetActivePage() == &self->m_pgSecond )
+ {
+ self->m_pgSecond.OnAddPrinter( newPrinter ? printer : NULL, moreComing );
}
if ( !service )
DEBUG_UNUSED( inInterfaceIndex );
DEBUG_UNUSED( inType );
DEBUG_UNUSED( inDomain );
+ DEBUG_UNUSED( moreComing );
try
{
m_printers.push_back( printer );
- if ( GetActivePage() == &m_pgSecond )
- {
- m_pgSecond.OnAddPrinter( printer, moreComing );
- }
-
exit:
return printer;
if ( TXTRecordContainsKey( inTXTSize, inTXT, "printer-state" ) || TXTRecordContainsKey( inTXTSize, inTXT, "printer-type" ) )
{
- service->printer->isSharedFromOSX = true;
+ service->printer->isCUPSPrinter = true;
}
exit:
* 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: 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
-
-Revision 1.11 2005/10/05 17:32:51 herscher
-<rdar://problem/4141221> Use a case insensitive compare operation to check whether a printer with the same name has already been installed.
-
-Revision 1.10 2005/07/07 17:53:19 shersche
-Fix problems associated with the CUPS printer workaround fix.
-
-Revision 1.9 2005/04/13 17:46:22 shersche
-<rdar://problem/4082122> Generic PCL not selected when printers advertise multiple text records
-
-Revision 1.8 2005/02/08 18:53:33 shersche
-Remove qtotalDefined parameter from ParseTextRecord()
-
-Revision 1.7 2005/01/31 23:54:29 shersche
-<rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
-
-Revision 1.6 2005/01/03 19:05:01 shersche
-Store pointer to instance of wizard sheet so that print driver install thread sends a window message to the correct window
-
-Revision 1.5 2004/12/29 18:53:38 shersche
-<rdar://problem/3725106>
-<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
-Bug #: 3725106, 3737413
-
-Revision 1.4 2004/07/13 21:24:23 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.3 2004/06/28 00:51:47 shersche
-Move call to EnumPrinters out of browse callback into standalone function
-
-Revision 1.2 2004/06/24 20:12:07 shersche
-Clean up source code
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#pragma once
-#include "firstpage.h"
#include "secondpage.h"
#include "thirdpage.h"
#include "fourthpage.h"
protected:
DECLARE_MESSAGE_MAP()
- CFirstPage m_pgFirst;
CSecondPage m_pgSecond;
CThirdPage m_pgThird;
CFourthPage m_pgFourth;
private:
+ // This is from <cups/http.h>
+ typedef enum http_encryption_e /**** HTTP encryption values ****/
+ {
+ HTTP_ENCRYPT_IF_REQUESTED, /* Encrypt if requested (TLS upgrade) */
+ HTTP_ENCRYPT_NEVER, /* Never encrypt */
+ HTTP_ENCRYPT_REQUIRED, /* Encryption is required (TLS upgrade) */
+ HTTP_ENCRYPT_ALWAYS /* Always encrypt (SSL) */
+ } http_encryption_t;
+
+ typedef void* ( *httpConnectEncryptFunc )( const char* host, int port, http_encryption_t encryption );
+ typedef http_encryption_t ( *cupsEncryptionFunc )( void );
+ typedef void ( *cupsSetEncryptionFunc )( http_encryption_t e );
+ typedef char* ( *cupsAdminCreateWindowsPPDFunc )( void * http, const char *dest, char *buffer, int bufsize );
+
+ class CUPSLibrary
+ {
+ public:
+
+ CUPSLibrary()
+ :
+ httpConnectEncrypt( NULL ),
+ cupsEncryption( NULL ),
+ cupsSetEncryption( NULL ),
+ cupsAdminCreateWindowsPPD( NULL ),
+ library( NULL )
+ {
+#if defined( LIBCUPS_ENABLED )
+ if ( ( library = LoadLibrary( TEXT( "libcups2.dll" ) ) ) != NULL )
+ {
+ httpConnectEncrypt = ( httpConnectEncryptFunc ) GetProcAddress( library, "httpConnectEncrypt" );
+ cupsEncryption = ( cupsEncryptionFunc ) GetProcAddress( library, "cupsEncryption" );
+ cupsSetEncryption = ( cupsSetEncryptionFunc ) GetProcAddress( library, "cupsSetEncryption" );
+ cupsAdminCreateWindowsPPD = ( cupsAdminCreateWindowsPPDFunc ) GetProcAddress( library, "cupsAdminCreateWindowsPPD" );
+ }
+#endif
+ }
+
+ ~CUPSLibrary()
+ {
+ if ( library )
+ {
+ FreeLibrary( library );
+ library = NULL;
+ }
+ }
+
+ BOOL
+ IsInstalled()
+ {
+ return ( ( httpConnectEncrypt != NULL ) && ( cupsEncryption != NULL ) && ( cupsSetEncryption != NULL ) && ( cupsAdminCreateWindowsPPD != NULL ) );
+ }
+
+ httpConnectEncryptFunc httpConnectEncrypt;
+ cupsEncryptionFunc cupsEncryption;
+ cupsSetEncryptionFunc cupsSetEncryption;
+ cupsAdminCreateWindowsPPDFunc cupsAdminCreateWindowsPPD;
+
+ private:
+
+ HMODULE library;
+ };
+
+
static void DNSSD_API
OnBrowse(
DNSServiceRef inRef,
InstallPrinter(Printer * printer);
OSStatus
- InstallPrinterPDLAndLPR(Printer * printer, Service * service, DWORD protocol, Logger & log);
+ InstallPrinterPort( Printer * printer, Service * service, DWORD protocol, Logger & log );
+
+ OSStatus
+ InstallPrinterPDLAndLPR(Printer * printer, Service * service, Logger & log);
OSStatus
InstallPrinterIPP(Printer * printer, Service * service, Logger & log);
+
+ OSStatus
+ InstallPrinterCUPS( Printer * printer, Service * service, CUPSLibrary & cupsLib );
+
+ OSStatus
+ InstallPrinterCUPS(Printer * printer, Service * service, CUPSLibrary & cupsLib, TCHAR * env );
static unsigned WINAPI
InstallDriverThread( LPVOID inParam );
* 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: 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
-
-Revision 1.18 2005/07/20 17:44:54 shersche
-<rdar://problem/4124524> UI fixes for CUPS workaround
-
-Revision 1.17 2005/07/11 20:17:15 shersche
-<rdar://problem/4124524> UI fixes associated with CUPS printer workaround fix.
-
-Revision 1.16 2005/07/07 17:53:20 shersche
-Fix problems associated with the CUPS printer workaround fix.
-
-Revision 1.15 2005/04/13 17:46:22 shersche
-<rdar://problem/4082122> Generic PCL not selected when printers advertise multiple text records
-
-Revision 1.14 2005/03/20 20:08:37 shersche
-<rdar://problem/4055670> Second screen should not select a printer by default
-
-Revision 1.13 2005/02/15 07:50:10 shersche
-<rdar://problem/4007151> Update name
-
-Revision 1.12 2005/02/10 22:35:11 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.11 2005/01/31 23:54:30 shersche
-<rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
-
-Revision 1.10 2005/01/20 19:54:38 shersche
-Fix parse error when text record is NULL
-
-Revision 1.9 2005/01/06 08:13:50 shersche
-Don't use moreComing flag to determine number of text record, disregard queue name if qtotal isn't defined, don't disregard queue name if "rp" is the only key specified
-
-Revision 1.8 2005/01/04 21:09:14 shersche
-Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
-
-Revision 1.7 2004/12/31 07:25:27 shersche
-Tidy up printer management, and fix memory leaks when hitting 'Cancel'
-
-Revision 1.6 2004/12/30 01:24:02 shersche
-<rdar://problem/3906182> Remove references to description key
-Bug #: 3906182
-
-Revision 1.5 2004/12/30 01:02:47 shersche
-<rdar://problem/3734478> Add Printer information box that displays description and location information when printer name is selected
-Bug #: 3734478
-
-Revision 1.4 2004/12/29 18:53:38 shersche
-<rdar://problem/3725106>
-<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
-Bug #: 3725106, 3737413
-
-Revision 1.3 2004/09/13 21:26:15 shersche
-<rdar://problem/3796483> Use the moreComing flag to determine whether drawing should take place in OnAddPrinter and OnRemovePrinter callbacks
-Bug #: 3796483
-
-Revision 1.2 2004/06/26 03:19:57 shersche
-clean up warning messages
-
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#include "stdafx.h"
#include "PrinterSetupWizardApp.h"
{
CPrinterSetupWizardSheet * psheet;
Printer * printer;
+ CWnd * pWnd;
Printers::iterator it;
OSStatus err = kNoErr;
BOOL b;
::SetFocus( m_browseList );
}
+ // Hide the back button
+ pWnd = ((CPropertySheet*)GetParent())->GetDlgItem(ID_WIZBACK);\r
+ if ( pWnd != NULL )\r
+ {\r
+ pWnd->ShowWindow(SW_HIDE);\r
+ }
+
exit:
return b;
BOOL
CSecondPage::OnKillActive()
{
- CPrinterSetupWizardSheet * psheet;
+ CPrinterSetupWizardSheet * psheet;
+ CWnd * pWnd;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
psheet->SetLastPage(this);
+ // Show the back button
+ pWnd = ((CPropertySheet*)GetParent())->GetDlgItem(ID_WIZBACK);\r
+ if ( pWnd != NULL )\r
+ {\r
+ pWnd->ShowWindow(SW_SHOW);\r
+ }
+
exit:
return CPropertyPage::OnKillActive();
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
-
- selectedPrinter = psheet->GetSelectedPrinter();
- printer->item = m_browseList.InsertItem(printer->displayName);
+ if ( printer )
+ {
+ selectedPrinter = psheet->GetSelectedPrinter();
+
+ printer->item = m_browseList.InsertItem(printer->displayName);
- m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
+ m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
- m_browseList.SortChildren(TVI_ROOT);
+ m_browseList.SortChildren(TVI_ROOT);
- //
- // if the searching item is still in the list
- // get rid of it
- //
- // note that order is important here. Insert the printer
- // item before removing the placeholder so we always have
- // an item in the list to avoid experiencing the bug
- // in Microsoft's implementation of CTreeCtrl
- //
- if (m_emptyListItem != NULL)
- {
- m_browseList.DeleteItem(m_emptyListItem);
- m_emptyListItem = NULL;
- m_browseList.EnableWindow(TRUE);
- }
+ //
+ // if the searching item is still in the list
+ // get rid of it
+ //
+ // note that order is important here. Insert the printer
+ // item before removing the placeholder so we always have
+ // an item in the list to avoid experiencing the bug
+ // in Microsoft's implementation of CTreeCtrl
+ //
+ if (m_emptyListItem != NULL)
+ {
+ m_browseList.DeleteItem(m_emptyListItem);
+ m_emptyListItem = NULL;
+ m_browseList.EnableWindow(TRUE);
+ }
- if ( !selectedPrinter )
- {
- psheet->SetSelectedPrinter( printer );
- m_browseList.SelectItem( printer->item );
- ::SetFocus( m_browseList );
+ if ( !selectedPrinter )
+ {
+ psheet->SetSelectedPrinter( printer );
+ m_browseList.SelectItem( printer->item );
+ ::SetFocus( m_browseList );
+ }
}
exit:
m_browseList.SetRedraw(FALSE);
- //
- // check to make sure if we're the only item in the control...i.e.
- // the list size is 1.
- //
- if (m_browseList.GetCount() > 1)
- {
- //
- // if we're not the only thing in the list, then
- // simply remove it from the list
- //
- m_browseList.DeleteItem( printer->item );
- }
- else
+ if ( printer )
{
//
- // if we're the only thing in the list, then redisplay
- // it with the no printers message
+ // check to make sure if we're the only item in the control...i.e.
+ // the list size is 1.
//
- InitBrowseList();
+ if (m_browseList.GetCount() > 1)
+ {
+ //
+ // if we're not the only thing in the list, then
+ // simply remove it from the list
+ //
+ m_browseList.DeleteItem( printer->item );
+ }
+ else
+ {
+ //
+ // if we're the only thing in the list, then redisplay
+ // it with the no printers message
+ //
+ InitBrowseList();
+ }
}
exit:
* 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: SecondPage.h,v $
-Revision 1.9 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.8 2005/03/20 20:08:37 shersche
-<rdar://problem/4055670> Second screen should not select a printer by default
-
-Revision 1.7 2005/01/31 23:54:30 shersche
-<rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
-
-Revision 1.6 2005/01/04 21:09:14 shersche
-Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
-
-Revision 1.5 2004/12/31 07:25:27 shersche
-Tidy up printer management, and fix memory leaks when hitting 'Cancel'
-
-Revision 1.4 2004/12/30 01:02:46 shersche
-<rdar://problem/3734478> Add Printer information box that displays description and location information when printer name is selected
-Bug #: 3734478
-
-Revision 1.3 2004/12/29 18:53:38 shersche
-<rdar://problem/3725106>
-<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
-Bug #: 3725106, 3737413
-
-Revision 1.2 2004/09/13 21:23:42 shersche
-<rdar://problem/3796483> Add moreComing argument to OnAddPrinter and OnRemovePrinter callbacks
-Bug #: 3796483
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#pragma once
* 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: ThirdPage.cpp,v $
-Revision 1.42 2009/07/07 22:04:55 herscher
-<rdar://problem/4176343> LOC Impact: Need custom text when selecting the wrong printer driver
-
-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
-
-Revision 1.36 2007/06/06 20:39:10 cheshire
-<rdar://problem/5254377> Printer Setup Wizard started crashing in Bonjour104A8, after update to Visual Studio 2005
-
-Revision 1.35 2007/06/06 20:08:01 cheshire
-<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
-AutoScroll model list as well as manufacturer list
-
-Revision 1.34 2007/06/06 19:53:48 cheshire
-<rdar://problem/5187308> Move build train to Visual Studio 2005
-
-Revision 1.33 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
-
-Revision 1.32 2007/04/13 23:42:20 herscher
-<rdar://problem/4580061> mDNS: Printers added using Bonjour should be set as the default printer.
-
-Revision 1.31 2007/04/13 21:38:46 herscher
-<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
-
-Revision 1.30 2007/04/13 20:23:40 herscher
-Fixed mistake in previous checkin that reverted license text for this file
-
-Revision 1.29 2007/04/13 18:10:24 herscher
-<rdar://problem/4496652> mDNS: Don't allow user to choose non-working driver
-
-Revision 1.28 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.27 2005/10/05 21:41:45 herscher
-<rdar://problem/4190104> Use "application/octet-stream" to determine if CUPS shared queue supports raw
-
-Revision 1.26 2005/07/11 20:17:15 shersche
-<rdar://problem/4124524> UI fixes associated with CUPS printer workaround fix.
-
-Revision 1.25 2005/07/07 17:53:20 shersche
-Fix problems associated with the CUPS printer workaround fix.
-
-Revision 1.24 2005/06/30 18:02:54 shersche
-<rdar://problem/4124524> Workaround for Mac OS X Printer Sharing bug
-
-Revision 1.23 2005/04/18 02:33:47 shersche
-<rdar://problem/4091216> Default printer option cannot be deselected
-
-Revision 1.22 2005/04/13 17:46:22 shersche
-<rdar://problem/4082122> Generic PCL not selected when printers advertise multiple text records
-
-Revision 1.21 2005/03/30 02:09:55 shersche
-Auto-resize the column width to account for differing fonts and font sizes
-
-Revision 1.20 2005/03/05 02:27:45 shersche
-<rdar://problem/4030388> Generic drivers don't do color
-
-Revision 1.19 2005/02/23 02:08:51 shersche
-<rdar://problem/4012275> If we can't match the manufacturer, and select a generic printer, then show all the manufacturers in the manufacturer pane, not just "Generic".
-
-Revision 1.18 2005/02/15 07:02:51 shersche
-<rdar://problem/4003724> Display different UI text when generic printer drivers are selected
-
-Revision 1.17 2005/02/08 21:45:06 shersche
-<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
-
-Revision 1.16 2005/02/08 18:56:03 shersche
-Fix generated IPP url so that it doesn't add "/printers" string
-
-Revision 1.15 2005/02/01 01:44:07 shersche
-Load ntprint.inf at startup. This will cause the wizard to take a second or two longer to come up, but will eliminate the pause when auto-selecting the print drivers.
-
-Revision 1.14 2005/01/25 08:55:54 shersche
-<rdar://problem/3911084> Load icons at run-time from resource DLL
-Bug #: 3911084
-
-Revision 1.13 2005/01/06 08:15:45 shersche
-Append queue name to end of LPR port name, correctly build port name when queue name is absent
-
-Revision 1.12 2005/01/05 01:06:12 shersche
-<rdar://problem/3841218> Strip the first substring off the product key if an initial match can't be found with the whole product key.
-Bug #: 3841218
-
-Revision 1.11 2004/12/29 18:53:38 shersche
-<rdar://problem/3725106>
-<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
-Bug #: 3725106, 3737413
-
-Revision 1.10 2004/10/11 22:55:34 shersche
-<rdar://problem/3827624> Use the IP port number when deriving the printer port name.
-Bug #: 3827624
-
-Revision 1.9 2004/06/27 23:08:00 shersche
-code cleanup, make sure EnumPrintDrivers returns non-zero value, ignore comments in inf files
-
-Revision 1.8 2004/06/27 08:06:45 shersche
-Parse [Strings] section of inf file
-
-Revision 1.7 2004/06/26 04:00:05 shersche
-fix warnings compiling in debug mode
-Submitted by: herscher
-
-Revision 1.6 2004/06/26 03:19:57 shersche
-clean up warning messages
-
-Submitted by: herscher
-
-Revision 1.5 2004/06/25 05:06:02 shersche
-Trim whitespace from key/value pairs when parsing inf files
-Submitted by: herscher
-
-Revision 1.4 2004/06/25 02:44:13 shersche
-Tweaked code to handle Xerox Phaser printer identification
-Submitted by: herscher
-
-Revision 1.3 2004/06/25 02:27:58 shersche
-Do a CListCtrl::FindItem() before calling CListCtrl::SetItemState().
-Submitted by: herscher
-
-Revision 1.2 2004/06/23 18:09:23 shersche
-Normalize tag names when parsing inf files.
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:36:58 rpantos
-First checked in
-*/
+ */
#include "stdafx.h"
#include "PrinterSetupWizardApp.h"
return;
}
-CThirdPage::~CThirdPage()
+
+void
+CThirdPage::FreeManufacturers( Manufacturers & manufacturers )
{
- //
- // clean up all the printer manufacturers
- //
- while (m_manufacturers.size())
+ for ( Manufacturers::iterator it = manufacturers.begin(); it != manufacturers.end(); it++ )
{
- Manufacturers::iterator iter = m_manufacturers.begin();
-
- while (iter->second->models.size())
+ for ( Models::iterator it2 = it->second->models.begin(); it2 != it->second->models.end(); it2++ )
{
- Models::iterator it = iter->second->models.begin();
-
- Model * model = *it;
-
- delete model;
-
- iter->second->models.erase(it);
+ delete *it2;
}
- delete iter->second;
-
- m_manufacturers.erase(iter);
+ delete it->second;
}
}
+
+CThirdPage::~CThirdPage()
+{
+ FreeManufacturers( m_manufacturers );
+}
+
// ----------------------------------------------------
// SelectMatch
//
void
CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufacturer * manufacturer, Model * model )
{
+ DWORD portNameLen;
+
printer->manufacturer = manufacturer->name;
printer->displayModelName = model->displayName;
printer->modelName = model->name;
service->protocol = L"IPP";
}
+
+ // If it's not an IPP printr, truncate the portName so that it's valid
+
+ if ( service->type != kIPPServiceType )
+ {
+ portNameLen = printer->portName.GetLength() + 1;
+
+ if ( portNameLen > MAX_PORTNAME_LEN )
+ {
+ printer->portName.Delete( MAX_PORTNAME_LEN - 1, ( portNameLen - MAX_PORTNAME_LEN ) );
+ }
+ }
}
// --------------------------------------------------------
useCUPSWorkaround = false;
}
- if ( useCUPSWorkaround && printer->isSharedFromOSX && hasGenericDriver )
+ if ( useCUPSWorkaround && printer->isCUPSPrinter && hasGenericDriver )
{
//
// <rdar://problem/4496652> mDNS: Don't allow user to choose non-working driver
LoadGenericPrintDriverDefs( genericManufacturers );
SelectMatch( genericManufacturers, printer, service, genericManufacturer, genericModel );
+
+ FreeManufacturers( genericManufacturers );
}
else
{
}
else if ( MatchGeneric( manufacturers, printer, service, &genericManufacturer, &genericModel ) )
{
- if ( printer->isSharedFromOSX )
+ if ( printer->isCUPSPrinter )
{
//
// <rdar://problem/4496652> mDNS: Don't allow user to choose non-working driver
SelectMatch( genericManufacturers, printer, service, genericManufacturer, genericModel );
text.LoadString(IDS_PRINTER_MATCH_GOOD);
+
+ FreeManufacturers( genericManufacturers );
}
else
{
exit:
+ FreeManufacturers( manufacturers );
return;
}
* 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: 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.
-
-Revision 1.8 2007/04/13 21:38:46 herscher
-<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
-
-Revision 1.7 2007/04/13 20:18:30 herscher
-<rdar://problem/4189721> mDNS: Epson shows up twice in the list
-
-Revision 1.6 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.5 2005/07/07 17:53:20 shersche
-Fix problems associated with the CUPS printer workaround fix.
-
-Revision 1.4 2005/02/08 21:45:06 shersche
-<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
-
-Revision 1.3 2005/01/25 08:57:28 shersche
-<rdar://problem/3911084> Add m_printerControl member for dynamic loading of icons from resource DLLs
-Bug #: 3911084
-
-Revision 1.2 2004/12/29 18:53:38 shersche
-<rdar://problem/3725106>
-<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
-Bug #: 3725106, 3737413
-
-Revision 1.1 2004/06/18 04:36:58 rpantos
-First checked in
-
-
-*/
+ */
#pragma once
#include "afxcmn.h"
//
void AutoScroll(CListCtrl & list, int nIndex);
+ void FreeManufacturers( Manufacturers & manufacturers );
+
Manufacturers m_manufacturers;
CListCtrl m_manufacturerListCtrl;
* 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: 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
-
-Revision 1.15 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.14 2005/06/30 18:02:54 shersche
-<rdar://problem/4124524> Workaround for Mac OS X Printer Sharing bug
-
-Revision 1.13 2005/04/13 17:46:22 shersche
-<rdar://problem/4082122> Generic PCL not selected when printers advertise multiple text records
-
-Revision 1.12 2005/03/16 03:12:28 shersche
-<rdar://problem/4050504> Generic PCL driver isn't selected correctly on Win2K
-
-Revision 1.11 2005/03/05 02:27:46 shersche
-<rdar://problem/4030388> Generic drivers don't do color
-
-Revision 1.10 2005/02/08 21:45:06 shersche
-<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
-
-Revision 1.9 2005/02/01 01:16:12 shersche
-Change window owner from CSecondPage to CPrinterSetupWizardSheet
-
-Revision 1.8 2005/01/06 08:18:26 shersche
-Add protocol field to service, add EmptyQueues() function to service
-
-Revision 1.7 2005/01/04 21:07:29 shersche
-add description member to service object. this member corresponds to the 'ty' key in a printer text record
-
-Revision 1.6 2004/12/30 01:24:02 shersche
-<rdar://problem/3906182> Remove references to description key
-Bug #: 3906182
-
-Revision 1.5 2004/12/29 18:53:38 shersche
-<rdar://problem/3725106>
-<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
-Bug #: 3725106, 3737413
-
-Revision 1.4 2004/09/13 21:22:44 shersche
-<rdar://problem/3796483> Add moreComing argument to OnAddPrinter and OnRemovePrinter callbacks
-Bug #: 3796483
-
-Revision 1.3 2004/06/26 23:27:12 shersche
-support for installing multiple printers of the same name
-
-Revision 1.2 2004/06/25 02:25:59 shersche
-Remove item field from manufacturer and model structures
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:36:58 rpantos
-First checked in
-
-
-*/
+ */
#pragma once
// This let's us know that this printer was discovered via OSX Printer Sharing.
// We use this knowledge to workaround a problem with OS X Printer sharing.
- bool isSharedFromOSX;
+ bool isCUPSPrinter;
//
// state
inline
Printer::Printer()
:
- isSharedFromOSX( false )
+ isCUPSPrinter( false )
{
}
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
* See the License for the specific language governing permissions and\r
* limitations under the License.\r
-\r
- Change History (most recent first):\r
-\r
*/\r
\r
\r
#define IDC_DESCRIPTION_FIELD 1030\r
#define IDC_LOCATION_FIELD 1032\r
#define IDC_DESCRIPTION_LABEL 1033\r
+#define IDC_COMPLETE1 1034\r
+#define IDC_COMPLETE2 1035\r
+#define IDC_INSTALLING 1036\r
+#define IDC_PROGRESS 1037\r
\r
// Next default values for new objects\r
-// \r
+//\r
#ifdef APSTUDIO_INVOKED\r
#ifndef APSTUDIO_READONLY_SYMBOLS\r
#define _APS_NEXT_RESOURCE_VALUE 142\r
#define IDC_DESCRIPTION_FIELD 1030\r
#define IDC_LOCATION_FIELD 1032\r
#define IDC_DESCRIPTION_LABEL 1033\r
+#define IDC_COMPLETE1 1034\r
+#define IDC_COMPLETE2 1035\r
+#define IDC_INSTALLING 1036\r
+#define IDC_PROGRESS 1037\r
\r
// Next default values for new objects\r
// \r
#define IDC_DESCRIPTION_FIELD 1030\r
#define IDC_LOCATION_FIELD 1032\r
#define IDC_DESCRIPTION_LABEL 1033\r
+#define IDC_COMPLETE1 1034\r
+#define IDC_COMPLETE2 1035\r
+#define IDC_INSTALLING 1036\r
+#define IDC_PROGRESS 1037\r
\r
// Next default values for new objects\r
// \r
* 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.cpp,v $
-Revision 1.2 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2004/06/18 04:36:58 rpantos
-First checked in
-
-
-*/
+ */
#include "stdafx.h"
* 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.3 2006/08/14 23:24:09 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/10/19 19:50:35 herscher
-Workaround a bug in the latest Microsoft Platform SDK when compiling C++ files that include (directly or indirectly) <WspiApi.h>
-
-Revision 1.1 2004/06/18 04:36:58 rpantos
-First checked in
-
-
-*/
+ */
#pragma once
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
* See the License for the specific language governing permissions and\r
* limitations under the License.\r
-\r
- Change History (most recent first):\r
- \r
-$Log: AssemblyInfo.cs,v $
-Revision 1.2 2006/08/14 23:24:21 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2004/07/19 07:57:08 shersche
-Initial revision
-\r
-\r
-\r
-*/\r
+ */\r
\r
using System.Reflection;\r
using System.Runtime.CompilerServices;\r
* 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: 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
-
-Revision 1.5 2004/09/13 19:37:42 shersche
-Change code to reflect namespace and type changes to dnssd.NET library
-
-Revision 1.4 2004/09/11 05:42:56 shersche
-don't reset SelectedIndex in OnRemove
-
-Revision 1.3 2004/09/11 00:38:58 shersche
-DNSService APIs now expect port in host format
-
-Revision 1.2 2004/07/19 22:08:53 shersche
-Fixed rdata->int conversion problem in QueryRecordReply
-
-Revision 1.1 2004/07/19 07:57:08 shersche
-Initial revision
-
-
-
-*/
+ */
using System;
using System.Drawing;
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 System.Windows.Forms.Label label1;
+
+ private Bonjour.DNSSDEventManager m_eventManager = null;
+
+ private Bonjour.DNSSDService m_service = null;
+
+ private Bonjour.DNSSDService m_registrar = null;
+
+ private Bonjour.DNSSDService m_browser = null;
+
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
+ private String m_name;
+
+ private Socket m_socket = null;
+
+ private const int BUFFER_SIZE = 1024;
+
+ public byte[] m_buffer = new byte[BUFFER_SIZE];
+
+ public bool m_complete = false;
+
+ public StringBuilder m_sb = new StringBuilder();
+
+ delegate void ReadMessageCallback(String data);
+
ReadMessageCallback m_readMessageCallback;
/// <summary>
/// Required designer variable.
//
// Called by DNSServices core as a result of Register()
// call
- //\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
+ //
+
+
+
+ public void
+
+ ServiceRegistered
+
+ (
+
+ DNSSDService service,
+
+ DNSSDFlags flags,
+
+ String name,
+
+ String regType,
+
+ String domain
+
+ )
+
+ {
+
+ m_name = name;
+
+
+
+ try
+
+ {
+
+ m_browser = m_service.Browse(0, 0, "_p2pchat._udp", null, m_eventManager);
+
+ }
+
+ catch
+
+ {
+
+ MessageBox.Show("Browse Failed", "Error");
+
+ Application.Exit();
+
+ }
+
}
//
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
+ {
+
+ if (serviceName != m_name)
+
+ {
+
+ PeerData peer = new PeerData();
+
+
+
+ peer.InterfaceIndex = ifIndex;
+
+ peer.Name = serviceName;
+
+ peer.Type = regType;
+
+ peer.Domain = domain;
+
+ peer.Address = null;
+
+
+
+ comboBox1.Items.Add(peer);
+
+
+
+ if (comboBox1.Items.Count == 1)
+
+ {
+
+ comboBox1.SelectedIndex = 0;
+
+ }
+
}
- }\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
+ }
+
+
+
+ //
+
+ // ServiceLost
+
+ //
+
+ // Called by DNSServices core as a result of a Browse call
+
+ //
+
+
+
+ public void
+
+ ServiceLost
+
+ (
+
+ DNSSDService sref,
+
+ DNSSDFlags flags,
+
+ uint ifIndex,
+
+ String serviceName,
+
+ String regType,
+
+ String domain
+
+ )
+
+ {
+
+ PeerData peer = new PeerData();
+
+
+
+ peer.InterfaceIndex = ifIndex;
+
+ peer.Name = serviceName;
+
+ peer.Type = regType;
+
+ peer.Domain = domain;
+
+ peer.Address = null;
+
+
+
+ comboBox1.Items.Remove(peer);
+
}
//
// Called by DNSServices core as a result of DNSService.Resolve()
// call
//
-\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
+
+
+ public void
+
+ ServiceResolved
+
+ (
+
+ DNSSDService sref,
+
+ DNSSDFlags flags,
+
+ uint ifIndex,
+
+ String fullName,
+
+ String hostName,
+
+ ushort port,
+
+ TXTRecord txtRecord
+
)
- {\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
+ {
+
+ m_resolver.Stop();
+
+ m_resolver = null;
+
+
+
+ PeerData peer = (PeerData)comboBox1.SelectedItem;
+
+
+
+ peer.Port = port;
+
+
+
+ try
+
+ {
+
+ m_resolver = m_service.QueryRecord(0, ifIndex, hostName, DNSSDRRType.kDNSSDType_A, DNSSDRRClass.kDNSSDClass_IN, m_eventManager );
+
+ }
+
+ catch
+
+ {
+
+ MessageBox.Show("QueryRecord Failed", "Error");
+
+ Application.Exit();
+
}
}
Object rdata,
uint ttl
)
- {\r
- m_resolver.Stop();\r
- m_resolver = null;\r
-\r
- PeerData peer = (PeerData) comboBox1.SelectedItem;\r
+ {
+
+ m_resolver.Stop();
+
+ m_resolver = null;
+
+
+
+ PeerData peer = (PeerData) comboBox1.SelectedItem;
+
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
+ }
+
+
+
+ public void
+
+ OperationFailed
+
+ (
+
+ DNSSDService service,
+
+ DNSSDError error
+
+ )
+
+ {
+
+ MessageBox.Show("Operation returned an error code " + error, "Error");
+
+ }
+
+
+
+ //
+
+ // 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 + Environment.NewLine);
+
}
//
//
// Required for Windows Form Designer support
//
- 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
+ InitializeComponent();
+
+
+
+ try
+
+ {
+
+ m_service = new DNSSDService();
+
+ }
+
+ catch
+
+ {
+
+ MessageBox.Show("Bonjour Service is not available", "Error");
+
+ Application.Exit();
+
+ }
+
+
+
+ m_eventManager = new DNSSDEventManager();
+
+ m_eventManager.ServiceRegistered += new _IDNSSDEvents_ServiceRegisteredEventHandler(this.ServiceRegistered);
+
+ m_eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
+
+ m_eventManager.ServiceLost += new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
+
+ m_eventManager.ServiceResolved += new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
+
+ m_eventManager.QueryRecordAnswered += new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);
+
m_eventManager.OperationFailed += new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
m_readMessageCallback = new ReadMessageCallback(OnReadMessage);
if (m_browser != null)
{
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
+ }
+
+
+
+ if (m_resolver != null)
+
+ {
+
+ m_resolver.Stop();
+
+ }
+
+
+
+ m_eventManager.ServiceFound -= new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
+
+ m_eventManager.ServiceLost -= new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
+
+ m_eventManager.ServiceResolved -= new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
+
+ m_eventManager.QueryRecordAnswered -= new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);
+
m_eventManager.OperationFailed -= new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
}
base.Dispose( disposing );
Byte[] bytes = Encoding.UTF8.GetBytes(message);
- IPEndPoint endPoint = new IPEndPoint( peer.Address, peer.Port );\r
-\r
+ IPEndPoint endPoint = new IPEndPoint( peer.Address, peer.Port );
+
+
+
m_socket.SendTo(bytes, endPoint);
richTextBox1.SelectionColor = Color.Black;
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
+ }
+
+
+
+ //
+
+ // PeerData
+
+ //
+
+ // Holds onto the information associated with a peer on the network
+
+ //
+
+ public class PeerData
+
+ {
+
+ public uint 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();
+
+ }
+
};
}
+'\r
+' Copyright (c) 2010 Apple Inc. All rights reserved.\r
+'\r
+' Licensed under the Apache License, Version 2.0 (the "License");\r
+' you may not use this file except in compliance with the License.\r
+' You may obtain a copy of the License at\r
+' \r
+' http://www.apache.org/licenses/LICENSE-2.0\r
+' \r
+' Unless required by applicable law or agreed to in writing, software\r
+' distributed under the License is distributed on an "AS IS" BASIS,\r
+' WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+' See the License for the specific language governing permissions and\r
+' limitations under the License.\r
+'\r
\r
Imports System.Net\r
Imports System.Net.Sockets\r
return name;
}
+ static size_t _sa_len(const struct sockaddr *addr)
+ {
+ if (addr->sa_family == AF_INET) return (sizeof(struct sockaddr_in));
+ else if (addr->sa_family == AF_INET6) return (sizeof(struct sockaddr_in6));
+ else return (sizeof(struct sockaddr));
+ }
+
+# define SA_LEN(addr) (_sa_len(addr))
+
#else
#include <unistd.h> // For getopt() and optind
#include <netdb.h> // For getaddrinfo()
#include <arpa/inet.h> // For inet_addr()
#include <net/if.h> // For if_nametoindex()
static const char kFilePathSep = '/';
+ #define SA_LEN(addr) ((addr)->sa_len)
#endif
#if (TEST_NEW_CLIENTSTUB && !defined(__APPLE_API_PRIVATE))
#define __APPLE_API_PRIVATE 1
#endif
+// DNSServiceSetDispatchQueue is not supported on 10.6 & prior
+#if ! TEST_NEW_CLIENTSTUB && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ % 10) <= 1060)
+#undef _DNS_SD_LIBDISPATCH
+#endif
#include "dns_sd.h"
-
#include "ClientCommon.h"
#if TEST_NEW_CLIENTSTUB
static char updatetest[3] = "\002AA";
static char bigNULL[8192]; // 8K is maximum rdata we support
+#if _DNS_SD_LIBDISPATCH
+dispatch_queue_t main_queue;
+dispatch_source_t timer_source;
+#endif
+
// Note: the select() implementation on Windows (Winsock2) fails with any timeout much larger than this
#define LONG_TIME 100000000
static volatile int stopNow = 0;
static volatile int timeOut = LONG_TIME;
+#if _DNS_SD_LIBDISPATCH
+#define EXIT_IF_LIBDISPATCH_FATAL_ERROR(E) \
+ if (main_queue && (E) == kDNSServiceErr_ServiceNotRunning) { fprintf(stderr, "Error code %d\n", (E)); exit(0); }
+#else
+#define EXIT_IF_LIBDISPATCH_FATAL_ERROR(E)
+#endif
+
//*************************************************************************************************************
// Supporting Utility Functions
(void)sdref; // Unused
(void)ifIndex; // Unused
(void)context; // Unused
+ EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
// 1. Print the header
if (num_printed++ == 0) printf("Timestamp Recommended %s domain\n", operation == 'E' ? "Registration" : "Browsing");
(void)sdref; // Unused
(void)context; // Unused
+ EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
if (!(flags & kDNSServiceFlagsAdd)) return;
if (errorCode) { printf("Error code %d\n", errorCode); return; }
char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
(void)sdref; // Unused
(void)context; // Unused
+ EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
+
if (num_printed++ == 0) printf("Timestamp A/R Flags if %-25s %-25s %s\n", "Domain", "Service Type", "Instance Name");
printtimestamp();
if (errorCode) printf("Error code %d\n", errorCode);
(void)sdref; // Unused
(void)ifIndex; // Unused
(void)context; // Unused
+ EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
- printtimestamp();
- if (errorCode) printf("Error code %d\n", errorCode);
+ if (errorCode)
+ printf("Error code %d\n", errorCode);
else
{
+ printtimestamp();
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
err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_NULL, sizeof(bigNULL), &bigNULL[0], 0);
if (err) printf("Failed: %d\n", err); else printf("Succeeded\n");
timeOut = LONG_TIME;
+#if _DNS_SD_LIBDISPATCH
+ if (timer_source)
+ dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)timeOut * NSEC_PER_SEC),
+ (uint64_t)timeOut * NSEC_PER_SEC, 0);
+#endif
}
break;
}
(void)sdref; // Unused
(void)flags; // Unused
(void)context; // Unused
+ EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
printtimestamp();
printf("Got a reply for service %s.%s%s: ", name, regtype, domain);
{
if (flags & kDNSServiceFlagsAdd) printf("Name now registered and active\n");
else printf("Name registration removed\n");
- if (operation == 'A' || operation == 'U' || operation == 'N') timeOut = 5;
+ if (operation == 'A' || operation == 'U' || operation == 'N')
+ {
+ timeOut = 5;
+#if _DNS_SD_LIBDISPATCH
+ if (timer_source)
+ dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)timeOut * NSEC_PER_SEC),
+ (uint64_t)timeOut * NSEC_PER_SEC, 0);
+#endif
+ }
}
else if (errorCode == kDNSServiceErr_NameConflict)
{
(void)ifIndex; // Unused
(void)ttl; // Unused
(void)context; // Unused
+ EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
if (num_printed++ == 0) printf("Timestamp A/R Flags if %-30s%4s%4s Rdata\n", "Name", "T", "C");
printtimestamp();
static void DNSSD_API port_mapping_create_reply(DNSServiceRef sdref, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, uint32_t publicAddress, uint32_t protocol, uint16_t privatePort, uint16_t publicPort, uint32_t ttl, void *context)
{
(void)sdref; // Unused
- (void)context; // Unused
(void)flags; // Unused
-
+ (void)context; // Unused
+ EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
+
if (num_printed++ == 0) printf("Timestamp if %-20s %-15s %-15s %-15s %-6s\n", "External Address", "Protocol", "Internal Port", "External Port", "TTL");
printtimestamp();
if (errorCode && errorCode != kDNSServiceErr_DoubleNAT) printf("Error code %d\n", errorCode);
snprintf(addr, sizeof(addr), "%d.%d.%d.%d", digits[0], digits[1], digits[2], digits[3]);
printf("%-4d %-20s %-15d %-15d %-15d %-6d%s\n", ifIndex, addr, protocol, ntohs(privatePort), ntohs(publicPort), ttl, errorCode == kDNSServiceErr_DoubleNAT ? " Double NAT" : "");
}
- fflush(stdout);
+
+ if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
#endif
char addr[256] = "";
(void) sdref;
(void) context;
-
+ EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
+
if (num_printed++ == 0) printf("Timestamp A/R Flags if %-25s %-44s %s\n", "Hostname", "Address", "TTL");
printtimestamp();
// The main test function
static void HandleEvents(void)
+#if _DNS_SD_LIBDISPATCH
+ {
+ main_queue = dispatch_get_main_queue();
+ if (client) DNSServiceSetDispatchQueue(client, main_queue);
+ if (client_pa) DNSServiceSetDispatchQueue(client_pa, main_queue);
+ if (operation == 'A' || operation == 'U' || operation == 'N')
+ {
+ timer_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, main_queue);
+ if (timer_source)
+ {
+ // Start the timer "timeout" seconds into the future and repeat it every "timeout" seconds
+ dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)timeOut * NSEC_PER_SEC),
+ (uint64_t)timeOut * NSEC_PER_SEC, 0);
+ dispatch_source_set_event_handler(timer_source, ^{myTimerCallBack();});
+ dispatch_resume(timer_source);
+ }
+ }
+ dispatch_main();
+ }
+#else
{
int dns_sd_fd = client ? DNSServiceRefSockFD(client ) : -1;
int dns_sd_fd2 = client_pa ? DNSServiceRefSockFD(client_pa) : -1;
}
}
}
+#endif
static int getfirstoption(int argc, char **argv, const char *optstr, int *pOptInd)
// Return the recognized option in optstr and the option index of the next arg.
char *name = (char *)context;
(void)service; // Unused
- (void)rec; // Unused
+ (void)rec; // Unused
(void)flags; // Unused
-
+ EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
+
printtimestamp();
printf("Got a reply for record %s: ", name);
}
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
// DNSServiceRemoveRecord(service, rec, 0); to test record removal
- }
-static unsigned long getip(const char *const name)
- {
- unsigned long ip = 0;
- struct addrinfo hints;
- struct addrinfo *addrs = NULL;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
-
- if (getaddrinfo(name, NULL, &hints, &addrs) == 0)
+#if 0 // To test updating of individual records registered via DNSServiceRegisterRecord
+ if (!errorCode)
{
- ip = ((struct sockaddr_in*) addrs->ai_addr)->sin_addr.s_addr;
+ int x = 0x11111111;
+ printf("Updating\n");
+ DNSServiceUpdateRecord(service, rec, 0, sizeof(x), &x, 0);
}
+#endif
- if (addrs)
- {
- freeaddrinfo(addrs);
- }
+ if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
+ }
- return(ip);
+static void getip(const char *const name, struct sockaddr_storage *result)
+ {
+ struct addrinfo *addrs = NULL;
+ int err = getaddrinfo(name, NULL, NULL, &addrs);
+ if (err) fprintf(stderr, "getaddrinfo error %d for %s", err, name);
+ else memcpy(result, addrs->ai_addr, SA_LEN(addrs->ai_addr));
+ if (addrs) freeaddrinfo(addrs);
}
static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef sdref, const char *host, const char *ip)
// On the Win32 platform, WinSock must be initialized for getip() to succeed.
// Any DNSService* call will initialize WinSock for us, so we make sure
// DNSServiceCreateConnection() is called before getip() is.
- unsigned long addr = getip(ip);
- return(DNSServiceRegisterRecord(sdref, &record, kDNSServiceFlagsUnique, opinterface, host,
- kDNSServiceType_A, kDNSServiceClass_IN, sizeof(addr), &addr, 240, MyRegisterRecordCallback, (void*)host));
- // Note, should probably add support for creating proxy AAAA records too, one day
+ struct sockaddr_storage hostaddr;
+ getip(ip, &hostaddr);
+ if (hostaddr.ss_family == AF_INET)
+ return(DNSServiceRegisterRecord(sdref, &record, kDNSServiceFlagsUnique, opinterface, host,
+ kDNSServiceType_A, kDNSServiceClass_IN, 4, &((struct sockaddr_in *)&hostaddr)->sin_addr, 240, MyRegisterRecordCallback, (void*)host));
+ else if (hostaddr.ss_family == AF_INET6)
+ return(DNSServiceRegisterRecord(sdref, &record, kDNSServiceFlagsUnique, opinterface, host,
+ kDNSServiceType_AAAA, kDNSServiceClass_IN, 16, &((struct sockaddr_in6*)&hostaddr)->sin6_addr, 240, MyRegisterRecordCallback, (void*)host));
+ else return(kDNSServiceErr_BadParam);
}
#define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0' ) : \
printf("Using LocalOnly\n");
}
+ if (argc > 1 && (!strcmp(argv[1], "-p2p") || !strcmp(argv[1], "-P2P")))
+ {
+ argc--;
+ argv++;
+ opinterface = kDNSServiceInterfaceIndexP2P;
+ printf("Using P2P\n");
+ }
+
if (argc > 2 && !strcmp(argv[1], "-i"))
{
opinterface = if_nametoindex(argv[2]);
}
if (argc < 2) goto Fail; // Minimum command line is the command name and one argument
- operation = getfirstoption(argc, argv, "EFBZLRPQCAUNTMISV"
+ operation = getfirstoption(argc, argv, "EFBZLRPQqCAUNTMISV"
#if HAS_NAT_PMP_API
"X"
#endif
//DNSServiceRemoveRecord(client_pa, record, 0);
break;
+ case 'q':
case 'Q':
case 'C': {
uint16_t rrtype, rrclass;
DNSServiceFlags flags = kDNSServiceFlagsReturnIntermediates;
+ if (operation == 'q') flags |= kDNSServiceFlagsSuppressUnusable;
if (argc < opi+1) goto Fail;
rrtype = (argc <= opi+1) ? kDNSServiceType_A : GetRRType(argv[opi+1]);
rrclass = (argc <= opi+2) ? kDNSServiceClass_IN : atoi(argv[opi+2]);
#endif
case 'S': {
- Opaque16 registerPort = { { 0x23, 0x45 } };
+ Opaque16 registerPort = { { 0x23, 0x45 } }; // 9029 decimal
unsigned char txtrec[16] = "\xF" "/path=test.html";
DNSRecordRef rec;
unsigned char nulrec[4] = "1234";
--- /dev/null
+// 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 "afxres.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 ""afxres.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "\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 0x17L\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x1L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", MASTER_COMPANY_NAME\r
+ VALUE "FileDescription", "Bonjour Network Utility"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "mDNSNetMonitor.exe"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "mDNSNetMonitor.exe"\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, 1200\r
+ END\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
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"\r
/>\r
<Tool\r
Name="VCPreLinkEventTool"\r
/>\r
<Tool\r
Name="VCLinkerTool"\r
+ AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
AdditionalDependencies="ws2_32.lib iphlpapi.lib crypt32.lib netapi32.lib powrprof.lib"\r
LinkIncremental="2"\r
GenerateDebugInformation="true"\r
/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"\r
/>\r
<Tool\r
Name="VCPreLinkEventTool"\r
/>\r
<Tool\r
Name="VCLinkerTool"\r
+ AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
AdditionalDependencies="ws2_32.lib iphlpapi.lib crypt32.lib netapi32.lib powrprof.lib"\r
LinkIncremental="1"\r
GenerateDebugInformation="true"\r
RelativePath="..\..\mDNSWindows\Secret.c"\r
>\r
</File>\r
- <File\r
- RelativePath="..\..\mDNSWindows\SystemService\Service.c"\r
- >\r
- </File>\r
<File\r
RelativePath="..\..\mDNSCore\uDNS.c"\r
>\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=".\mDNSNetMonitor.rc"\r
+ >\r
+ </File>\r
</Filter>\r
</Files>\r
<Globals>\r
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by mDNSNetMonitor.rc\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE 101\r
+#define _APS_NEXT_COMMAND_VALUE 40001\r
+#define _APS_NEXT_CONTROL_VALUE 1001\r
+#define _APS_NEXT_SYMED_VALUE 101\r
+#endif\r
+#endif\r
include /Developer/Makefiles/pb_makefiles/platform.make
-MVERS = "mDNSResponder-214.3.2"
+MVERS = "mDNSResponder-258.13"
DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
ditto . "$(SRCROOT)"
installhdrs::
- cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild installhdrs OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS)
+ cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild installhdrs OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) -target SystemLibraries
clean::
echo clean
* 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: DNSCommon.c,v $
-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
-Make sure we add the record when sending LLQ refreshes
-
-Revision 1.198 2008/03/07 23:29:24 cheshire
-Fixed cosmetic byte order display issue in DumpPacket output
-
-Revision 1.197 2008/03/05 22:51:29 mcguire
-<rdar://problem/5500969> BTMM: Need ability to identify version of mDNSResponder client
-Even further refinements
-
-Revision 1.196 2008/03/05 22:01:53 cheshire
-<rdar://problem/5500969> BTMM: Need ability to identify version of mDNSResponder client
-Now that we optionally add the HINFO record, when rewriting the header fields into network byte
-order, we need to use our updated msg->h.numAdditionals, not the stack variable numAdditionals
-
-Revision 1.195 2008/03/05 19:06:30 mcguire
-<rdar://problem/5500969> BTMM: Need ability to identify version of mDNSResponder client
-further refinements
-
-Revision 1.194 2008/03/05 00:26:06 cheshire
-<rdar://problem/5500969> BTMM: Need ability to identify version of mDNSResponder client
-
-Revision 1.193 2007/12/17 23:42:36 cheshire
-Added comments about DNSDigest_SignMessage()
-
-Revision 1.192 2007/12/17 21:24:09 cheshire
-<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
-We suspend sending of mDNS queries responses when going to sleep, so calculate GetNextScheduledEvent() time accordingly
-
-Revision 1.191 2007/12/14 00:59:36 cheshire
-<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
-While going to sleep, don't block event scheduling
-
-Revision 1.190 2007/12/13 20:20:17 cheshire
-Minor efficiency tweaks -- converted IdenticalResourceRecord, IdenticalSameNameRecord, and
-SameRData from functions to macros, which allows the code to be inlined (the compiler can't
-inline a function defined in a different compilation unit) and therefore optimized better.
-
-Revision 1.189 2007/12/13 00:17:32 cheshire
-RDataHashValue was not calculating hash value reliably for RDATA types that have 'holes' in the
-in-memory representation (particularly SOA was affected by this, resulting in multiple duplicate
-cache entities for the same SOA record, because they had erroneously different rdatahash values).
-
-Revision 1.188 2007/12/13 00:13:03 cheshire
-Simplified RDataHashValue to take a single ResourceRecord pointer, instead of separate rdlength and RDataBody
-
-Revision 1.187 2007/12/08 00:35:20 cheshire
-<rdar://problem/5636422> Updating TXT records is too slow
-m->SuppressSending should not suppress all activity, just mDNS Query/Probe/Response
-
-Revision 1.186 2007/11/15 22:52:29 cheshire
-<rdar://problem/5589039> ERROR: mDNSPlatformWriteTCP - send Broken pipe
-
-Revision 1.185 2007/10/10 20:22:03 cheshire
-Added sanity checks in mDNSSendDNSMessage -- we've seen crashes in DNSDigest_SignMessage
-apparently caused by trying to sign zero-length messages
-
-Revision 1.184 2007/10/05 17:56:07 cheshire
-Move CountLabels and SkipLeadingLabels to DNSCommon.c so they're callable from other files
-
-Revision 1.183 2007/10/02 18:33:46 cheshire
-Improved GetRRDisplayString to show all constituent strings within a text record
-(up to the usual MaxMsg 120-character limit)
-
-Revision 1.182 2007/10/01 19:45:01 cheshire
-<rdar://problem/5514859> BTMM: Sometimes Back to My Mac autotunnel registrations are malformed
-
-Revision 1.181 2007/10/01 18:36:53 cheshire
-Yet another fix to finally get the DumpPacket RCODE display right
-
-Revision 1.180 2007/09/29 21:30:38 cheshire
-In DumpPacket/DumpRecords, show an error line if we run out of packet data
-
-Revision 1.179 2007/09/29 20:44:56 cheshire
-Fix error in DumpPacket where it was not displaying the RCODE field properly
-
-Revision 1.178 2007/09/27 21:11:44 cheshire
-Fixed spelling mistake: ROCDE -> RCODE
-
-Revision 1.177 2007/09/27 18:51:26 cheshire
-Improved DumpPacket to use "Zone/Prerequisites/Updates" nomenclature when displaying a DNS Update packet
-
-Revision 1.176 2007/09/27 17:53:37 cheshire
-Add display of RCODE and flags in DumpPacket output
-
-Revision 1.175 2007/09/26 22:26:40 cheshire
-Also show DNS query/response ID in DumpPacket output
-
-Revision 1.174 2007/09/26 16:36:02 cheshire
-In DumpPacket output, begin header line with "-- " to make it visually stand out better
-
-Revision 1.173 2007/09/26 00:49:46 cheshire
-Improve packet logging to show sent and received packets,
-transport protocol (UDP/TCP/TLS) and source/destination address:port
-
-Revision 1.172 2007/09/21 23:14:39 cheshire
-<rdar://problem/5498009> BTMM: Need to log updates and query packet contents in verbose debug mode
-Changed DumpRecords to use LargeCacheRecord on the stack instead of the shared m->rec storage,
-to eliminate "GetLargeResourceRecord: m->rec appears to be already in use" warnings
-
-Revision 1.171 2007/09/21 21:12:36 cheshire
-<rdar://problem/5498009> BTMM: Need to log updates and query packet contents
-
-Revision 1.170 2007/09/07 21:16:58 cheshire
-Add new symbol "NATPMPAnnouncementPort" (5350)
-
-Revision 1.169 2007/08/30 00:31:20 cheshire
-Improve "locking failure" debugging messages to show function name using __func__ macro
-
-Revision 1.168 2007/08/28 23:58:42 cheshire
-Rename HostTarget -> AutoTarget
-
-Revision 1.167 2007/08/10 23:10:05 vazquez
-<rdar://problem/5389850> mDNS: Reverse lookups of IPv6 link-local addresses always fail
-
-Revision 1.166 2007/08/01 16:09:13 cheshire
-Removed unused NATTraversalInfo substructure from AuthRecord; reduced structure sizecheck values accordingly
-
-Revision 1.165 2007/08/01 00:04:13 cheshire
-<rdar://problem/5261696> Crash in tcpKQSocketCallback
-Half-open TCP connections were not being cancelled properly
-
-Revision 1.164 2007/07/27 20:48:43 cheshire
-In DumpRecords(), include record TTL in output
-
-Revision 1.163 2007/07/16 20:10:11 vazquez
-<rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite
-Added SSDP port number
-
-Revision 1.162 2007/07/10 01:59:33 cheshire
-<rdar://problem/3557903> Performance: Core code will not work on platforms with small stacks
-Fixed GetPktLease to use shared m->rec instead of putting LargeCacheRecord on the stack
-
-Revision 1.161 2007/07/06 18:56:26 cheshire
-Check m->NextScheduledNATOp in GetNextScheduledEvent()
-
-Revision 1.160 2007/06/29 00:06:42 vazquez
-<rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes)
-
-Revision 1.159 2007/06/28 21:17:17 cheshire
-Rename "m->nextevent" as more informative "m->NextuDNSEvent"
-
-Revision 1.158 2007/05/25 00:25:43 cheshire
-<rdar://problem/5227737> Need to enhance putRData to output all current known types
-
-Revision 1.157 2007/05/23 00:32:15 cheshire
-Don't treat uDNS responses as an entire RRSet (kDNSRecordTypePacketUniqueMask)
-when received in a truncated UDP response
-
-Revision 1.156 2007/05/15 00:29:00 cheshire
-Print «ZERO ADDRESS» for %#a with a zero mDNSAddr
-
-Revision 1.155 2007/05/07 22:07:47 cheshire
-<rdar://problem/4738025> Enhance GetLargeResourceRecord to decompress more record types
-
-Revision 1.154 2007/05/04 20:19:53 cheshire
-Improve DumpPacket() output
-
-Revision 1.153 2007/05/01 21:46:31 cheshire
-Move GetLLQOptData/GetPktLease from uDNS.c into DNSCommon.c so that dnsextd can use them
-
-Revision 1.152 2007/04/27 19:28:01 cheshire
-Any code that calls StartGetZoneData needs to keep a handle to the structure, so
-it can cancel it if necessary. (First noticed as a crash in Apple Remote Desktop
--- it would start a query and then quickly cancel it, and then when
-StartGetZoneData completed, it had a dangling pointer and crashed.)
-
-Revision 1.151 2007/04/26 13:35:25 cheshire
-Add kDNSType_SOA case in SameRDataBody, and a comment in GetLargeResourceRecord about why this is important
-
-Revision 1.150 2007/04/24 00:17:33 cheshire
-Made LocateLLQOptData guard against packets with bogus numAdditionals value
-
-Revision 1.149 2007/04/23 21:43:00 cheshire
-Remove debugging check
-
-Revision 1.148 2007/04/23 04:55:29 cheshire
-Add some defensive null pointer checks
-
-Revision 1.147 2007/04/22 20:18:10 cheshire
-Add comment about mDNSRandom()
-
-Revision 1.146 2007/04/22 06:02:02 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.145 2007/04/20 21:17:24 cheshire
-For naming consistency, kDNSRecordTypeNegative should be kDNSRecordTypePacketNegative
-
-Revision 1.144 2007/04/19 18:02:43 cheshire
-<rdar://problem/5140504> Unicast DNS response records should tagged with kDNSRecordTypePacketUnique bit
-
-Revision 1.143 2007/04/16 21:53:49 cheshire
-Improve display of negative cache entries
-
-Revision 1.142 2007/04/05 22:55:35 cheshire
-<rdar://problem/5077076> Records are ending up in Lighthouse without expiry information
-
-Revision 1.141 2007/04/04 01:33:11 cheshire
-<rdar://problem/5075200> DNSServiceAddRecord is failing to advertise NULL record
-Overly defensive code was zeroing too much of the AuthRecord structure
-
-Revision 1.140 2007/04/03 19:37:58 cheshire
-Rename mDNSAddrIsv4Private() to more precise mDNSAddrIsRFC1918()
-
-Revision 1.139 2007/04/03 19:18:39 cheshire
-Use mDNSSameIPv4Address (and similar) instead of accessing internal fields directly
-
-Revision 1.138 2007/03/28 21:14:08 cheshire
-The rrclass field of an OPT pseudo-RR holds the sender's UDP payload size
-
-Revision 1.137 2007/03/28 20:59:26 cheshire
-<rdar://problem/4743285> Remove inappropriate use of IsPrivateV4Addr()
-
-Revision 1.136 2007/03/28 15:56:37 cheshire
-<rdar://problem/5085774> Add listing of NAT port mapping and GetAddrInfo requests in SIGINFO output
-
-Revision 1.135 2007/03/28 01:20:05 cheshire
-<rdar://problem/4883206> Improve/create logging for secure browse
-
-Revision 1.134 2007/03/27 23:25:35 cheshire
-Fix error caching SOA records
-(cache entry was size of wire-format packed data, not size of in-memory structure)
-
-Revision 1.133 2007/03/26 22:55:45 cheshire
-Add OPT and TSIG to list of types DNSTypeName() knows about
-
-Revision 1.132 2007/03/22 18:31:48 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.131 2007/03/21 21:55:20 cheshire
-<rdar://problem/5069688> Hostname gets ; or : which are illegal characters
-Error in AppendLabelSuffix() for numbers close to the 32-bit limit
-
-Revision 1.130 2007/03/21 19:23:37 cheshire
-<rdar://problem/5076826> jmDNS advertised garbage that shows up weird in Safari
-Make check less strict so we don't break Bonjour Browser
-
-Revision 1.129 2007/03/21 01:00:45 cheshire
-<rdar://problem/5076826> jmDNS advertised garbage that shows up weird in Safari
-DeconstructServiceName() needs to be more defensive about what it considers legal
-
-Revision 1.128 2007/03/21 00:30:02 cheshire
-<rdar://problem/4789455> Multiple errors in DNameList-related code
-
-Revision 1.127 2007/03/20 17:07:15 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.126 2007/03/10 03:26:44 cheshire
-<rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache
-
-Revision 1.125 2007/03/07 00:08:58 cheshire
-<rdar://problem/4347550> Don't allow hyphens at start of service type
-
-Revision 1.124 2007/01/19 18:04:05 cheshire
-For naming consistency, use capital letters for RR types: rdataOpt should be rdataOPT
-
-Revision 1.123 2007/01/10 22:45:51 cheshire
-Cast static strings to "(const domainname*)", not "(domainname*)"
-
-Revision 1.122 2007/01/06 00:47:35 cheshire
-Improve GetRRDisplayString to indicate when record has zero-length rdata
-
-Revision 1.121 2007/01/05 08:30:39 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.120 2007/01/05 05:23:00 cheshire
-Zero DNSQuestion structure in getQuestion (specifically, need TargetQID to be zero'd)
-
-Revision 1.119 2007/01/05 04:30:16 cheshire
-Change a couple of "(domainname *)" casts to "(const domainname *)"
-
-Revision 1.118 2007/01/04 20:21:59 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-Don't return multicast answers in response to unicast questions
-
-Revision 1.117 2006/12/22 20:59:49 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.116 2006/12/21 00:04:07 cheshire
-To be defensive, put a mDNSPlatformMemZero() at the start of mDNS_SetupResourceRecord()
-
-Revision 1.115 2006/12/20 04:07:34 cheshire
-Remove uDNS_info substructure from AuthRecord_struct
-
-Revision 1.114 2006/12/19 22:40:04 cheshire
-Fix compiler warnings
-
-Revision 1.113 2006/12/19 02:21:08 cheshire
-Delete spurious spaces
-
-Revision 1.112 2006/12/15 20:42:10 cheshire
-<rdar://problem/4769083> ValidateRData() should be stricter about malformed MX and SRV records
-Additional defensive coding in GetLargeResourceRecord() to reject apparently-valid
-rdata that actually runs past the end of the received packet data.
-
-Revision 1.111 2006/12/15 19:09:57 cheshire
-<rdar://problem/4769083> ValidateRData() should be stricter about malformed MX and SRV records
-Made DomainNameLength() more defensive by adding a limit parameter, so it can be
-safely used to inspect potentially malformed data received from external sources.
-Without this, a domain name that starts off apparently valid, but extends beyond the end of
-the received packet data, could have appeared valid if the random bytes are already in memory
-beyond the end of the packet just happened to have reasonable values (e.g. all zeroes).
-
-Revision 1.110 2006/11/18 05:01:30 cheshire
-Preliminary support for unifying the uDNS and mDNS code,
-including caching of uDNS answers
-
-Revision 1.109 2006/11/10 00:54:14 cheshire
-<rdar://problem/4816598> Changing case of Computer Name doesn't work
-
-Revision 1.108 2006/10/05 23:11:18 cheshire
-<rdar://problem/4769083> ValidateRData() should be stricter about malformed MX and SRV records
-
-Revision 1.107 2006/09/15 21:20:14 cheshire
-Remove uDNS_info substructure from mDNS_struct
-
-Revision 1.106 2006/08/14 23:24:22 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.105 2006/07/15 02:01:28 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Fix broken "empty string" browsing
-
-Revision 1.104 2006/07/05 23:09:13 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Update mDNSSendDNSMessage() to use uDNS_TCPSocket type instead of "int"
-
-Revision 1.103 2006/06/29 07:42:14 cheshire
-<rdar://problem/3922989> Performance: Remove unnecessary SameDomainName() checks
-
-Revision 1.102 2006/06/22 19:49:11 cheshire
-Added (commented out) definitions for the LLMNR UDP port and multicast addresses
-
-Revision 1.101 2006/06/15 21:35:15 cheshire
-Move definitions of mDNS_vsnprintf, mDNS_SetupResourceRecord, and some constants
-from mDNS.c to DNSCommon.c, so they can be accessed from dnsextd code
-
-Revision 1.100 2006/06/08 22:58:46 cheshire
-<rdar://problem/4335605> IPv6 link-local address prefix is FE80::/10, not FE80::/16
-
-Revision 1.99 2006/05/18 01:32:33 cheshire
-<rdar://problem/4472706> iChat: Lost connection with Bonjour
-(mDNSResponder insufficiently defensive against malformed browsing PTR responses)
-
-Revision 1.98 2006/03/19 17:00:58 cheshire
-Define symbol MaxMsg instead of using hard-coded constant value '80'
-
-Revision 1.97 2006/03/18 21:47:56 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.96 2006/03/10 21:51:42 cheshire
-<rdar://problem/4111464> After record update, old record sometimes remains in cache
-Split out SameRDataBody() into a separate routine so it can be called from other code
-
-Revision 1.95 2006/03/08 22:43:11 cheshire
-Use "localdomain" symbol instead of literal string
-
-Revision 1.94 2006/03/02 21:59:55 cheshire
-<rdar://problem/4395331> Spurious warning "GetLargeResourceRecord: m->rec appears to be already in use"
-Improve sanity checks & debugging support in GetLargeResourceRecord()
-
-Revision 1.93 2006/03/02 20:30:47 cheshire
-Improved GetRRDisplayString to also show priority, weight, and port for SRV records
-
-*/
+ */
// Set mDNS_InstantiateInlines to tell mDNSEmbeddedAPI.h to instantiate inline functions, if necessary
#define mDNS_InstantiateInlines 1
#pragma mark - Program Constants
#endif
-mDNSexport const mDNSIPPort zeroIPPort = { { 0 } };
-mDNSexport const mDNSv4Addr zerov4Addr = { { 0 } };
-mDNSexport const mDNSv6Addr zerov6Addr = { { 0 } };
-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 mDNSInterfaceMark = (mDNSInterfaceID)-1;
+mDNSexport const mDNSInterfaceID mDNSInterfaceMark = (mDNSInterfaceID)-1;
mDNSexport const mDNSInterfaceID mDNSInterface_LocalOnly = (mDNSInterfaceID)-2;
mDNSexport const mDNSInterfaceID mDNSInterface_Unicast = (mDNSInterfaceID)-3;
+mDNSexport const mDNSInterfaceID mDNSInterface_P2P = (mDNSInterfaceID)-4;
// Note: Microsoft's proposed "Link Local Multicast Name Resolution Protocol" (LLMNR) is essentially a limited version of
// Multicast DNS, using the same packet formats, naming syntax, and record types as Multicast DNS, but on a different UDP
mDNSexport const mDNSIPPort LoopbackIPCPort = { { LoopbackIPCPortAsNumber >> 8, LoopbackIPCPortAsNumber & 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 OwnerOptData zeroOwner = { 0, 0, { { 0 } }, { { 0 } }, { { 0 } } };
+
+mDNSexport const mDNSIPPort zeroIPPort = { { 0 } };
+mDNSexport const mDNSv4Addr zerov4Addr = { { 0 } };
+mDNSexport const mDNSv6Addr zerov6Addr = { { 0 } };
+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 mDNSEthAddr onesEthAddr = { { 255, 255, 255, 255, 255, 255 } };
+mDNSexport const mDNSAddr zeroAddr = { mDNSAddrType_None, {{{ 0 }}} };
+
+mDNSexport const mDNSv4Addr AllDNSAdminGroup = { { 239, 255, 255, 251 } };
+mDNSexport const mDNSv4Addr AllHosts_v4 = { { 224, 0, 0, 1 } }; // For NAT-PMP Annoucements
+mDNSexport const mDNSv6Addr AllHosts_v6 = { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01 } };
+mDNSexport const mDNSv6Addr NDP_prefix = { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01, 0xFF,0x00,0x00,0xFB } }; // FF02:0:0:0:0:1:FF00::/104
+mDNSexport const mDNSEthAddr AllHosts_v6_Eth = { { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 } };
+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 } };
break;
case kDNSType_NSEC: {
- int i;
+ mDNSu16 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));
src = type->c; // Put the service type into the domain name
len = *src;
- if (len < 2 || len > 15)
+ if (len < 2 || len > 16)
{
- LogMsg("Bad service type in %#s.%##s%##s Application protocol name must be underscore plus 1-14 characters. "
+ LogMsg("Bad service type in %#s.%##s%##s Application protocol name must be underscore plus 1-15 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 (len < 2 || len >= 0x40 || (len > 16 && !SameDomainName(domain, &localdomain))) return(mDNSNULL);
if (src[1] != '_') { errormsg = "Application protocol name must begin with underscore"; goto fail; }
for (i=2; i<=len; i++)
{
rr->resrec.rrtype = rrtype;
rr->resrec.rrclass = kDNSClass_IN;
rr->resrec.rroriginalttl = ttl;
+ rr->resrec.rDNSServer = mDNSNULL;
// rr->resrec.rdlength = MUST set by client and/or in mDNS_Register_internal
// rr->resrec.rdestimate = set in mDNS_Register_internal
// rr->resrec.rdata = MUST be set by client
rr->Private = 0;
rr->updateid = zeroID;
rr->zone = rr->resrec.name;
- rr->UpdateServer = zeroAddr;
- rr->UpdatePort = zeroIPPort;
rr->nta = mDNSNULL;
rr->tcp = mDNSNULL;
rr->OrigRData = 0;
rr->InFlightRDLen = 0;
rr->QueuedRData = 0;
rr->QueuedRDLen = 0;
+ mDNSPlatformMemZero(&rr->NATinfo, sizeof(rr->NATinfo));
+ rr->SRVChanged = mDNSfalse;
+ rr->mState = mergeState_Zero;
rr->namestorage.c[0] = 0; // MUST be set by client before calling mDNS_Register()
}
q->ExpectUnique = (qtype != kDNSType_PTR);
q->ForceMCast = mDNSfalse;
q->ReturnIntermed = mDNSfalse;
+ q->SuppressUnusable = mDNSfalse;
q->QuestionCallback = callback;
q->QuestionContext = context;
}
// r1 has to be a full ResourceRecord including rrtype and rdlength
// 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)
+mDNSexport mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2, DomainNameComparisonFn *samename)
{
const RDataBody2 *const b1 = (RDataBody2 *)r1->rdata->u.data;
const RDataBody2 *const b2 = (RDataBody2 *)r2;
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));
+ samename(&b1->soa.mname, &b2->soa.mname) &&
+ samename(&b1->soa.rname, &b2->soa.rname));
case kDNSType_MX:
case kDNSType_AFSDB:
case kDNSType_RT:
case kDNSType_KX: return(mDNSBool)( b1->mx.preference == b2->mx.preference &&
- SameDomainName(&b1->mx.exchange, &b2->mx.exchange));
+ samename(&b1->mx.exchange, &b2->mx.exchange));
- case kDNSType_RP: return(mDNSBool)( SameDomainName(&b1->rp.mbox, &b2->rp.mbox) &&
- SameDomainName(&b1->rp.txt, &b2->rp.txt));
+ case kDNSType_RP: return(mDNSBool)( samename(&b1->rp.mbox, &b2->rp.mbox) &&
+ samename(&b1->rp.txt, &b2->rp.txt));
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));
+ samename(&b1->px.map822, &b2->px.map822) &&
+ samename(&b1->px.mapx400, &b2->px.mapx400));
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));
+ samename(&b1->srv.target, &b2->srv.target));
case kDNSType_OPT: return mDNSfalse; // OPT is a pseudo-RR container structure; makes no sense to compare
q ->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly &&
rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
+ // Resource record received via unicast, the DNSServer entries should match ?
+ if (!rr->InterfaceID && rr->rDNSServer != q->qDNSServer) 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);
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
+ // Resource record received via unicast, the DNSServer entries should match ?
+ if (!rr->InterfaceID && rr->rDNSServer != q->qDNSServer) return(mDNSfalse);
+
+ // If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question.
+ // This also covers the case where the ResourceRecord is mDNSInterface_LocalOnly and the question is expecting a unicast
+ // DNS response. We don't want a local process to be able to create a fake LocalOnly address record for "www.bigbank.com"
+ // which would then cause other applications (e.g. Safari) to connect to the wrong address. If we decide to support this later,
+ // the restrictions need to be at least as strict as the restrictions on who can edit /etc/hosts and put fake addresses there.
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.
q ->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly &&
rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
+ // Resource record received via unicast, the DNSServer entries should match ?
+ // Note that Auth Records are normally setup with NULL InterfaceID and
+ // both the DNSServers are assumed to be NULL in that case
+ if (!rr->InterfaceID && rr->rDNSServer != q->qDNSServer) 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);
return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
}
+// This is called only when the caller knows that it is a Unicast Resource Record and it is a Unicast Question
+// and hence we don't need InterfaceID checks like above. Though this may not be a big optimization, the main
+// reason we need this is that we can't compare DNSServers between the question and the resource record because
+// the resource record may not be completely initialized e.g., mDNSCoreReceiveResponse
+mDNSexport mDNSBool UnicastResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
+ {
+ // RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
+ 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 mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate)
{
const RDataBody2 *const rd = (RDataBody2 *)rr->rdata->u.data;
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);
+ // and if we have at least one record type that exists,
+ // - 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(mDNSu16)((estimate ? 2 : DomainNameLength(rr->name)) + (i ? (2 + i) : 0));
}
default: debugf("Warning! Don't know how to get length of resource type %d", rr->rrtype);
{
const int space = DNSOpt_Data_Space(opt);
ptr = putVal16(ptr, opt->opt);
- ptr = putVal16(ptr, space - 4);
+ ptr = putVal16(ptr, (mDNSu16)space - 4);
switch (opt->opt)
{
case kDNSOpt_LLQ:
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];
+ if (i) // Only put a block if at least one type exists for this name
+ {
+ if (ptr + 2 + i > limit) return(mDNSNULL);
+ *ptr++ = 0;
+ *ptr++ = (mDNSu8)i;
+ for (j=0; j<i; j++) *ptr++ = rdb->nsec.bitmap[j];
+ }
return ptr;
}
ptr[5] = (mDNSu8)((ttl >> 16) & 0xFF);
ptr[6] = (mDNSu8)((ttl >> 8) & 0xFF);
ptr[7] = (mDNSu8)( ttl & 0xFF);
+ // ptr[8] and ptr[9] filled in *after* we find out how much space the rdata takes
+
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); }
return ptr;
}
-mDNSexport mDNSu8 *putDeleteRRSet(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype)
+// for dynamic updates
+mDNSexport mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit)
+ {
+ // deletion: specify record w/ TTL 0, class NONE
+ const mDNSu16 origclass = rr->rrclass;
+ rr->rrclass = kDNSClass_NONE;
+ ptr = PutResourceRecordTTLWithLimit(msg, ptr, &msg->h.mDNS_numUpdates, rr, 0, limit);
+ rr->rrclass = origclass;
+ return ptr;
+ }
+
+mDNSexport mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit)
{
- const mDNSu8 *limit = msg->data + AbsoluteMaxDNSMessageData;
mDNSu16 class = kDNSQClass_ANY;
ptr = putDomainNameAsLabels(msg, ptr, limit, name);
return end;
}
-mDNSexport mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *end, DomainAuthInfo *authInfo)
+// for dynamic updates
+mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease, mDNSu8 *limit)
+ {
+ AuthRecord rr;
+ mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
+ rr.resrec.rrclass = NormalMaxDNSMessageData;
+ 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 = PutResourceRecordTTLWithLimit(msg, end, &msg->h.numAdditionals, &rr.resrec, 0, limit);
+ if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTLWithLimit"); return mDNSNULL; }
+ return end;
+ }
+
+mDNSexport mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *end, DomainAuthInfo *authInfo, mDNSu8 *limit)
{
if (authInfo && authInfo->AutoTunnel)
{
mDNSPlatformMemCopy(h, &m->HISoftware, 1 + (mDNSu32)m->HISoftware.c[0]);
hinfo.resrec.rdlength = len;
hinfo.resrec.rdestimate = len;
- newptr = PutResourceRecord(msg, end, &msg->h.numAdditionals, &hinfo.resrec);
+ newptr = PutResourceRecordTTLWithLimit(msg, end, &msg->h.numAdditionals, &hinfo.resrec, 0, limit);
return newptr;
}
else
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 *const largecr)
{
rr->NextInKAList = mDNSNULL;
rr->TimeRcvd = m ? m->timenow : 0;
rr->DelayDelivery = 0;
- rr->NextRequiredQuery = m ? m->timenow : 0; // Will be updated to the real value when we call SetNextCacheCheckTime()
+ rr->NextRequiredQuery = m ? m->timenow : 0; // Will be updated to the real value when we call SetNextCacheCheckTimeForRecord()
rr->LastUsed = m ? m->timenow : 0;
rr->CRActiveQuestion = mDNSNULL;
rr->UnansweredQueries = 0;
rr->NextInCFList = mDNSNULL;
rr->resrec.InterfaceID = InterfaceID;
- ptr = getDomainName(msg, ptr, end, &largecr->namestorage);
+ rr->resrec.rDNSServer = mDNSNULL;
+
+ ptr = getDomainName(msg, ptr, end, &largecr->namestorage); // Will bail out correctly if ptr is NULL
if (!ptr) { debugf("GetLargeResourceRecord: Malformed RR name"); return(mDNSNULL); }
+ rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
if (ptr + 10 > end) { debugf("GetLargeResourceRecord: Malformed RR -- no type/class/ttl/len!"); return(mDNSNULL); }
rr->resrec.rdlength = 0;
else switch (rr->resrec.rrtype)
{
- case kDNSType_A: if (pktrdlength != sizeof(mDNSv4Addr)) return(mDNSNULL);
+ case kDNSType_A: if (pktrdlength != sizeof(mDNSv4Addr)) goto fail;
rdb->ipv4.b[0] = ptr[0];
rdb->ipv4.b[1] = ptr[1];
rdb->ipv4.b[2] = ptr[2];
case kDNSType_CNAME:
case kDNSType_PTR:
case kDNSType_DNAME:ptr = getDomainName(msg, ptr, end, &rdb->name);
- if (ptr != end) { debugf("GetLargeResourceRecord: Malformed CNAME/PTR RDATA name"); return(mDNSNULL); }
+ if (ptr != end) { debugf("GetLargeResourceRecord: Malformed CNAME/PTR RDATA name"); goto fail; }
//debugf("%##s PTR %##s rdlen %d", rr->resrec.name.c, rdb->name.c, pktrdlength);
break;
case kDNSType_SOA: ptr = getDomainName(msg, ptr, end, &rdb->soa.mname);
- if (!ptr) { debugf("GetLargeResourceRecord: Malformed SOA RDATA mname"); return mDNSNULL; }
+ if (!ptr) { debugf("GetLargeResourceRecord: Malformed SOA RDATA mname"); goto fail; }
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; }
- 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;
+ if (!ptr) { debugf("GetLargeResourceRecord: Malformed SOA RDATA rname"); goto fail; }
+ if (ptr + 0x14 != end) { debugf("GetLargeResourceRecord: Malformed SOA RDATA"); goto fail; }
+ 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:
case kDNSType_HINFO:
{
debugf("GetLargeResourceRecord: %s rdata size (%d) exceeds storage (%d)",
DNSTypeName(rr->resrec.rrtype), pktrdlength, rr->resrec.rdata->MaxRDLength);
- return(mDNSNULL);
+ goto fail;
}
rr->resrec.rdlength = pktrdlength;
mDNSPlatformMemCopy(rdb->data, ptr, pktrdlength);
case kDNSType_MX:
case kDNSType_AFSDB:
case kDNSType_RT:
- case kDNSType_KX: if (pktrdlength < 3) return(mDNSNULL); // Preference + domainname
+ case kDNSType_KX: if (pktrdlength < 3) goto fail; // Preference + domainname
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); }
+ if (ptr != end) { debugf("GetLargeResourceRecord: Malformed MX name"); goto fail; }
//debugf("%##s SRV %##s rdlen %d", rr->resrec.name.c, rdb->srv.target.c, pktrdlength);
break;
case kDNSType_RP: ptr = getDomainName(msg, ptr, end, &rdb->rp.mbox); // Domainname + domainname
- if (!ptr) { debugf("GetLargeResourceRecord: Malformed RP mbox"); return mDNSNULL; }
+ if (!ptr) { debugf("GetLargeResourceRecord: Malformed RP mbox"); goto fail; }
ptr = getDomainName(msg, ptr, end, &rdb->rp.txt);
- if (ptr != end) { debugf("GetLargeResourceRecord: Malformed RP txt"); return mDNSNULL; }
+ if (ptr != end) { debugf("GetLargeResourceRecord: Malformed RP txt"); goto fail; }
break;
- case kDNSType_PX: if (pktrdlength < 4) return(mDNSNULL); // Preference + domainname + domainname
+ case kDNSType_PX: if (pktrdlength < 4) goto fail; // Preference + domainname + domainname
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; }
+ if (!ptr) { debugf("GetLargeResourceRecord: Malformed PX map822"); goto fail; }
ptr = getDomainName(msg, ptr, end, &rdb->px.mapx400);
- if (ptr != end) { debugf("GetLargeResourceRecord: Malformed PX mapx400"); return mDNSNULL; }
+ if (ptr != end) { debugf("GetLargeResourceRecord: Malformed PX mapx400"); goto fail; }
break;
- case kDNSType_AAAA: if (pktrdlength != sizeof(mDNSv6Addr)) return(mDNSNULL);
+ case kDNSType_AAAA: if (pktrdlength != sizeof(mDNSv6Addr)) goto fail;
mDNSPlatformMemCopy(&rdb->ipv6, ptr, sizeof(rdb->ipv6));
break;
- case kDNSType_SRV: if (pktrdlength < 7) return(mDNSNULL); // Priority + weight + port + domainname
+ case kDNSType_SRV: if (pktrdlength < 7) goto fail; // Priority + weight + port + domainname
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); }
+ if (ptr != end) { debugf("GetLargeResourceRecord: Malformed SRV RDATA name"); goto fail; }
//debugf("%##s SRV %##s rdlen %d", rr->resrec.name.c, rdb->srv.target.c, pktrdlength);
break;
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)
+ const rdataOPT *const currentopt = opt;
+ if (ptr + 4 > end) { LogInfo("GetLargeResourceRecord: OPT RDATA ptr + 4 > end"); goto fail; }
+ opt->opt = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]);
+ opt->optlen = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]);
+ ptr += 4;
+ if (ptr + opt->optlen > end) { LogInfo("GetLargeResourceRecord: ptr + opt->optlen > end"); goto fail; }
+ 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);
+ if (opt->optlen == DNSOpt_LLQData_Space - 4)
+ {
+ opt->u.llq.vers = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]);
+ opt->u.llq.llqOp = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]);
+ opt->u.llq.err = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]);
+ mDNSPlatformMemCopy(opt->u.llq.id.b, ptr+6, 8);
+ opt->u.llq.llqlease = (mDNSu32) ((mDNSu32)ptr[14] << 24 | (mDNSu32)ptr[15] << 16 | (mDNSu32)ptr[16] << 8 | ptr[17]);
+ if (opt->u.llq.llqlease > 0x70000000UL / mDNSPlatformOneSecond)
+ opt->u.llq.llqlease = 0x70000000UL / mDNSPlatformOneSecond;
+ opt++;
+ }
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);
+ if (opt->optlen == DNSOpt_LeaseData_Space - 4)
+ {
+ 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;
+ opt++;
+ }
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)
+ if (ValidOwnerLength(opt->optlen))
{
- 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));
+ 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
+ // This mDNSPlatformMemCopy is safe because the ValidOwnerLength(opt->optlen) check above
+ // ensures that opt->optlen is no more than DNSOpt_OwnerData_ID_Wake_PW6_Space - 4
+ 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));
+ }
+ opt++;
}
- ptr += opt->optlen;
break;
}
- opt++; // increment pointer into rdatabody
+ ptr += currentopt->optlen;
}
- rr->resrec.rdlength = (mDNSu8*)opt - rr->resrec.rdata->u.data;
- if (ptr != end) { LogMsg("GetLargeResourceRecord: Malformed OptRdata"); return(mDNSNULL); }
+ rr->resrec.rdlength = (mDNSu16)((mDNSu8*)opt - rr->resrec.rdata->u.data);
+ if (ptr != end) { LogInfo("GetLargeResourceRecord: Malformed OptRdata"); goto fail; }
break;
}
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; }
+ if (!ptr) { LogInfo("GetLargeResourceRecord: Malformed NSEC nextname"); goto fail; }
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); }
+ if (ptr < end)
+ {
+ if (*ptr++ != 0) { debugf("GetLargeResourceRecord: We only handle block zero NSECs"); goto fail; }
+ i = *ptr++;
+ if (i > sizeof(rdataNSEC)) { debugf("GetLargeResourceRecord: invalid block length %d", i); goto fail; }
+ for (j=0; j<i; j++) rdb->nsec.bitmap[j] = *ptr++;
+ }
+ if (ptr != end) { debugf("GetLargeResourceRecord: Malformed NSEC"); goto fail; }
break;
}
{
debugf("GetLargeResourceRecord: rdata %d (%s) size (%d) exceeds storage (%d)",
rr->resrec.rrtype, DNSTypeName(rr->resrec.rrtype), pktrdlength, rr->resrec.rdata->MaxRDLength);
- return(mDNSNULL);
+ goto fail;
}
debugf("GetLargeResourceRecord: Warning! Reading resource type %d (%s) as opaque data",
rr->resrec.rrtype, DNSTypeName(rr->resrec.rrtype));
break;
}
- rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rdlength, rdestimate, rdatahash for us
// Success! Now fill in RecordType to show this record contains valid data
rr->resrec.RecordType = RecordType;
return(end);
+
+fail:
+ // If we were unable to parse the rdata in this record, we indicate that by
+ // returing a 'kDNSRecordTypePacketNegative' record with rdlength set to zero
+ rr->resrec.RecordType = kDNSRecordTypePacketNegative;
+ rr->resrec.rdlength = 0;
+ rr->resrec.rdestimate = 0;
+ rr->resrec.rdatahash = 0;
+ return(end);
}
mDNSexport const mDNSu8 *skipQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end)
if (ptr)
{
ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
- if (ptr) return(&m->rec.r.resrec.rdata->u.opt[0]);
+ if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative) return(&m->rec.r.resrec.rdata->u.opt[0]);
}
return(mDNSNULL);
}
mStatus status = mStatus_NoError;
const mDNSu16 numAdditionals = msg->h.numAdditionals;
mDNSu8 *newend;
+ mDNSu8 *limit = 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)
return mStatus_BadParamErr;
}
- newend = putHINFO(m, msg, end, authInfo);
- if (!newend) LogMsg("mDNSSendDNSMessage: putHINFO failed"); // Not fatal
+ newend = putHINFO(m, msg, end, authInfo, limit);
+ if (!newend) LogMsg("mDNSSendDNSMessage: putHINFO failed msg %p end %p, limit %p", msg->data, end, limit); // Not fatal
else end = newend;
// Put all the integer values in IETF byte-order (MSB first, LSB second)
#pragma mark - RR List Management & Task Management
#endif
-mDNSexport void mDNS_Lock_(mDNS *const m)
+mDNSexport void mDNS_Lock_(mDNS *const m, const char * const functionname)
{
// MUST grab the platform lock FIRST!
mDNSPlatformLock(m);
// However, when we call a client callback mDNS_busy is one, and we increment mDNS_reentrancy too
// If that client callback does mDNS API calls, mDNS_reentrancy and mDNS_busy will both be one
// If mDNS_busy != mDNS_reentrancy that's a bad sign
-#if ForceAlerts
if (m->mDNS_busy != m->mDNS_reentrancy)
{
- LogMsg("mDNS_Lock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
+ LogMsg("%s: mDNS_Lock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy);
+#if ForceAlerts
*(long*)0 = 0;
- }
#endif
+ }
// If this is an initial entry into the mDNSCore code, set m->timenow
// else, if this is a re-entrant entry into the mDNSCore code, m->timenow should already be set
if (m->mDNS_busy == 0)
{
if (m->timenow)
- LogMsg("mDNS_Lock: m->timenow already set (%ld/%ld)", m->timenow, mDNS_TimeNow_NoLock(m));
+ LogMsg("%s: mDNS_Lock: m->timenow already set (%ld/%ld)", functionname, m->timenow, mDNS_TimeNow_NoLock(m));
m->timenow = mDNS_TimeNow_NoLock(m);
if (m->timenow == 0) m->timenow = 1;
}
else if (m->timenow == 0)
{
- LogMsg("mDNS_Lock: m->mDNS_busy is %ld but m->timenow not set", m->mDNS_busy);
+ LogMsg("%s: mDNS_Lock: m->mDNS_busy is %ld but m->timenow not set", functionname, m->mDNS_busy);
m->timenow = mDNS_TimeNow_NoLock(m);
if (m->timenow == 0) m->timenow = 1;
}
if (m->timenow_last - m->timenow > 0)
{
m->timenow_adjust += m->timenow_last - m->timenow;
- LogMsg("mDNSPlatformRawTime went backwards by %ld ticks; setting correction factor to %ld", m->timenow_last - m->timenow, m->timenow_adjust);
+ LogMsg("%s: mDNSPlatformRawTime went backwards by %ld ticks; setting correction factor to %ld", functionname, m->timenow_last - m->timenow, m->timenow_adjust);
m->timenow = m->timenow_last;
}
m->timenow_last = m->timenow;
m->mDNS_busy++;
}
+mDNSlocal AuthRecord *AnyLocalRecordReady(const mDNS *const m)
+ {
+ AuthRecord *rr;
+ for (rr = m->NewLocalRecords; rr; rr = rr->next)
+ if (LocalRecordReady(rr)) return rr;
+ return mDNSNULL;
+ }
+
mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
{
mDNSs32 e = m->timenow + 0x78000000;
if (m->NewQuestions->DelayAnswering) e = m->NewQuestions->DelayAnswering;
else return(m->timenow);
}
- if (m->NewLocalOnlyQuestions) return(m->timenow);
- if (m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords)) return(m->timenow);
- if (m->SPSProxyListChanged) return(m->timenow);
+ if (m->NewLocalOnlyQuestions) return(m->timenow);
+ if (m->NewLocalRecords && AnyLocalRecordReady(m)) return(m->timenow);
+ if (m->SPSProxyListChanged) return(m->timenow);
+ if (m->LocalRemoveEvents) return(m->timenow);
+
#ifndef UNICAST_DISABLED
if (e - m->NextuDNSEvent > 0) e = m->NextuDNSEvent;
if (e - m->NextScheduledNATOp > 0) e = m->NextScheduledNATOp;
+ if (m->NextSRVUpdate && e - m->NextSRVUpdate > 0) e = m->NextSRVUpdate;
#endif
+
if (e - m->NextCacheCheck > 0) e = m->NextCacheCheck;
if (e - m->NextScheduledSPS > 0) e = m->NextScheduledSPS;
// NextScheduledSPRetry only valid when DelaySleep not set
if (!m->DelaySleep && m->SleepLimit && e - m->NextScheduledSPRetry > 0) e = m->NextScheduledSPRetry;
- if (m->DelaySleep && e - m->DelaySleep > 0) e = m->DelaySleep;
+ if (m->DelaySleep && e - m->DelaySleep > 0) e = m->DelaySleep;
if (m->SuppressSending)
{
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->NewLocalRecords)
+ {
+ AuthRecord *rr = AnyLocalRecordReady(m);
+ if (rr) LogMsg("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, rr));
+ }
+
+ if (m->SPSProxyListChanged) LogMsg("Task Scheduling Error: SPSProxyListChanged");
+ if (m->LocalRemoveEvents) LogMsg("Task Scheduling Error: LocalRemoveEvents");
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);
+
+#ifndef UNICAST_DISABLED
+ if (m->timenow - m->NextuDNSEvent >= 0)
+ LogMsg("Task Scheduling Error: m->NextuDNSEvent %d", m->timenow - m->NextuDNSEvent);
if (m->timenow - m->NextScheduledNATOp >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledNATOp %d", m->timenow - m->NextScheduledNATOp);
+ if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0)
+ LogMsg("Task Scheduling Error: m->NextSRVUpdate %d", m->timenow - m->NextSRVUpdate);
+#endif
+
+ if (m->timenow - m->NextCacheCheck >= 0)
+ LogMsg("Task Scheduling Error: m->NextCacheCheck %d", m->timenow - m->NextCacheCheck);
if (m->timenow - m->NextScheduledSPS >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledSPS %d", m->timenow - m->NextScheduledSPS);
if (!m->DelaySleep && 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
+
+ if (m->SuppressSending && m->timenow - m->SuppressSending >= 0)
+ LogMsg("Task Scheduling Error: m->SuppressSending %d", m->timenow - m->SuppressSending);
+ 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);
mDNS_Unlock(m);
}
-mDNSexport void mDNS_Unlock_(mDNS *const m)
+mDNSexport void mDNS_Unlock_(mDNS *const m, const char * const functionname)
{
// Decrement mDNS_busy
m->mDNS_busy--;
// Check for locking failures
-#if ForceAlerts
if (m->mDNS_busy != m->mDNS_reentrancy)
{
- LogMsg("mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
+ LogMsg("%s: mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy);
+#if ForceAlerts
*(long*)0 = 0;
- }
#endif
+ }
// If this is a final exit from the mDNSCore code, set m->NextScheduledEvent and clear m->timenow
if (m->mDNS_busy == 0)
{
m->NextScheduledEvent = GetNextScheduledEvent(m);
- if (m->timenow == 0) LogMsg("mDNS_Unlock: ERROR! m->timenow aready zero");
+ if (m->timenow == 0) LogMsg("%s: mDNS_Unlock: ERROR! m->timenow aready zero", functionname);
m->timenow = 0;
}
break;
case 'p' : F.havePrecision = F.lSize = 1;
- F.precision = 8;
+ F.precision = sizeof(void*) * 2; // 8 characters on 32-bit; 16 characters on 64-bit
case 'X' : digits = "0123456789ABCDEF";
goto hexadecimal;
case 'x' : digits = "0123456789abcdef";
* 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: DNSCommon.h,v $
-svn merge: Revision 1.75 2009/07/21 23:35:01 cheshire
-<rdar://problem/6434656> Sleep Proxy: Put owner OPT records in multicast announcements to avoid conflicts
-Added PutRR_OS macros to put a ResourceRecord while taking into account the space needed to add an OWNER option at the end
-
-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
-
-Revision 1.59 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.58 2008/03/06 21:26:10 cheshire
-Moved duplicated STRINGIFY macro from individual C files to DNSCommon.h
-
-Revision 1.57 2007/12/13 20:20:17 cheshire
-Minor efficiency tweaks -- converted IdenticalResourceRecord, IdenticalSameNameRecord, and
-SameRData from functions to macros, which allows the code to be inlined (the compiler can't
-inline a function defined in a different compilation unit) and therefore optimized better.
-
-Revision 1.56 2007/12/13 00:13:03 cheshire
-Simplified RDataHashValue to take a single ResourceRecord pointer, instead of separate rdlength and RDataBody
-
-Revision 1.55 2007/12/13 00:09:28 cheshire
-For completeness added MX, AFSDB, RT, KX to list of RRTYPES that are considered to have a target domainname in their rdata
-
-Revision 1.54 2007/10/05 17:56:10 cheshire
-Move CountLabels and SkipLeadingLabels to DNSCommon.c so they're callable from other files
-
-Revision 1.53 2007/09/27 17:42:49 cheshire
-Fix naming: for consistency, "kDNSFlag1_RC" should be "kDNSFlag1_RC_Mask"
-
-Revision 1.52 2007/09/26 00:49:46 cheshire
-Improve packet logging to show sent and received packets,
-transport protocol (UDP/TCP/TLS) and source/destination address:port
-
-Revision 1.51 2007/09/21 21:12:36 cheshire
-<rdar://problem/5498009> BTMM: Need to log updates and query packet contents
-
-Revision 1.50 2007/09/20 01:12:06 cheshire
-Moved HashSlot(X) from mDNS.c to DNSCommon.h so it's usable in other files
-
-Revision 1.49 2007/08/30 00:31:20 cheshire
-Improve "locking failure" debugging messages to show function name using __func__ macro
-
-Revision 1.48 2007/05/25 00:25:44 cheshire
-<rdar://problem/5227737> Need to enhance putRData to output all current known types
-
-Revision 1.47 2007/05/01 21:46:31 cheshire
-Move GetLLQOptData/GetPktLease from uDNS.c into DNSCommon.c so that dnsextd can use them
-
-Revision 1.46 2007/04/22 20:18:10 cheshire
-Add comment about mDNSRandom()
-
-Revision 1.45 2007/04/22 06:02:02 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.44 2007/03/28 01:20:05 cheshire
-<rdar://problem/4883206> Improve/create logging for secure browse
-
-Revision 1.43 2007/03/20 17:07:15 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.42 2007/03/10 03:26:44 cheshire
-<rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache
-
-Revision 1.41 2007/01/18 23:18:17 cheshire
-Source code tidying: Delete extraneous white space
-
-Revision 1.40 2007/01/05 08:30:40 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.39 2007/01/04 21:45:20 cheshire
-Added mDNS_DropLockBeforeCallback/mDNS_ReclaimLockAfterCallback macros,
-to do additional lock sanity checking around callback invocations
-
-Revision 1.38 2006/12/22 20:59:49 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.37 2006/08/14 23:24:22 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.36 2006/07/05 22:56:07 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Update mDNSSendDNSMessage() to use uDNS_TCPSocket type instead of "int"
-
-Revision 1.35 2006/06/29 07:42:14 cheshire
-<rdar://problem/3922989> Performance: Remove unnecessary SameDomainName() checks
-
-Revision 1.34 2006/03/18 21:47:56 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.33 2006/03/10 21:51:41 cheshire
-<rdar://problem/4111464> After record update, old record sometimes remains in cache
-Split out SameRDataBody() into a separate routine so it can be called from other code
-
-*/
+ */
#ifndef __DNSCOMMON_H_
#define __DNSCOMMON_H_
extern mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max);
extern mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText);
extern mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText);
-extern void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichText);
+extern void AppendLabelSuffix(domainlabel *const name, mDNSu32 val, const mDNSBool RichText);
#define ValidateDomainName(N) (DomainNameLength(N) <= MAX_DOMAIN_NAME)
// ***************************************************************************
(r1)->namehash == (r2)->namehash && \
(r1)->rdlength == (r2)->rdlength && \
(r1)->rdatahash == (r2)->rdatahash && \
- SameRDataBody((r1), &(r2)->rdata->u) && \
+ SameRDataBody((r1), &(r2)->rdata->u, SameDomainName) && \
SameDomainName((r1)->name, (r2)->name))
#define IdenticalSameNameRecord(r1,r2) ( \
(r1)->rrclass == (r2)->rrclass && \
(r1)->rdlength == (r2)->rdlength && \
(r1)->rdatahash == (r2)->rdatahash && \
- SameRDataBody((r1), &(r2)->rdata->u))
+ SameRDataBody((r1), &(r2)->rdata->u, SameDomainName))
// 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 RRTypeAnswersQuestionType(R,Q) ((R)->rrtype == kDNSType_CNAME || (R)->rrtype == (Q) || (Q) == kDNSQType_ANY || RRAssertsNonexistence((R),(Q)))
#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);
+extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2, DomainNameComparisonFn *samename);
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 mDNSBool UnicastResourceRecordAnswersQuestion(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);
((RR)->rrtype == kDNSType_MX || (RR)->rrtype == kDNSType_AFSDB || (RR)->rrtype == kDNSType_RT || (RR)->rrtype == kDNSType_KX ) ? &(RR)->rdata->u.mx.exchange : \
((RR)->rrtype == kDNSType_SRV ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
-#define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique && (X)->resrec.RecordType != kDNSRecordTypeDeregistering)
+#define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique)
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
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);
-extern mDNSu8 *putPrereqNameNotInUse(const domainname *const name, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *end);
+extern mDNSu8 *putPrereqNameNotInUse(const domainname *const name, DNSMessage *const msg, mDNSu8 *const ptr, mDNSu8 *const end);
extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr);
-extern mDNSu8 *putDeleteRRSet(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype);
+extern mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit);
+extern mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit);
extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name);
extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease);
+extern mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit);
-extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *end, DomainAuthInfo *authInfo);
+extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *ptr, DomainAuthInfo *authInfo, mDNSu8 *limit);
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
domainname *const name);
extern const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
extern 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);
extern const mDNSu8 *skipQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
extern const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end, const mDNSInterfaceID InterfaceID,
DNSQuestion *question);
#endif
extern void ShowTaskSchedulingError(mDNS *const m);
-extern void mDNS_Lock_(mDNS *const m);
-extern void mDNS_Unlock_(mDNS *const m);
+extern void mDNS_Lock_(mDNS *const m, const char * const functionname);
+extern void mDNS_Unlock_(mDNS *const m, const char * const functionname);
#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)
+#define mDNS_Lock(X) mDNS_Lock_((X), __func__)
-#define mDNS_Unlock(X) do { mDNS_Unlock_(X); \
- if ((X)->mDNS_busy != (X)->mDNS_reentrancy) LogMsg("%s: mDNS_Unlock locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy); \
- } while (0)
+#define mDNS_Unlock(X) mDNS_Unlock_((X), __func__)
#define mDNS_DropLockBeforeCallback() do { m->mDNS_reentrancy++; \
if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \
* 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: 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
-
-Revision 1.24 2007/11/30 23:03:51 cheshire
-Fixes for EFI: Use "mDNSPlatformMemCopy" instead of assuming existence of "memcpy"
-
-Revision 1.23 2007/09/21 21:12:36 cheshire
-DNSDigest_SignMessage does not need separate "mDNSu16 *numAdditionals" parameter
-
-Revision 1.22 2007/04/22 06:02:02 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.21 2007/03/22 18:31:48 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.20 2006/12/22 20:59:49 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.19 2006/12/21 00:06:07 cheshire
-Don't need to do mDNSPlatformMemZero() -- mDNS_SetupResourceRecord() does it for us
-
-Revision 1.18 2006/12/19 22:41:21 cheshire
-Fix compiler warnings
-
-Revision 1.17 2006/08/14 23:24:22 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.16 2006/07/05 23:05:15 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-Add DNSDigest_VerifyMessage() function
-
-Revision 1.15 2006/06/20 04:12:30 cheshire
-<rdar://problem/4490961> DNS Update broken
-
-Revision 1.14 2006/02/25 23:12:07 cheshire
-<rdar://problem/4427969> Fix to avoid code generation warning/error on FreeBSD 7
-
-Revision 1.13 2004/12/16 20:12:59 cheshire
-<rdar://problem/3324626> Cache memory management improvements
-
-Revision 1.12 2004/12/03 07:20:50 ksekar
-<rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
-
-Revision 1.11 2004/12/02 01:10:27 cheshire
-Fix to compile cleanly on 64-bit x86
-
-Revision 1.10 2004/11/01 20:36:04 ksekar
-<rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
-
-Revision 1.9 2004/10/26 09:00:12 cheshire
-Save a few bytes by creating HMAC_MD5_AlgName as a C string instead of a 256-byte object
-
-Revision 1.8 2004/09/17 01:08:48 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.7 2004/08/15 18:36:38 cheshire
-Don't use strcpy() and strlen() on "struct domainname" objects;
-use AssignDomainName() and DomainNameLength() instead
-(A "struct domainname" is a collection of packed pascal strings, not a C string.)
-
-Revision 1.6 2004/06/02 00:17:46 ksekar
-Referenced original OpenSSL license headers in source file description.
-
-Revision 1.5 2004/05/20 18:37:37 cheshire
-Fix compiler warnings
-
-Revision 1.4 2004/04/22 20:28:20 cheshire
-Use existing facility of PutResourceRecordTTL() to update count field for us
-
-Revision 1.3 2004/04/22 03:05:28 cheshire
-kDNSClass_ANY should be kDNSQClass_ANY
-
-Revision 1.2 2004/04/15 00:51:28 bradley
-Minor tweaks for Windows and C++ builds. Added casts for signed/unsigned integers and 64-bit pointers.
-Prefix some functions with mDNS to avoid conflicts. Disable benign warnings on Microsoft compilers.
-
-Revision 1.1 2004/04/14 23:09:28 ksekar
-Support for TSIG signed dynamic updates.
-
-
-
-*/
+ */
#ifdef __cplusplus
*
* <appro@fy.chalmers.se>
*/
+ /*
+ * LLVM is more strict about compatibility of types between input & output constraints,
+ * but we want these to be rotations of 32 bits, not 64, so we explicitly drop the
+ * most significant bytes by casting to an unsigned int.
+ */
# if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
# define ROTATE(a,n) ({ register unsigned int ret; \
asm ( \
"roll %1,%0" \
: "=r"(ret) \
- : "I"(n), "0"(a) \
+ : "I"(n), "0"((unsigned int)a) \
: "cc"); \
ret; \
})
* thinking that variables x and y are both of type "char*" -- and anyone who doesn't
* understand why variable y is not of type "char*" just proves the point that poor code
* layout leads people to unfortunate misunderstandings about how the C language really works.)
-
- Change History (most recent first):
-
-$Log: mDNS.c,v $
-Revision 1.977 2009/07/23 23:30:01 cheshire
-<rdar://problem/7086623> Sleep Proxy: Ten-second maintenance wake not long enough to reliably get network connectivity
-
-Revision 1.976 2009/07/23 09:15:06 cheshire
-<rdar://problem/6434656> Sleep Proxy: Put owner OPT records in multicast announcements to avoid conflicts
-Fixed silly mistake in checkin 1.974 that broke SendResponses
-
-Revision 1.975 2009/07/21 23:46:19 cheshire
-Improved "DNS Message too short" syslog debugging message
-
-Revision 1.974 2009/07/21 23:41:05 cheshire
-<rdar://problem/6434656> Sleep Proxy: Put owner OPT records in multicast announcements to avoid conflicts
-Fixed silly mistake in checkin 1.974 that broke SendResponses
-
-svn merge: Revision 1.974 2009/07/21 23:41:05 cheshire
-<rdar://problem/6434656> Sleep Proxy: Put owner OPT records in multicast announcements to avoid conflicts
-Another refinement: When building a response packet, if we're going to add an OWNER option at the end,
-reserve enough bytes to ensure that we'll be able to do that
-
-svn merge: Revision 1.973 2009/07/16 00:34:18 cheshire
-<rdar://problem/6434656> Sleep Proxy: Put owner OPT records in multicast announcements to avoid conflicts
-Additional refinement: If we didn't register with a Sleep Proxy when going to sleep,
-we don't need to include our OWNER option in our packets when we re-awaken
-
-svn merge: Revision 1.972 2009/07/16 00:12:23 cheshire
-<rdar://problem/6434656> Sleep Proxy: Put owner OPT records in multicast announcements to avoid conflicts
-Additional fixes: Only add and send OWNER option if we were already going to send a non-empty packet anyway
-
-svn merge: Revision 1.971 2009/07/15 23:35:40 cheshire
-<rdar://problem/6434656> Sleep Proxy: Put owner OPT records in multicast announcements to avoid conflicts
-
-Revision 1.970.2.1 2009/07/23 23:36:04 cheshire
-<rdar://problem/7086623> Sleep Proxy: Ten-second maintenance wake not long enough to reliably get network connectivity
-
-Revision 1.970 2009/07/11 01:59:27 cheshire
-<rdar://problem/6613674> Sleep Proxy: Add support for using sleep proxy in local network interface hardware
-When going to sleep, try calling ActivateLocalProxy before registering with remote sleep proxy
-
-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.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.784 2008/08/13 00:47:53 mcguire
-Handle failures when packet logging
-
-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.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
-
-Revision 1.776 2008/04/17 20:14:14 cheshire
-<rdar://problem/5870023> CurrentAnswers/LargeAnswers/UniqueAnswers counter mismatch
-
-Revision 1.775 2008/03/26 01:53:34 mcguire
-<rdar://problem/5820489> Can't resolve via uDNS when an interface is specified
-
-Revision 1.774 2008/03/17 17:46:08 mcguire
-When activating an LLQ, reset all the important state and destroy any tcp connection,
-so that everything will be restarted as if the question had just been asked.
-Also reset servPort, so that the SOA query will be re-issued.
-
-Revision 1.773 2008/03/14 22:52:36 mcguire
-<rdar://problem/5321824> write status to the DS
-Update status when any unicast LLQ is started
-
-Revision 1.772 2008/03/06 02:48:34 mcguire
-<rdar://problem/5321824> write status to the DS
-
-Revision 1.771 2008/02/26 22:04:44 cheshire
-<rdar://problem/5661661> BTMM: Too many members.mac.com SOA queries
-Additional fixes -- should not be calling uDNS_CheckCurrentQuestion on a
-question while it's still in our 'm->NewQuestions' section of the list
-
-Revision 1.770 2008/02/22 23:09:02 cheshire
-<rdar://problem/5338420> BTMM: Not processing additional records
-Refinements:
-1. Check rdatahash == namehash, to skip expensive SameDomainName check when possible
-2. Once we decide a record is acceptable, we can break out of the loop
-
-Revision 1.769 2008/02/22 00:00:19 cheshire
-<rdar://problem/5338420> BTMM: Not processing additional records
-
-Revision 1.768 2008/02/19 23:26:50 cheshire
-<rdar://problem/5661661> BTMM: Too many members.mac.com SOA queries
-
-Revision 1.767 2007/12/22 02:25:29 cheshire
-<rdar://problem/5661128> Records and Services sometimes not re-registering on wake from sleep
-
-Revision 1.766 2007/12/15 01:12:27 cheshire
-<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
-
-Revision 1.765 2007/12/15 00:18:51 cheshire
-Renamed question->origLease to question->ReqLease
-
-Revision 1.764 2007/12/14 00:49:53 cheshire
-Fixed crash in mDNS_StartExit -- the service deregistration loop needs to use
-the CurrentServiceRecordSet mechanism to guard against services being deleted,
-just like the record deregistration loop uses m->CurrentRecord.
-
-Revision 1.763 2007/12/13 20:20:17 cheshire
-Minor efficiency tweaks -- converted IdenticalResourceRecord, IdenticalSameNameRecord, and
-SameRData from functions to macros, which allows the code to be inlined (the compiler can't
-inline a function defined in a different compilation unit) and therefore optimized better.
-
-Revision 1.762 2007/12/13 00:13:03 cheshire
-Simplified RDataHashValue to take a single ResourceRecord pointer, instead of separate rdlength and RDataBody
-
-Revision 1.761 2007/12/13 00:03:31 cheshire
-Improved efficiency in IdenticalResourceRecord() by doing SameRData() check before SameDomainName() check
-
-Revision 1.760 2007/12/08 00:36:19 cheshire
-<rdar://problem/5636422> Updating TXT records is too slow
-Remove unnecessary delays on announcing record updates, and on processing them on reception
-
-Revision 1.759 2007/12/07 22:41:29 cheshire
-<rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
-Further refinements -- records on the DuplicateRecords list were getting missed on shutdown
-
-Revision 1.758 2007/12/07 00:45:57 cheshire
-<rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
-
-Revision 1.757 2007/12/06 00:22:27 mcguire
-<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
-
-Revision 1.756 2007/12/05 01:52:30 cheshire
-<rdar://problem/5624763> BTMM: getaddrinfo_async_start returns EAI_NONAME when resolving BTMM hostname
-Delay returning IPv4 address ("A") results for autotunnel names until after we've set up the tunnel (or tried to)
-
-Revision 1.755 2007/12/03 23:36:45 cheshire
-<rdar://problem/5623140> mDNSResponder unicast DNS improvements
-Need to check GetServerForName() result is non-null before dereferencing pointer
-
-Revision 1.754 2007/12/01 01:21:27 jgraessley
-<rdar://problem/5623140> mDNSResponder unicast DNS improvements
-
-Revision 1.753 2007/12/01 00:44:15 cheshire
-Fixed compile warnings, e.g. declaration of 'rr' shadows a previous local
-
-Revision 1.752 2007/11/14 01:10:51 cheshire
-Fixed LogOperation() message wording
-
-Revision 1.751 2007/10/30 23:49:41 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-LLQ state was not being transferred properly between duplicate questions
-
-Revision 1.750 2007/10/29 23:58:52 cheshire
-<rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events
-Use standard "if (mDNSIPv4AddressIsOnes(....ExternalAddress))" mechanism to determine whether callback has been invoked yet
-
-Revision 1.749 2007/10/29 21:28:36 cheshire
-Change "Correcting TTL" log message to LogOperation to suppress it in customer build
-
-Revision 1.748 2007/10/29 20:02:50 cheshire
-<rdar://problem/5526813> BTMM: Wide-area records being announced via multicast
-
-Revision 1.747 2007/10/26 22:53:50 cheshire
-Made mDNS_Register_internal and mDNS_Deregister_internal use AuthRecord_uDNS macro
-instead of replicating the logic in both places
-
-Revision 1.746 2007/10/25 22:48:50 cheshire
-Added LogOperation message saying when we restart GetZoneData for record and service registrations
-
-Revision 1.745 2007/10/25 20:48:47 cheshire
-For naming consistency (with AuthRecord's UpdateServer) renamed 'ns' to 'SRSUpdateServer'
-
-Revision 1.744 2007/10/25 20:06:14 cheshire
-Don't try to do SOA queries using private DNS (TLS over TCP) queries
-
-Revision 1.743 2007/10/25 00:12:46 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-Retrigger service registrations whenever a new network interface is added
-
-Revision 1.742 2007/10/24 22:40:06 cheshire
-Renamed: RecordRegistrationCallback -> RecordRegistrationGotZoneData
-Renamed: ServiceRegistrationZoneDataComplete -> ServiceRegistrationGotZoneData
-
-Revision 1.741 2007/10/24 00:50:29 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-Retrigger record registrations whenever a new network interface is added
-
-Revision 1.740 2007/10/23 00:38:03 cheshire
-When sending uDNS cache expiration query, need to increment rr->UnansweredQueries
-or code will spin sending the same cache expiration query repeatedly
-
-Revision 1.739 2007/10/22 23:46:41 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Need to clear question->nta pointer after calling CancelGetZoneData()
-
-Revision 1.738 2007/10/19 22:08:49 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Additional fixes and refinements
-
-Revision 1.737 2007/10/18 23:06:42 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Additional fixes and refinements
-
-Revision 1.736 2007/10/18 20:23:17 cheshire
-Moved SuspendLLQs into mDNS.c, since it's only called from one place
-
-Revision 1.735 2007/10/18 00:12:34 cheshire
-Fixed "unused variable" compiler warning
-
-Revision 1.734 2007/10/17 22:49:54 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-
-Revision 1.733 2007/10/17 22:37:23 cheshire
-<rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events
-
-Revision 1.732 2007/10/17 21:53:51 cheshire
-Improved debugging messages; renamed startLLQHandshakeCallback to LLQGotZoneData
-
-Revision 1.731 2007/10/17 18:37:50 cheshire
-<rdar://problem/5539930> Goodbye packets not being sent for services on shutdown
-Further refinement: pre-increment m->CurrentRecord before calling mDNS_Deregister_internal()
-
-Revision 1.730 2007/10/16 21:16:07 cheshire
-<rdar://problem/5539930> Goodbye packets not being sent for services on shutdown
-
-Revision 1.729 2007/10/05 17:56:10 cheshire
-Move CountLabels and SkipLeadingLabels to DNSCommon.c so they're callable from other files
-
-Revision 1.728 2007/10/04 23:18:14 cheshire
-<rdar://problem/5523706> mDNSResponder flooding DNS servers with unreasonable query level
-
-Revision 1.727 2007/10/04 22:51:57 cheshire
-Added debugging LogOperation message to show when we're sending cache expiration queries
-
-Revision 1.726 2007/10/03 00:14:24 cheshire
-Removed write to null to generate stack trace for SetNextQueryTime locking failure
-
-Revision 1.725 2007/10/02 21:11:08 cheshire
-<rdar://problem/5518270> LLQ refreshes don't work, which breaks BTMM browsing
-
-Revision 1.724 2007/10/02 20:10:23 cheshire
-Additional debugging checks on shutdown -- list all records we didn't send a goodbye for, not just the first one
-
-Revision 1.723 2007/10/02 19:56:54 cheshire
-<rdar://problem/5518310> Double-dispose causes crash changing Dynamic DNS hostname
-
-Revision 1.722 2007/10/01 22:59:46 cheshire
-<rdar://problem/5516303> mDNSResponder did not shut down after 20 seconds
-Need to shut down NATTraversals on exit
-
-Revision 1.721 2007/10/01 18:42:07 cheshire
-To make packet logs appear in a more intuitive order, dump received packets *before* handling them, not after
-
-Revision 1.720 2007/09/29 20:40:19 cheshire
-<rdar://problem/5513378> Crash in ReissueBlockedQuestions
-
-Revision 1.719 2007/09/27 22:23:56 cheshire
-<rdar://problem/4947392> uDNS: Use SOA to determine TTL for negative answers
-Need to clear m->rec.r.resrec.RecordType after we've finished using m->rec
-
-Revision 1.718 2007/09/27 22:02:33 cheshire
-<rdar://problem/5464941> BTMM: Registered records in BTMM don't get removed from server after calling RemoveRecord
-
-Revision 1.717 2007/09/27 21:21:39 cheshire
-Export CompleteDeregistration so it's callable from other files
-
-Revision 1.716 2007/09/27 02:12:21 cheshire
-Updated GrantCacheExtensions degugging message to show new record lifetime
-
-Revision 1.715 2007/09/27 01:20:06 cheshire
-<rdar://problem/5500077> BTMM: Need to refresh LLQs based on lease life and not TTL of response
-
-Revision 1.714 2007/09/27 00:37:01 cheshire
-<rdar://problem/4947392> BTMM: Use SOA to determine TTL for negative answers
-
-Revision 1.713 2007/09/27 00:25:39 cheshire
-Added ttl_seconds parameter to MakeNegativeCacheRecord in preparation for:
-<rdar://problem/4947392> uDNS: Use SOA to determine TTL for negative answers
-
-Revision 1.712 2007/09/26 23:16:58 cheshire
-<rdar://problem/5496399> BTMM: Leopard sending excessive LLQ registration requests to .Mac
-
-Revision 1.711 2007/09/26 22:06:02 cheshire
-<rdar://problem/5507399> BTMM: No immediate failure notifications for BTMM names
-
-Revision 1.710 2007/09/26 00:49:46 cheshire
-Improve packet logging to show sent and received packets,
-transport protocol (UDP/TCP/TLS) and source/destination address:port
-
-Revision 1.709 2007/09/21 21:12:36 cheshire
-<rdar://problem/5498009> BTMM: Need to log updates and query packet contents
-
-Revision 1.708 2007/09/20 23:13:37 cheshire
-<rdar://problem/4038277> BTMM: Not getting LLQ remove events when logging out of VPN or disconnecting from network
-Additional fix: If we have no DNS servers at all, then immediately purge all unicast cache records (including for LLQs)
-
-Revision 1.707 2007/09/20 02:29:37 cheshire
-<rdar://problem/4038277> BTMM: Not getting LLQ remove events when logging out of VPN or disconnecting from network
-
-Revision 1.706 2007/09/20 01:13:19 cheshire
-Export CacheGroupForName so it's callable from other files
-
-Revision 1.705 2007/09/20 01:12:06 cheshire
-Moved HashSlot(X) from mDNS.c to DNSCommon.h so it's usable in other files
-
-Revision 1.704 2007/09/19 22:47:25 cheshire
-<rdar://problem/5490182> Memory corruption freeing a "no such service" service record
-
-Revision 1.703 2007/09/14 01:46:59 cheshire
-Fix Posix build (#ifdef _LEGACY_NAT_TRAVERSAL_ section included a closing curly brace it should not have)
-
-Revision 1.702 2007/09/13 22:06:46 cheshire
-<rdar://problem/5480643> Tully's Free WiFi: DNS fails
-Need to accept DNS responses where the query ID field matches, even if the source address does not
-
-Revision 1.701 2007/09/12 23:22:32 cheshire
-<rdar://problem/5476979> Only accept NAT Port Mapping packets from our default gateway
-
-Revision 1.700 2007/09/12 23:03:08 cheshire
-<rdar://problem/5476978> DNSServiceNATPortMappingCreate callback not giving correct interface index
-
-Revision 1.699 2007/09/12 22:19:28 cheshire
-<rdar://problem/5476977> Need to listen for port 5350 NAT-PMP announcements
-
-Revision 1.698 2007/09/12 22:13:27 cheshire
-Remove DynDNSHostNames cleanly on shutdown
-
-Revision 1.697 2007/09/12 01:44:47 cheshire
-<rdar://problem/5475938> Eliminate "Correcting TTL" syslog messages for unicast DNS records
-
-Revision 1.696 2007/09/12 01:26:08 cheshire
-Initialize LastNATReplyLocalTime to timenow, so that gateway uptime checks work more reliably
-
-Revision 1.695 2007/09/11 19:19:16 cheshire
-Correct capitalization of "uPNP" to "UPnP"
-
-Revision 1.694 2007/09/10 22:06:51 cheshire
-Rename uptime => upseconds and LastNATUptime => LastNATupseconds to make it clear these time values are in seconds
-
-Revision 1.693 2007/09/07 22:24:36 vazquez
-<rdar://problem/5466301> Need to stop spewing mDNSResponderHelper logs
-
-Revision 1.692 2007/09/07 00:12:09 cheshire
-<rdar://problem/5466010> Unicast DNS changes broke efficiency fix 3928456
-
-Revision 1.691 2007/09/05 22:25:01 vazquez
-<rdar://problem/5400521> update_record mDNSResponder leak
-
-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 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.
-
-Revision 1.689 2007/09/05 02:29:06 cheshire
-<rdar://problem/5457287> mDNSResponder taking up 100% CPU in ReissueBlockedQuestions
-Additional fixes to code implementing "NoAnswer" logic
-
-Revision 1.688 2007/08/31 22:56:39 cheshire
-<rdar://problem/5407080> BTMM: TTLs incorrect on cached BTMM records
-
-Revision 1.687 2007/08/31 19:53:14 cheshire
-<rdar://problem/5431151> BTMM: IPv6 address lookup should not succeed if autotunnel cannot be setup
-If AutoTunnel setup fails, the code now generates a fake NXDomain error saying that the requested AAAA record does not exist
-
-Revision 1.686 2007/08/30 00:01:56 cheshire
-Added comment about SetTargetToHostName()
-
-Revision 1.685 2007/08/29 01:19:24 cheshire
-<rdar://problem/5400181> BTMM: Tunneled services do not need NAT port mappings
-Set AutoTarget to Target_AutoHostAndNATMAP for non-AutoTunnel wide-area services
-
-Revision 1.684 2007/08/28 23:58:42 cheshire
-Rename HostTarget -> AutoTarget
-
-Revision 1.683 2007/08/28 23:53:21 cheshire
-Rename serviceRegistrationCallback -> ServiceRegistrationZoneDataComplete
-
-Revision 1.682 2007/08/27 20:28:19 cheshire
-Improve "suspect uDNS response" log message
-
-Revision 1.681 2007/08/24 23:37:23 cheshire
-Added debugging message to show when ExtraResourceRecord callback gets invoked
-
-Revision 1.680 2007/08/24 00:15:19 cheshire
-Renamed GetAuthInfoForName() to GetAuthInfoForName_internal() to make it clear that it may only be called with the lock held
-
-Revision 1.679 2007/08/23 21:47:09 vazquez
-<rdar://problem/5427316> BTMM: mDNSResponder sends NAT-PMP packets on public network
-make sure we clean up port mappings on base stations by sending a lease value of 0,
-and only send NAT-PMP packets on private networks; also save some memory by
-not using packet structs in NATTraversals.
-
-Revision 1.678 2007/08/01 16:09:13 cheshire
-Removed unused NATTraversalInfo substructure from AuthRecord; reduced structure sizecheck values accordingly
-
-Revision 1.677 2007/08/01 01:58:24 cheshire
-Added RecordType sanity check in mDNS_Register_internal
-
-Revision 1.676 2007/08/01 00:04:13 cheshire
-<rdar://problem/5261696> Crash in tcpKQSocketCallback
-Half-open TCP connections were not being cancelled properly
-
-Revision 1.675 2007/07/31 02:28:35 vazquez
-<rdar://problem/3734269> NAT-PMP: Detect public IP address changes and base station reboot
-
-Revision 1.674 2007/07/31 01:57:23 cheshire
-Adding code to respect TTL received in uDNS responses turned out to
-expose other problems; backing out change for now.
-
-Revision 1.673 2007/07/30 23:31:26 cheshire
-Code for respecting TTL received in uDNS responses should exclude LLQ-type responses
-
-Revision 1.672 2007/07/28 01:25:56 cheshire
-<rdar://problem/4780038> BTMM: Add explicit UDP event port to LLQ setup request, to fix LLQs not working behind NAT
-
-Revision 1.671 2007/07/27 22:32:54 cheshire
-When processing TTLs in uDNS responses, we'll currently impose a minimum effective TTL
-of 2 seconds, or other stuff breaks (e.g. we end up making a negative cache entry).
-
-Revision 1.670 2007/07/27 20:54:43 cheshire
-Fixed code to respect real record TTL received in uDNS responses
-
-Revision 1.669 2007/07/27 20:09:32 cheshire
-Don't need to dump out all received mDNS packets; they're easily viewed using mDNSNetMonitor
-
-Revision 1.668 2007/07/27 19:58:47 cheshire
-Use symbolic names QC_add and QC_rmv instead of mDNStrue/mDNSfalse
-
-Revision 1.667 2007/07/27 19:52:10 cheshire
-Don't increment m->rrcache_active for no-cache add events
-
-Revision 1.666 2007/07/27 19:30:39 cheshire
-Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
-to properly reflect tri-state nature of the possible responses
-
-Revision 1.665 2007/07/27 18:44:01 cheshire
-Rename "AnswerQuestionWithResourceRecord" to more informative "AnswerCurrentQuestionWithResourceRecord"
-
-Revision 1.664 2007/07/27 18:38:56 cheshire
-Rename "uDNS_CheckQuery" to more informative "uDNS_CheckCurrentQuestion"
-
-Revision 1.663 2007/07/25 03:05:02 vazquez
-Fixes for:
-<rdar://problem/5338913> LegacyNATTraversal: UPnP heap overflow
-<rdar://problem/5338933> LegacyNATTraversal: UPnP stack buffer overflow
-and a myriad of other security problems
-
-Revision 1.662 2007/07/24 20:22:46 cheshire
-Make sure all fields of main mDNS object are initialized correctly
-
-Revision 1.661 2007/07/21 00:54:45 cheshire
-<rdar://problem/5344576> Delay IPv6 address callback until AutoTunnel route and policy is configured
-
-Revision 1.660 2007/07/20 20:00:45 cheshire
-"Legacy Browse" is better called "Automatic Browse"
-
-Revision 1.659 2007/07/20 00:54:18 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
-
-Revision 1.658 2007/07/18 02:28:57 cheshire
-Don't set AutoTunnel settings in uDNS_RegisterService; should be done in GetServiceTarget
-
-Revision 1.657 2007/07/18 00:57:10 cheshire
-<rdar://problem/5303834> Automatically configure IPSec policy when resolving services
-Only need to call AddNewClientTunnel() for IPv6 addresses
-
-Revision 1.656 2007/07/16 23:54:48 cheshire
-<rdar://problem/5338850> Crash when removing or changing DNS keys
-
-Revision 1.655 2007/07/16 20:11:37 vazquez
-<rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite
-Init LNT stuff and handle SSDP packets
-
-Revision 1.654 2007/07/12 23:30:23 cheshire
-Changed some 'LogOperation' calls to 'debugf' to reduce verbosity in syslog
-
-Revision 1.653 2007/07/12 02:51:27 cheshire
-<rdar://problem/5303834> Automatically configure IPSec policy when resolving services
-
-Revision 1.652 2007/07/11 23:43:42 cheshire
-Rename PurgeCacheResourceRecord to mDNS_PurgeCacheResourceRecord
-
-Revision 1.651 2007/07/11 22:44:40 cheshire
-<rdar://problem/5328801> SIGHUP should purge the cache
-
-Revision 1.650 2007/07/11 21:34:09 cheshire
-<rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
-Need to hold mDNS_Lock when calling mDNS_AddDynDNSHostName/mDNS_RemoveDynDNSHostName
-
-Revision 1.649 2007/07/11 02:52:52 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-In uDNS_RegisterService, set HostTarget for AutoTunnel services
-
-Revision 1.648 2007/07/09 23:48:12 cheshire
-Add parentheses around bitwise operation for clarity
-
-Revision 1.647 2007/07/06 21:17:55 cheshire
-Initialize m->retryGetAddr to timenow + 0x78000000;
-
-Revision 1.646 2007/07/06 18:55:49 cheshire
-Initialize m->NextScheduledNATOp
-
-Revision 1.645 2007/06/29 22:55:54 cheshire
-Move declaration of DNSServer *s; Fixed incomplete comment.
-
-Revision 1.644 2007/06/29 00:07:29 vazquez
-<rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes)
-
-Revision 1.643 2007/06/20 01:10:12 cheshire
-<rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
-
-Revision 1.642 2007/06/15 21:54:50 cheshire
-<rdar://problem/4883206> Add packet logging to help debugging private browsing over TLS
-
-Revision 1.641 2007/05/25 00:30:24 cheshire
-When checking for duplicate questions, make sure privacy (or not) status, and long-lived (or not)
-status matches. This is particularly important when doing a private query for an SOA record,
-which will result in a call StartGetZoneData which does a non-private query for the same SOA record.
-If the latter is tagged as a duplicate of the former, then we have deadlock, and neither will complete.
-
-Revision 1.640 2007/05/25 00:25:44 cheshire
-<rdar://problem/5227737> Need to enhance putRData to output all current known types
-
-Revision 1.639 2007/05/23 00:51:33 cheshire
-Increase threshold for shedding cache records from 512 to 3000. The 512 figure was calculated when
-each cache entry took about 700 bytes; now they're only 164 bytes. Also, machines have more RAM these
-days, and there are more services being advertised using DNS-SD, so it makes sense to cache more.
-
-Revision 1.638 2007/05/23 00:43:16 cheshire
-If uDNS UDP response has TC (truncated) bit set, don't interpret it as being the entire RRSet
-
-Revision 1.637 2007/05/14 23:53:00 cheshire
-Export mDNS_StartQuery_internal and mDNS_StopQuery_internal so they can be called from uDNS.c
-
-Revision 1.636 2007/05/10 23:27:15 cheshire
-Update mDNS_Deregister_internal debugging messages
-
-Revision 1.635 2007/05/07 20:43:45 cheshire
-<rdar://problem/4241419> Reduce the number of queries and announcements
-
-Revision 1.634 2007/05/04 22:09:08 cheshire
-Only do "restarting exponential backoff sequence" for mDNS questions
-In mDNS_RegisterInterface, only retrigger mDNS questions
-In uDNS_SetupDNSConfig, use ActivateUnicastQuery() instead of just setting q->ThisQInterval directly
-
-Revision 1.633 2007/05/04 21:45:12 cheshire
-Get rid of unused q->RestartTime; Get rid of uDNS_Close (synonym for uDNS_Sleep)
-
-Revision 1.632 2007/05/04 20:20:50 cheshire
-<rdar://problem/5167331> RegisterRecord and RegisterService need to cancel StartGetZoneData
-Need to set srs->nta = mDNSNULL; when regState_NoTarget
-
-Revision 1.631 2007/05/04 00:39:42 cheshire
-<rdar://problem/4410011> Eliminate looping SOA lookups
-When creating a cascade of negative SOA cache entries, CacheGroup pointer cg needs to be updated
-each time round the loop to reference the right CacheGroup for each newly fabricated SOA name
-
-Revision 1.630 2007/05/03 22:40:38 cheshire
-<rdar://problem/4669229> mDNSResponder ignores bogus null target in SRV record
-
-Revision 1.629 2007/05/03 00:15:51 cheshire
-<rdar://problem/4410011> Eliminate looping SOA lookups
-
-Revision 1.628 2007/05/02 22:21:33 cheshire
-<rdar://problem/5167331> RegisterRecord and RegisterService need to cancel StartGetZoneData
-
-Revision 1.627 2007/04/30 19:29:13 cheshire
-Fix display of port number in "Updating DNS Server" message
-
-Revision 1.626 2007/04/30 04:21:13 cheshire
-Can't safely call AnswerLocalQuestions() from within mDNS_Deregister() -- need to defer it until mDNS_Execute time
-
-Revision 1.625 2007/04/28 01:34:21 cheshire
-Fixed crashing bug: We need to update rr->CRActiveQuestion pointers for *all* questions
-(Code was explicitly ignoring wide-area unicast questions, leading to stale pointers and crashes)
-
-Revision 1.624 2007/04/27 21:04:30 cheshire
-On network configuration change, need to call uDNS_RegisterSearchDomains
-
-Revision 1.623 2007/04/27 19:28:01 cheshire
-Any code that calls StartGetZoneData needs to keep a handle to the structure, so
-it can cancel it if necessary. (First noticed as a crash in Apple Remote Desktop
--- it would start a query and then quickly cancel it, and then when
-StartGetZoneData completed, it had a dangling pointer and crashed.)
-
-Revision 1.622 2007/04/26 16:09:22 cheshire
-mDNS_StopQueryWithRemoves should ignore kDNSRecordTypePacketNegative records
-
-Revision 1.621 2007/04/26 15:43:22 cheshire
-Make sure DNSServer *s is non-null before using value in LogOperation
-
-Revision 1.620 2007/04/26 13:11:05 cheshire
-Fixed crash when logging out of VPN
-
-Revision 1.619 2007/04/26 00:35:15 cheshire
-<rdar://problem/5140339> uDNS: Domain discovery not working over VPN
-Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server
-inside the firewall may give answers where a public one gives none, and vice versa.)
-
-Revision 1.618 2007/04/25 19:26:01 cheshire
-m->NextScheduledQuery was getting set too early in SendQueries()
-Improved "SendQueries didn't send all its queries" debugging message
-
-Revision 1.617 2007/04/25 17:48:22 cheshire
-Update debugging message
-
-Revision 1.616 2007/04/25 16:38:32 cheshire
-If negative cache entry already exists, reactivate it instead of creating a new one
-
-Revision 1.615 2007/04/25 02:14:38 cheshire
-<rdar://problem/4246187> uDNS: Identical client queries should reference a single shared core query
-Additional fixes to make LLQs work properly
-
-Revision 1.614 2007/04/23 21:52:45 cheshire
-<rdar://problem/5094009> IPv6 filtering in AirPort base station breaks Wide-Area Bonjour
-
-Revision 1.613 2007/04/23 04:58:20 cheshire
-<rdar://problem/5072548> Crash when setting extremely large TXT records
-
-Revision 1.612 2007/04/22 20:39:38 cheshire
-<rdar://problem/4633194> Add 20 to 120ms random delay to browses
-
-Revision 1.611 2007/04/22 18:16:29 cheshire
-Removed incorrect ActiveQuestion(q) check that was preventing suspended questions from getting reactivated
-
-Revision 1.610 2007/04/22 06:02:02 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-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 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
-
-Revision 1.606 2007/04/19 22:50:53 cheshire
-<rdar://problem/4246187> Identical client queries should reference a single shared core query
-
-Revision 1.605 2007/04/19 20:06:41 cheshire
-Rename field 'Private' (sounds like a boolean) to more informative 'AuthInfo' (it's a DomainAuthInfo pointer)
-
-Revision 1.604 2007/04/19 18:03:04 cheshire
-Add "const" declaration
-
-Revision 1.603 2007/04/06 21:00:25 cheshire
-Fix log message typo
-
-Revision 1.602 2007/04/05 22:55:35 cheshire
-<rdar://problem/5077076> Records are ending up in Lighthouse without expiry information
-
-Revision 1.601 2007/04/04 21:48:52 cheshire
-<rdar://problem/4720694> Combine unicast authoritative answer list with multicast list
-
-Revision 1.600 2007/04/04 01:31:33 cheshire
-Improve debugging message
-
-Revision 1.599 2007/04/04 00:03:26 cheshire
-<rdar://problem/5089862> DNSServiceQueryRecord is returning kDNSServiceErr_NoSuchRecord for empty rdata
-
-Revision 1.598 2007/04/03 19:43:16 cheshire
-Use mDNSSameIPPort (and similar) instead of accessing internal fields directly
-
-Revision 1.597 2007/03/31 00:32:32 cheshire
-After skipping OPT and TSIG, clear m->rec.r.resrec.RecordType
-
-Revision 1.596 2007/03/28 20:59:26 cheshire
-<rdar://problem/4743285> Remove inappropriate use of IsPrivateV4Addr()
-
-Revision 1.595 2007/03/26 23:48:16 cheshire
-<rdar://problem/4848295> Advertise model information via Bonjour
-Refinements to reduce unnecessary transmissions of the DeviceInfo TXT record
-
-Revision 1.594 2007/03/26 23:05:05 cheshire
-<rdar://problem/5089257> Don't cache TSIG records
-
-Revision 1.593 2007/03/23 17:40:08 cheshire
-<rdar://problem/4060169> Bug when auto-renaming Computer Name after name collision
-
-Revision 1.592 2007/03/22 18:31:48 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.591 2007/03/22 00:49:19 cheshire
-<rdar://problem/4848295> Advertise model information via Bonjour
-
-Revision 1.590 2007/03/21 23:05:59 cheshire
-Rename uDNS_HostnameInfo to HostnameInfo; deleted some unused fields
-
-Revision 1.589 2007/03/20 15:37:19 cheshire
-Delete unnecessary log message
-
-Revision 1.588 2007/03/20 00:24:44 cheshire
-<rdar://problem/4175213> Should deliver "name registered" callback slightly *before* announcing PTR record
-
-Revision 1.587 2007/03/16 22:10:56 cheshire
-<rdar://problem/4471307> mDNS: Query for *either* type A or AAAA should return both types
-
-Revision 1.586 2007/03/10 03:26:44 cheshire
-<rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache
-
-Revision 1.585 2007/03/10 02:02:58 cheshire
-<rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache
-Eliminate unnecessary "InternalResponseHndlr responseCallback" function pointer
-
-Revision 1.584 2007/02/28 01:51:27 cheshire
-Added comment about reverse-order IP address
-
-Revision 1.583 2007/01/27 03:19:33 cheshire
-Need to initialize question->sock
-
-Revision 1.582 2007/01/25 00:40:16 cheshire
-Unified CNAME-following functionality into cache management code (which means CNAME-following
-should now also work for mDNS queries too); deleted defunct pktResponseHndlr() routine.
-
-Revision 1.581 2007/01/23 02:56:11 cheshire
-Store negative results in the cache, instead of generating them out of pktResponseHndlr()
-
-Revision 1.580 2007/01/19 21:17:33 cheshire
-StartLLQPolling needs to call SetNextQueryTime() to cause query to be done in a timely fashion
-
-Revision 1.579 2007/01/19 18:39:10 cheshire
-Fix a bunch of parameters that should have been declared "const"
-
-Revision 1.578 2007/01/10 22:51:57 cheshire
-<rdar://problem/4917539> Add support for one-shot private queries as well as long-lived private queries
-
-Revision 1.577 2007/01/10 02:05:21 cheshire
-Delay uDNS_SetupDNSConfig() until *after* the platform layer
-has set up the interface list and security credentials
-
-Revision 1.576 2007/01/09 02:40:57 cheshire
-uDNS_SetupDNSConfig() shouldn't be called from mDNSMacOSX.c (platform support layer);
-moved it to mDNS_Init() in mDNS.c (core code)
-
-Revision 1.575 2007/01/09 00:17:25 cheshire
-Improve "ERROR m->CurrentRecord already set" debugging messages
-
-Revision 1.574 2007/01/05 08:30:41 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.573 2007/01/05 06:34:03 cheshire
-Improve "ERROR m->CurrentQuestion already set" debugging messages
-
-Revision 1.572 2007/01/04 23:11:11 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-When an automatic browsing domain is removed, generate appropriate "remove" events for legacy queries
-
-Revision 1.571 2007/01/04 21:45:20 cheshire
-Added mDNS_DropLockBeforeCallback/mDNS_ReclaimLockAfterCallback macros,
-to do additional lock sanity checking around callback invocations
-
-Revision 1.570 2007/01/04 20:57:47 cheshire
-Rename ReturnCNAME to ReturnIntermed (for ReturnIntermediates)
-
-Revision 1.569 2007/01/04 20:27:27 cheshire
-Change a LogMsg() to debugf()
-
-Revision 1.568 2007/01/04 02:39:53 cheshire
-<rdar://problem/4030599> Hostname passed into DNSServiceRegister ignored for Wide-Area service registrations
-
-Revision 1.567 2006/12/21 00:01:37 cheshire
-Tidy up code alignment
-
-Revision 1.566 2006/12/20 04:07:34 cheshire
-Remove uDNS_info substructure from AuthRecord_struct
-
-Revision 1.565 2006/12/19 22:49:23 cheshire
-Remove uDNS_info substructure from ServiceRecordSet_struct
-
-Revision 1.564 2006/12/19 02:38:20 cheshire
-Get rid of unnecessary duplicate query ID field from DNSQuestion_struct
-
-Revision 1.563 2006/12/19 02:18:48 cheshire
-Get rid of unnecessary duplicate "void *context" field from DNSQuestion_struct
-
-Revision 1.562 2006/12/16 01:58:31 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-
-Revision 1.561 2006/12/01 07:38:53 herscher
-Only perform cache workaround fix if query is wide-area
-
-Revision 1.560 2006/11/30 23:07:56 herscher
-<rdar://problem/4765644> uDNS: Sync up with Lighthouse changes for Private DNS
-
-Revision 1.559 2006/11/27 08:20:57 cheshire
-Preliminary support for unifying the uDNS and mDNS code, including caching of uDNS answers
-
-Revision 1.558 2006/11/10 07:44:03 herscher
-<rdar://problem/4825493> Fix Daemon locking failures while toggling BTMM
-
-Revision 1.557 2006/11/10 01:12:51 cheshire
-<rdar://problem/4829718> Incorrect TTL corrections
-
-Revision 1.556 2006/11/10 00:54:14 cheshire
-<rdar://problem/4816598> Changing case of Computer Name doesn't work
-
-Revision 1.555 2006/10/30 20:03:37 cheshire
-<rdar://problem/4456945> After service restarts on different port, for a few seconds DNS-SD may return stale port number
-
-Revision 1.554 2006/10/20 05:35:04 herscher
-<rdar://problem/4720713> uDNS: Merge unicast active question list with multicast list.
-
-Revision 1.553 2006/10/05 03:42:43 herscher
-Remove embedded uDNS_info struct in DNSQuestion_struct
-
-Revision 1.552 2006/09/15 21:20:15 cheshire
-Remove uDNS_info substructure from mDNS_struct
-
-Revision 1.551 2006/08/14 23:24:22 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.550 2006/07/27 17:58:34 cheshire
-Improved text of "SendQueries didn't send all its queries; will try again" debugging message
-
-Revision 1.549 2006/07/20 22:07:31 mkrochma
-<rdar://problem/4633196> Wide-area browsing is currently broken in TOT
-More fixes for uninitialized variables
-
-Revision 1.548 2006/07/20 19:30:19 mkrochma
-<rdar://problem/4633196> Wide-area browsing sometimes doesn't work in TOT
-
-Revision 1.547 2006/07/15 02:31:30 cheshire
-<rdar://problem/4630812> Suppress log messages for certain old devices with inconsistent TXT RRSet TTLs
-
-Revision 1.546 2006/07/07 01:09:09 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-Only use mallocL/freeL debugging routines when building mDNSResponder, not dnsextd
-
-Revision 1.545 2006/07/05 23:10:30 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Update mDNSSendDNSMessage() to use uDNS_TCPSocket type instead of "int"
-
-Revision 1.544 2006/06/29 07:42:14 cheshire
-<rdar://problem/3922989> Performance: Remove unnecessary SameDomainName() checks
-
-Revision 1.543 2006/06/29 01:38:43 cheshire
-<rdar://problem/4605285> Only request unicast responses on wake from sleep and network connection
-
-Revision 1.542 2006/06/27 23:40:29 cheshire
-Fix typo in comment: mis-spelled "compile"
-
-Revision 1.541 2006/06/27 19:46:24 cheshire
-Updated comments and debugging messages
-
-Revision 1.540 2006/06/15 21:35:16 cheshire
-Move definitions of mDNS_vsnprintf, mDNS_SetupResourceRecord, and some constants
-from mDNS.c to DNSCommon.c, so they can be accessed from dnsextd code
-
-Revision 1.539 2006/06/08 23:45:46 cheshire
-Change SimultaneousProbe messages from debugf() to LogOperation()
-
-Revision 1.538 2006/03/19 17:13:06 cheshire
-<rdar://problem/4483117> Need faster purging of stale records
-Shorten kDefaultReconfirmTimeForNoAnswer to five seconds
-and reconfirm whole chain of antecedents ot once
-
-Revision 1.537 2006/03/19 02:00:07 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.536 2006/03/08 23:29:53 cheshire
-<rdar://problem/4468716> Improve "Service Renamed" log message
-
-Revision 1.535 2006/03/02 20:41:17 cheshire
-<rdar://problem/4111464> After record update, old record sometimes remains in cache
-Minor code tidying and comments to reduce the risk of similar programming errors in future
-
-Revision 1.534 2006/03/02 03:25:46 cheshire
-<rdar://problem/4111464> After record update, old record sometimes remains in cache
-Code to harmonize RRSet TTLs was inadvertently rescuing expiring records
-
-Revision 1.533 2006/02/26 00:54:41 cheshire
-Fixes to avoid code generation warning/error on FreeBSD 7
-
-*/
+ */
#include "DNSCommon.h" // Defines general DNS untility routines
#include "uDNS.h" // Defines entry points into unicast-specific routines
#pragma warning(disable:4706)
#endif
+#if APPLE_OSX_mDNSResponder
+
+#include <WebFilterDNS/WebFilterDNS.h>
+
+#if ! NO_WCF
+WCFConnection *WCFConnectionNew(void) __attribute__((weak_import));
+void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import));
+
+// Do we really need to define a macro for "if"?
+#define CHECK_WCF_FUNCTION(X) if (X)
+#endif // ! NO_WCF
+
+#else
+
+#define NO_WCF 1
+#endif // APPLE_OSX_mDNSResponder
+
// Forward declarations
mDNSlocal void BeginSleepProcessing(mDNS *const m);
mDNSlocal void RetrySPSRegistrations(mDNS *const m);
+mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password);
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark - General Utility Functions
#endif
-#define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
-#define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - ((Q)->LastQTime + (Q)->ThisQInterval) >= 0)
-
mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q)
{
if (m->mDNS_busy != m->mDNS_reentrancy+1)
if (ActiveQuestion(q))
{
- mDNSs32 sendtime = q->LastQTime + q->ThisQInterval;
-
- // Don't allow sendtime to be earlier than SuppressStdPort53Queries
- if (!mDNSOpaque16IsZero(q->TargetQID) && !q->LongLived && m->SuppressStdPort53Queries && (sendtime - m->SuppressStdPort53Queries < 0))
- sendtime = m->SuppressStdPort53Queries;
-
- if (m->NextScheduledQuery - sendtime > 0)
- m->NextScheduledQuery = sendtime;
+ // Depending on whether this is a multicast or unicast question we want to set either:
+ // m->NextScheduledQuery = NextQSendTime(q) or
+ // m->NextuDNSEvent = NextQSendTime(q)
+ mDNSs32 *const timer = mDNSOpaque16IsZero(q->TargetQID) ? &m->NextScheduledQuery : &m->NextuDNSEvent;
+ if (*timer - NextQSendTime(q) > 0)
+ *timer = NextQSendTime(q);
}
}
return(CacheGroupForName(m, slot, rr->namehash, rr->name));
}
-mDNSlocal mDNSBool AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
+mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
{
NetworkInterfaceInfo *intf;
// Used by AnswerAllLocalQuestionsWithLocalAuthRecord() and AnswerNewLocalOnlyQuestion()
mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, QC_result AddRecord)
{
+ // We should not be delivering results for record types Unregistered, Deregistering, and (unverified) Unique
+ if (!(rr->resrec.RecordType & kDNSRecordTypeActiveMask))
+ {
+ LogMsg("AnswerLocalQuestionWithLocalAuthRecord: *NOT* delivering %s event for local record type %X %s",
+ AddRecord ? "Add" : "Rmv", rr->resrec.RecordType, ARDisplayString(m, rr));
+ return;
+ }
+
// 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
mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again
}
-// 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()
+// When a new local AuthRecord is created or deleted, AnswerAllLocalQuestionsWithLocalAuthRecord()
+// delivers the appropriate add/remove events to listening questions:
+// 1. It runs though all our LocalOnlyQuestions delivering answers as appropriate,
+// stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion().
+// 2. If the AuthRecord is marked mDNSInterface_LocalOnly or mDNSInterface_P2P, then it also runs though
+// our main question list, delivering answers to mDNSInterface_Any questions as appropriate,
+// stopping if it reaches a NewQuestion -- brand-new questions are handled by AnswerNewQuestion().
+//
+// AnswerAllLocalQuestionsWithLocalAuthRecord is used by the m->NewLocalRecords loop in mDNS_Execute(),
+// and by mDNS_Deregister_internal()
+
mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
{
if (m->CurrentQuestion)
- LogMsg("AnswerAllLocalQuestionsWithLocalAuthRecord 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)
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
- if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
+ // If this AuthRecord is marked LocalOnly or P2P, then we want to deliver it to all local 'mDNSInterface_Any' questions
+ if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly || rr->resrec.InterfaceID == mDNSInterface_P2P)
{
m->CurrentQuestion = m->Questions;
while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
#define InitialAnnounceCount ((mDNSu8)8)
+// For goodbye packets we set the count to 3, and for wakeups we set it to 18
+// (which will be up to 15 wakeup attempts over the course of 30 seconds,
+// and then if the machine fails to wake, 3 goodbye packets).
+#define GoodbyeCount ((mDNSu8)3)
+#define WakeupCount ((mDNSu8)18)
+
// Note that the announce intervals use exponential backoff, doubling each time. The probe intervals do not.
// This means that because the announce interval is doubled after sending the first packet, the first
// observed on-the-wire inter-packet interval between announcements is actually one second.
#define DefaultAnnounceIntervalForTypeShared (mDNSPlatformOneSecond/2)
#define DefaultAnnounceIntervalForTypeUnique (mDNSPlatformOneSecond/2)
-#define DefaultAPIntervalForRecordType(X) ((X) & (kDNSRecordTypeAdvisory | kDNSRecordTypeShared ) ? DefaultAnnounceIntervalForTypeShared : \
- (X) & (kDNSRecordTypeUnique ) ? DefaultProbeIntervalForTypeUnique : \
- (X) & (kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique) ? DefaultAnnounceIntervalForTypeUnique : 0)
+#define DefaultAPIntervalForRecordType(X) ((X) & kDNSRecordTypeActiveSharedMask ? DefaultAnnounceIntervalForTypeShared : \
+ (X) & kDNSRecordTypeUnique ? DefaultProbeIntervalForTypeUnique : \
+ (X) & kDNSRecordTypeActiveUniqueMask ? DefaultAnnounceIntervalForTypeUnique : 0)
#define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0)
#define TimeToSendThisRecord(RR,time) ((TimeToAnnounceThisRecord(RR,time) || (RR)->ImmedAnswer) && ResourceRecordIsValidAnswer(RR))
{
if (rr->resrec.RecordType == kDNSRecordTypeUnique)
{
- //LogMsg("ProbeCount %d Next %ld %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr));
+ if ((rr->LastAPTime + rr->ThisAPInterval) - m->timenow > mDNSPlatformOneSecond * 10)
+ {
+ LogMsg("SetNextAnnounceProbeTime: ProbeCount %d Next in %d %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr));
+ LogMsg("SetNextAnnounceProbeTime: m->SuppressProbes %d m->timenow %d diff %d", m->SuppressProbes, m->timenow, m->SuppressProbes - m->timenow);
+ }
if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval);
+ // Some defensive code:
+ // If (rr->LastAPTime + rr->ThisAPInterval) happens to be far in the past, we don't want to allow
+ // NextScheduledProbe to be set excessively in the past, because that can cause bad things to happen.
+ // See: <rdar://problem/7795434> mDNS: Sometimes advertising stops working and record interval is set to zero
+ if (m->NextScheduledProbe - m->timenow < 0)
+ m->NextScheduledProbe = m->timenow;
}
- else if (rr->AnnounceCount && ResourceRecordIsValidAnswer(rr))
+ else if (rr->AnnounceCount && (ResourceRecordIsValidAnswer(rr) || rr->resrec.RecordType == kDNSRecordTypeDeregistering))
{
if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
// 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:
- // 1/4 second wait; probe
- // 1/4 second wait; probe
- // 1/4 second wait; probe
- // 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered)
+ // * If this is a record type that's going to probe, then we use the m->SuppressProbes time.
+ // * Otherwise, if it's not going to probe, but m->SuppressProbes is set because we have other
+ // records that are going to probe, then we delay its first announcement so that it will
+ // go out synchronized with the first announcement for the other records that *are* probing.
+ // This is a minor performance tweak that helps keep groups of related records synchronized together.
+ // The addition of "interval / 2" is to make sure that, in the event that any of the probes are
+ // 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 it's not going to probe and m->SuppressProbes is not already set then we should announce immediately.
if (rr->ProbeCount)
{
// If we have no probe suppression time set, or it is in the past, set it now
if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0)
{
- m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique);
+ // 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:
+ // 1/4 second wait; probe
+ // 1/4 second wait; probe
+ // 1/4 second wait; probe
+ // 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered)
+ m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2));
+
// If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation
if (m->SuppressProbes - m->NextScheduledProbe >= 0)
- m->SuppressProbes = m->NextScheduledProbe;
+ m->SuppressProbes = NonZeroTime(m->NextScheduledProbe);
+ if (m->SuppressProbes - m->timenow < 0) // Make sure we don't set m->SuppressProbes excessively in the past
+ m->SuppressProbes = m->timenow;
+
// If we already have a *query* scheduled to go out sooner, then use that time to get better aggregation
if (m->SuppressProbes - m->NextScheduledQuery >= 0)
- m->SuppressProbes = m->NextScheduledQuery;
+ m->SuppressProbes = NonZeroTime(m->NextScheduledQuery);
+ if (m->SuppressProbes - m->timenow < 0) // Make sure we don't set m->SuppressProbes excessively in the past
+ m->SuppressProbes = m->timenow;
+
+ // except... don't expect to be able to send before the m->SuppressSending timer fires
+ if (m->SuppressSending && m->SuppressProbes - m->SuppressSending < 0)
+ m->SuppressProbes = NonZeroTime(m->SuppressSending);
+
+ if (m->SuppressProbes - m->timenow > mDNSPlatformOneSecond * 8)
+ {
+ LogMsg("InitializeLastAPTime ERROR m->SuppressProbes %d m->NextScheduledProbe %d m->NextScheduledQuery %d m->SuppressSending %d %d",
+ m->SuppressProbes - m->timenow,
+ m->NextScheduledProbe - m->timenow,
+ m->NextScheduledQuery - m->timenow,
+ m->SuppressSending,
+ m->SuppressSending - m->timenow);
+ m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2));
+ }
}
+ rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval;
}
-
- 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;
- rr->LastMCInterface = mDNSInterfaceMark;
-
- // If this is a record type that's not going to probe, then delay its first announcement so that
- // it will go out synchronized with the first announcement for the other records that *are* probing.
- // This is a minor performance tweak that helps keep groups of related records synchronized together.
- // The addition of "interval / 2" is to make sure that, in the event that any of the probes are
- // 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)
+ else if (m->SuppressProbes && m->SuppressProbes - m->timenow >= 0)
+ rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
+ else
rr->LastAPTime = m->timenow - rr->ThisAPInterval;
// For reverse-mapping Sleep Proxy PTR records we don't want to start probing instantly -- we
// (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;
+ // Unsolicited Neighbor Advertisements (RFC 2461 Section 7.2.6) give us fast address cache updating,
+ // but some older IPv6 clients get confused by them, so for now we don't send them. Without Unsolicited
+ // Neighbor Advertisements we have to rely on Neighbor Unreachability Detection instead, which is slower.
+ // Given this, we'll do our best to wake for existing IPv6 connections, but we don't want to encourage
+ // new ones for sleeping clients, so we'll we send deletions for our SPS clients' AAAA records.
+ if (m->KnownBugs & mDNS_KnownBug_LimitedIPv6)
+ if (rr->WakeUp.HMAC.l[0] && rr->resrec.rrtype == kDNSType_AAAA)
+ rr->LastAPTime = m->timenow - rr->ThisAPInterval + mDNSPlatformOneSecond * 10;
+
+ // Set LastMCTime to now, to inhibit multicast responses
+ // (no need to send additional multicast responses when we're announcing anyway)
+ rr->LastMCTime = m->timenow;
+ rr->LastMCInterface = mDNSInterfaceMark;
SetNextAnnounceProbeTime(m, rr);
}
+mDNSlocal const domainname *SetUnicastTargetToHostName(mDNS *const m, AuthRecord *rr)
+ {
+ const domainname *target;
+ if (rr->AutoTarget)
+ {
+ // For autotunnel services pointing at our IPv6 ULA we don't need or want a NAT mapping, but for all other
+ // advertised services referencing our uDNS hostname, we want NAT mappings automatically created as appropriate,
+ // with the port number in our advertised SRV record automatically tracking the external mapped port.
+ DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name);
+ if (!AuthInfo || !AuthInfo->AutoTunnel) rr->AutoTarget = Target_AutoHostAndNATMAP;
+ }
+
+ target = GetServiceTarget(m, rr);
+ if (!target || target->c[0] == 0)
+ {
+ // defer registration until we've got a target
+ LogInfo("SetUnicastTargetToHostName No target for %s", ARDisplayString(m, rr));
+ rr->state = regState_NoTarget;
+ return mDNSNULL;
+ }
+ else
+ {
+ LogInfo("SetUnicastTargetToHostName target %##s for resource record %s", target->c, ARDisplayString(m,rr));
+ return target;
+ }
+ }
+
// Right now this only applies to mDNS (.local) services where the target host is always m->MulticastHostname
// Eventually we should unify this with GetServiceTarget() in uDNS.c
mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
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) LogInfo("SetTargetToHostName: Don't know how to set the target of rrtype %s", DNSTypeName(rr->resrec.rrtype));
- if (!(rr->ForceMCast || rr->resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&rr->namestorage)))
+ if (!(rr->ForceMCast || rr->resrec.InterfaceID == mDNSInterface_LocalOnly || rr->resrec.InterfaceID == mDNSInterface_P2P || IsLocalDomain(&rr->namestorage)))
{
- const domainname *const n = GetServiceTarget(m, rr);
+ const domainname *const n = SetUnicastTargetToHostName(m, rr);
if (n) newname = n;
+ else { target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; }
}
if (target && SameDomainName(target, newname))
rr->RecordCallback(m, rr, mStatus_NoError);
mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again
}
- }
+ }
+
+mDNSexport void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr)
+ {
+ // Make sure that we don't activate the SRV record and associated service records, if it is in
+ // NoTarget state. First time when a service is being instantiated, SRV record may be in NoTarget state.
+ // We should not activate any of the other reords (PTR, TXT) that are part of the service. When
+ // the target becomes available, the records will be reregistered.
+ if (rr->resrec.rrtype != kDNSType_SRV)
+ {
+ AuthRecord *srvRR = mDNSNULL;
+ if (rr->resrec.rrtype == kDNSType_PTR)
+ srvRR = rr->Additional1;
+ else if (rr->resrec.rrtype == kDNSType_TXT)
+ srvRR = rr->DependentOn;
+ if (srvRR)
+ {
+ if (srvRR->resrec.rrtype != kDNSType_SRV)
+ {
+ LogMsg("ActivateUnicastRegistration: ERROR!! Resource record %s wrong, expecting SRV type", ARDisplayString(m, srvRR));
+ }
+ else
+ {
+ LogInfo("ActivateUnicastRegistration: Found Service Record %s in state %d for %##s (%s)",
+ ARDisplayString(m, srvRR), srvRR->state, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+ rr->state = srvRR->state;
+ }
+ }
+ }
-mDNSlocal void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr)
- {
+ if (rr->state == regState_NoTarget)
+ {
+ LogInfo("ActivateUnicastRegistration record %s in regState_NoTarget, not activating", ARDisplayString(m, rr));
+ return;
+ }
+ // When we wake up from sleep, we call ActivateUnicastRegistration. It is possible that just before we went to sleep,
+ // the service/record was being deregistered. In that case, we should not try to register again. For the cases where
+ // the records are deregistered due to e.g., no target for the SRV record, we would have returned from above if it
+ // was already in NoTarget state. If it was in the process of deregistration but did not complete fully before we went
+ // to sleep, then it is okay to start in Pending state as we will go back to NoTarget state if we don't have a target.
+ if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
+ {
+ LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to DeregPending", ARDisplayString(m, rr), rr->state);
+ rr->state = regState_DeregPending;
+ }
+ else
+ {
+ LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to Pending", ARDisplayString(m, rr), rr->state);
+ rr->state = regState_Pending;
+ }
rr->ProbeCount = 0;
rr->AnnounceCount = 0;
- rr->ThisAPInterval = 5 * mDNSPlatformOneSecond; // After doubling, first retry will happen after ten seconds
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
rr->LastAPTime = m->timenow - rr->ThisAPInterval;
- rr->state = regState_FetchingZoneData;
- rr->uselease = mDNStrue;
- }
-
-// Two records qualify to be local duplicates if the RecordTypes are the same, or if one is Unique and the other Verified
+ rr->expire = 0; // Forget about all the leases, start fresh
+ rr->uselease = mDNStrue;
+ rr->updateid = zeroID;
+ rr->SRVChanged = mDNSfalse;
+ rr->updateError = mStatus_NoError;
+ // RestartRecordGetZoneData calls this function whenever a new interface gets registered with core.
+ // The records might already be registered with the server and hence could have NAT state.
+ if (rr->NATinfo.clientContext)
+ {
+ mDNS_StopNATOperation_internal(m, &rr->NATinfo);
+ rr->NATinfo.clientContext = mDNSNULL;
+ }
+ if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
+ if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
+ if (m->NextuDNSEvent - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
+ m->NextuDNSEvent = (rr->LastAPTime + rr->ThisAPInterval);
+ }
+
+// Two records qualify to be local duplicates if:
+// (a) the RecordTypes are the same, or
+// (b) one is Unique and the other Verified
+// (c) either is in the process of deregistering
#define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \
- ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified))
+ ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified) || \
+ ((A)->resrec.RecordType == kDNSRecordTypeDeregistering || (B)->resrec.RecordType == kDNSRecordTypeDeregistering))
+
#define RecordIsLocalDuplicate(A,B) \
((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(&(A)->resrec, &(B)->resrec))
AuthRecord **d = &m->DuplicateRecords;
if ((mDNSs32)rr->resrec.rroriginalttl <= 0)
- { LogMsg("mDNS_Register_internal: TTL must be 1 - 0x7FFFFFFF %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
+ { LogMsg("mDNS_Register_internal: TTL %X should be 1 - 0x7FFFFFFF %s", rr->resrec.rroriginalttl, ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
if (!rr->resrec.RecordType)
{ LogMsg("mDNS_Register_internal: RecordType must be non-zero %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
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_Any || rr->resrec.InterfaceID == mDNSInterface_P2P) rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
{
NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
}
// If this resource record is referencing a specific interface, make sure it exists
- if (rr->resrec.InterfaceID && rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
+ if (rr->resrec.InterfaceID && rr->resrec.InterfaceID != mDNSInterface_LocalOnly && rr->resrec.InterfaceID != mDNSInterface_P2P)
{
NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
if (!intf)
rr->Private = 0;
rr->updateid = zeroID;
rr->zone = rr->resrec.name;
- rr->UpdateServer = zeroAddr;
- rr->UpdatePort = zeroIPPort;
rr->nta = mDNSNULL;
rr->tcp = mDNSNULL;
rr->OrigRData = 0;
// rr->resrec.rroriginalttl = already set in mDNS_SetupResourceRecord
// rr->resrec.rdata = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set
+ // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
+ // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
+ // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
+ if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; }
+
if (rr->AutoTarget)
+ {
SetTargetToHostName(m, rr); // Also sets rdlength and rdestimate for us, and calls InitializeLastAPTime();
+#ifndef UNICAST_DISABLED
+ // If we have no target record yet, SetTargetToHostName will set rr->state == regState_NoTarget
+ // In this case we leave the record half-formed in the list, and later we'll remove it from the list and re-add it properly.
+ if (rr->state == regState_NoTarget)
+ {
+ // Initialize the target so that we don't crash while logging etc.
+ domainname *tar = GetRRDomainNameTarget(&rr->resrec);
+ if (tar) tar->c[0] = 0;
+ LogInfo("mDNS_Register_internal: record %s in NoTarget state", ARDisplayString(m, rr));
+ }
+#endif
+ }
else
{
rr->resrec.rdlength = GetRDLength(&rr->resrec, mDNSfalse);
if (!ValidateDomainName(rr->resrec.name))
{ LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
- // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
- // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
- // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
- if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; }
-
// Don't do this until *after* we've set rr->resrec.rdlength
if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata))
{ LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
rr->resrec.rdatahash = target ? DomainNameHashValue(target) : RDataHashValue(&rr->resrec);
- if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
+ if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly || rr->resrec.InterfaceID == mDNSInterface_P2P)
{
// If this is supposed to be unique, make sure we don't have any name conflicts
if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
rr->resrec.RecordType = kDNSRecordTypeDeregistering;
rr->resrec.rroriginalttl = 0;
rr->ImmedAnswer = mDNSInterfaceMark;
+ m->LocalRemoveEvents = mDNStrue;
m->NextScheduledResponse = m->timenow;
}
}
}
+ // For uDNS records, we don't support duplicate checks at this time
+#ifndef UNICAST_DISABLED
+ if (AuthRecord_uDNS(rr))
+ {
+ if (!m->NewLocalRecords) m->NewLocalRecords = rr;
+ // When we called SetTargetToHostName, it may have caused mDNS_Register_internal to be re-entered, appending new
+ // records to the list, so we now need to update p to advance to the new end to the list before appending our new record.
+ // Note that for AutoTunnel this should never happen, but this check makes the code future-proof.
+ while (*p) p=&(*p)->next;
+ *p = rr;
+ if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
+ rr->ProbeCount = 0;
+ rr->AnnounceCount = 0;
+ if (rr->state != regState_NoTarget) ActivateUnicastRegistration(m, rr);
+ return(mStatus_NoError); // <--- Note: For unicast records, code currently bails out at this point
+ }
+#endif
+
// Now that we've finished building our new record, make sure it's not identical to one we already have
- for (r = m->ResourceRecords; r; r=r->next) if (RecordIsLocalDuplicate(r, rr)) break;
+ for (r = m->ResourceRecords; r; r=r->next)
+ if (RecordIsLocalDuplicate(r, rr))
+ {
+ if (r->resrec.RecordType == kDNSRecordTypeDeregistering) r->AnnounceCount = 0;
+ else break;
+ }
if (r)
{
- debugf("Adding to duplicate list %p %s", rr, ARDisplayString(m,rr));
+ debugf("mDNS_Register_internal:Adding to duplicate list %s", ARDisplayString(m,rr));
*d = rr;
// If the previous copy of this record is already verified unique,
// then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
}
else
{
- debugf("Adding to active record list %p %s", rr, ARDisplayString(m,rr));
+ debugf("mDNS_Register_internal: Adding to active record list %s", ARDisplayString(m,rr));
if (!m->NewLocalRecords) m->NewLocalRecords = rr;
*p = rr;
}
- if (!AuthRecord_uDNS(rr))
+ if (!AuthRecord_uDNS(rr)) // This check is superfluous, given that for unicast records we (currently) bail out above
{
// For records that are not going to probe, acknowledge them right away
if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering)
AcknowledgeRecord(m, rr);
+
+ // Adding a record may affect whether or not we should sleep
+ mDNS_UpdateAllowSleep(m);
}
-#ifndef UNICAST_DISABLED
- else
- {
- if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
- ActivateUnicastRegistration(m, rr);
- }
-#endif
-
+
return(mStatus_NoError);
}
mDNSlocal void CompleteRDataUpdate(mDNS *const m, AuthRecord *const rr)
{
RData *OldRData = rr->resrec.rdata;
+ mDNSu16 OldRDLen = rr->resrec.rdlength;
SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength); // Update our rdata
rr->NewRData = mDNSNULL; // Clear the NewRData pointer ...
if (rr->UpdateCallback)
- rr->UpdateCallback(m, rr, OldRData); // ... and let the client know
+ rr->UpdateCallback(m, rr, OldRData, OldRDLen); // ... and let the client know
}
// Note: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list.
if (*d)
{
AuthRecord *dup = *d;
- debugf("Duplicate record %p taking over from %p %##s (%s)",
+ debugf("mDNS_Register_internal: Duplicate record %p taking over from %p %##s (%s)",
dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
*d = dup->next; // Cut replacement record from DuplicateRecords list
dup->next = rr->next; // And then...
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;
while (*p && *p != rr) p=&(*p)->next;
// If we found our record on the duplicate list, then make sure we don't send a goodbye for it
if (*p) rr->RequireGoodbye = mDNSfalse;
- if (*p) debugf("DNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)",
+ if (*p) debugf("mDNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)",
rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
}
// actual goodbye packets.
#ifndef UNICAST_DISABLED
- if (AuthRecord_uDNS(rr) && rr->RequireGoodbye)
- {
- if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
- rr->resrec.RecordType = kDNSRecordTypeDeregistering;
- uDNS_DeregisterRecord(m, rr);
- // At this point unconditionally we bail out
- // Either uDNS_DeregisterRecord will have completed synchronously, and called CompleteDeregistration,
- // which calls us back here with RequireGoodbye set to false, or it will have initiated the deregistration
- // process and will complete asynchronously. Either way we don't need to do anything more here.
- return(mStatus_NoError);
+ if (AuthRecord_uDNS(rr))
+ {
+ if (rr->RequireGoodbye)
+ {
+ if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
+ rr->resrec.RecordType = kDNSRecordTypeDeregistering;
+ m->LocalRemoveEvents = mDNStrue;
+ uDNS_DeregisterRecord(m, rr);
+ // At this point unconditionally we bail out
+ // Either uDNS_DeregisterRecord will have completed synchronously, and called CompleteDeregistration,
+ // which calls us back here with RequireGoodbye set to false, or it will have initiated the deregistration
+ // process and will complete asynchronously. Either way we don't need to do anything more here.
+ return(mStatus_NoError);
+ }
+ // Sometimes the records don't complete proper deregistration i.e., don't wait for a response
+ // from the server. In that case, if the records have been part of a group update, clear the
+ // state here. Some recors e.g., AutoTunnel gets reused without ever being completely initialized
+ rr->updateid = zeroID;
+
+ // We defer cleaning up NAT state only after sending goodbyes. This is important because
+ // RecordRegistrationGotZoneData guards against creating NAT state if clientContext is non-NULL.
+ // This happens today when we turn on/off interface where we get multiple network transitions
+ // and RestartRecordGetZoneData triggers re-registration of the resource records even though
+ // they may be in Registered state which causes NAT information to be setup multiple times. Defering
+ // the cleanup here keeps clientContext non-NULL and hence prevents that. Note that cleaning up
+ // NAT state here takes care of the case where we did not send goodbyes at all.
+ if (rr->NATinfo.clientContext)
+ {
+ mDNS_StopNATOperation_internal(m, &rr->NATinfo);
+ rr->NATinfo.clientContext = mDNSNULL;
+ }
+ if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
+ if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
}
#endif // UNICAST_DISABLED
- if (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->AnsweredLocalQ))
+ if (RecordType == kDNSRecordTypeUnregistered)
+ LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeUnregistered", ARDisplayString(m, rr));
+ else if (RecordType == kDNSRecordTypeDeregistering)
{
- verbosedebugf("mDNS_Deregister_internal: Sending deregister for %s", ARDisplayString(m, rr));
+ LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeDeregistering", ARDisplayString(m, rr));
+ return(mStatus_BadReferenceErr);
+ }
+
+ // <rdar://problem/7457925> Local-only questions don't get remove events for unique records
+ // We may want to consider changing this code so that we generate local-only question "rmv"
+ // events (and maybe goodbye packets too) for unique records as well as for shared records
+ // Note: If we change the logic for this "if" statement, need to ensure that the code in
+ // CompleteDeregistration() sets the appropriate state variables to gaurantee that "else"
+ // clause will execute here and the record will be cut from the list.
+ if (rr->WakeUp.HMAC.l[0] ||
+ (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->AnsweredLocalQ)))
+ {
+ verbosedebugf("mDNS_Deregister_internal: Starting deregistration for %s", ARDisplayString(m, rr));
rr->resrec.RecordType = kDNSRecordTypeDeregistering;
rr->resrec.rroriginalttl = 0;
- rr->ImmedAnswer = mDNSInterfaceMark;
+ rr->AnnounceCount = rr->WakeUp.HMAC.l[0] ? WakeupCount : (drt == mDNS_Dereg_rapid) ? 1 : GoodbyeCount;
+ rr->ThisAPInterval = mDNSPlatformOneSecond * 2;
+ rr->LastAPTime = m->timenow - rr->ThisAPInterval;
+ m->LocalRemoveEvents = mDNStrue;
if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0)
m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10);
}
if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next;
rr->next = mDNSNULL;
- if (RecordType == kDNSRecordTypeUnregistered)
- LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeUnregistered", ARDisplayString(m, rr));
- else if (RecordType == kDNSRecordTypeDeregistering)
- LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeDeregistering", ARDisplayString(m, rr));
- else
- {
- verbosedebugf("mDNS_Deregister_internal: Deleting record for %s", ARDisplayString(m, rr));
- rr->resrec.RecordType = kDNSRecordTypeUnregistered;
- }
+ // Should we generate local remove events here?
+ // i.e. something like:
+ // if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; }
+
+ verbosedebugf("mDNS_Deregister_internal: Deleting record for %s", ARDisplayString(m, rr));
+ rr->resrec.RecordType = kDNSRecordTypeUnregistered;
if ((drt == mDNS_Dereg_conflict || drt == mDNS_Dereg_repeat) && RecordType == kDNSRecordTypeShared)
debugf("mDNS_Deregister_internal: Cannot have a conflict on a shared record! %##s (%s)",
// If we have an update queued up which never executed, give the client a chance to free that memory
if (rr->NewRData) CompleteRDataUpdate(m, rr); // Update our rdata, clear the NewRData pointer, and return memory to the client
- if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
- if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
// CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
// is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
if (drt != mDNS_Dereg_conflict)
{
mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback
+ LogInfo("mDNS_Deregister_internal: mStatus_MemFree for %s", ARDisplayString(m, rr));
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
}
}
}
+ mDNS_UpdateAllowSleep(m);
return(mStatus_NoError);
}
rr->NR_AdditionalTo = mDNSNULL;
}
- if (m->omsg.h.numAnswers) mDNSSendDNSMessage(m, &m->omsg, responseptr, mDNSInterface_Any, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL);
+ if (m->omsg.h.numAnswers)
+ mDNSSendDNSMessage(m, &m->omsg, responseptr, mDNSInterface_Any, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL);
}
}
+// CompleteDeregistration guarantees that on exit the record will have been cut from the m->ResourceRecords list
+// and the client's mStatus_MemFree callback will have been invoked
mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr)
{
+ LogInfo("CompleteDeregistration: called for Resource record %s", ARDisplayString(m, rr));
// Clearing rr->RequireGoodbye signals mDNS_Deregister_internal() that
// it should go ahead and immediately dispose of this registration
rr->resrec.RecordType = kDNSRecordTypeShared;
rr->RequireGoodbye = mDNSfalse;
+ rr->WakeUp.HMAC = zeroEthAddr;
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
-// the record list and/or question list.
+// DiscardDeregistrations is used on shutdown and sleep to discard (forcibly and immediately)
+// any deregistering records that remain in the m->ResourceRecords list.
+// 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)
{
while (m->CurrentRecord)
{
AuthRecord *rr = m->CurrentRecord;
- if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
+ if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
CompleteDeregistration(m, rr); // Don't touch rr after this
else
m->CurrentRecord = rr->next;
val = val * 10 + src[i] - '0';
}
if (val > 255) return(mStatus_Invalid);
- *dst = val;
+ *dst = (mDNSu8)val;
return(mStatus_NoError);
}
n = (const domainname *)(n->c + 2);
if (l<0 || h<0) return mStatus_Invalid;
- a->ip.v6.b[15-i] = (h << 4) | l;
+ a->ip.v6.b[15-i] = (mDNSu8)((h << 4) | l);
}
a->type = mDNSAddrType_IPv6;
}
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)
+ const mDNSv4Addr *const spa, const mDNSEthAddr *const tha, const mDNSv4Addr *const tpa, const mDNSEthAddr *const dst)
{
int i;
mDNSu8 *ptr = m->omsg.data;
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];
+ for (i=0; i<6; i++) *ptr++ = dst->b[i];
- // 0x06 Source address (we just use zero -- driver/hardware will fill in real interface address)
- for (i=0; i<6; i++) *ptr++ = 0x0;
+ // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
+ for (i=0; i<6; i++) *ptr++ = intf->MAC.b[0];
// 0x0C ARP Ethertype (0x0806)
*ptr++ = 0x08; *ptr++ = 0x06;
for (i=0; i<6; i++) *ptr++ = intf->MAC.b[i];
// 0x1C Sender protocol address
- for (i=0; i<4; i++) *ptr++ = spa[i];
+ for (i=0; i<4; i++) *ptr++ = spa->b[i];
// 0x20 Target hardware address
- for (i=0; i<6; i++) *ptr++ = tha[i];
+ for (i=0; i<6; i++) *ptr++ = tha->b[i];
// 0x26 Target protocol address
- for (i=0; i<4; i++) *ptr++ = tpa[i];
+ for (i=0; i<4; i++) *ptr++ = tpa->b[i];
// 0x2A Total ARP Packet length 42 bytes
mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID);
}
+mDNSlocal mDNSu16 CheckSum(const void *const data, mDNSs32 length, mDNSu32 sum)
+ {
+ const mDNSu16 *ptr = data;
+ while (length > 0) { length -= 2; sum += *ptr++; }
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ return(sum != 0xFFFF ? sum : 0);
+ }
+
+mDNSlocal mDNSu16 IPv6CheckSum(const mDNSv6Addr *const src, const mDNSv6Addr *const dst, const mDNSu8 protocol, const void *const data, const mDNSu32 length)
+ {
+ IPv6PseudoHeader ph;
+ ph.src = *src;
+ ph.dst = *dst;
+ ph.len.b[0] = length >> 24;
+ ph.len.b[1] = length >> 16;
+ ph.len.b[2] = length >> 8;
+ ph.len.b[3] = length;
+ ph.pro.b[0] = 0;
+ ph.pro.b[1] = 0;
+ ph.pro.b[2] = 0;
+ ph.pro.b[3] = protocol;
+ return CheckSum(&ph, sizeof(ph), CheckSum(data, length, 0));
+ }
+
+mDNSlocal void SendNDP(mDNS *const m, const mDNSu8 op, const mDNSu8 flags, const AuthRecord *const rr,
+ const mDNSv6Addr *const spa, const mDNSEthAddr *const tha, const mDNSv6Addr *const tpa, const mDNSEthAddr *const dst)
+ {
+ int i;
+ mDNSOpaque16 checksum;
+ mDNSu8 *ptr = m->omsg.data;
+ // Some recipient hosts seem to ignore Neighbor Solicitations if the IPv6-layer destination address is not the
+ // appropriate IPv6 solicited node multicast address, so we use that IPv6-layer destination address, even though
+ // at the Ethernet-layer we unicast the packet to the intended target, to avoid wasting network bandwidth.
+ const mDNSv6Addr mc = { { 0xFF,0x02,0x00,0x00, 0,0,0,0, 0,0,0,1, 0xFF,tpa->b[0xD],tpa->b[0xE],tpa->b[0xF] } };
+ const mDNSv6Addr *const v6dst = (op == NDP_Sol) ? &mc : tpa;
+ NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
+ if (!intf) { LogMsg("SendNDP: 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->b[i];
+ // Right now we only send Neighbor Solicitations to verify whether the host we're proxying for has gone to sleep yet.
+ // Since we know who we're looking for, we send it via Ethernet-layer unicast, rather than bothering every host on the
+ // link with a pointless link-layer multicast.
+ // Should we want to send traditional Neighbor Solicitations in the future, where we really don't know in advance what
+ // Ethernet-layer address we're looking for, we'll need to send to the appropriate Ethernet-layer multicast address:
+ // *ptr++ = 0x33;
+ // *ptr++ = 0x33;
+ // *ptr++ = 0xFF;
+ // *ptr++ = tpa->b[0xD];
+ // *ptr++ = tpa->b[0xE];
+ // *ptr++ = tpa->b[0xF];
+
+ // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
+ for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i];
+
+ // 0x0C IPv6 Ethertype (0x86DD)
+ *ptr++ = 0x86; *ptr++ = 0xDD;
+
+ // 0x0E IPv6 header
+ *ptr++ = 0x60; *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00; // Version, Traffic Class, Flow Label
+ *ptr++ = 0x00; *ptr++ = 0x20; // Length
+ *ptr++ = 0x3A; // Protocol == ICMPv6
+ *ptr++ = 0xFF; // Hop Limit
+
+ // 0x16 Sender IPv6 address
+ for (i=0; i<16; i++) *ptr++ = spa->b[i];
+
+ // 0x26 Destination IPv6 address
+ for (i=0; i<16; i++) *ptr++ = v6dst->b[i];
+
+ // 0x36 NDP header
+ *ptr++ = op; // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
+ *ptr++ = 0x00; // Code
+ *ptr++ = 0x00; *ptr++ = 0x00; // Checksum placeholder (0x38, 0x39)
+ *ptr++ = flags;
+ *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00;
+
+ if (op == NDP_Sol) // Neighbor Solicitation. The NDP "target" is the address we seek.
+ {
+ // 0x3E NDP target.
+ for (i=0; i<16; i++) *ptr++ = tpa->b[i];
+ // 0x4E Source Link-layer Address
+ // <http://www.ietf.org/rfc/rfc2461.txt>
+ // MUST NOT be included when the source IP address is the unspecified address.
+ // Otherwise, on link layers that have addresses this option MUST be included
+ // in multicast solicitations and SHOULD be included in unicast solicitations.
+ if (!mDNSIPv6AddressIsZero(*spa))
+ {
+ *ptr++ = NDP_SrcLL; // Option Type 1 == Source Link-layer Address
+ *ptr++ = 0x01; // Option length 1 (in units of 8 octets)
+ for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i];
+ }
+ }
+ else // Neighbor Advertisement. The NDP "target" is the address we're giving information about.
+ {
+ // 0x3E NDP target.
+ for (i=0; i<16; i++) *ptr++ = spa->b[i];
+ // 0x4E Target Link-layer Address
+ *ptr++ = NDP_TgtLL; // Option Type 2 == Target Link-layer Address
+ *ptr++ = 0x01; // Option length 1 (in units of 8 octets)
+ for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i];
+ }
+
+ // 0x4E or 0x56 Total NDP Packet length 78 or 86 bytes
+ m->omsg.data[0x13] = ptr - &m->omsg.data[0x36]; // Compute actual length
+ checksum.NotAnInteger = ~IPv6CheckSum(spa, v6dst, 0x3A, &m->omsg.data[0x36], m->omsg.data[0x13]);
+ m->omsg.data[0x38] = checksum.b[0];
+ m->omsg.data[0x39] = checksum.b[1];
+
+ 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;
for (rr = m->ResourceRecords; rr; rr=rr->next)
{
while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
- if (TimeToAnnounceThisRecord(rr, m->timenow) && ResourceRecordIsValidAnswer(rr))
+ if (TimeToAnnounceThisRecord(rr, m->timenow))
{
- if (rr->AddressProxy.type)
+ if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
{
- rr->AnnounceCount--;
- rr->ThisAPInterval *= 2;
- rr->LastAPTime = m->timenow;
- if (rr->AddressProxy.type == mDNSAddrType_IPv4)
+ if (!rr->WakeUp.HMAC.l[0])
{
- 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);
+ if (rr->AnnounceCount) rr->ImmedAnswer = mDNSInterfaceMark; // Send goodbye packet on all interfaces
}
- else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
+ else
{
- //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);
+ LogSPS("SendResponses: Sending wakeup %2d for %.6a %s", rr->AnnounceCount-3, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
+ SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password);
+ for (r2 = rr; r2; r2=r2->next)
+ if (r2->AnnounceCount && r2->resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC))
+ {
+ // For now we only want to send a single Unsolicited Neighbor Advertisement restoring the address to the original
+ // owner, because these packets can cause some IPv6 stacks to falsely conclude that there's an address conflict.
+ if (r2->AddressProxy.type == mDNSAddrType_IPv6 && r2->AnnounceCount == WakeupCount)
+ {
+ LogSPS("NDP Announcement %2d Releasing traffic for H-MAC %.6a I-MAC %.6a %s",
+ r2->AnnounceCount-3, &r2->WakeUp.HMAC, &r2->WakeUp.IMAC, ARDisplayString(m,r2));
+ SendNDP(m, NDP_Adv, NDP_Override, r2, &r2->AddressProxy.ip.v6, &r2->WakeUp.IMAC, &AllHosts_v6, &AllHosts_v6_Eth);
+ }
+ r2->LastAPTime = m->timenow;
+ if (--r2->AnnounceCount <= GoodbyeCount) r2->WakeUp.HMAC = zeroEthAddr;
+ }
}
}
- else
+ else if (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 %2d 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, &zeroEthAddr, &rr->AddressProxy.ip.v4, &onesEthAddr);
+ }
+ else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
+ {
+ LogSPS("NDP Announcement %2d Capturing traffic for H-MAC %.6a I-MAC %.6a %s",
+ rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
+ SendNDP(m, NDP_Adv, NDP_Override, rr, &rr->AddressProxy.ip.v6, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth);
+ }
+ }
+ else
+ {
+ rr->ImmedAnswer = mDNSInterfaceMark; // Send on all interfaces
+ if (maxExistingAnnounceInterval < rr->ThisAPInterval)
+ maxExistingAnnounceInterval = rr->ThisAPInterval;
+ if (rr->UpdateBlocked) rr->UpdateBlocked = 0;
+ }
}
}
}
if (TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2))
{
rr->AnnounceCount--;
- rr->ThisAPInterval *= 2;
+ if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
+ rr->ThisAPInterval *= 2;
rr->LastAPTime = m->timenow;
debugf("Announcing %##s (%s) %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->AnnounceCount);
}
{
if (rr->SendRNow == intf->InterfaceID)
{
+ RData *OldRData = rr->resrec.rdata;
+ mDNSu16 oldrdlength = rr->resrec.rdlength;
+ mDNSu8 active = (mDNSu8)
+ (rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
+ (m->SleepState != SleepState_Sleeping || intf->SPSAddr[0].type || intf->SPSAddr[1].type || intf->SPSAddr[2].type));
newptr = mDNSNULL;
- if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
- {
- newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
- if (newptr) { responseptr = newptr; numDereg++; }
- }
- else if (rr->NewRData && !m->SleepState) // If we have new data for this record
+ if (rr->NewRData && active)
{
- RData *OldRData = rr->resrec.rdata;
- mDNSu16 oldrdlength = rr->resrec.rdlength;
// See if we should send a courtesy "goodbye" for the old data before we replace it.
- if (ResourceRecordIsValidAnswer(rr) && rr->RequireGoodbye)
+ if (ResourceRecordIsValidAnswer(rr) && rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye)
{
newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
if (newptr) { responseptr = newptr; numDereg++; rr->RequireGoodbye = mDNSfalse; }
+ else continue; // If this packet is already too full to hold the goodbye for this record, skip it for now and we'll retry later
}
- // 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);
- if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
- rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the cache flush bit so PutResourceRecord will set it
- newptr = PutRR_OS(responseptr, &m->omsg.h.numAnswers, &rr->resrec);
- rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear cache flush bit back to normal state
- if (newptr) { responseptr = newptr; rr->RequireGoodbye = mDNStrue; }
- SetNewRData(&rr->resrec, OldRData, oldrdlength);
}
- else
+
+ if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
+ rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the cache flush bit so PutResourceRecord will set it
+ newptr = PutRR_OS_TTL(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)
{
- 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 = PutRR_OS_TTL(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 = active;
- if (rr->LastAPTime == m->timenow) numAnnounce++; else numAnswer++;
- }
-
- // 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 = mDNSInterfaceMark;
+ responseptr = newptr;
+ rr->RequireGoodbye = active;
+ if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) numDereg++;
+ else if (rr->LastAPTime == m->timenow) numAnnounce++; else numAnswer++;
}
+ if (rr->NewRData && active)
+ SetNewRData(&rr->resrec, OldRData, oldrdlength);
+
+ // The first time through (pktcount==0), if this record is verified unique
+ // (i.e. typically A, AAAA, SRV, TXT and reverse-mapping PTR), set the flag to add an NSEC too.
+ if (!pktcount && active && (rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && !rr->SendNSECNow)
+ rr->SendNSECNow = mDNSInterfaceMark;
+
if (newptr) // If succeeded in sending, advance to next interface
{
// If sending on all interfaces, go to next interface; else we're finished now
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 = mDNSInterfaceMark;
+ // (i.e. typically A, AAAA, SRV, TXT and reverse-mapping PTR), set the flag to add an NSEC too.
+ if (!pktcount && (rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && !rr->SendNSECNow)
+ rr->SendNSECNow = mDNSInterfaceMark;
if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the cache flush bit so PutResourceRecord will set it
}
// Third Pass. Add NSEC records, if there's space.
+ // When we're generating an NSEC record in response to a specify query for that type
+ // (recognized by rr->SendNSECNow == intf->InterfaceID) we should really put the NSEC in the Answer Section,
+ // not Additional Section, but for now it's easier to handle both cases in this Additional Section loop here.
for (rr = m->ResourceRecords; rr; rr=rr->next)
if (rr->SendNSECNow == mDNSInterfaceMark || rr->SendNSECNow == intf->InterfaceID)
{
opt.resrec.rdestimate = sizeof(rdataOPT);
SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &opt.resrec);
- if (newptr) { responseptr = newptr; LogSPS("SendResponses put %s", ARDisplayString(m, &opt)); }
- else LogMsg("SendResponses: 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 (newptr) { responseptr = newptr; LogSPS("SendResponses put %s", ARDisplayString(m, &opt)); }
+ else if (m->omsg.h.numAnswers + m->omsg.h.numAuthorities + m->omsg.h.numAdditionals == 1)
+ LogSPS("SendResponses: No space in packet for Owner 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));
+ else
+ LogMsg("SendResponses: How did we fail to have space for Owner 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));
}
debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p",
if (rr->SendRNow)
{
- if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
- LogMsg("SendResponses: No active interface to send: %02X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
+ if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly && rr->resrec.InterfaceID != mDNSInterface_P2P)
+ LogMsg("SendResponses: No active interface %p to send: %p %02X %s", rr->SendRNow, rr->resrec.InterfaceID, rr->resrec.RecordType, ARDisplayString(m, rr));
rr->SendRNow = mDNSNULL;
}
- if (rr->ImmedAnswer)
+ if (rr->ImmedAnswer || rr->resrec.RecordType == kDNSRecordTypeDeregistering)
{
if (rr->NewRData) CompleteRDataUpdate(m, rr); // Update our rdata, clear the NewRData pointer, and return memory to the client
- if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
- CompleteDeregistration(m, rr); // Don't touch rr after this
+ if (rr->resrec.RecordType == kDNSRecordTypeDeregistering && rr->AnnounceCount == 0)
+ {
+ // For Unicast, when we get the response from the server, we will call CompleteDeregistration
+ if (!AuthRecord_uDNS(rr)) CompleteDeregistration(m, rr); // Don't touch rr after this
+ }
else
{
rr->ImmedAnswer = mDNSNULL;
// 5. For records with rroriginalttl set to zero, that means we really want to delete them immediately
// (we have a new record with DelayDelivery set, waiting for the old record to go away before we can notify clients).
#define CacheCheckGracePeriod(RR) ( \
- ((RR)->DelayDelivery ) ? (mDNSPlatformOneSecond/10) : \
((RR)->CRActiveQuestion == mDNSNULL ) ? (60 * mDNSPlatformOneSecond) : \
((RR)->UnansweredQueries < MaxUnansweredQueries) ? (TicksTTL(rr)/50) : \
((RR)->resrec.rroriginalttl > 10 ) ? (mDNSPlatformOneSecond) : \
((RR)->resrec.rroriginalttl > 0 ) ? (mDNSPlatformOneSecond/10) : 0)
-// Note: MUST call SetNextCacheCheckTime any time we change:
+#define NextCacheCheckEvent(RR) ((RR)->NextRequiredQuery + CacheCheckGracePeriod(RR))
+
+mDNSexport void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event)
+ {
+ if (m->rrcache_nextcheck[slot] - event > 0)
+ m->rrcache_nextcheck[slot] = event;
+ if (m->NextCacheCheck - event > 0)
+ m->NextCacheCheck = event;
+ }
+
+// Note: MUST call SetNextCacheCheckTimeForRecord any time we change:
// rr->TimeRcvd
// rr->resrec.rroriginalttl
// rr->UnansweredQueries
// rr->CRActiveQuestion
-// Also, any time we set rr->DelayDelivery we should call SetNextCacheCheckTime to ensure m->NextCacheCheck is set if necessary
-// Clearing rr->DelayDelivery does not require a call to SetNextCacheCheckTime
-mDNSlocal void SetNextCacheCheckTime(mDNS *const m, CacheRecord *const rr)
+mDNSlocal void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr)
{
rr->NextRequiredQuery = RRExpireTime(rr);
{
rr->NextRequiredQuery -= TicksTTL(rr)/20 * (MaxUnansweredQueries - rr->UnansweredQueries);
rr->NextRequiredQuery += mDNSRandom((mDNSu32)TicksTTL(rr)/50);
- verbosedebugf("SetNextCacheCheckTime: %##s (%s) NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks",
- rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype),
- (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr));
+ verbosedebugf("SetNextCacheCheckTimeForRecord: NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks for %s",
+ (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m,rr));
}
- if (m->NextCacheCheck - (rr->NextRequiredQuery + CacheCheckGracePeriod(rr)) > 0)
- m->NextCacheCheck = (rr->NextRequiredQuery + CacheCheckGracePeriod(rr));
-
- if (rr->DelayDelivery)
- if (m->NextCacheCheck - rr->DelayDelivery > 0)
- m->NextCacheCheck = rr->DelayDelivery;
+ ScheduleNextCacheCheckTime(m, HashSlot(rr->resrec.name), NextCacheCheckEvent(rr));
}
#define kMinimumReconfirmTime ((mDNSu32)mDNSPlatformOneSecond * 5)
interval += m->RandomReconfirmDelay % ((interval/3) + 1);
rr->TimeRcvd = m->timenow - (mDNSs32)interval * 3;
rr->resrec.rroriginalttl = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond;
- SetNextCacheCheckTime(m, rr);
+ SetNextCacheCheckTimeForRecord(m, rr);
}
debugf("mDNS_Reconfirm_internal:%6ld ticks to go for %s %p",
RRExpireTime(rr) - m->timenow, CRDisplayString(m, rr), rr->CRActiveQuestion);
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // If we have a resource record in our cache,
if (rr->resrec.InterfaceID == q->SendQNow && // received on this interface
+ !(rr->resrec.RecordType & kDNSRecordTypeUniqueMask) && // which is a shared (i.e. not unique) record type
rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList && // which is not already in the known answer list
rr->resrec.rdlength <= SmallRecordLimit && // which is small enough to sensibly fit in the packet
SameNameRecordAnswersQuestion(&rr->resrec, q) && // which answers our question
rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow > // and its half-way-to-expiry time is at least 1 second away
mDNSPlatformOneSecond) // (also ensures we never include goodbye records with TTL=1)
{
+ // We don't want to include unique records in the Known Answer section. The Known Answer section
+ // is intended to suppress floods of shared-record replies from many other devices on the network.
+ // That concept really does not apply to unique records, and indeed if we do send a query for
+ // which we have a unique record already in our cache, then including that unique record as a
+ // Known Answer, so as to suppress the only answer we were expecting to get, makes little sense.
+
*ka = rr; // Link this record into our known answer chain
ka = &rr->NextInKAList;
// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
{
rr->UnansweredQueries++; // indicate that we're expecting a response
rr->LastUnansweredTime = m->timenow;
- SetNextCacheCheckTime(m, rr);
+ SetNextCacheCheckTimeForRecord(m, rr);
}
return(mDNStrue);
CacheRecord *KnownAnswerList = mDNSNULL;
// 1. If time for a query, work out what we need to do
- if (m->timenow - m->NextScheduledQuery >= 0)
- {
- CacheRecord *rr;
- // We're expecting to send a query anyway, so see if any expiring cache records are close enough
- // to their NextRequiredQuery to be worth batching them together with this one
- FORALL_CACHERECORDS(slot, cg, rr)
- if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
- if (m->timenow + TicksTTL(rr)/50 - rr->NextRequiredQuery >= 0)
- {
- 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,
- // and bump UnansweredQueries so that we don't spin trying to send the same cache expiration query repeatedly
- if (q->Target.type) q->SendQNow = mDNSInterfaceMark; // If targeted query, mark it
- else if (!mDNSOpaque16IsZero(q->TargetQID)) { q->LastQTime = m->timenow - q->ThisQInterval; rr->UnansweredQueries++; }
- else if (q->SendQNow == mDNSNULL) q->SendQNow = rr->resrec.InterfaceID;
- else if (q->SendQNow != rr->resrec.InterfaceID) q->SendQNow = mDNSInterfaceMark;
- }
+ // We're expecting to send a query anyway, so see if any expiring cache records are close enough
+ // to their NextRequiredQuery to be worth batching them together with this one
+ FORALL_CACHERECORDS(slot, cg, cr)
+ if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries)
+ if (m->timenow + TicksTTL(cr)/50 - cr->NextRequiredQuery >= 0)
+ {
+ debugf("Sending %d%% cache expiration query for %s", 80 + 5 * cr->UnansweredQueries, CRDisplayString(m, cr));
+ q = cr->CRActiveQuestion;
+ ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(cr)/20, cr->resrec.InterfaceID);
+ // For uDNS queries (TargetQID non-zero) we adjust LastQTime,
+ // and bump UnansweredQueries so that we don't spin trying to send the same cache expiration query repeatedly
+ if (q->Target.type) q->SendQNow = mDNSInterfaceMark; // If targeted query, mark it
+ else if (!mDNSOpaque16IsZero(q->TargetQID)) { q->LastQTime = m->timenow - q->ThisQInterval; cr->UnansweredQueries++; }
+ else if (q->SendQNow == mDNSNULL) q->SendQNow = cr->resrec.InterfaceID;
+ else if (q->SendQNow != cr->resrec.InterfaceID) q->SendQNow = mDNSInterfaceMark;
+ }
- if (m->SuppressStdPort53Queries && m->timenow - m->SuppressStdPort53Queries >= 0)
- m->SuppressStdPort53Queries = 0; // If suppression time has passed, clear it
-
- // Scan our list of questions to see which:
- // *WideArea* queries need to be sent
- // *unicast* queries need to be sent
- // *multicast* queries we're definitely going to send
- if (m->CurrentQuestion)
- LogMsg("SendQueries ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
- m->CurrentQuestion = m->Questions;
- while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
+ // Scan our list of questions to see which:
+ // *WideArea* queries need to be sent
+ // *unicast* queries need to be sent
+ // *multicast* queries we're definitely going to send
+ if (m->CurrentQuestion)
+ LogMsg("SendQueries ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+ m->CurrentQuestion = m->Questions;
+ while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
+ {
+ q = m->CurrentQuestion;
+ if (q->Target.type && (q->SendQNow || TimeToSendThisQuestion(q, m->timenow)))
{
- q = m->CurrentQuestion;
- if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID)) uDNS_CheckCurrentQuestion(m);
- else if (mDNSOpaque16IsZero(q->TargetQID) && q->Target.type && (q->SendQNow || TimeToSendThisQuestion(q, m->timenow)))
- {
- mDNSu8 *qptr = m->omsg.data;
- const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data);
+ mDNSu8 *qptr = m->omsg.data;
+ const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data);
- // 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;
- q->LastQTxTime = m->timenow;
- q->RecentAnswerPkts = 0;
- q->SendQNow = mDNSNULL;
- q->ExpectUnicastResp = NonZeroTime(m->timenow);
- }
- else if (mDNSOpaque16IsZero(q->TargetQID) && !q->Target.type && TimeToSendThisQuestion(q, m->timenow))
+ // 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)
{
- //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;
+ 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 m->CurrentQuestion wasn't modified out from under us, advance it now
- // We can't do this at the start of the loop because uDNS_CheckCurrentQuestion() depends on having
- // m->CurrentQuestion point to the right question
- if (q == m->CurrentQuestion) m->CurrentQuestion = m->CurrentQuestion->next;
- }
- m->CurrentQuestion = mDNSNULL;
+ if (q->ThisQInterval > MaxQuestionInterval)
+ q->ThisQInterval = MaxQuestionInterval;
+ q->LastQTime = m->timenow;
+ q->LastQTxTime = m->timenow;
+ q->RecentAnswerPkts = 0;
+ q->SendQNow = mDNSNULL;
+ q->ExpectUnicastResp = NonZeroTime(m->timenow);
+ }
+ else if (mDNSOpaque16IsZero(q->TargetQID) && !q->Target.type && TimeToSendThisQuestion(q, m->timenow))
+ {
+ //LogInfo("Time to send %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - NextQSendTime(q));
+ q->SendQNow = mDNSInterfaceMark; // Mark this question for sending on all interfaces
+ if (maxExistingQuestionInterval < q->ThisQInterval)
+ maxExistingQuestionInterval = q->ThisQInterval;
+ }
+ // If m->CurrentQuestion wasn't modified out from under us, advance it now
+ // We can't do this at the start of the loop because uDNS_CheckCurrentQuestion() depends on having
+ // m->CurrentQuestion point to the right question
+ if (q == m->CurrentQuestion) m->CurrentQuestion = m->CurrentQuestion->next;
+ }
+ while (m->CurrentQuestion)
+ {
+ LogInfo("SendQueries question loop 1: Skipping NewQuestion %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+ m->CurrentQuestion = m->CurrentQuestion->next;
+ }
+ m->CurrentQuestion = mDNSNULL;
- // Scan our list of questions
- // (a) to see if there are any more that are worth accelerating, and
- // (b) to update the state variables for *all* the questions we're going to send
- // Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list,
- // which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very
- // next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value.
- m->NextScheduledQuery = m->timenow + 0x78000000;
- for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
- {
- if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow ||
- (!q->Target.type && ActiveQuestion(q) && q->ThisQInterval <= maxExistingQuestionInterval && AccelerateThisQuery(m,q))))
+ // Scan our list of questions
+ // (a) to see if there are any more that are worth accelerating, and
+ // (b) to update the state variables for *all* the questions we're going to send
+ // Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list,
+ // which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very
+ // next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value.
+ m->NextScheduledQuery = m->timenow + 0x78000000;
+ for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
+ {
+ if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow ||
+ (!q->Target.type && ActiveQuestion(q) && q->ThisQInterval <= maxExistingQuestionInterval && AccelerateThisQuery(m,q))))
+ {
+ // If at least halfway to next query time, advance to next interval
+ // If less than halfway to next query time, then
+ // treat this as logically a repeat of the last transmission, without advancing the interval
+ if (m->timenow - (q->LastQTime + (q->ThisQInterval/2)) >= 0)
{
- // If at least halfway to next query time, advance to next interval
- // If less than halfway to next query time, then
- // treat this as logically a repeat of the last transmission, without advancing the interval
- if (m->timenow - (q->LastQTime + q->ThisQInterval/2) >= 0)
+ //LogInfo("Accelerating %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - NextQSendTime(q));
+ 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);
+ q->ThisQInterval *= QuestionIntervalStep;
+ if (q->ThisQInterval > MaxQuestionInterval)
+ q->ThisQInterval = MaxQuestionInterval;
+ else if (q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * QuestionIntervalStep3 && !q->RequestUnicast &&
+ !(RRTypeIsAddressType(q->qtype) && CacheHasAddressTypeForName(m, &q->qname, q->qnamehash)))
{
- //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);
- q->ThisQInterval *= QuestionIntervalStep;
- if (q->ThisQInterval > MaxQuestionInterval)
- q->ThisQInterval = MaxQuestionInterval;
- else if (q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * QuestionIntervalStep3 && !q->RequestUnicast &&
- !(RRTypeIsAddressType(q->qtype) && CacheHasAddressTypeForName(m, &q->qname, q->qnamehash)))
- {
- // Generally don't need to log this.
- // It's not especially noteworthy if a query finds no results -- this usually happens for domain
- // enumeration queries in the LL subdomain (e.g. "db._dns-sd._udp.0.0.254.169.in-addr.arpa")
- // and when there simply happen to be no instances of the service the client is looking
- // for (e.g. iTunes is set to look for RAOP devices, and the current network has none).
- debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents",
- q->qname.c, DNSTypeName(q->qtype));
- // Sending third query, and no answers yet; time to begin doubting the source
- ReconfirmAntecedents(m, &q->qname, q->qnamehash, 0);
- }
+ // Generally don't need to log this.
+ // It's not especially noteworthy if a query finds no results -- this usually happens for domain
+ // enumeration queries in the LL subdomain (e.g. "db._dns-sd._udp.0.0.254.169.in-addr.arpa")
+ // and when there simply happen to be no instances of the service the client is looking
+ // for (e.g. iTunes is set to look for RAOP devices, and the current network has none).
+ debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents",
+ q->qname.c, DNSTypeName(q->qtype));
+ // Sending third query, and no answers yet; time to begin doubting the source
+ ReconfirmAntecedents(m, &q->qname, q->qnamehash, 0);
}
+ }
- // Mark for sending. (If no active interfaces, then don't even try.)
- q->SendOnAll = (q->SendQNow == mDNSInterfaceMark);
- if (q->SendOnAll)
- {
- q->SendQNow = !intf ? mDNSNULL : (q->InterfaceID) ? q->InterfaceID : intf->InterfaceID;
- q->LastQTime = m->timenow;
- }
+ // Mark for sending. (If no active interfaces, then don't even try.)
+ q->SendOnAll = (q->SendQNow == mDNSInterfaceMark);
+ if (q->SendOnAll)
+ {
+ q->SendQNow = !intf ? mDNSNULL : (q->InterfaceID) ? q->InterfaceID : intf->InterfaceID;
+ q->LastQTime = m->timenow;
+ }
- // If we recorded a duplicate suppression for this question less than half an interval ago,
- // then we consider it recent enough that we don't need to do an identical query ourselves.
- ExpireDupSuppressInfo(q->DupSuppress, m->timenow - q->ThisQInterval/2);
+ // If we recorded a duplicate suppression for this question less than half an interval ago,
+ // then we consider it recent enough that we don't need to do an identical query ourselves.
+ ExpireDupSuppressInfo(q->DupSuppress, m->timenow - q->ThisQInterval/2);
- q->LastQTxTime = m->timenow;
- q->RecentAnswerPkts = 0;
- if (q->RequestUnicast) q->RequestUnicast--;
- }
- // For all questions (not just the ones we're sending) check what the next scheduled event will be
- SetNextQueryTime(m,q);
+ q->LastQTxTime = m->timenow;
+ q->RecentAnswerPkts = 0;
+ if (q->RequestUnicast) q->RequestUnicast--;
}
+ // For all questions (not just the ones we're sending) check what the next scheduled event will be
+ // We don't need to consider NewQuestions here because for those we'll set m->NextScheduledQuery in AnswerNewQuestion
+ SetNextQueryTime(m,q);
}
// 2. Scan our authoritative RR list to see what probes we might need to send
- if (m->timenow - m->NextScheduledProbe >= 0)
- {
- m->NextScheduledProbe = m->timenow + 0x78000000;
- if (m->CurrentRecord)
- LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
- m->CurrentRecord = m->ResourceRecords;
- while (m->CurrentRecord)
+ m->NextScheduledProbe = m->timenow + 0x78000000;
+
+ if (m->CurrentRecord)
+ LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
+ m->CurrentRecord = m->ResourceRecords;
+ while (m->CurrentRecord)
+ {
+ ar = m->CurrentRecord;
+ m->CurrentRecord = ar->next;
+ if (!AuthRecord_uDNS(ar) && ar->resrec.RecordType == kDNSRecordTypeUnique) // For all records that are still probing...
{
- AuthRecord *rr = m->CurrentRecord;
- m->CurrentRecord = rr->next;
- if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType == kDNSRecordTypeUnique) // For all records that are still probing...
+ // 1. If it's not reached its probe time, just make sure we update m->NextScheduledProbe correctly
+ if (m->timenow - (ar->LastAPTime + ar->ThisAPInterval) < 0)
{
- // 1. If it's not reached its probe time, just make sure we update m->NextScheduledProbe correctly
- if (m->timenow - (rr->LastAPTime + rr->ThisAPInterval) < 0)
+ SetNextAnnounceProbeTime(m, ar);
+ }
+ // 2. else, if it has reached its probe time, mark it for sending and then update m->NextScheduledProbe correctly
+ else if (ar->ProbeCount)
+ {
+ if (ar->AddressProxy.type == mDNSAddrType_IPv4)
{
- SetNextAnnounceProbeTime(m, rr);
+ LogSPS("SendQueries ARP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar));
+ SendARP(m, 1, ar, &zerov4Addr, &zeroEthAddr, &ar->AddressProxy.ip.v4, &ar->WakeUp.IMAC);
}
- // 2. else, if it has reached its probe time, mark it for sending and then update m->NextScheduledProbe correctly
- else if (rr->ProbeCount)
+ else if (ar->AddressProxy.type == mDNSAddrType_IPv6)
{
- if (rr->AddressProxy.type == mDNSAddrType_IPv4)
- {
- char *ifname = InterfaceNameForID(m, rr->resrec.InterfaceID);
- if (!ifname) ifname = "<NULL InterfaceID>";
- LogSPS("SendQueries ARP Probe %d %s %s", rr->ProbeCount, ifname, 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 || 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)
- {
- // If this is the last probe for this record, then see if we have any matching records
- // on our duplicate list which should similarly have their ProbeCount cleared to zero...
- AuthRecord *r2;
- for (r2 = m->DuplicateRecords; r2; r2=r2->next)
- if (r2->resrec.RecordType == kDNSRecordTypeUnique && RecordIsLocalDuplicate(r2, rr))
- r2->ProbeCount = 0;
- // ... then acknowledge this record to the client.
- // We do this optimistically, just as we're about to send the third probe.
- // This helps clients that both advertise and browse, and want to filter themselves
- // from the browse results list, because it helps ensure that the registration
- // confirmation will be delivered 1/4 second *before* the browse "add" event.
- // A potential downside is that we could deliver a registration confirmation and then find out
- // moments later that there's a name conflict, but applications have to be prepared to handle
- // late conflicts anyway (e.g. on connection of network cable, etc.), so this is nothing new.
- if (!rr->Acknowledged) AcknowledgeRecord(m, rr);
- }
+ LogSPS("SendQueries NDP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar));
+ // IPv6 source = zero
+ // No target hardware address
+ // IPv6 target address is address we're probing
+ // Ethernet destination address is Ethernet interface address of the Sleep Proxy client we're probing
+ SendNDP(m, NDP_Sol, 0, ar, &zerov6Addr, mDNSNULL, &ar->AddressProxy.ip.v6, &ar->WakeUp.IMAC);
}
- // else, if it has now finished probing, move it to state Verified,
- // and update m->NextScheduledResponse so it will be announced
- else
+ // Mark for sending. (If no active interfaces, then don't even try.)
+ ar->SendRNow = (!intf || ar->WakeUp.HMAC.l[0]) ? mDNSNULL : ar->resrec.InterfaceID ? ar->resrec.InterfaceID : intf->InterfaceID;
+ ar->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 ar->ProbeCount back to the right value.
+ if (ar->ProbeCount > DefaultProbeCountForTypeUnique)
+ ar->ProbeCount = DefaultProbeCountForTypeUnique;
+ ar->ProbeCount--;
+ SetNextAnnounceProbeTime(m, ar);
+ if (ar->ProbeCount == 0)
{
- if (!rr->Acknowledged) AcknowledgeRecord(m, rr); // Defensive, just in case it got missed somehow
- rr->resrec.RecordType = kDNSRecordTypeVerified;
- rr->ThisAPInterval = DefaultAnnounceIntervalForTypeUnique;
- rr->LastAPTime = m->timenow - DefaultAnnounceIntervalForTypeUnique;
- SetNextAnnounceProbeTime(m, rr);
+ // If this is the last probe for this record, then see if we have any matching records
+ // on our duplicate list which should similarly have their ProbeCount cleared to zero...
+ AuthRecord *r2;
+ for (r2 = m->DuplicateRecords; r2; r2=r2->next)
+ if (r2->resrec.RecordType == kDNSRecordTypeUnique && RecordIsLocalDuplicate(r2, ar))
+ r2->ProbeCount = 0;
+ // ... then acknowledge this record to the client.
+ // We do this optimistically, just as we're about to send the third probe.
+ // This helps clients that both advertise and browse, and want to filter themselves
+ // from the browse results list, because it helps ensure that the registration
+ // confirmation will be delivered 1/4 second *before* the browse "add" event.
+ // A potential downside is that we could deliver a registration confirmation and then find out
+ // moments later that there's a name conflict, but applications have to be prepared to handle
+ // late conflicts anyway (e.g. on connection of network cable, etc.), so this is nothing new.
+ if (!ar->Acknowledged) AcknowledgeRecord(m, ar);
}
}
+ // else, if it has now finished probing, move it to state Verified,
+ // and update m->NextScheduledResponse so it will be announced
+ else
+ {
+ if (!ar->Acknowledged) AcknowledgeRecord(m, ar); // Defensive, just in case it got missed somehow
+ ar->resrec.RecordType = kDNSRecordTypeVerified;
+ ar->ThisAPInterval = DefaultAnnounceIntervalForTypeUnique;
+ ar->LastAPTime = m->timenow - DefaultAnnounceIntervalForTypeUnique;
+ SetNextAnnounceProbeTime(m, ar);
+ }
}
- m->CurrentRecord = m->DuplicateRecords;
- while (m->CurrentRecord)
- {
- AuthRecord *rr = m->CurrentRecord;
- m->CurrentRecord = rr->next;
- if (rr->resrec.RecordType == kDNSRecordTypeUnique && rr->ProbeCount == 0 && !rr->Acknowledged)
- AcknowledgeRecord(m, rr);
- }
+ }
+ m->CurrentRecord = m->DuplicateRecords;
+ while (m->CurrentRecord)
+ {
+ ar = m->CurrentRecord;
+ m->CurrentRecord = ar->next;
+ if (ar->resrec.RecordType == kDNSRecordTypeUnique && ar->ProbeCount == 0 && !ar->Acknowledged)
+ AcknowledgeRecord(m, ar);
}
// 3. Now we know which queries and probes we're sending,
while (intf)
{
const int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0;
- AuthRecord *rr;
mDNSu8 *queryptr = m->omsg.data;
InitializeDNSMessage(&m->omsg.h, zeroID, QueryFlags);
if (KnownAnswerList) verbosedebugf("SendQueries: KnownAnswerList set... Will continue from previous packet");
}
// Put probe questions in this packet
- for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (rr->SendRNow == intf->InterfaceID)
+ for (ar = m->ResourceRecords; ar; ar=ar->next)
+ if (ar->SendRNow == intf->InterfaceID)
{
- mDNSBool ucast = (rr->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353;
+ mDNSBool ucast = (ar->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);
// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
- mDNSu32 forecast = answerforecast + 12 + rr->resrec.rdestimate;
- mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, rr->resrec.name, kDNSQType_ANY, (mDNSu16)(rr->resrec.rrclass | ucbit));
+ mDNSu32 forecast = answerforecast + 12 + ar->resrec.rdestimate;
+ mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, ar->resrec.name, kDNSQType_ANY, (mDNSu16)(ar->resrec.rrclass | ucbit));
if (newptr)
{
queryptr = newptr;
answerforecast = forecast;
- rr->SendRNow = (rr->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
- rr->IncludeInProbe = mDNStrue;
+ ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
+ ar->IncludeInProbe = mDNStrue;
verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d",
- rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->ProbeCount);
+ ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype), ar->ProbeCount);
}
}
}
}
}
- for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (rr->IncludeInProbe)
+ for (ar = m->ResourceRecords; ar; ar=ar->next)
+ if (ar->IncludeInProbe)
{
- mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, &rr->resrec);
- rr->IncludeInProbe = mDNSfalse;
+ mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, &ar->resrec);
+ ar->IncludeInProbe = mDNSfalse;
if (newptr) queryptr = newptr;
- else LogMsg("SendQueries: How did we fail to have space for the Update record %s", ARDisplayString(m,rr));
+ else LogMsg("SendQueries: How did we fail to have space for the Update record %s", ARDisplayString(m,ar));
}
if (queryptr > m->omsg.data)
for (ar = m->ResourceRecords; ar; ar=ar->next)
if (ar->SendRNow)
{
- if (ar->resrec.InterfaceID != mDNSInterface_LocalOnly)
- LogMsg("SendQueries: No active interface to send: %s", ARDisplayString(m, ar));
+ if (ar->resrec.InterfaceID != mDNSInterface_LocalOnly && ar->resrec.InterfaceID != mDNSInterface_P2P)
+ LogMsg("SendQueries: No active interface %p to send probe: %p %s", ar->SendRNow, ar->resrec.InterfaceID, ARDisplayString(m, ar));
ar->SendRNow = mDNSNULL;
}
// state machine ticking over we just pretend we did so.
// If the interface does not come back in time, the cache record will expire naturally
FORALL_CACHERECORDS(slot, cg, cr)
- if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries && m->timenow - cr->NextRequiredQuery >= 0)
- {
- cr->UnansweredQueries++;
- cr->CRActiveQuestion->SendQNow = mDNSNULL;
- SetNextCacheCheckTime(m, cr);
- }
+ if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries)
+ if (m->timenow + TicksTTL(cr)/50 - cr->NextRequiredQuery >= 0)
+ {
+ cr->UnansweredQueries++;
+ cr->CRActiveQuestion->SendQNow = mDNSNULL;
+ SetNextCacheCheckTimeForRecord(m, cr);
+ }
// 4c. Debugging check: Make sure we sent all our planned questions
// Do this AFTER the lingering cache records check above, because that will prevent spurious warnings for questions
for (q = m->Questions; q; q=q->next)
if (q->SendQNow)
{
- LogMsg("SendQueries: No active interface to send: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ DNSQuestion *x;
+ for (x = m->NewQuestions; x; x=x->next) if (x == q) break; // Check if this question is a NewQuestion
+ LogMsg("SendQueries: No active interface %p to send %s question: %p %##s (%s)", q->SendQNow, x ? "new" : "old", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
q->SendQNow = mDNSNULL;
}
}
{
int i, j;
mDNSu8 *ptr = m->omsg.data;
-
- if (!InterfaceID) { LogMsg("SendWakeup: No InterfaceID specified"); return; }
+ NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
+ if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found", InterfaceID); 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;
+ // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
+ for (i=0; i<6; i++) *ptr++ = intf->MAC.b[0];
// 0x0C Ethertype (0x0842)
*ptr++ = 0x08;
DNSQuestion *const q = m->CurrentQuestion;
mDNSBool followcname = rr->resrec.RecordType != kDNSRecordTypePacketNegative && AddRecord &&
rr->resrec.rrtype == kDNSType_CNAME && q->qtype != kDNSType_CNAME;
- verbosedebugf("AnswerCurrentQuestionWithResourceRecord:%4lu %s TTL %d %s", q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, CRDisplayString(m, rr));
+ verbosedebugf("AnswerCurrentQuestionWithResourceRecord:%4lu %s TTL %d %s",
+ q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, CRDisplayString(m, rr));
+
+ if (QuerySuppressed(q)) return;
// Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerCurrentQuestionWithResourceRecord(... mDNStrue)
// may be called twice, once when the record is received, and again when it's time to notify local clients.
if (AddRecord == QC_add && !q->DuplicateOf && rr->CRActiveQuestion != q)
{
if (!rr->CRActiveQuestion) m->rrcache_active++; // If not previously active, increment rrcache_active count
- debugf("AnswerCurrentQuestionWithResourceRecord: Updating CRActiveQuestion to %p for cache record %s", q, CRDisplayString(m,rr));
+ debugf("AnswerCurrentQuestionWithResourceRecord: Updating CRActiveQuestion from %p to %p for cache record %s, CurrentAnswer %d",
+ rr->CRActiveQuestion, q, CRDisplayString(m,rr), q->CurrentAnswers);
rr->CRActiveQuestion = q; // We know q is non-null
- SetNextCacheCheckTime(m, rr);
+ SetNextCacheCheckTimeForRecord(m, rr);
}
// If this is:
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);
+ MakeNegativeCacheRecord(m, &neg, &q->qname, q->qnamehash, q->qtype, q->qclass, 1, rr->resrec.InterfaceID, q->qDNSServer);
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,
- // 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 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.
- LogInfo("AnswerCurrentQuestionWithResourceRecord: following CNAME referral for %s", CRDisplayString(m, rr));
-
- // If this query is a duplicate of another query, UpdateQuestionDuplicates called from
- // mDNS_StopQuery_internal copies the value of CNAMEReferrals from this query to the other
- // query on the Questions list. By setting the new value before calling mDNS_StopQuery_internal,
- // we ensure that the duplicate question gets a hgigher value and eventually the check for 10 above
- // would be true. Otherwise, the two queries would end up as active questions
- // sending mDNSResponder in an infinite loop e.g., Two queries starting off unique but receives
- // a CNAME response that refers to itself (test IN CNAME test) which makes it a duplicate of
- // one another. This fix now will make sure that stop at the 10th iteration.
- //
- // Though CNAME records that refer to itself are not added anymore in mDNSCoreReceiveResponse, this fix is
- // still needed to catch the cases where the CNAME referral spans across multiple records with a potential
- // cycle in it which in turn can make multiple queries duplicate of each other
-
- q->CNAMEReferrals = c;
- 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
- mDNS_StartQuery_internal(m, q); // start new query
- q->CNAMEReferrals = c; // and keep count of how many times we've done this
+ 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,
+ // including starting/stopping queries, registering/deregistering records, etc.
+
+ if (followcname && m->CurrentQuestion == q)
+ {
+ const mDNSBool selfref = SameDomainName(&q->qname, &rr->resrec.rdata->u.name);
+ if (q->CNAMEReferrals >= 10 || selfref)
+ LogMsg("AnswerCurrentQuestionWithResourceRecord: %p %##s (%s) NOT following CNAME referral %d%s for %s",
+ q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, selfref ? " (Self-Referential)" : "", CRDisplayString(m, rr));
+ else
+ {
+ const mDNSu32 c = q->CNAMEReferrals + 1; // Stash a copy of the new q->CNAMEReferrals value
+
+ // The SameDomainName check above is to ignore bogus CNAME records that point right back at
+ // themselves. Without that check we can get into a case where we have two duplicate questions,
+ // A and B, and when we stop question A, UpdateQuestionDuplicates copies the value of CNAMEReferrals
+ // from A to B, and then A is re-appended to the end of the list as a duplicate of B (because
+ // the target name is still the same), and then when we stop question B, UpdateQuestionDuplicates
+ // copies the B's value of CNAMEReferrals back to A, and we end up not incrementing CNAMEReferrals
+ // for either of them. This is not a problem for CNAME loops of two or more records because in
+ // those cases the newly re-appended question A has a different target name and therefore cannot be
+ // a duplicate of any other question ('B') which was itself a duplicate of the previous question A.
+
+ // 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 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.
+ LogInfo("AnswerCurrentQuestionWithResourceRecord: %p %##s (%s) following CNAME referral %d for %s",
+ q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, 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
+ mDNS_StartQuery_internal(m, q); // start new query
+ // Record how many times we've done this. We need to do this *after* mDNS_StartQuery_internal,
+ // because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero
+ q->CNAMEReferrals = c;
+ }
+ }
+ }
+
+// New Questions are answered through AnswerNewQuestion. But there may not have been any
+// matching cache records for the questions when it is called. There are two possibilities.
+//
+// 1) There are no cache records
+// 2) There are cache records but the DNSServers between question and cache record don't match.
+//
+// In the case of (1), where there are no cache records and later we add them when we get a response,
+// CacheRecordAdd/CacheRecordDeferredAdd will take care of adding the cache and delivering the ADD
+// events to the application. If we already have a cache entry, then no ADD events are delivered
+// unless the RDATA has changed
+//
+// In the case of (2) where we had the cache records and did not answer because of the DNSServer mismatch,
+// we need to answer them whenever we change the DNSServer. But we can't do it at the instant the DNSServer
+// changes because when we do the callback, the question can get deleted and the calling function would not
+// know how to handle it. So, we run this function from mDNS_Execute to handle DNSServer changes on the
+// question
+
+mDNSlocal void AnswerQuestionsForDNSServerChanges(mDNS *const m)
+ {
+ DNSQuestion *q;
+ DNSQuestion *qnext;
+ CacheRecord *rr;
+ mDNSu32 slot;
+ CacheGroup *cg;
+
+ if (m->CurrentQuestion)
+ LogMsg("AnswerQuestionsForDNSServerChanges: ERROR m->CurrentQuestion already set: %##s (%s)",
+ m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+
+ for (q = m->Questions; q && q != m->NewQuestions; q = qnext)
+ {
+ qnext = q->next;
+
+ // multicast or DNSServers did not change.
+ if (mDNSOpaque16IsZero(q->TargetQID)) continue;
+ if (!q->deliverAddEvents) continue;
+
+ // We are going to look through the cache for this question since it changed
+ // its DNSserver last time. Reset it so that we don't call them again. Calling
+ // them again will deliver duplicate events to the application
+ q->deliverAddEvents = mDNSfalse;
+ if (QuerySuppressed(q)) continue;
+ m->CurrentQuestion = q;
+ slot = HashSlot(&q->qname);
+ cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
+ {
+ if (SameNameRecordAnswersQuestion(&rr->resrec, q))
+ {
+ LogInfo("AnswerQuestionsForDNSServerChanges: Calling AnswerCurrentQuestionWithResourceRecord for question %p %##s using resource record %s",
+ q, q->qname.c, CRDisplayString(m, rr));
+ // When this question penalizes a DNS server and has no more DNS servers to pick, we normally
+ // deliver a negative cache response and suspend the question for 60 seconds (see uDNS_CheckCurrentQuestion).
+ // But sometimes we may already find the negative cache entry and deliver that here as the process
+ // of changing DNS servers. When the cache entry is about to expire, we will resend the question and
+ // that time, we need to make sure that we have a valid DNS server. Otherwise, we will deliver
+ // a negative cache response without trying the server.
+ if (!q->qDNSServer && !q->DuplicateOf && rr->resrec.RecordType == kDNSRecordTypePacketNegative)
+ {
+ DNSQuestion *qptr;
+ SetValidDNSServers(m, q);
+ q->qDNSServer = GetServerForQuestion(m, q);
+ for (qptr = q->next ; qptr; qptr = qptr->next)
+ if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; }
+ }
+ q->CurrentAnswers++;
+ if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
+ if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
+ AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
+ if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here
+ }
+ }
}
+ m->CurrentQuestion = mDNSNULL;
}
mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr)
{
- rr->DelayDelivery = 0; // Note, only need to call SetNextCacheCheckTime() when DelayDelivery is set, not when it's cleared
+ rr->DelayDelivery = 0;
if (m->CurrentQuestion)
- LogMsg("CacheRecordDeferredAdd ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+ LogMsg("CacheRecordDeferredAdd ERROR m->CurrentQuestion already set: %##s (%s)",
+ m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
m->CurrentQuestion = m->Questions;
while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
{
else return(0);
}
-// CacheRecordAdd is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call.
+// CacheRecordAdd is only called from CreateNewCacheEntry, *never* directly as a result of a client API call.
// If new questions are created as a result of invoking client callbacks, they will be added to
// 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
SetNextQueryTime(m,q);
}
}
- verbosedebugf("CacheRecordAdd %p %##s (%s) %lu",
- rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl);
+ verbosedebugf("CacheRecordAdd %p %##s (%s) %lu %#a:%d question %p", rr, rr->resrec.name->c,
+ DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl, rr->resrec.rDNSServer ?
+ &rr->resrec.rDNSServer->addr : mDNSNULL, mDNSVal16(rr->resrec.rDNSServer ?
+ rr->resrec.rDNSServer->port : zeroIPPort), q);
q->CurrentAnswers++;
q->unansweredQueries = 0;
if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
m->CurrentQuestion = mDNSNULL;
}
- SetNextCacheCheckTime(m, rr);
+ SetNextCacheCheckTimeForRecord(m, rr);
}
// NoCacheAnswer is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call.
mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr)
{
if (m->CurrentQuestion)
- LogMsg("CacheRecordRmv ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+ LogMsg("CacheRecordRmv ERROR m->CurrentQuestion already set: %##s (%s)",
+ m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
m->CurrentQuestion = m->Questions;
// We stop when we get to NewQuestions -- for new questions their CurrentAnswers/LargeAnswers/UniqueAnswers counters
while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
{
DNSQuestion *q = m->CurrentQuestion;
- if (ResourceRecordAnswersQuestion(&rr->resrec, q))
+ // When a question enters suppressed state, we generate RMV events and generate a negative
+ // response. A cache may be present that answers this question e.g., cache entry generated
+ // before the question became suppressed. We need to skip the suppressed questions here as
+ // the RMV event has already been generated.
+ if (!QuerySuppressed(q) && ResourceRecordAnswersQuestion(&rr->resrec, q))
{
verbosedebugf("CacheRecordRmv %p %s", rr, CRDisplayString(m, rr));
q->FlappingInterface1 = mDNSNULL;
q->FlappingInterface2 = mDNSNULL;
+
+ // When a question changes DNS server, it is marked with deliverAddEvents if we find any
+ // cache entry corresponding to the new DNS server. Before we deliver the ADD event, the
+ // cache entry may be removed in which case CurrentAnswers can be zero.
+ if (q->deliverAddEvents && !q->CurrentAnswers)
+ {
+ LogInfo("CacheRecordRmv: Question %p %##s (%s) deliverAddEvents set, DNSServer %#a:%d",
+ q, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL,
+ mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort));
+ m->CurrentQuestion = q->next;
+ continue;
+ }
if (q->CurrentAnswers == 0)
- LogMsg("CacheRecordRmv ERROR: How can CurrentAnswers already be zero for %p %##s (%s)?",
- q, q->qname.c, DNSTypeName(q->qtype));
+ LogMsg("CacheRecordRmv ERROR!!: How can CurrentAnswers already be zero for %p %##s (%s) DNSServer %#a:%d",
+ q, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL,
+ mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort));
else
{
q->CurrentAnswers--;
// Note: We want to be careful that we deliver all the CacheRecordRmv calls before delivering
// CacheRecordDeferredAdd calls. The in-order nature of the cache lists ensures that all
// callbacks for old records are delivered before callbacks for newer records.
-mDNSlocal void CheckCacheExpiration(mDNS *const m, CacheGroup *const cg)
+mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGroup *const cg)
{
CacheRecord **rp = &cg->members;
m->timenow - rr->TimeRcvd, rr->resrec.rroriginalttl, rr->CRActiveQuestion, CRDisplayString(m, rr));
if (rr->CRActiveQuestion) // If this record has one or more active questions, tell them it's going away
{
+ DNSQuestion *q = rr->CRActiveQuestion;
+ // When a cache record is about to expire, we expect to do four queries at 80-82%, 85-87%, 90-92% and
+ // then 95-97% of the TTL. If the DNS server does not respond, then we will remove the cache entry
+ // before we pick a new DNS server. As the question interval is set to MaxQuestionInterval, we may
+ // not send out a query anytime soon. Hence, we need to reset the question interval. If this is
+ // a normal deferred ADD case, then AnswerCurrentQuestionWithResourceRecord will reset it to
+ // MaxQuestionInterval. If we have inactive questions referring to negative cache entries,
+ // don't ressurect them as they will deliver duplicate "No such Record" ADD events
+ if (!mDNSOpaque16IsZero(q->TargetQID) && !q->LongLived && ActiveQuestion(q))
+ {
+ q->ThisQInterval = InitialQuestionInterval;
+ q->LastQTime = m->timenow - q->ThisQInterval;
+ SetNextQueryTime(m, q);
+ }
CacheRecordRmv(m, rr);
m->rrcache_active--;
}
}
else // else, not expired; see if we need to query
{
+ // If waiting to delay delivery, do nothing until then
if (rr->DelayDelivery && rr->DelayDelivery - m->timenow > 0)
event = rr->DelayDelivery;
else
if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
{
if (m->timenow - rr->NextRequiredQuery < 0) // If not yet time for next query
- event = rr->NextRequiredQuery; // then just record when we want the next query
+ event = NextCacheCheckEvent(rr); // then just record when we want the next query
else // else trigger our question to go out now
{
// Set NextScheduledQuery to timenow so that SendQueries() will run.
// SendQueries() will see that we have records close to expiration, and send FEQs for them.
m->NextScheduledQuery = m->timenow;
- // After sending the query we'll increment UnansweredQueries and call SetNextCacheCheckTime(),
+ // After sending the query we'll increment UnansweredQueries and call SetNextCacheCheckTimeForRecord(),
// which will correctly update m->NextCacheCheck for us.
event = m->timenow + 0x3FFFFFFF;
}
}
verbosedebugf("CheckCacheExpiration:%6d %5d %s",
(event - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m, rr));
- if (m->NextCacheCheck - (event + CacheCheckGracePeriod(rr)) > 0)
- m->NextCacheCheck = (event + CacheCheckGracePeriod(rr));
+ if (m->rrcache_nextcheck[slot] - event > 0)
+ m->rrcache_nextcheck[slot] = event;
rp = &rr->next;
}
}
m->lock_rrcache = 0;
}
+// Caller should hold the lock
+mDNSlocal void AnswerSuppressUnusableQuestion(mDNS *const m, DNSQuestion *q)
+ {
+ LogInfo("AnswerSuppressUnusableQuestion: Generating negative response for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ if (!m->CurrentQuestion) LogMsg("AnswerSuppressUnusableQuestion: ERROR!! CurrentQuestion not set");
+
+ MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any, mDNSNULL);
+ AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, QC_addnocache);
+ if (m->CurrentQuestion == q) q->ThisQInterval = 0; // Deactivate this question
+ // Don't touch the question after this
+ m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
+ }
+
mDNSlocal void AnswerNewQuestion(mDNS *const m)
{
mDNSBool ShouldQueryImmediately = mDNStrue;
- DNSQuestion *q = m->NewQuestions; // Grab the question we're going to answer
+ DNSQuestion *const q = m->NewQuestions; // Grab the question we're going to answer
const mDNSu32 slot = HashSlot(&q->qname);
CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
verbosedebugf("AnswerNewQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- if (cg) CheckCacheExpiration(m, cg);
- m->NewQuestions = q->next; // Advance NewQuestions to the next *after* calling CheckCacheExpiration();
-
+ if (cg) CheckCacheExpiration(m, slot, cg);
+ if (m->NewQuestions != q) { LogInfo("AnswerNewQuestion: Question deleted while doing CheckCacheExpiration"); goto exit; }
+ m->NewQuestions = q->next;
+ // Advance NewQuestions to the next *after* calling CheckCacheExpiration, because if we advance it first
+ // then CheckCacheExpiration may give this question add/remove callbacks, and it's not yet ready for that.
+ //
+ // Also, CheckCacheExpiration() calls CacheRecordDeferredAdd() and CacheRecordRmv(), which invoke
+ // client callbacks, which may delete their own or any other question. Our mechanism for detecting
+ // whether our current m->NewQuestions question got deleted by one of these callbacks is to store the
+ // value of m->NewQuestions in 'q' before calling CheckCacheExpiration(), and then verify afterwards
+ // that they're still the same. If m->NewQuestions has changed (because mDNS_StopQuery_internal
+ // advanced it), that means the question was deleted, so we no longer need to worry about answering
+ // it (and indeed 'q' is now a dangling pointer, so dereferencing it at all would be bad, and the
+ // values we computed for slot and cg are now stale and relate to a question that no longer exists).
+ //
+ // We can't use the usual m->CurrentQuestion mechanism for this because CacheRecordDeferredAdd() and
+ // CacheRecordRmv() both use that themselves when walking the list of (non-new) questions generating callbacks.
+ // Fortunately mDNS_StopQuery_internal auto-advances both m->CurrentQuestion *AND* m->NewQuestions when
+ // deleting a question, so luckily we have an easy alternative way of detecting if our question got deleted.
+
if (m->lock_rrcache) LogMsg("AnswerNewQuestion ERROR! Cache already locked!");
// This should be safe, because calling the client's question callback may cause the
// question list to be modified, but should not ever cause the rrcache list to be modified.
// be advanced, and we'll exit out of the loop
m->lock_rrcache = 1;
if (m->CurrentQuestion)
- LogMsg("AnswerNewQuestion ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+ LogMsg("AnswerNewQuestion ERROR m->CurrentQuestion already set: %##s (%s)",
+ m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
m->CurrentQuestion = q; // Indicate which question we're answering, so we'll know if it gets deleted
if (q->NoAnswer == NoAnswer_Fail)
{
LogMsg("AnswerNewQuestion: NoAnswer_Fail %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any);
+ MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any, q->qDNSServer);
q->NoAnswer = NoAnswer_Normal; // Temporarily turn off answer suppression
AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, QC_addnocache);
q->NoAnswer = NoAnswer_Fail; // Restore NoAnswer state
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
}
+ if (m->CurrentQuestion != q) { LogInfo("AnswerNewQuestion: Question deleted while generating NoAnswer_Fail response"); goto exit; }
// If 'mDNSInterface_Any' question, see if we want to tell it about LocalOnly records
- if (m->CurrentQuestion == q && q->InterfaceID == mDNSInterface_Any)
+ if (q->InterfaceID == mDNSInterface_Any)
{
if (m->CurrentRecord)
LogMsg("AnswerNewQuestion ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
{
AuthRecord *rr = m->CurrentRecord;
m->CurrentRecord = rr->next;
- if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
+ if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly || rr->resrec.InterfaceID == mDNSInterface_P2P)
if (ResourceRecordAnswersQuestion(&rr->resrec, q))
{
AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, mDNStrue);
}
m->CurrentRecord = mDNSNULL;
}
+ if (m->CurrentQuestion != q) { LogInfo("AnswerNewQuestion: Question deleted while while giving LocalOnly record answers"); goto exit; }
- if (m->CurrentQuestion != q) debugf("AnswerNewQuestion: question deleted while giving LocalOnly record answers");
-
- if (m->CurrentQuestion == q)
+ // If we are not supposed to answer this question, generate a negative response.
+ // Temporarily suspend the SuppressQuery so that AnswerCurrentQuestionWithResourceRecord can answer the question
+ if (QuerySuppressed(q)) { q->SuppressQuery = mDNSfalse; AnswerSuppressUnusableQuestion(m, q); q->SuppressQuery = mDNStrue; }
+ else
{
CacheRecord *rr;
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
else if (RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype))
ShouldQueryImmediately = mDNSfalse;
}
+ // We don't use LogInfo for this "Question deleted" message because it happens so routinely that
+ // it's not remotely remarkable, and therefore unlikely to be of much help tracking down bugs.
+ if (m->CurrentQuestion != q) { debugf("AnswerNewQuestion: Question deleted while giving cache answers"); goto exit; }
- if (m->CurrentQuestion != q) debugf("AnswerNewQuestion: question deleted while giving cache answers");
-
- if (m->CurrentQuestion == q && ShouldQueryImmediately && ActiveQuestion(q))
+ if (ShouldQueryImmediately && ActiveQuestion(q))
{
debugf("AnswerNewQuestion: ShouldQueryImmediately %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
q->ThisQInterval = InitialQuestionInterval;
m->RandomQueryDelay = (mDNSPlatformOneSecond + mDNSRandom(mDNSPlatformOneSecond*5) - 1) / 50 + 1;
q->LastQTime += m->RandomQueryDelay;
}
-
- if (m->NextScheduledQuery - (q->LastQTime + q->ThisQInterval) > 0)
- m->NextScheduledQuery = (q->LastQTime + q->ThisQInterval);
}
+ // IN ALL CASES make sure that m->NextScheduledQuery is set appropriately.
+ // In cases where m->NewQuestions->DelayAnswering is set, we may have delayed generating our
+ // answers for this question until *after* its scheduled transmission time, in which case
+ // m->NextScheduledQuery may now be set to 'never', and in that case -- even though we're *not* doing
+ // ShouldQueryImmediately -- we still need to make sure we set m->NextScheduledQuery correctly.
+ SetNextQueryTime(m,q);
+
+exit:
m->CurrentQuestion = mDNSNULL;
m->lock_rrcache = 0;
}
debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
if (m->CurrentQuestion)
- LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+ LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentQuestion already set: %##s (%s)",
+ m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
m->CurrentQuestion = q; // Indicate which question we're answering, so we'll know if it gets deleted
if (m->CurrentRecord)
rr->TimeRcvd = m->timenow - mDNSPlatformOneSecond * 60;
rr->UnansweredQueries = MaxUnansweredQueries;
rr->resrec.rroriginalttl = 0;
- SetNextCacheCheckTime(m, rr);
+ SetNextCacheCheckTimeForRecord(m, rr);
}
mDNSexport mDNSs32 mDNS_TimeNow(const mDNS *const m)
while (m->CurrentRecord)
{
AuthRecord *rr = m->CurrentRecord;
- if (rr->WakeUp.HMAC.l[0])
+ if (rr->resrec.RecordType != kDNSRecordTypeDeregistering && rr->WakeUp.HMAC.l[0])
{
- if (m->timenow - rr->TimeExpire < 0) // If proxy record not expired yet, update m->NextScheduledSPS
+ // If m->SPSSocket is NULL that means we're not acting as a sleep proxy any more,
+ // so we need to cease proxying for *all* records we may have, expired or not.
+ if (m->SPSSocket && 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
+ else // else proxy record expired, so remove it
{
- LogSPS("mDNS_Execute: Removing %d H-MAC %.6a I-MAC %.6a %d %s",
+ LogSPS("CheckProxyRecords: 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.
+ // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
+ // new records could have been added to the end of the list as a result of that call.
if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
m->CurrentRecord = rr->next;
}
if (m->timenow - m->NextScheduledEvent >= 0)
{
int i;
-
- // If there are DNS servers that will come out of the Penalty box, we should do that now
- // so that any questions that we send below can start using that
- ResetDNSServerPenalties(m);
+ AuthRecord *head, *tail;
verbosedebugf("mDNS_Execute");
+
if (m->CurrentQuestion)
- LogMsg("mDNS_Execute: ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+ LogMsg("mDNS_Execute: ERROR m->CurrentQuestion already set: %##s (%s)",
+ m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+
+ if (m->CurrentRecord)
+ LogMsg("mDNS_Execute: ERROR m->CurrentRecord already set: %s", ARDisplayString(m, m->CurrentRecord));
// 1. If we're past the probe suppression time, we can clear it
if (m->SuppressProbes && m->timenow - m->SuppressProbes >= 0) m->SuppressProbes = 0;
// 3. Purge our cache of stale old records
if (m->rrcache_size && m->timenow - m->NextCacheCheck >= 0)
{
- mDNSu32 slot;
+ mDNSu32 slot, numchecked = 0;
m->NextCacheCheck = m->timenow + 0x3FFFFFFF;
for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
{
- CacheGroup **cp = &m->rrcache_hash[slot];
- while (*cp)
+ if (m->timenow - m->rrcache_nextcheck[slot] >= 0)
{
- CheckCacheExpiration(m, *cp);
- if ((*cp)->members) cp=&(*cp)->next;
- else ReleaseCacheGroup(m, cp);
+ CacheGroup **cp = &m->rrcache_hash[slot];
+ m->rrcache_nextcheck[slot] = m->timenow + 0x3FFFFFFF;
+ while (*cp)
+ {
+ debugf("m->NextCacheCheck %4d Slot %3d %##s", numchecked, slot, *cp ? (*cp)->name : (domainname*)"\x04NULL");
+ numchecked++;
+ CheckCacheExpiration(m, slot, *cp);
+ if ((*cp)->members) cp=&(*cp)->next;
+ else ReleaseCacheGroup(m, cp);
+ }
}
+ // Even if we didn't need to actually check this slot yet, still need to
+ // factor its nextcheck time into our overall NextCacheCheck value
+ if (m->NextCacheCheck - m->rrcache_nextcheck[slot] > 0)
+ m->NextCacheCheck = m->rrcache_nextcheck[slot];
}
+ debugf("m->NextCacheCheck %4d checked, next in %d", numchecked, m->NextCacheCheck - m->timenow);
}
if (m->timenow - m->NextScheduledSPS >= 0)
AnswerNewQuestion(m);
}
if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewQuestion exceeded loop limit");
+
+ // Make sure we deliver *all* local RMV events, and clear the corresponding rr->AnsweredLocalQ flags, *before*
+ // we begin generating *any* new ADD events in the m->NewLocalOnlyQuestions and m->NewLocalRecords loops below.
+ for (i=0; i<1000 && m->LocalRemoveEvents; i++)
+ {
+ m->LocalRemoveEvents = mDNSfalse;
+ m->CurrentRecord = m->ResourceRecords;
+ while (m->CurrentRecord)
+ {
+ AuthRecord *rr = m->CurrentRecord;
+ if (rr->AnsweredLocalQ && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
+ {
+ debugf("mDNS_Execute: Generating local RMV events for %s", ARDisplayString(m, rr));
+ rr->resrec.RecordType = kDNSRecordTypeShared;
+ AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse);
+ if (m->CurrentRecord == rr) // If rr still exists in list, restore its state now
+ {
+ rr->resrec.RecordType = kDNSRecordTypeDeregistering;
+ rr->AnsweredLocalQ = mDNSfalse;
+ }
+ }
+ if (m->CurrentRecord == rr) // If m->CurrentRecord was not auto-advanced, do it ourselves now
+ m->CurrentRecord = rr->next;
+ }
+ }
+ if (i >= 1000) LogMsg("mDNS_Execute: m->LocalRemoveEvents exceeded loop limit");
for (i=0; m->NewLocalOnlyQuestions && i<1000; i++) AnswerNewLocalOnlyQuestion(m);
if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewLocalOnlyQuestion exceeded loop limit");
- for (i=0; i<1000 && m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords); i++)
+ head = tail = mDNSNULL;
+ for (i=0; i<1000 && m->NewLocalRecords && m->NewLocalRecords != head; i++)
{
AuthRecord *rr = m->NewLocalRecords;
m->NewLocalRecords = m->NewLocalRecords->next;
- AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNStrue);
+ if (LocalRecordReady(rr))
+ {
+ debugf("mDNS_Execute: Delivering Add event with LocalAuthRecord %s", ARDisplayString(m, rr));
+ AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNStrue);
+ }
+ else if (!rr->next)
+ {
+ // If we have just one record that is not ready, we don't have to unlink and
+ // reinsert. As the NewLocalRecords will be NULL for this case, the loop will
+ // terminate and set the NewLocalRecords to rr.
+ debugf("mDNS_Execute: Just one LocalAuthRecord %s, breaking out of the loop early", ARDisplayString(m, rr));
+ if (head != mDNSNULL || m->NewLocalRecords != mDNSNULL)
+ LogMsg("mDNS_Execute: ERROR!!: head %p, NewLocalRecords %p", head, m->NewLocalRecords);
+
+ head = rr;
+ }
+ else
+ {
+ AuthRecord **p = &m->ResourceRecords; // Find this record in our list of active records
+ debugf("mDNS_Execute: Skipping LocalAuthRecord %s", ARDisplayString(m, rr));
+ // if this is the first record we are skipping, move to the end of the list.
+ // if we have already skipped records before, append it at the end.
+ while (*p && *p != rr) p=&(*p)->next;
+ if (*p) *p = rr->next; // Cut this record from the list
+ else { LogMsg("mDNS_Execute: ERROR!! Cannot find record %s in ResourceRecords list", ARDisplayString(m, rr)); break; }
+ if (!head)
+ {
+ while (*p) p=&(*p)->next;
+ *p = rr;
+ head = tail = rr;
+ }
+ else
+ {
+ tail->next = rr;
+ tail = rr;
+ }
+ rr->next = mDNSNULL;
+ }
}
- if (i >= 1000) LogMsg("mDNS_Execute: AnswerForNewLocalRecords exceeded loop limit");
+ m->NewLocalRecords = head;
+ debugf("mDNS_Execute: Setting NewLocalRecords to %s", (head ? ARDisplayString(m, head) : "NULL"));
+
+ if (i >= 1000) LogMsg("mDNS_Execute: m->NewLocalRecords exceeded loop limit");
- // 5. See what packets we need to send
+ // 5. Some questions may have picked a new DNS server and the cache may answer these questions now.
+ AnswerQuestionsForDNSServerChanges(m);
+
+ // 6. See what packets we need to send
if (m->mDNSPlatformStatus != mStatus_NoError || (m->SleepState == SleepState_Sleeping))
DiscardDeregistrations(m);
if (m->mDNSPlatformStatus == mStatus_NoError && (m->SuppressSending == 0 || m->timenow - m->SuppressSending >= 0))
// Finally, we send responses, including the previously mentioned records that just completed probing.
m->SuppressSending = 0;
- // 6. Send Query packets. This may cause some probing records to advance to announcing state
+ // 7. Send Query packets. This may cause some probing records to advance to announcing state
if (m->timenow - m->NextScheduledQuery >= 0 || m->timenow - m->NextScheduledProbe >= 0) SendQueries(m);
if (m->timenow - m->NextScheduledQuery >= 0)
{
m->timenow, m->NextScheduledQuery, m->timenow - m->NextScheduledQuery);
m->NextScheduledQuery = m->timenow + mDNSPlatformOneSecond;
for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
- if (ActiveQuestion(q) && q->LastQTime + q->ThisQInterval - m->timenow <= 0)
+ if (ActiveQuestion(q) && m->timenow - NextQSendTime(q) >= 0)
LogMsg("mDNS_Execute: SendQueries didn't send %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
}
if (m->timenow - m->NextScheduledProbe >= 0)
m->NextScheduledProbe = m->timenow + mDNSPlatformOneSecond;
}
- // 7. Send Response packets, including probing records just advanced to announcing state
+ // 8. Send Response packets, including probing records just advanced to announcing state
if (m->timenow - m->NextScheduledResponse >= 0) SendResponses(m);
if (m->timenow - m->NextScheduledResponse >= 0)
{
// Clear RandomDelay values, ready to pick a new different value next time
m->RandomQueryDelay = 0;
m->RandomReconfirmDelay = 0;
+
+#ifndef UNICAST_DISABLED
+ if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0) UpdateAllSRVRecords(m);
+ if (m->timenow - m->NextScheduledNATOp >= 0) CheckNATMappings(m);
+ if (m->timenow - m->NextuDNSEvent >= 0) uDNS_Tasks(m);
+#endif
}
// Note about multi-threaded systems:
// callback function should call mDNS_Execute() (and ignore the return value, which may already be stale
// by the time it gets to the timer callback function).
-#ifndef UNICAST_DISABLED
- uDNS_Execute(m);
-#endif
mDNS_Unlock(m); // Calling mDNS_Unlock is what gives m->NextScheduledEvent its new value
return(m->NextScheduledEvent);
}
// Otherwise we can get the situation where the A query completes really fast (with an NXDOMAIN result) and the
// caller then gives up waiting for the AAAA result while we're still in the process of setting up the tunnel.
// To level the playing field, we block both A and AAAA queries while tunnel setup is in progress, and then
- // returns results for both at the same time.
- if (RRTypeIsAddressType(question->qtype) && question->AuthInfo && question->AuthInfo->AutoTunnel && question->QuestionCallback != AutoTunnelCallback)
+ // returns results for both at the same time. If we are looking for the _autotunnel6 record, then skip this logic
+ // as this would trigger looking up _autotunnel6._autotunnel6 and end up failing the original query.
+
+ if (RRTypeIsAddressType(question->qtype) && PrivateQuery(question) &&
+ !SameDomainLabel(question->qname.c, (const mDNSu8 *)"\x0c_autotunnel6")&& question->QuestionCallback != AutoTunnelCallback)
{
question->NoAnswer = NoAnswer_Suspended;
AddNewClientTunnel(m, question);
if (!question->DuplicateOf)
{
debugf("ActivateUnicastQuery: %##s %s%s%s",
- question->qname.c, DNSTypeName(question->qtype), question->AuthInfo ? " (Private)" : "", ScheduleImmediately ? " ScheduleImmediately" : "");
+ question->qname.c, DNSTypeName(question->qtype), PrivateQuery(question) ? " (Private)" : "", ScheduleImmediately ? " ScheduleImmediately" : "");
+ question->CNAMEReferrals = 0;
if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
if (question->LongLived)
{
#ifndef UNICAST_DISABLED
// 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));
+ LogMsg("mDNSCoreRestartQueries: ERROR m->CurrentQuestion already set: %##s (%s)",
+ m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
m->CurrentQuestion = m->Questions;
while (m->CurrentQuestion)
{
q = m->CurrentQuestion;
m->CurrentQuestion = m->CurrentQuestion->next;
- if (!mDNSOpaque16IsZero(q->TargetQID)) ActivateUnicastQuery(m, q, mDNStrue);
+ if (!mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q)) ActivateUnicastQuery(m, q, mDNStrue);
}
#endif
#pragma mark - Power Management (Sleep/Wake)
#endif
+mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m)
+ {
+#ifndef IDLESLEEPCONTROL_DISABLED
+ mDNSBool allowSleep = mDNStrue;
+
+ if (m->SystemSleepOnlyIfWakeOnLAN)
+ {
+ // Don't sleep if we are a proxy for any services
+ if (m->ProxyRecords)
+ {
+ allowSleep = mDNSfalse;
+ LogInfo("Sleep disabled because we are proxying %d records", m->ProxyRecords);
+ }
+
+ if (allowSleep && mDNSCoreHaveAdvertisedMulticastServices(m))
+ {
+ // Scan the list of active interfaces
+ NetworkInterfaceInfo *intf;
+ for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+ {
+ if (intf->McastTxRx)
+ {
+ // Disallow sleep if this interface doesn't support NetWake
+ if (!intf->NetWake)
+ {
+ allowSleep = mDNSfalse;
+ LogInfo("Sleep disabled because %s does not support NetWake", intf->ifname);
+ break;
+ }
+
+ // Disallow sleep if there is no sleep proxy server
+ if (FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL) == mDNSNULL)
+ {
+ allowSleep = mDNSfalse;
+ LogInfo("Sleep disabled because %s has no sleep proxy", intf->ifname);
+ break;
+ }
+ }
+ }
+ }
+#endif /* !defined(IDLESLEEPCONTROL_DISABLED) */
+ }
+
+ // Call the platform code to enable/disable sleep
+ mDNSPlatformSetAllowSleep(m, allowSleep);
+ }
+
mDNSlocal void SendSPSRegistration(mDNS *const m, NetworkInterfaceInfo *intf, const mDNSOpaque16 id)
{
const int optspace = DNSOpt_Header_Space + DNSOpt_LeaseData_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC);
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;
+ int sps = (int)(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
- // if (answer->rrtype == kDNSType_AAAA) return; // To test failing to resolve sleep proxy's address
-
- mDNS_StopQuery(m, question);
- question->ThisQInterval = -1;
+ // if (answer->rrtype == kDNSType_AAAA && sps == 0) return; // To test failing to resolve sleep proxy's address
if (answer->rrtype == kDNSType_SRV)
{
+ // 1. Got the SRV record; now look up the target host's IPv6 link-local address
+ mDNS_StopQuery(m, question);
intf->SPSPort[sps] = answer->rdata->u.srv.port;
AssignDomainName(&question->qname, &answer->rdata->u.srv.target);
question->qtype = kDNSType_AAAA;
}
else if (answer->rrtype == kDNSType_AAAA && answer->rdlength == sizeof(mDNSv6Addr) && mDNSv6AddressIsLinkLocal(&answer->rdata->u.ipv6))
{
+ // 2. Got the target host's IPv6 link-local address; record address and initiate an SPS registration if appropriate
+ mDNS_StopQuery(m, question);
+ question->ThisQInterval = -1;
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
+ else if (answer->rrtype == kDNSType_AAAA && answer->rdlength == 0)
{
+ // 3. Got negative response -- target host apparently has IPv6 disabled -- so try looking up the target host's IPv4 address(es) instead
+ mDNS_StopQuery(m, question);
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))
{
+ // 4. Got an IPv4 address for the target host; record address and initiate an SPS registration if appropriate
+ mDNS_StopQuery(m, question);
+ question->ThisQInterval = -1;
intf->SPSAddr[sps].type = mDNSAddrType_IPv4;
intf->SPSAddr[sps].ip.v4 = answer->rdata->u.ipv4;
mDNS_Lock(m);
m->SleepState = SleepState_Sleeping;
#ifndef UNICAST_DISABLED
- SleepServiceRegistrations(m);
SleepRecordRegistrations(m); // If we have no SPS, need to deregister our uDNS records
-#endif
+#endif /* UNICAST_DISABLED */
// Mark all the records we need to deregister and send them
for (rr = m->ResourceRecords; rr; rr=rr->next)
{
FindSPSInCache(m, &intf->NetWakeBrowse, sps);
if (!sps[0]) LogSPS("BeginSleepProcessing: %-6s %#a No Sleep Proxy Server found (Next Browse Q in %d, interval %d)",
- intf->ifname, &intf->ip, intf->NetWakeBrowse.LastQTime + intf->NetWakeBrowse.ThisQInterval - m->timenow, intf->NetWakeBrowse.ThisQInterval);
+ intf->ifname, &intf->ip, NextQSendTime(&intf->NetWakeBrowse) - m->timenow, intf->NetWakeBrowse.ThisQInterval);
else
{
int i;
{
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
{
+ mDNS_Lock(m);
// If we're going to sleep, need to stop advertising that we're a Sleep Proxy Server
if (m->SPSSocket)
{
{
// 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;
+ m->SleepLimit = NonZeroTime(m->DelaySleep + mDNSPlatformOneSecond * 10);
}
else
{
m->DelaySleep = 0;
- m->SleepLimit = m->timenow + mDNSPlatformOneSecond * 10;
+ m->SleepLimit = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 10);
BeginSleepProcessing(m);
}
#ifndef UNICAST_DISABLED
SuspendLLQs(m);
+#endif
+ mDNS_Unlock(m);
+ // RemoveAutoTunnel6Record needs to be called outside the lock, as it grabs the lock also.
+#if APPLE_OSX_mDNSResponder
+ RemoveAutoTunnel6Record(m);
#endif
LogSPS("mDNSCoreMachineSleep: m->SleepState %d (%s) seq %d", m->SleepState,
- m->SleepState == SleepState_Transferring ? "Transferring" :
+ m->SleepState == SleepState_Transferring ? "Transferring" :
m->SleepState == SleepState_Sleeping ? "Sleeping" : "?", m->SleepSeqNum);
}
else if (!sleep) // Waking up
CacheRecord *cr;
NetworkInterfaceInfo *intf;
+ mDNS_Lock(m);
+ // Reset SleepLimit back to 0 now that we're awake again.
+ m->SleepLimit = 0;
+
// 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)
{
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();
+ mDNSCoreBeSleepProxyServer_internal(m, m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower);
}
// In case we gave up waiting and went to sleep before we got an ack from the Sleep Proxy,
// and reactivtate service registrations
m->NextSRVUpdate = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
- LogInfo("WakeServiceRegistrations %d %d", m->timenow, m->NextSRVUpdate);
+ LogInfo("mDNSCoreMachineSleep waking: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
// 2. Re-validate our cache records
- m->NextCacheCheck = m->timenow;
FORALL_CACHERECORDS(slot, cg, cr)
mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForWake);
if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType);
rr->AnnounceCount = InitialAnnounceCount;
+ rr->SendNSECNow = mDNSNULL;
InitializeLastAPTime(m, rr);
}
// 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
// We typically wake up with no interfaces active, so there's no need to rush to try to find our external address.
- // When we get a DHCP address and mDNS_SetPrimaryInterfaceInfo is called, we'll then set m->retryGetAddr
- // to immediately request our external address from the NAT gateway.
+ // When we get a network configuration change, mDNSMacOSXNetworkChanged calls uDNS_SetupDNSConfig, which calls
+ // mDNS_SetPrimaryInterfaceInfo, which then sets m->retryGetAddr to immediately request our external address from the NAT gateway.
m->retryIntervalGetAddr = NATMAP_INIT_RETRY;
m->retryGetAddr = m->timenow + mDNSPlatformOneSecond * 5;
LogInfo("mDNSCoreMachineSleep: retryGetAddr in %d %d", m->retryGetAddr - m->timenow, m->timenow);
RecreateNATMappings(m);
+ mDNS_Unlock(m);
}
-
- mDNS_Unlock(m);
}
mDNSexport mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now)
{
DNSQuestion *q;
AuthRecord *rr;
- ServiceRecordSet *srs;
NetworkInterfaceInfo *intf;
mDNS_Lock(m);
{
if (now - intf->NextSPSAttemptTime >= 0)
{
- LogSPS("ReadyForSleep retrying SPS %s %d", intf->ifname, intf->NextSPSAttempt);
+ LogSPS("mDNSCoreReadyForSleep: retrying for %s SPS %d try %d",
+ intf->ifname, intf->NextSPSAttempt/3, intf->NextSPSAttempt);
SendSPSRegistration(m, intf, zeroID);
- // Don't need to "goto notready" here, becase if we do still have record registrations
+ // Don't need to "goto notready" here, because if we do still have record registrations
// that have not been acknowledged yet, we'll catch that in the record list scan below.
}
else
// Scan list of interfaces, and see if we're still waiting for any sleep proxy resolves to complete
for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
- if (intf->NetWakeResolve[0].ThisQInterval >= 0)
+ {
+ int sps = (intf->NextSPSAttempt == 0) ? 0 : (intf->NextSPSAttempt-1)/3;
+ if (intf->NetWakeResolve[sps].ThisQInterval >= 0)
{
- LogSPS("ReadyForSleep waiting for SPS Resolve %s %##s (%s)", intf->ifname, intf->NetWakeResolve[0].qname.c, DNSTypeName(intf->NetWakeResolve[0].qtype));
+ LogSPS("mDNSCoreReadyForSleep: waiting for SPS Resolve %s %##s (%s)",
+ intf->ifname, intf->NetWakeResolve[sps].qname.c, DNSTypeName(intf->NetWakeResolve[sps].qtype));
goto spsnotready;
}
+ }
// Scan list of registered records
for (rr = m->ResourceRecords; rr; rr = rr->next)
if (!AuthRecord_uDNS(rr))
if (!mDNSOpaque16IsZero(rr->updateid))
- { LogSPS("ReadyForSleep waiting for SPS Update ID %d %s", mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto spsnotready; }
+ { LogSPS("mDNSCoreReadyForSleep: waiting for SPS Update ID %d %s", mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto spsnotready; }
// 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));
+ LogSPS("mDNSCoreReadyForSleep: waiting for LLQ %##s (%s)", q->qname.c, DNSTypeName(q->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; }
-
- // Scan list of registered services
- for (srs = m->ServiceRegistrations; srs; srs = srs->uDNS_next)
- if (srs->state == regState_NoTarget && srs->tcp) goto notready;
+ { LogSPS("mDNSCoreReadyForSleep: waiting for Record Update ID %d %s", mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; }
+ #if APPLE_OSX_mDNSResponder
+ if (!RecordReadyForSleep(m, rr)) { LogSPS("mDNSCoreReadyForSleep: waiting for %s", ARDisplayString(m, rr)); goto notready; }
+ #endif
+ }
mDNS_Unlock(m);
return mDNStrue;
for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
if (intf->NetWakeBrowse.ThisQInterval >= 0)
{
- LogSPS("ReadyForSleep mDNS_DeactivateNetWake %s %##s (%s)", intf->ifname, intf->NetWakeResolve[0].qname.c, DNSTypeName(intf->NetWakeResolve[0].qtype));
+ LogSPS("ReadyForSleep mDNS_DeactivateNetWake %s %##s (%s)",
+ intf->ifname, intf->NetWakeResolve[0].qname.c, DNSTypeName(intf->NetWakeResolve[0].qtype));
mDNS_DeactivateNetWake_internal(m, intf);
}
// ***
if (LegacyQuery)
{
- maxttl = 10;
+ maxttl = kStaticCacheTTL;
for (i=0; i<query->h.numQuestions; i++) // For each question...
{
DNSQuestion q;
{
ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
if (!ptr) break;
- if (ResourceRecordAnswersQuestion(&m->rec.r.resrec, q))
+ if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && ResourceRecordAnswersQuestion(&m->rec.r.resrec, q))
{
FoundUpdate = mDNStrue;
if (PacketRRConflict(m, our, &m->rec.r))
if (result)
{
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));
+ LogMsg("ResolveSimultaneousProbe: %p Pkt Record: %08lX %s", q->InterfaceID, m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
+ LogMsg("ResolveSimultaneousProbe: %p Our Record %d %s %08lX %s", our->resrec.InterfaceID, 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.
+ // Instead we pause for one second, to give the other host (if real) a chance 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)
{
#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));
+ LogMsg("ResolveSimultaneousProbe: %p Pkt Record: %08lX %s", q->InterfaceID, m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
+ LogMsg("ResolveSimultaneousProbe: %p Our Record %d ign: %08lX %s", our->resrec.InterfaceID, our->ProbeCount, our->resrec.rdatahash, ARDisplayString(m, our));
}
#endif
}
mDNSu32 slot = HashSlot(pktrr->name);
CacheGroup *cg = CacheGroupForRecord(m, slot, pktrr);
CacheRecord *rr;
+ mDNSBool match;
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
- if (pktrr->InterfaceID == rr->resrec.InterfaceID && IdenticalSameNameRecord(pktrr, &rr->resrec)) break;
+ {
+ match = !pktrr->InterfaceID ? pktrr->rDNSServer == rr->resrec.rDNSServer : pktrr->InterfaceID == rr->resrec.InterfaceID;
+ if (match && IdenticalSameNameRecord(pktrr, &rr->resrec)) break;
+ }
return(rr);
}
+// Called from mDNSCoreReceiveUpdate when we get a sleep proxy registration request,
+// to check our lists and discard any stale duplicates of this record we already have
+mDNSlocal void ClearIdenticalProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist)
+ {
+ if (m->CurrentRecord)
+ LogMsg("ClearIdenticalProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
+ 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 (IdenticalResourceRecord(&rr->resrec, &m->rec.r.resrec))
+ {
+ LogSPS("ClearIdenticalProxyRecords: 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));
+ rr->WakeUp.HMAC = zeroEthAddr; // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host
+ rr->RequireGoodbye = mDNSfalse; // and we don't want to send goodbye for it
+ 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
+ // new records could have been added to the end of the list as a result of that call.
+ if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
+ m->CurrentRecord = rr->next;
+ }
+ }
+
// 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)
{
+ if (m->CurrentRecord)
+ LogMsg("ClearProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
m->CurrentRecord = thelist;
while (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));
+ if (rr->AddressProxy.type == mDNSAddrType_IPv6)
+ {
+ // We don't do this here because we know that the host is waking up at this point, so we don't send
+ // Unsolicited Neighbor Advertisements -- even Neighbor Advertisements agreeing with what the host should be
+ // saying itself -- because it can cause some IPv6 stacks to falsely conclude that there's an address conflict.
+ #if MDNS_USE_Unsolicited_Neighbor_Advertisements
+ LogSPS("NDP Announcement -- Releasing traffic for H-MAC %.6a I-MAC %.6a %s",
+ &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
+ SendNDP(m, NDP_Adv, NDP_Override, rr, &rr->AddressProxy.ip.v6, &rr->WakeUp.IMAC, &AllHosts_v6, &AllHosts_v6_Eth);
+ #endif
+ }
+ LogSPS("ClearProxyRecords: Removing %3d AC %2d %02X H-MAC %.6a I-MAC %.6a %d %d %s",
+ m->ProxyRecords, rr->AnnounceCount, rr->resrec.RecordType,
+ &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, owner->seq, ARDisplayString(m, rr));
+ if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) rr->resrec.RecordType = kDNSRecordTypeShared;
+ rr->WakeUp.HMAC = zeroEthAddr; // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host
+ rr->RequireGoodbye = mDNSfalse; // and we don't want to send goodbye for it, since real host is now back and functional
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.
+ // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
+ // new records could have been added to the end of the list as a result of that call.
if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
m->CurrentRecord = rr->next;
}
const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast,
mDNSBool QueryWasLocalUnicast, DNSMessage *const response)
{
- mDNSBool FromLocalSubnet = srcaddr && AddressIsLocalSubnet(m, InterfaceID, srcaddr);
+ mDNSBool FromLocalSubnet = srcaddr && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr);
AuthRecord *ResponseRecords = mDNSNULL;
AuthRecord **nrp = &ResponseRecords;
CacheRecord *ExpectedAnswers = mDNSNULL; // Records in our cache we expect to see updated
if (ptr)
{
ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &m->rec);
- if (m->rec.r.resrec.rrtype == kDNSType_OPT)
+ if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && 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];
else if (!rr->NR_AnswerTo) rr->NR_AnswerTo = LegacyQuery ? ptr : (mDNSu8*)~1;
}
}
- else if (rr->resrec.RecordType == kDNSRecordTypeVerified)
+ else if ((rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && ResourceRecordIsValidAnswer(rr))
{
// 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
+ // then we'll want to mark it to generate an NSEC record on this interface
if (!NSECAnswer) NSECAnswer = rr;
}
}
CacheRecord *ourcacherr;
ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &m->rec);
if (!ptr) goto exit;
-
- // See if this Known-Answer suppresses any of our currently planned answers
- for (rr=ResponseRecords; rr; rr=rr->NextResponse)
- if (MustSendRecord(rr) && ShouldSuppressKnownAnswer(&m->rec.r, rr))
- { rr->NR_AnswerTo = mDNSNULL; rr->NR_AdditionalTo = mDNSNULL; }
-
- // See if this Known-Answer suppresses any previously scheduled answers (for multi-packet KA suppression)
- for (rr=m->ResourceRecords; rr; rr=rr->next)
+ if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative)
{
- // If we're planning to send this answer on this interface, and only on this interface, then allow KA suppression
- if (rr->ImmedAnswer == InterfaceID && ShouldSuppressKnownAnswer(&m->rec.r, rr))
+ // See if this Known-Answer suppresses any of our currently planned answers
+ for (rr=ResponseRecords; rr; rr=rr->NextResponse)
+ if (MustSendRecord(rr) && ShouldSuppressKnownAnswer(&m->rec.r, rr))
+ { rr->NR_AnswerTo = mDNSNULL; rr->NR_AdditionalTo = mDNSNULL; }
+
+ // See if this Known-Answer suppresses any previously scheduled answers (for multi-packet KA suppression)
+ for (rr=m->ResourceRecords; rr; rr=rr->next)
{
- if (srcaddr->type == mDNSAddrType_IPv4)
+ // If we're planning to send this answer on this interface, and only on this interface, then allow KA suppression
+ if (rr->ImmedAnswer == InterfaceID && ShouldSuppressKnownAnswer(&m->rec.r, rr))
{
- if (mDNSSameIPv4Address(rr->v4Requester, srcaddr->ip.v4)) rr->v4Requester = zerov4Addr;
- }
- else if (srcaddr->type == mDNSAddrType_IPv6)
- {
- if (mDNSSameIPv6Address(rr->v6Requester, srcaddr->ip.v6)) rr->v6Requester = zerov6Addr;
- }
- if (mDNSIPv4AddressIsZero(rr->v4Requester) && mDNSIPv6AddressIsZero(rr->v6Requester))
- {
- rr->ImmedAnswer = mDNSNULL;
- rr->ImmedUnicast = mDNSfalse;
-#if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
- LogMsg("Suppressed after%4d: %s", m->timenow - rr->ImmedAnswerMarkTime, ARDisplayString(m, rr));
-#endif
+ if (srcaddr->type == mDNSAddrType_IPv4)
+ {
+ if (mDNSSameIPv4Address(rr->v4Requester, srcaddr->ip.v4)) rr->v4Requester = zerov4Addr;
+ }
+ else if (srcaddr->type == mDNSAddrType_IPv6)
+ {
+ if (mDNSSameIPv6Address(rr->v6Requester, srcaddr->ip.v6)) rr->v6Requester = zerov6Addr;
+ }
+ if (mDNSIPv4AddressIsZero(rr->v4Requester) && mDNSIPv6AddressIsZero(rr->v6Requester))
+ {
+ rr->ImmedAnswer = mDNSNULL;
+ rr->ImmedUnicast = mDNSfalse;
+ #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
+ LogMsg("Suppressed after%4d: %s", m->timenow - rr->ImmedAnswerMarkTime, ARDisplayString(m, rr));
+ #endif
+ }
}
}
- }
-
- 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).
- 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 then remove
- // any records that are suppressed by the Known Answer list in this packet.
- eap = &ExpectedAnswers;
- while (*eap)
- {
- CacheRecord *cr = *eap;
- if (cr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&m->rec.r.resrec, &cr->resrec))
- { *eap = cr->NextInKAList; cr->NextInKAList = mDNSNULL; }
- else eap = &cr->NextInKAList;
- }
-
- // See if this Known-Answer is a surprise to us. If so, we shouldn't suppress our own query.
- if (!ourcacherr)
- {
- dqp = &DupQuestions;
- while (*dqp)
+
+ 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).
+ 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 then remove
+ // any records that are suppressed by the Known Answer list in this packet.
+ eap = &ExpectedAnswers;
+ while (*eap)
+ {
+ CacheRecord *cr = *eap;
+ if (cr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&m->rec.r.resrec, &cr->resrec))
+ { *eap = cr->NextInKAList; cr->NextInKAList = mDNSNULL; }
+ else eap = &cr->NextInKAList;
+ }
+
+ // See if this Known-Answer is a surprise to us. If so, we shouldn't suppress our own query.
+ if (!ourcacherr)
{
- DNSQuestion *q = *dqp;
- if (ResourceRecordAnswersQuestion(&m->rec.r.resrec, q))
- { *dqp = q->NextInDQList; q->NextInDQList = mDNSNULL; }
- else dqp = &q->NextInDQList;
+ dqp = &DupQuestions;
+ while (*dqp)
+ {
+ DNSQuestion *q = *dqp;
+ if (ResourceRecordAnswersQuestion(&m->rec.r.resrec, q))
+ { *dqp = q->NextInDQList; q->NextInDQList = mDNSNULL; }
+ else dqp = &q->NextInDQList;
+ }
}
}
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s",
cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
#endif
- SetNextCacheCheckTime(m, cr);
+ SetNextCacheCheckTimeForRecord(m, cr);
}
// If we've seen multiple unanswered queries for this record,
{
mDNSu8 *responseend = mDNSNULL;
mDNSBool QueryWasLocalUnicast = srcaddr && dstaddr &&
- !mDNSAddrIsDNSMulticast(dstaddr) && AddressIsLocalSubnet(m, InterfaceID, srcaddr);
+ !mDNSAddrIsDNSMulticast(dstaddr) && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr);
if (!InterfaceID && dstaddr && mDNSAddrIsDNSMulticast(dstaddr))
{
LogMsg("Ignoring Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
- "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s (Multicast, but no InterfaceID)",
+ "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes (Multicast, but no InterfaceID)",
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.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");
+ msg->h.numAdditionals, msg->h.numAdditionals == 1 ? " " : "s", end - msg->data);
return;
}
verbosedebugf("Received Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
- "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s",
+ "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes",
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.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");
+ msg->h.numAdditionals, msg->h.numAdditionals == 1 ? " " : "s", end - msg->data);
responseend = ProcessQuery(m, msg, end, srcaddr, InterfaceID,
!mDNSSameIPPort(srcport, MulticastDNSPort), mDNSAddrIsDNSMulticast(dstaddr), QueryWasLocalUnicast, &m->omsg);
mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
};
-mDNSlocal 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, mDNSBool tcp)
{
DNSQuestion *q;
for (q = m->Questions; q; q=q->next)
- if (q->LocalSocket &&
- mDNSSameIPPort (q->LocalSocket->port, port) &&
+ {
+ if (!tcp && !q->LocalSocket) continue;
+ if (mDNSSameIPPort(tcp ? q->tcpSrcPort : 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);
}
-mDNSlocal mDNSBool ExpectingUnicastResponseForRecord(mDNS *const m, const mDNSAddr *const srcaddr, const mDNSBool SrcLocal, const mDNSIPPort port, const mDNSOpaque16 id, const CacheRecord *const rr)
+mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m,
+ const mDNSAddr *const srcaddr, const mDNSBool SrcLocal, const mDNSIPPort port, const mDNSOpaque16 id, const CacheRecord *const rr, mDNSBool tcp)
{
DNSQuestion *q;
(void)id;
(void)srcaddr;
+
+ // Unicast records have zero as InterfaceID
+ if (rr->resrec.InterfaceID) return mDNSNULL;
+
for (q = m->Questions; q; q=q->next)
- if (!q->DuplicateOf && ResourceRecordAnswersQuestion(&rr->resrec, q))
+ {
+ if (!q->DuplicateOf && UnicastResourceRecordAnswersQuestion(&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 (q->LocalSocket && mDNSSameIPPort(q->LocalSocket->port, port)) return(mDNStrue);
+ mDNSIPPort srcp;
+ if (!tcp)
+ {
+ srcp = q->LocalSocket ? q->LocalSocket->port : zeroIPPort;
+ }
+ else
+ {
+ srcp = q->tcpSrcPort;
+ }
+ if (mDNSSameIPPort(srcp, port)) return(q);
+
// 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);
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);
+ q->qname.c, DNSTypeName(q->qtype), &q->Target, mDNSVal16(srcp), srcaddr, mDNSVal16(port), CRDisplayString(m, rr));
+ return(mDNSNULL);
}
}
else
{
if (SrcLocal && q->ExpectUnicastResp && (mDNSu32)(m->timenow - q->ExpectUnicastResp) < (mDNSu32)(mDNSPlatformOneSecond*2))
- return(mDNStrue);
+ return(q);
}
}
- return(mDNSfalse);
+ }
+ return(mDNSNULL);
}
// Certain data types need more space for in-memory storage than their in-packet rdlength would imply
}
}
-mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg)
+mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay)
{
CacheRecord *rr = mDNSNULL;
mDNSu16 RDLength = GetRDLengthMem(&m->rec.r.resrec);
{
RData *saveptr = rr->resrec.rdata; // Save the rr->resrec.rdata pointer
*rr = m->rec.r; // Block copy the CacheRecord object
- rr->resrec.rdata = saveptr; // Restore rr->resrec.rdata after the structure assignment
- rr->resrec.name = cg->name; // And set rr->resrec.name to point into our CacheGroup header
+ rr->resrec.rdata = saveptr; // Restore rr->resrec.rdata after the structure assignment
+ rr->resrec.name = cg->name; // And set rr->resrec.name to point into our CacheGroup header
+ rr->DelayDelivery = delay;
// If this is an oversized record with external storage allocated, copy rdata to external storage
if (rr->resrec.rdata == (RData*)&rr->smallrdatastorage && RDLength > InlineCacheRDSize)
rr->next = mDNSNULL; // Clear 'next' pointer
*(cg->rrcache_tail) = rr; // Append this record to tail of cache slot list
cg->rrcache_tail = &(rr->next); // Advance tail pointer
- if (rr->resrec.RecordType == kDNSRecordTypePacketNegative)
- rr->DelayDelivery = NonZeroTime(m->timenow);
- else if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask && // If marked unique,
- rr->resrec.rdata->MaxRDLength != 0) // and non-negative, assume we may have
- rr->DelayDelivery = NonZeroTime(m->timenow + mDNSPlatformOneSecond); // to delay delivery of this 'add' event
- 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 SetNextCacheCheckTimeForRecord(m, rr); for us
}
return(rr);
}
rr->MPUnansweredKA = 0;
rr->MPExpectingKA = mDNSfalse;
#endif
- SetNextCacheCheckTime(m, rr);
+ SetNextCacheCheckTimeForRecord(m, rr);
}
mDNSexport void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease)
// For mDNS, TTL zero means "delete this record"
// For uDNS, TTL zero means: this data is true at this moment, but don't cache it.
// For the sake of network efficiency, we impose a minimum effective TTL of 15 seconds.
- // If we allow a TTL of less than 2 seconds things really break (e.g. we end up making a negative cache entry).
+ // This means that we'll do our 80, 85, 90, 95% queries at 12.00, 12.75, 13.50, 14.25 seconds
+ // respectively, and then if we get no response, delete the record from the cache at 15 seconds.
+ // This gives the server up to three seconds to respond between when we send our 80% query at 12 seconds
+ // and when we delete the record at 15 seconds. Allowing cache lifetimes less than 15 seconds would
+ // (with the current code) result in the server having even less than three seconds to respond
+ // before we deleted the record and reported a "remove" event to any active questions.
+ // Furthermore, with the current code, if we were to allow a TTL of less than 2 seconds
+ // then things really break (e.g. we end up making a negative cache entry).
// In the future we may want to revisit this and consider properly supporting non-cached (TTL=0) uDNS answers.
if (ttl < 15) ttl = 15;
}
{
int i;
mDNSBool ResponseMCast = dstaddr && mDNSAddrIsDNSMulticast(dstaddr);
- mDNSBool ResponseSrcLocal = !srcaddr || AddressIsLocalSubnet(m, InterfaceID, srcaddr);
- uDNS_LLQType LLQType = uDNS_recvLLQResponse(m, response, end, srcaddr, srcport);
+ mDNSBool ResponseSrcLocal = !srcaddr || mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr);
+ DNSQuestion *llqMatch = mDNSNULL;
+ uDNS_LLQType LLQType = uDNS_recvLLQResponse(m, response, end, srcaddr, srcport, &llqMatch);
// "(CacheRecord*)1" is a special (non-zero) end-of-list marker
// We use this non-zero marker so that records in our CacheFlushRecords list will always have NextInCFList
int firstadditional = firstauthority + response->h.numAuthorities;
int totalrecords = firstadditional + response->h.numAdditionals;
const mDNSu8 *ptr = response->data;
+ DNSServer *uDNSServer = mDNSNULL;
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",
+ "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes LLQType %d",
srcaddr, dstaddr, InterfaceID,
- response->h.numQuestions, response->h.numQuestions == 1 ? ", " : "s,",
- response->h.numAnswers, response->h.numAnswers == 1 ? ", " : "s,",
+ response->h.numQuestions, response->h.numQuestions == 1 ? ", " : "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", LLQType);
+ response->h.numAdditionals, response->h.numAdditionals == 1 ? " " : "s", end - response->data, LLQType);
// According to RFC 2181 <http://www.ietf.org/rfc/rfc2181.txt>
// When a DNS client receives a reply with TC
{
DNSQuestion q, *qptr = mDNSNULL;
ptr = getQuestion(response, ptr, end, InterfaceID, &q);
- if (ptr && (!dstaddr || (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q))))
+ if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr)))
{
if (!failure)
{
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))
+ if (SameNameRecordAnswersQuestion(&rr->resrec, qptr))
{
debugf("uDNS marking %p %##s (%s) %p %s", q.InterfaceID, q.qname.c, DNSTypeName(q.qtype),
rr->resrec.InterfaceID, CRDisplayString(m, rr));
{
if (qptr)
{
- LogInfo("Server %p responded with code %d to query %##s (%s)", qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype));
- PenalizeDNSServer(m, qptr, mDNSfalse);
+ LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to query %##s (%s)", qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype));
+ PenalizeDNSServer(m, qptr);
}
returnEarly = mDNStrue;
}
(i < firstadditional) ? (mDNSu8)kDNSRecordTypePacketAuth : (mDNSu8)kDNSRecordTypePacketAdd;
ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, RecordType, &m->rec);
if (!ptr) goto exit; // Break out of the loop and clean up our CacheFlushRecords list before exiting
+ if (m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative) { m->rec.r.resrec.RecordType = 0; continue; }
// Don't want to cache OPT or TSIG pseudo-RRs
- if (m->rec.r.resrec.rrtype == kDNSType_OPT || m->rec.r.resrec.rrtype == kDNSType_TSIG)
- { m->rec.r.resrec.RecordType = 0; continue; }
-
+ if (m->rec.r.resrec.rrtype == kDNSType_TSIG) { m->rec.r.resrec.RecordType = 0; continue; }
+ 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;
+ continue;
+ }
+
// if a CNAME record points to itself, then don't add it to the cache
if ((m->rec.r.resrec.rrtype == kDNSType_CNAME) && SameDomainName(m->rec.r.resrec.name, &m->rec.r.resrec.rdata->u.name))
- {
+ {
LogInfo("mDNSCoreReceiveResponse: CNAME loop domain name %##s", m->rec.r.resrec.name->c);
- m->rec.r.resrec.RecordType = 0;
- continue;
+ m->rec.r.resrec.RecordType = 0;
+ continue;
}
-
+
// When we receive uDNS LLQ responses, we assume a long cache lifetime --
// In the case of active LLQs, we'll get remove events when the records actually do go away
// In the case of polling LLQs, we assume the record remains valid until the next poll
// If response was not sent via LL multicast,
// then see if it answers a recent query of ours, which would also make it acceptable for caching.
- if (!AcceptableResponse) AcceptableResponse = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r);
+ if (!ResponseMCast)
+ {
+ if (LLQType)
+ {
+ // For Long Lived queries that are both sent over UDP and Private TCP, LLQType is set.
+ // Even though it is AcceptableResponse, we need a matching DNSServer pointer for the
+ // queries to get ADD/RMV events. To lookup the question, we can't use
+ // ExpectingUnicastResponseForRecord as the port numbers don't match. uDNS_recvLLQRespose
+ // has already matched the question using the 64 bit Id in the packet and we use that here.
+
+ if (llqMatch != mDNSNULL) m->rec.r.resrec.rDNSServer = uDNSServer = llqMatch->qDNSServer;
+ }
+ else if (!AcceptableResponse || !dstaddr)
+ {
+ // For responses that come over TCP (Responses that can't fit within UDP) or TLS (Private queries
+ // that are not long lived e.g., AAAA lookup in a Private domain), it is indicated by !dstaddr.
+ // Even though it is AcceptableResponse, we still need a DNSServer pointer for the resource records that
+ // we create.
+
+ DNSQuestion *q = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r, !dstaddr);
+
+ // Intialize the DNS server on the resource record which will now filter what questions we answer with
+ // this record.
+ //
+ // We could potentially lookup the DNS server based on the source address, but that may not work always
+ // and that's why ExpectingUnicastResponseForRecord does not try to verify whether the response came
+ // from the DNS server that queried. We follow the same logic here. If we can find a matching quetion based
+ // on the "id" and "source port", then this response answers the question and assume the response
+ // came from the same DNS server that we sent the query to.
+
+ if (q != mDNSNULL)
+ {
+ AcceptableResponse = mDNStrue;
+ if (!InterfaceID)
+ {
+ debugf("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
+ m->rec.r.resrec.rDNSServer = uDNSServer = q->qDNSServer;
+ }
+ }
+ else
+ {
+ // If we can't find a matching question, we need to see whether we have seen records earlier that matched
+ // the question. The code below does that. So, make this record unacceptable for now
+ if (!InterfaceID)
+ {
+ debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c);
+ AcceptableResponse = mDNSfalse;
+ }
+ }
+ }
+ }
// 1. Check that this packet resource record does not conflict with any of ours
if (mDNSOpaque16IsZero(response->h.id) && m->rec.r.resrec.rrtype != kDNSType_NSEC)
for (cr = CacheFlushRecords; cr != (CacheRecord*)1; cr = cr->NextInCFList)
{
domainname *target = GetRRDomainNameTarget(&cr->resrec);
+ // When we issue a query for A record, the response might contain both a CNAME and A records. Only the CNAME would
+ // match the question and we already created a cache entry in the previous pass of this loop. Now when we process
+ // the A record, it does not match the question because the record name here is the CNAME. Hence we try to
+ // match with the previous records to make it an AcceptableResponse. We have to be careful about setting the
+ // DNSServer value that we got in the previous pass. This can happen for other record types like SRV also.
+
if (target && cr->resrec.rdatahash == m->rec.r.resrec.namehash && SameDomainName(target, m->rec.r.resrec.name))
- { AcceptableResponse = mDNStrue; break; }
+ {
+ debugf("mDNSCoreReceiveResponse: Found a matching entry for %##s in the CacheFlushRecords", m->rec.r.resrec.name->c);
+ AcceptableResponse = mDNStrue;
+ m->rec.r.resrec.rDNSServer = uDNSServer;
+ break;
+ }
}
}
// 2. See if we want to add this packet resource record to our cache
// We only try to cache answers if we have a cache to put them in
// Also, we ignore any apparent attempts at cache poisoning unicast to us that do not answer any outstanding active query
- if (!AcceptableResponse) debugf("mDNSCoreReceiveResponse ignoring %s", CRDisplayString(m, &m->rec.r));
+ if (!AcceptableResponse) LogInfo("mDNSCoreReceiveResponse ignoring %s", CRDisplayString(m, &m->rec.r));
if (m->rrcache_size && AcceptableResponse)
{
const mDNSu32 slot = HashSlot(m->rec.r.resrec.name);
// 2a. Check if this packet resource record is already in our cache
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
{
+ mDNSBool match = !InterfaceID ? m->rec.r.resrec.rDNSServer == rr->resrec.rDNSServer : rr->resrec.InterfaceID == InterfaceID;
// If we found this exact resource record, refresh its TTL
- if (rr->resrec.InterfaceID == InterfaceID && IdenticalSameNameRecord(&m->rec.r.resrec, &rr->resrec))
+ if (match && IdenticalSameNameRecord(&m->rec.r.resrec, &rr->resrec))
{
if (m->rec.r.resrec.rdlength > InlineCacheRDSize)
verbosedebugf("Found record size %5d interface %p already in cache: %s",
m->rec.r.resrec.rdlength, InterfaceID, CRDisplayString(m, &m->rec.r));
- rr->TimeRcvd = m->timenow;
if (m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask)
{
}
}
- if (!mDNSPlatformMemSame(m->rec.r.resrec.rdata->u.data, rr->resrec.rdata->u.data, m->rec.r.resrec.rdlength))
+ if (!SameRDataBody(&m->rec.r.resrec, &rr->resrec.rdata->u, SameDomainNameCS))
{
// If the rdata of the packet record differs in name capitalization from the record in our cache
// then mDNSPlatformMemSame will detect this. In this case, throw the old record away, so that clients get
// a 'remove' event for the record with the old capitalization, and then an 'add' event for the new one.
+ // <rdar://problem/4015377> mDNS -F returns the same domain multiple times with different casing
rr->resrec.rroriginalttl = 0;
+ rr->TimeRcvd = m->timenow;
rr->UnansweredQueries = MaxUnansweredQueries;
- SetNextCacheCheckTime(m, rr);
+ SetNextCacheCheckTimeForRecord(m, rr);
+ LogInfo("Discarding due to domainname case change old: %s", CRDisplayString(m,rr));
+ LogInfo("Discarding due to domainname case change new: %s", CRDisplayString(m,&m->rec.r));
+ LogInfo("Discarding due to domainname case change in %d slot %3d in %d %d",
+ NextCacheCheckEvent(rr) - m->timenow, slot, m->rrcache_nextcheck[slot] - m->timenow, m->NextCacheCheck - m->timenow);
// DO NOT break out here -- we want to continue as if we never found it
}
else if (m->rec.r.resrec.rroriginalttl > 0)
{
for (q = m->Questions; q; q=q->next)
{
-
- if (!q->DuplicateOf && !q->LongLived &&
+ if (!q->DuplicateOf && !q->LongLived &&
ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q))
{
q->LastQTime = m->timenow;
q->ThisQInterval = MaxQuestionInterval;
q->RequestUnicast = mDNSfalse;
q->unansweredQueries = 0;
- debugf("mDNSCoreReceiveResponse: Set MaxQuestionInterval for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- break;
+ debugf("mDNSCoreReceiveResponse: Set MaxQuestionInterval for %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+ break; // Why break here? Aren't there other questions we might want to look at?-- SC July 2010
}
}
}
// out one second into the future. Also, we set UnansweredQueries to MaxUnansweredQueries.
// Otherwise, we'll do final queries for this record at 80% and 90% of its apparent
// lifetime (800ms and 900ms from now) which is a pointless waste of network bandwidth.
+ // If record's current expiry time is more than a second from now, we set it to expire in one second.
+ // If the record is already going to expire in less than one second anyway, we leave it alone --
+ // we don't want to let the goodbye packet *extend* the record's lifetime in our cache.
debugf("DE for %s", CRDisplayString(m, rr));
- rr->resrec.rroriginalttl = 1;
- rr->UnansweredQueries = MaxUnansweredQueries;
- SetNextCacheCheckTime(m, rr);
+ if (RRExpireTime(rr) - m->timenow > mDNSPlatformOneSecond)
+ {
+ rr->resrec.rroriginalttl = 1;
+ rr->TimeRcvd = m->timenow;
+ rr->UnansweredQueries = MaxUnansweredQueries;
+ SetNextCacheCheckTimeForRecord(m, rr);
+ }
break;
}
}
// (unless it is just a deletion of a record we never had, in which case we don't care)
if (!rr && m->rec.r.resrec.rroriginalttl > 0)
{
- rr = CreateNewCacheEntry(m, slot, cg);
- if (rr && (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) && LLQType != uDNS_LLQ_Events)
- { *cfp = rr; cfp = &rr->NextInCFList; *cfp = (CacheRecord*)1; }
+ const mDNSBool AddToCFList = (m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && (LLQType != uDNS_LLQ_Events);
+ const mDNSs32 delay = AddToCFList ? NonZeroTime(m->timenow + mDNSPlatformOneSecond) :
+ CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash, slot);
+ // If unique, assume we may have to delay delivery of this 'add' event.
+ // Below, where we walk the CacheFlushRecords list, we either call CacheRecordDeferredAdd()
+ // to immediately to generate answer callbacks, or we call ScheduleNextCacheCheckTime()
+ // to schedule an mDNS_Execute task at the appropriate time.
+ rr = CreateNewCacheEntry(m, slot, cg, delay);
+ if (rr)
+ {
+ if (AddToCFList) { *cfp = rr; cfp = &rr->NextInCFList; *cfp = (CacheRecord*)1; }
+ else if (rr->DelayDelivery) ScheduleNextCacheCheckTime(m, slot, rr->DelayDelivery);
+ }
}
}
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
// To avoid this, we need to ensure that the cache flushing operation will only act to
// *decrease* a record's remaining lifetime, never *increase* it.
for (r2 = cg ? cg->members : mDNSNULL; r2; r2=r2->next)
- if (r1->resrec.InterfaceID == r2->resrec.InterfaceID &&
+ // For Unicast (null InterfaceID) the DNSservers should also match
+ if ((r1->resrec.InterfaceID == r2->resrec.InterfaceID) &&
+ (r1->resrec.InterfaceID || (r1->resrec.rDNSServer == r2->resrec.rDNSServer)) &&
r1->resrec.rrtype == r2->resrec.rrtype &&
r1->resrec.rrclass == r2->resrec.rrclass)
{
{
// If we find mismatched TTLs in an RRSet, correct them.
// We only do this for records with a TTL of 2 or higher. It's possible to have a
- // goodbye announcement with the cache flush bit set (or a case change on record rdata,
+ // goodbye announcement with the cache flush bit set (or a case-change on record rdata,
// which we treat as a goodbye followed by an addition) and in that case it would be
// inappropriate to synchronize all the other records to a TTL of 0 (or 1).
// We suppress the message for the specific case of correcting from 240 to 60 for type TXT,
}
else // else, if record is old, mark it to be flushed
{
- verbosedebugf("Cache flush %p X %p %s", r1, r2, CRDisplayString(m, r2));
+ verbosedebugf("Cache flush new %p age %d expire in %d %s", r1, m->timenow - r1->TimeRcvd, RRExpireTime(r1) - m->timenow, CRDisplayString(m, r1));
+ verbosedebugf("Cache flush old %p age %d expire in %d %s", r2, m->timenow - r2->TimeRcvd, RRExpireTime(r2) - m->timenow, CRDisplayString(m, r2));
// We set stale records to expire in one second.
// This gives the owner a chance to rescue it if necessary.
// This is important in the case of multi-homing and bridged networks:
// If a record is deleted twice, first with an explicit DE record, then a second time by virtue of the cache
// flush bit on the new record replacing it, then we allow the record to be deleted immediately, without the usual
// one-second grace period. This improves responsiveness for mDNS_Update(), as used for things like iChat status updates.
- if (r2->TimeRcvd == m->timenow && r2->resrec.rroriginalttl <= 1 && r2->UnansweredQueries == MaxUnansweredQueries)
+ // <rdar://problem/5636422> Updating TXT records is too slow
+ // We check for "rroriginalttl == 1" because we want to include records tagged by the "packet TTL is zero" check above,
+ // which sets rroriginalttl to 1, but not records tagged by the rdata case-change check, which sets rroriginalttl to 0.
+ if (r2->TimeRcvd == m->timenow && r2->resrec.rroriginalttl == 1 && r2->UnansweredQueries == MaxUnansweredQueries)
{
- debugf("Cache flush for DE record %s", CRDisplayString(m, r2));
+ LogInfo("Cache flush for DE record %s", CRDisplayString(m, r2));
r2->resrec.rroriginalttl = 0;
- m->NextCacheCheck = m->timenow;
- m->NextScheduledEvent = m->timenow;
}
else if (RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond)
{
// that we marked for deletion via an explicit DE record
}
}
- SetNextCacheCheckTime(m, r2);
+ SetNextCacheCheckTimeForRecord(m, r2);
}
+
if (r1->DelayDelivery) // If we were planning to delay delivery of this record, see if we still need to
{
- // Note, only need to call SetNextCacheCheckTime() when DelayDelivery is set, not when it's cleared
r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, slot);
+ // If no longer delaying, deliver answer now, else schedule delivery for the appropriate time
if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1);
+ else ScheduleNextCacheCheckTime(m, slot, r1->DelayDelivery);
}
}
for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++)
{
DNSQuestion q;
+ DNSQuestion *qptr = mDNSNULL;
ptr = getQuestion(response, ptr, end, InterfaceID, &q);
- if (ptr && (!dstaddr || ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q)))
+ if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr)))
{
// 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.
// 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));
+ LogInfo("Skipping check to see if we need to generate a negative cache entry for %##s (%s)", q.qname.c, DNSTypeName(q.qtype));
else
{
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))
+ if (SameNameRecordAnswersQuestion(&rr->resrec, qptr))
{
// 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;
+ if (RRExpireTime(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 (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)
+ if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_SOA)
{
const rdataSOA *const soa = (const rdataSOA *)m->rec.r.resrec.rdata->u.data;
mDNSu32 ttl_s = soa->min;
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);
+ MakeNegativeCacheRecord(m, &m->rec.r, name, hash, q.qtype, q.qclass, negttl, mDNSInterface_Any, qptr->qDNSServer);
+ CreateNewCacheEntry(m, slot, cg, 0); // We never need any delivery delay for these generated negative cache records
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
if (!repeat) break;
repeat--;
}
}
+mDNSlocal void ScheduleWakeupForList(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *e, AuthRecord *const thelist)
+ {
+ AuthRecord *rr;
+ for (rr = thelist; rr; rr=rr->next)
+ if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering && mDNSSameEthAddress(&rr->WakeUp.HMAC, e))
+ mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
+ }
+
+mDNSlocal void ScheduleWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *e)
+ {
+ ScheduleWakeupForList(m, InterfaceID, e, m->DuplicateRecords);
+ ScheduleWakeupForList(m, InterfaceID, e, m->ResourceRecords);
+ }
+
mDNSlocal void SPSRecordCallback(mDNS *const m, AuthRecord *const ar, mStatus result)
{
if (result && result != mStatus_MemFree)
if (result == mStatus_NameConflict)
{
- char *ifname = InterfaceNameForID(m, ar->resrec.InterfaceID);
- if (!ifname) ifname = "<NULL InterfaceID>";
- LogMsg("Received Conflicting mDNS -- waking %s %.6a %s", ifname, &ar->WakeUp.HMAC, ARDisplayString(m, ar));
+ 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);
+ ScheduleWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.HMAC);
}
else if (result == mStatus_MemFree)
{
m->ProxyRecords--;
mDNSPlatformMemFree(ar);
+ mDNS_UpdateAllowSleep(m);
}
}
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",
+ "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes",
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.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");
+ msg->h.numAdditionals, msg->h.numAdditionals == 1 ? " " : "s", end - msg->data);
if (!InterfaceID || !m->SPSSocket || !mDNSSameIPPort(dstport, m->SPSSocket->port)) return;
if (ptr)
{
ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
- if (ptr && m->rec.r.resrec.rrtype == kDNSType_OPT)
+ if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && 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 (i = 0; i < msg->h.mDNS_numUpdates && ptr && ptr < end; i++)
{
ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
- if (ptr)
+ if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative)
{
mDNSu16 RDLengthMem = GetRDLengthMem(&m->rec.r.resrec);
AuthRecord *ar = mDNSPlatformMemAllocate(sizeof(AuthRecord) - sizeof(RDataBody) + RDLengthMem);
{
mDNSu8 RecordType = m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask ? kDNSRecordTypeUnique : kDNSRecordTypeShared;
m->rec.r.resrec.rrclass &= ~kDNSClass_UniqueRRSet;
+ ClearIdenticalProxyRecords(m, &owner, m->DuplicateRecords); // Make sure we don't have any old stale duplicates of this record
+ ClearIdenticalProxyRecords(m, &owner, m->ResourceRecords);
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;
+ ar->ForceMCast = mDNStrue;
+ ar->WakeUp = owner;
if (m->rec.r.resrec.rrtype == kDNSType_PTR)
{
mDNSs32 t = ReverseMapDomainType(m->rec.r.resrec.name);
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;
+ // Unsolicited Neighbor Advertisements (RFC 2461 Section 7.2.6) give us fast address cache updating,
+ // but some older IPv6 clients get confused by them, so for now we don't send them. Without Unsolicited
+ // Neighbor Advertisements we have to rely on Neighbor Unreachability Detection instead, which is slower.
+ // Given this, we'll do our best to wake for existing IPv6 connections, but we don't want to encourage
+ // new ones for sleeping clients, so we'll we send deletions for our SPS clients' AAAA records.
+ if (m->KnownBugs & mDNS_KnownBug_LimitedIPv6)
+ if (ar->resrec.rrtype == kDNSType_AAAA) ar->resrec.rroriginalttl = 0;
m->ProxyRecords++;
+ mDNS_UpdateAllowSleep(m);
LogSPS("SPS Registered %4d %X %s", m->ProxyRecords, RecordType, ARDisplayString(m,ar));
}
}
if (ptr)
{
ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
- if (ptr && m->rec.r.resrec.rrtype == kDNSType_OPT)
+ if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && 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];
}
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)
+ const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds, mDNSInterfaceID InterfaceID, DNSServer *dnsserver)
{
if (cr == &m->rec.r && m->rec.r.resrec.RecordType)
{
// Create empty resource record
cr->resrec.RecordType = kDNSRecordTypePacketNegative;
cr->resrec.InterfaceID = InterfaceID;
+ cr->resrec.rDNSServer = dnsserver;
cr->resrec.name = name; // Will be updated to point to cg->name when we call CreateNewCacheEntry
cr->resrec.rrtype = rrtype;
cr->resrec.rrclass = rrclass;
// and we have a key for company.com, so we try to locate the private query server for company.com, which necessarily entails
// 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.
+//
+// We keep SuppressUnusable questions separate so that we can return a quick response to them and not get blocked behind
+// the queries that are not marked SuppressUnusable. But if the query is not suppressed, they are treated the same as
+// non-SuppressUnusable questions. This should be fine as the goal of SuppressUnusable is to return quickly only if it
+// is suppressed. If it is not suppressed, we do try all the DNS servers for valid answers like any other question.
+// The main reason for this design is that cache entries point to a *single* question and that question is responsible
+// for keeping the cache fresh as long as it is active. Having multiple active question for a single cache entry
+// breaks this design principle.
// If IsLLQ(Q) is true, it means the question is both:
// (a) long-lived and
q->qclass == question->qclass && // class,
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->SuppressQuery == question->SuppressQuery) && // Questions that are suppressed/not suppressed
q->qnamehash == question->qnamehash &&
SameDomainName(&q->qname, &question->qname)) // and name
return(q);
q->servAddr = question->servAddr;
q->servPort = question->servPort;
q->qDNSServer = question->qDNSServer;
+ q->validDNSServers = question->validDNSServers;
q->unansweredQueries = question->unansweredQueries;
+ q->noServerResponse = question->noServerResponse;
+ q->triedAllServersOnce = question->triedAllServersOnce;
q->TargetQID = question->TargetQID;
q->LocalSocket = question->LocalSocket;
// This should always be a positive value between 0 and DNSSERVER_PENALTY_TIME
// If it does not get reset in ResetDNSServerPenalties for some reason, we do it
// here
- LogMsg("PenaltyTimeForServer: PenaltyTime negative %d, (server penaltyTime %d, timenow %d) resetting the penalty", ptime, server->penaltyTime, m->timenow);
+ LogMsg("PenaltyTimeForServer: PenaltyTime negative %d, (server penaltyTime %d, timenow %d) resetting the penalty",
+ ptime, server->penaltyTime, m->timenow);
server->penaltyTime = 0;
ptime = 0;
}
return ptime;
}
-// Return the next server to "prev" if it is a match and unpenalized
-mDNSlocal DNSServer *GetNextUnPenalizedServer(mDNS *m, DNSServer *prev)
- {
- int curmatchlen = -1;
- DNSServer *curr = m->DNSServers;
-
- if (prev == mDNSNULL) return mDNSNULL;
-
- while (curr != mDNSNULL && curr != prev)
- curr = curr->next;
-
- if (curr == mDNSNULL)
- return mDNSNULL;
-
-
- // We need to set the curmatchlen as though we are walking the list
- // from the beginning. Otherwise, we may not pick the best match.
- // For example, if we are looking up xxx.com, and we used the "xxx.com"
- // entry the previous time and the next one is "com", we should not pick
- // "com" now
- curmatchlen = CountLabels(&curr->domain);
- curr = curr->next;
- while (curr != mDNSNULL)
- {
- int scount = CountLabels(&curr->domain);
-
- // Should not be delete because it is marked temporarily for cleaning up
- // entries during configuration change and we pass NULL as the last argument
- // to GetServerForName
- if (curr->flags & DNSServer_FlagDelete)
- {
- LogInfo("GetServerForName: DNS Server is marked delete, cannot happen");
- curr = curr->next;
- continue;
- }
-
-
- debugf("GetNextUnPenalizedServer: Address %#a (Domain %##s), PenaltyTime(abs) %d, PenaltyTime(rel) %d", &curr->addr, curr->domain.c, curr->penaltyTime, PenaltyTimeForServer(m,curr));
-
- // Note the "==" in comparing scount and curmatchlen. When we picked a match
- // for the question the first time, we already made sure that prev is the best match.
- // Any other match is as good if we can find another entry with same number of
- // labels. There can't be better matches that have more labels, because
- // we would have picked that in the first place. Also we don't care what the
- // name in the question is as we picked the best server for the question first
- // time and the domain name is in prev now
-
- if ((curr->penaltyTime == 0) && (scount == curmatchlen) && SameDomainName(&prev->domain, &curr->domain))
- return curr;
- curr = curr->next;
- }
- return mDNSNULL;
- }
-
-
//Checks to see whether the newname is a better match for the name, given the best one we have
//seen so far (given in bestcount).
//Returns -1 if the newname is not a better match
// If we find a match and the number of labels is more than bestcount, then we
// return 1 so that the caller can pick this over the old one.
//
- // NOTE: newcount can either be equal or greater than bestcount beause of the
+ // Note: newcount can either be equal or greater than bestcount beause of the
// check above.
if (SameDomainName(SkipLeadingLabels(name, namecount - newcount), newname))
return -1;
}
+// Sets all the Valid DNS servers for a question
+mDNSexport void SetValidDNSServers(mDNS *m, DNSQuestion *question)
+ {
+ DNSServer *curmatch = mDNSNULL;
+ int bestmatchlen = -1, namecount = CountLabels(&question->qname);
+ DNSServer *curr;
+ int bettermatch, currcount;
+ int index = 0;
+
+ question->validDNSServers = zeroOpaque64;
+ for (curr = m->DNSServers; curr; curr = curr->next)
+ {
+ debugf("SetValidDNSServers: Parsing DNS server Address %#a (Domain %##s), Scope: %d", &curr->addr, curr->domain.c, curr->scoped);
+ // skip servers that will soon be deleted
+ if (curr->flags & DNSServer_FlagDelete)
+ { debugf("SetValidDNSServers: Delete set for index %d, DNS server %#a (Domain %##s), scoped %d", index, &curr->addr, curr->domain.c, curr->scoped); continue; }
+
+ currcount = CountLabels(&curr->domain);
+ if ((!curr->scoped && (!question->InterfaceID || (question->InterfaceID == mDNSInterface_Unicast))) || (curr->interface == question->InterfaceID))
+ {
+ bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen);
+
+ // If we found a better match (bettermatch == 1) then clear all the bits
+ // corresponding to the old DNSServers that we have may set before and start fresh.
+ // If we find an equal match, then include that DNSServer also by setting the corresponding
+ // bit
+ if ((bettermatch == 1) || (bettermatch == 0))
+ {
+ curmatch = curr;
+ bestmatchlen = currcount;
+ if (bettermatch) { debugf("SetValidDNSServers: Resetting all the bits"); question->validDNSServers = zeroOpaque64; }
+ debugf("SetValidDNSServers: Setting the bit for DNS server Address %#a (Domain %##s), Scoped:%d index %d", &curr->addr, curr->domain.c, curr->scoped, index);
+ bit_set_opaque64(question->validDNSServers, index);
+ }
+ }
+ index++;
+ }
+ question->noServerResponse = 0;
+ debugf("SetValidDNSServers: ValidDNSServer bits 0x%x%x for question %p %##s (%s)",
+ question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype));
+ }
+
// Get the Best server that matches a name. If you find penalized servers, look for the one
// that will come out of the penalty box soon
-mDNSlocal DNSServer *GetAnyBestServer(mDNS *m, const domainname *name)
+mDNSlocal DNSServer *GetBestServer(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSOpaque64 validBits, int *selected, mDNSBool nameMatch)
{
DNSServer *curmatch = mDNSNULL;
int bestmatchlen = -1, namecount = name ? CountLabels(name) : 0;
DNSServer *curr;
- mDNSs32 bestPenaltyTime;
- int bettermatch;
+ mDNSs32 bestPenaltyTime, currPenaltyTime;
+ int bettermatch, currcount;
+ int index = 0;
+ int currindex = -1;
- bestmatchlen = -1;
+ debugf("GetBestServer: ValidDNSServer bits 0x%x%x", validBits.l[1], validBits.l[0]);
bestPenaltyTime = DNSSERVER_PENALTY_TIME + 1;
for (curr = m->DNSServers; curr; curr = curr->next)
{
- int currcount = CountLabels(&curr->domain);
- mDNSs32 currPenaltyTime = PenaltyTimeForServer(m, curr);
+ // skip servers that will soon be deleted
+ if (curr->flags & DNSServer_FlagDelete)
+ { debugf("GetBestServer: Delete set for index %d, DNS server %#a (Domain %##s), scoped %d", index, &curr->addr, curr->domain.c, curr->scoped); continue; }
- debugf("GetAnyBestServer: Address %#a (Domain %##s), PenaltyTime(abs) %d, PenaltyTime(rel) %d",
- &curr->addr, curr->domain.c, curr->penaltyTime, currPenaltyTime);
+ // Check if this is a valid DNSServer
+ if (!bit_get_opaque64(validBits, index)) { debugf("GetBestServer: continuing for index %d", index); index++; continue; }
+ currcount = CountLabels(&curr->domain);
+ currPenaltyTime = PenaltyTimeForServer(m, curr);
+
+ debugf("GetBestServer: Address %#a (Domain %##s), PenaltyTime(abs) %d, PenaltyTime(rel) %d",
+ &curr->addr, curr->domain.c, curr->penaltyTime, currPenaltyTime);
// If there are multiple best servers for a given question, we will pick the first one
// if none of them are penalized. If some of them are penalized in that list, we pick
// "currPenaltyTime < bestPenaltyTime" check lets us either pick the first best server
// in the list when there are no penalized servers and least one among them
// when there are some penalized servers
-
- if (!(curr->flags & DNSServer_FlagDelete))
- {
-
- bettermatch = BetterMatchForName(name, namecount, &curr->domain, currcount, bestmatchlen);
+ //
+ // Notes on InterfaceID matching:
+ //
+ // 1) A DNSServer entry may have an InterfaceID but the scoped flag may not be set. This
+ // is the old way of specifying an InterfaceID option for DNSServer. We recoginize these
+ // entries by "scoped" being false. These are like any other unscoped entries except that
+ // if it is picked e.g., domain match, when the packet is sent out later, the packet will
+ // be sent out on that interface. Theese entries can be matched by either specifying a
+ // zero InterfaceID or non-zero InterfaceID on the question. Specifying an InterfaceID on
+ // the question will cause an extra check on matching the InterfaceID on the question
+ // against the DNSServer.
+ //
+ // 2) A DNSServer may also have both scoped set and InterfaceID non-NULL. This
+ // is the new way of specifying an InterfaceID option for DNSServer. These will be considered
+ // only when the question has non-zero interfaceID.
+
+ if ((!curr->scoped && !InterfaceID) || (curr->interface == InterfaceID))
+ {
+
+ // If we know that all the names are already equally good matches, then skip calling BetterMatchForName.
+ // This happens when we initially walk all the DNS servers and set the validity bit on the question.
+ // Actually we just need PenaltyTime match, but for the sake of readability we just skip the expensive
+ // part and still do some redundant steps e.g., InterfaceID match
+
+ if (nameMatch) bettermatch = BetterMatchForName(name, namecount, &curr->domain, currcount, bestmatchlen);
+ else bettermatch = 0;
// If we found a better match (bettermatch == 1) then we don't need to
// compare penalty times. But if we found an equal match, then we compare
// the penalty times to pick a better match
if ((bettermatch == 1) || ((bettermatch == 0) && currPenaltyTime < bestPenaltyTime))
- { curmatch = curr; bestmatchlen = currcount; bestPenaltyTime = currPenaltyTime;}
+ { currindex = index; curmatch = curr; bestmatchlen = currcount; bestPenaltyTime = currPenaltyTime; }
}
+ index++;
}
-
+ if (selected) *selected = currindex;
return curmatch;
}
-// Look up a DNS Server, matching by name in split-dns configurations.
-mDNSexport DNSServer *GetServerForName(mDNS *m, const domainname *name, DNSServer *prev)
+// Look up a DNS Server, matching by name and InterfaceID
+mDNSexport DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID)
+ {
+ DNSServer *curmatch = mDNSNULL;
+ char *ifname = mDNSNULL; // for logging purposes only
+ mDNSOpaque64 allValid;
+
+ if ((InterfaceID == mDNSInterface_Unicast) || (InterfaceID == mDNSInterface_LocalOnly))
+ InterfaceID = mDNSNULL;
+
+ if (InterfaceID) ifname = InterfaceNameForID(m, InterfaceID);
+
+ // By passing in all ones, we make sure that every DNS server is considered
+ allValid.l[0] = allValid.l[1] = 0xFFFFFFFF;
+
+ curmatch = GetBestServer(m, name, InterfaceID, allValid, mDNSNULL, mDNStrue);
+
+ if (curmatch != mDNSNULL)
+ LogInfo("GetServerForName: DNS server %#a:%d (Penalty Time Left %d) (Scope %s:%p) found for name %##s", &curmatch->addr,
+ mDNSVal16(curmatch->port), (curmatch->penaltyTime ? (curmatch->penaltyTime - m->timenow) : 0), ifname ? ifname : "None",
+ InterfaceID, name);
+ else
+ LogInfo("GetServerForName: no DNS server (Scope %s:%p) found for name %##s", ifname ? ifname : "None", InterfaceID, name);
+
+ return(curmatch);
+ }
+
+// Look up a DNS Server for a question within its valid DNSServer bits
+mDNSexport DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question)
{
DNSServer *curmatch = mDNSNULL;
+ char *ifname = mDNSNULL; // for logging purposes only
+ mDNSInterfaceID InterfaceID = question->InterfaceID;
+ const domainname *name = &question->qname;
+ int currindex;
- // prev is the previous DNS server used by some question
- if (prev != mDNSNULL)
+ if ((InterfaceID == mDNSInterface_Unicast) || (InterfaceID == mDNSInterface_LocalOnly))
+ InterfaceID = mDNSNULL;
+
+ if (InterfaceID) ifname = InterfaceNameForID(m, InterfaceID);
+
+ if (!mDNSOpaque64IsZero(&question->validDNSServers))
{
- curmatch = GetNextUnPenalizedServer(m, prev);
- if (curmatch != mDNSNULL)
- {
- LogInfo("GetServerForName: Good DNS server %#a:%d (Penalty Time Left %d) found", &curmatch->addr,
- mDNSVal16(curmatch->port), (curmatch->penaltyTime ? (curmatch->penaltyTime - m->timenow) : 0));
- return curmatch;
- }
+ curmatch = GetBestServer(m, name, InterfaceID, question->validDNSServers, &currindex, mDNSfalse);
+ if (currindex != -1) bit_clr_opaque64(question->validDNSServers, currindex);
}
-
- // We are here for many reasons.
- //
- // 1. We are looking up the DNS server first time for this question
- // 2. We reached the end of list looking for unpenalized servers
- //
- // In the case of (1) we want to find the best match for the name. If nothing is penalized,
- // we want the first one in the list. If some are penalized, we want the one that will get
- // out of penalty box sooner
- //
- // In the case of (2) we want to select the first server that matches the name if StrictUnicastOrdering
- // is TRUE. As penaltyTime is zero for all of them in that case, we automatically achieve that below.
- // If StrictUnicastOrdering is FALSE, we want to pick the least penalized server in the list
- curmatch = GetAnyBestServer(m, name);
-
- if (curmatch != mDNSNULL)
- LogInfo("GetServerForName: DNS server %#a:%d (Penalty Time Left %d) found", &curmatch->addr,
- mDNSVal16(curmatch->port), (curmatch->penaltyTime ? (curmatch->penaltyTime - m->timenow) : 0));
+ if (curmatch != mDNSNULL)
+ LogInfo("GetServerForQuestion: %p DNS server %#a:%d (Penalty Time Left %d) (Scope %s:%p) found for name %##s (%s)", question, &curmatch->addr,
+ mDNSVal16(curmatch->port), (curmatch->penaltyTime ? (curmatch->penaltyTime - m->timenow) : 0), ifname ? ifname : "None",
+ InterfaceID, name, DNSTypeName(question->qtype));
else
- LogInfo("GetServerForName: no DNS server found");
+ LogInfo("GetServerForQuestion: %p no DNS server (Scope %s:%p) found for name %##s (%s)", question, ifname ? ifname : "None", InterfaceID, name, DNSTypeName(question->qtype));
return(curmatch);
}
+
#define ValidQuestionTarget(Q) (((Q)->Target.type == mDNSAddrType_IPv4 || (Q)->Target.type == mDNSAddrType_IPv6) && \
(mDNSSameIPPort((Q)->TargetPort, UnicastDNSPort) || mDNSSameIPPort((Q)->TargetPort, MulticastDNSPort)))
DNSQuestion *q;
(void)n; // Unused
mDNS_Lock(m);
- LogInfo("LLQNATCallback external address:port %.4a:%u", &n->ExternalAddress, mDNSVal16(n->ExternalPort));
+ LogInfo("LLQNATCallback external address:port %.4a:%u, NAT result %d", &n->ExternalAddress, mDNSVal16(n->ExternalPort), n->Result);
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
mDNS_Unlock(m);
}
+mDNSlocal mDNSBool ShouldSuppressQuery(mDNS *const m, domainname *qname, mDNSu16 qtype, mDNSInterfaceID InterfaceID)
+ {
+ NetworkInterfaceInfo *i;
+ mDNSs32 iptype;
+ DomainAuthInfo *AuthInfo;
+
+ if (qtype == kDNSType_A) iptype = mDNSAddrType_IPv4;
+ else if (qtype == kDNSType_AAAA) iptype = mDNSAddrType_IPv6;
+ else { LogInfo("ShouldSuppressQuery: Query not suppressed for %##s, qtype %s, not A/AAAA type", qname, DNSTypeName(qtype)); return mDNSfalse; }
+
+ // We still want the ability to be able to listen to the local services and hence
+ // don't fail .local requests. We always have a loopback interface which we don't
+ // check here.
+ if (IsLocalDomain(qname)) { LogInfo("ShouldSuppressQuery: Query not suppressed for %##s, qtype %s, Local question", qname, DNSTypeName(qtype)); return mDNSfalse; }
+
+ // Skip Private domains as we have special addresses to get the hosts in the Private domain
+ AuthInfo = GetAuthInfoForName_internal(m, qname);
+ if (AuthInfo && !AuthInfo->deltime && AuthInfo->AutoTunnel)
+ { LogInfo("ShouldSuppressQuery: Query not suppressed for %##s, qtype %s, Private Domain", qname, DNSTypeName(qtype)); return mDNSfalse; }
+
+ // Match on Type, Address and InterfaceID
+ //
+ // Check whether we are looking for a name that ends in .local, then presence of a link-local
+ // address on the interface is sufficient.
+ for (i = m->HostInterfaces; i; i = i->next)
+ {
+ if (i->ip.type != iptype) continue;
+
+ if (!InterfaceID || (InterfaceID == mDNSInterface_LocalOnly) || (InterfaceID == mDNSInterface_P2P) ||
+ (i->InterfaceID == InterfaceID))
+ {
+ if (iptype == mDNSAddrType_IPv4 && !mDNSv4AddressIsLoopback(&i->ip.ip.v4) && !mDNSv4AddressIsLinkLocal(&i->ip.ip.v4))
+ {
+ LogInfo("ShouldSuppressQuery: Query not suppressed for %##s, qtype %s, Local Address %.4a found", qname, DNSTypeName(qtype),
+ &i->ip.ip.v4);
+ return mDNSfalse;
+ }
+ else if (iptype == mDNSAddrType_IPv6 &&
+ !mDNSv6AddressIsLoopback(&i->ip.ip.v6) &&
+ !mDNSv6AddressIsLinkLocal(&i->ip.ip.v6) &&
+ !mDNSSameIPv6Address(i->ip.ip.v6, m->AutoTunnelHostAddr) &&
+ !mDNSSameIPv6Address(i->ip.ip.v6, m->AutoTunnelRelayAddr))
+ {
+ LogInfo("ShouldSuppressQuery: Query not suppressed for %##s, qtype %s, Local Address %.16a found", qname, DNSTypeName(qtype),
+ &i->ip.ip.v6);
+ return mDNSfalse;
+ }
+ }
+ }
+ LogInfo("ShouldSuppressQuery: Query suppressed for %##s, qtype %s, because no matching interface found", qname, DNSTypeName(qtype));
+ return mDNStrue;
+ }
+
+mDNSlocal void CheckSuppressedCurrentQuestion(mDNS *const m, DNSQuestion *q)
+ {
+ CacheRecord *rr;
+ mDNSu32 slot;
+ CacheGroup *cg;
+
+ // Temporarily turn off suppression so that AnswerCurrentQuestionWithResourceRecord
+ // can answer the question
+ q->SuppressQuery = mDNSfalse;
+ slot = HashSlot(&q->qname);
+ cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
+ {
+ // Don't deliver RMV events for negative records
+ if (rr->resrec.RecordType == kDNSRecordTypePacketNegative)
+ {
+ LogInfo("CheckSuppressedCurrentQuestion: CacheRecord %s Suppressing RMV events for question %p %##s (%s), CRActiveQuestion %p, CurrentAnswers %d",
+ CRDisplayString(m, rr), q, q->qname.c, DNSTypeName(q->qtype), rr->CRActiveQuestion, q->CurrentAnswers);
+ continue;
+ }
+
+ if (SameNameRecordAnswersQuestion(&rr->resrec, q))
+ {
+ LogInfo("CheckSuppressedCurrentQuestion: Calling AnswerCurrentQuestionWithResourceRecord (RMV) for question %##s using resource record %s",
+ q->qname.c, CRDisplayString(m, rr));
+
+ q->CurrentAnswers--;
+ if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers--;
+ if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers--;
+
+ if (rr->CRActiveQuestion == q)
+ {
+ DNSQuestion *qptr;
+ // If this was the active question for this cache entry, it was the one that was
+ // responsible for keeping the cache entry fresh when the cache entry was reaching
+ // its expiry. We need to handover the responsibility to someone else. Otherwise,
+ // when the cache entry is about to expire, we won't find an active question
+ // (pointed by CRActiveQuestion) to refresh the cache.
+ for (qptr = m->Questions; qptr; qptr=qptr->next)
+ if (ActiveQuestion(qptr) && ResourceRecordAnswersQuestion(&rr->resrec, qptr))
+ break;
+
+ if (qptr)
+ LogInfo("CheckSuppressedCurrentQuestion: Updating CRActiveQuestion to %p for cache record %s, "
+ "Original question CurrentAnswers %d, new question CurrentAnswers %d, SuppressUnusable %d, SuppressQuery %d",
+ qptr, CRDisplayString(m,rr), q->CurrentAnswers, qptr->CurrentAnswers, qptr->SuppressUnusable, qptr->SuppressQuery);
+
+ rr->CRActiveQuestion = qptr; // Question used to be active; new value may or may not be null
+ if (!qptr) m->rrcache_active--; // If no longer active, decrement rrcache_active count
+ }
+ AnswerCurrentQuestionWithResourceRecord(m, rr, QC_rmv);
+ if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here
+ }
+ }
+ if (m->CurrentQuestion == q) q->SuppressQuery = mDNStrue;
+ }
+
+mDNSlocal mDNSBool IsQuestionNew(mDNS *const m, DNSQuestion *question)
+ {
+ DNSQuestion *q;
+ for (q = m->NewQuestions; q; q = q->next)
+ if (q == question) return mDNStrue;
+ return mDNSfalse;
+ }
+
+// The caller should hold the lock
+mDNSexport void CheckSuppressUnusableQuestions(mDNS *const m)
+ {
+ DNSQuestion *q, *qnext;
+ DNSQuestion *restart = mDNSNULL;
+
+ // We look through all questions including new questions. During network change events,
+ // we potentially restart questions here in this function that ends up as new questions,
+ // which may be suppressed at this instance. Before it is handled we get another network
+ // event that changes the status e.g., address becomes available. If we did not process
+ // new questions, we would never change its SuppressQuery status.
+ for (q = m->Questions; q ; q = qnext)
+ {
+ qnext = q->next;
+ if (!mDNSOpaque16IsZero(q->TargetQID) && q->SuppressUnusable)
+ {
+ mDNSBool old = q->SuppressQuery;
+ q->SuppressQuery = ShouldSuppressQuery(m, &q->qname, q->qtype, q->InterfaceID);
+ if (q->SuppressQuery != old)
+ {
+ if (q->SuppressQuery)
+ {
+ // Previously it was not suppressed, Generate RMV events for the ADDs that we might have delivered before
+ // followed by a negative cache response
+ if (m->CurrentQuestion)
+ LogMsg("CheckSuppressUnusableQuestions: ERROR m->CurrentQuestion already set: %##s (%s)",
+ m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+
+ // If it is a new question, we have not delivered any ADD events yet. So, don't deliver RMV events.
+ if (!IsQuestionNew(m, q))
+ {
+ m->CurrentQuestion = q;
+ CheckSuppressedCurrentQuestion(m, q);
+ if (m->CurrentQuestion != q)
+ {
+ m->CurrentQuestion = mDNSNULL;
+ LogInfo("CheckSuppressUnusableQuestions: Question deleted while giving RMV events");
+ continue;
+ }
+ m->CurrentQuestion = mDNSNULL;
+ }
+ else { debugf("CheckSuppressUnusableQuestion: Question %p %##s (%s) is a new question", q, q->qname.c, DNSTypeName(q->qtype)); }
+ }
+
+ // There are two cases here.
+ //
+ // 1. Previously it was suppressed and now it is not suppressed, restart the question so
+ // that it will start as a new question. Note that we can't just call ActivateUnicastQuery
+ // because when we get the response, if we had entries in the cache already, it will not answer
+ // this question if the cache entry did not change. Hence, we need to restart
+ // the query so that it can be answered from the cache.
+ //
+ // 2. Previously it was not suppressed and now it is suppressed. We need to restart the questions
+ // so that we redo the duplicate checks in mDNS_StartQuery_internal. A SuppressUnusable question
+ // is a duplicate of non-SuppressUnusable question if it is not suppressed (SuppressQuery is false).
+ // A SuppressUnusable question is not a duplicate of non-SuppressUnusable question if it is suppressed
+ // (SuppressQuery is true). The reason for this is that when a question is suppressed, we want an
+ // immediate response and not want to be blocked behind a question that is querying DNS servers.
+ // When the question is not suppressed, we don't want two active questions sending packets on the wire.
+ // This affects both efficiency and also the current design where there is only one active question
+ // pointed to from a cache entry.
+ //
+ // We restart queries in a two step process by first calling stop and build a temporary list which we
+ // will restart at the end. The main reason for the two step process is to handle duplicate questions.
+ // If there are duplicate questions, calling stop inherits the values from another question on the list (which
+ // will soon become the real question) including q->ThisQInterval which might be zero if it was
+ // suppressed before. At the end when we have restarted all questions, none of them is active as each
+ // inherits from one another and we need to reactivate one of the questions here which is a little hacky.
+ //
+ // It is much cleaner and less error prone to build a list of questions and restart at the end.
+
+ LogInfo("CheckSuppressUnusableQuestions: Stop question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+ mDNS_StopQuery_internal(m, q);
+ q->next = restart;
+ restart = q;
+ }
+ }
+ }
+ while (restart)
+ {
+ q = restart;
+ restart = restart->next;
+ q->next = mDNSNULL;
+ LogInfo("CheckSuppressUnusableQuestions: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+ mDNS_StartQuery_internal(m, q);
+ }
+ }
+
mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question)
{
if (question->Target.type && !ValidQuestionTarget(question))
question->Target.type = mDNSAddrType_None;
}
- if (!question->Target.type) question->TargetPort = zeroIPPort; // If question->Target specified clear TargetPort
+ if (!question->Target.type) question->TargetPort = zeroIPPort; // If no question->Target specified clear TargetPort
question->TargetQID =
#ifndef UNICAST_DISABLED
- (question->Target.type || (question->InterfaceID == mDNSInterface_Unicast) ||
- (question->InterfaceID != mDNSInterface_LocalOnly && !question->ForceMCast && !IsLocalDomain(&question->qname)))
- ? mDNS_NewMessageID(m) :
+ (question->Target.type || Question_uDNS(question)) ? mDNS_NewMessageID(m) :
#endif // UNICAST_DISABLED
zeroID;
// Note: It important that new questions are appended at the *end* of the list, not prepended at the start
q = &m->Questions;
- if (question->InterfaceID == mDNSInterface_LocalOnly) q = &m->LocalOnlyQuestions;
+ if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) q = &m->LocalOnlyQuestions;
while (*q && *q != question) q=&(*q)->next;
if (*q)
*q = question;
// If this question is referencing a specific interface, verify it exists
- if (question->InterfaceID && question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_Unicast)
+ if (question->InterfaceID && question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_Unicast && question->InterfaceID != mDNSInterface_P2P)
{
NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID);
if (!intf)
question->UniqueAnswers = 0;
question->FlappingInterface1 = mDNSNULL;
question->FlappingInterface2 = mDNSNULL;
- question->AuthInfo = GetAuthInfoForQuestion(m, question); // Must do this before calling FindDuplicateQuestion()
+ // Must do AuthInfo and SuppressQuery before calling FindDuplicateQuestion()
+ question->AuthInfo = GetAuthInfoForQuestion(m, question);
+ if (question->SuppressUnusable)
+ question->SuppressQuery = ShouldSuppressQuery(m, &question->qname, question->qtype, question->InterfaceID);
+ else
+ question->SuppressQuery = 0;
question->DuplicateOf = FindDuplicateQuestion(m, question);
question->NextInDQList = mDNSNULL;
question->SendQNow = mDNSNULL;
// 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->deliverAddEvents = mDNSfalse;
question->qDNSServer = mDNSNULL;
question->unansweredQueries = 0;
question->nta = mDNSNULL;
question->expire = 0;
question->ntries = 0;
question->id = zeroOpaque64;
+ question->validDNSServers = zeroOpaque64;
+ question->triedAllServersOnce = 0;
+ question->noServerResponse = 0;
if (question->DuplicateOf) question->AuthInfo = question->DuplicateOf->AuthInfo;
debugf("mDNS_StartQuery: Question %##s (%s) Interface %p Now %d Send in %d Answer in %d (%p) %s (%p)",
question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, m->timenow,
- question->LastQTime + question->ThisQInterval - m->timenow,
+ NextQSendTime(question) - m->timenow,
question->DelayAnswering ? question->DelayAnswering - m->timenow : 0,
question, question->DuplicateOf ? "duplicate of" : "not duplicate", question->DuplicateOf);
- if (question->InterfaceID == mDNSInterface_LocalOnly)
+ if (question->DelayAnswering)
+ LogInfo("mDNS_StartQuery_internal: Delaying answering for %d ticks while cache stabilizes for %##s (%s)",
+ question->DelayAnswering - m->timenow, question->qname.c, DNSTypeName(question->qtype));
+
+ if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P)
{
if (!m->NewLocalOnlyQuestions) m->NewLocalOnlyQuestions = question;
}
// this routine with the question list data structures in an inconsistent state.
if (!mDNSOpaque16IsZero(question->TargetQID))
{
- question->qDNSServer = GetServerForName(m, &question->qname, mDNSNULL);
+ // Duplicate questions should have the same DNSServers so that when we find
+ // a matching resource record, all of them get the answers. Calling GetServerForQuestion
+ // for the duplicate question may get a different DNS server from the original question
+ if (question->DuplicateOf)
+ {
+ question->validDNSServers = question->DuplicateOf->validDNSServers;
+ question->qDNSServer = question->DuplicateOf->qDNSServer;
+ LogInfo("mDNS_StartQuery_internal: Duplicate question %p (%p) %##s (%s), DNS Server %#a:%d",
+ question, question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype),
+ question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
+ mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort));
+ }
+ else
+ {
+ SetValidDNSServers(m, question);
+ question->qDNSServer = GetServerForQuestion(m, question);
+ LogInfo("mDNS_StartQuery_internal: question %p %##s (%s), DNS Server %#a:%d",
+ question, question->qname.c, DNSTypeName(question->qtype),
+ question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
+ mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort));
+ }
ActivateUnicastQuery(m, question, mDNSfalse);
// If long-lived query, and we don't have our NAT mapping active, start it now
mDNSexport void CancelGetZoneData(mDNS *const m, ZoneData *nta)
{
debugf("CancelGetZoneData %##s (%s)", nta->question.qname.c, DNSTypeName(nta->question.qtype));
- mDNS_StopQuery_internal(m, &nta->question);
+ // This function may be called anytime to free the zone information.The question may or may not have stopped.
+ // If it was already stopped, mDNS_StopQuery_internal would have set q->ThisQInterval to -1 and should not
+ // call it again
+ if (nta->question.ThisQInterval != -1)
+ {
+ mDNS_StopQuery_internal(m, &nta->question);
+ if (nta->question.ThisQInterval != -1)
+ LogMsg("CancelGetZoneData: Question %##s (%s) ThisQInterval %d not -1", nta->question.qname.c, DNSTypeName(nta->question.qtype), nta->question.ThisQInterval);
+ }
mDNSPlatformMemFree(nta);
}
//LogInfo("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
- if (question->InterfaceID == mDNSInterface_LocalOnly) qp = &m->LocalOnlyQuestions;
+ if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) qp = &m->LocalOnlyQuestions;
while (*qp && *qp != question) qp=&(*qp)->next;
if (*qp) *qp = (*qp)->next;
else
if (rr->CRActiveQuestion == question)
{
DNSQuestion *q;
+ // Checking for ActiveQuestion filters questions that are suppressed also
+ // as suppressed questions are not active
for (q = m->Questions; q; q=q->next) // Scan our list of questions
if (ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q))
break;
- debugf("mDNS_StopQuery_internal: Updating CRActiveQuestion to %p for cache record %s", q, CRDisplayString(m,rr));
+ if (q)
+ debugf("mDNS_StopQuery_internal: Updating CRActiveQuestion to %p for cache record %s, Original question CurrentAnswers %d, new question "
+ "CurrentAnswers %d, SuppressQuery %d", q, CRDisplayString(m,rr), question->CurrentAnswers, q->CurrentAnswers, q->SuppressQuery);
rr->CRActiveQuestion = q; // Question used to be active; new value may or may not be null
if (!q) m->rrcache_active--; // If no longer active, decrement rrcache_active count
}
// so if we delete it earlier in this routine, we could find that our "question->next" pointer above is already
// invalid before we even use it. By making sure that we update m->CurrentQuestion and m->NewQuestions if necessary
// *first*, then they're all ready to be updated a second time if necessary when we cancel our GetZoneData query.
- if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; }
if (question->LocalSocket) { mDNSPlatformUDPClose(question->LocalSocket); question->LocalSocket = mDNSNULL; }
if (!mDNSOpaque16IsZero(question->TargetQID) && question->LongLived)
UpdateAutoTunnelDomainStatuses(m);
#endif
}
+ // wait until we send the refresh above which needs the nta
+ if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
return(mStatus_NoError);
}
question->Target = zeroAddr;
question->qtype = kDNSType_PTR;
question->qclass = kDNSClass_IN;
- question->LongLived = mDNSfalse;
+ question->LongLived = mDNStrue;
question->ExpectUnique = mDNSfalse;
question->ForceMCast = ForceMCast;
question->ReturnIntermed = mDNSfalse;
+ question->SuppressUnusable = mDNSfalse;
question->QuestionCallback = Callback;
question->QuestionContext = Context;
if (!ConstructServiceName(&question->qname, mDNSNULL, srv, domain)) return(mStatus_BadParamErr);
-#ifndef UNICAST_DISABLED
- if (Question_uDNS(question))
- {
- question->LongLived = mDNStrue;
- question->ThisQInterval = InitialQuestionInterval;
- question->LastQTime = m->timenow - question->ThisQInterval;
- }
-#endif // UNICAST_DISABLED
return(mDNS_StartQuery_internal(m, question));
}
query->qSRV.ExpectUnique = mDNStrue;
query->qSRV.ForceMCast = mDNSfalse;
query->qSRV.ReturnIntermed = mDNSfalse;
+ query->qSRV.SuppressUnusable = mDNSfalse;
query->qSRV.QuestionCallback = FoundServiceInfoSRV;
query->qSRV.QuestionContext = query;
query->qTXT.ExpectUnique = mDNStrue;
query->qTXT.ForceMCast = mDNSfalse;
query->qTXT.ReturnIntermed = mDNSfalse;
+ query->qTXT.SuppressUnusable = mDNSfalse;
query->qTXT.QuestionCallback = FoundServiceInfoTXT;
query->qTXT.QuestionContext = query;
query->qAv4.ExpectUnique = mDNStrue;
query->qAv4.ForceMCast = mDNSfalse;
query->qAv4.ReturnIntermed = mDNSfalse;
+ query->qAv4.SuppressUnusable = mDNSfalse;
query->qAv4.QuestionCallback = FoundServiceInfo;
query->qAv4.QuestionContext = query;
query->qAv6.ExpectUnique = mDNStrue;
query->qAv6.ForceMCast = mDNSfalse;
query->qAv6.ReturnIntermed = mDNSfalse;
+ query->qAv6.SuppressUnusable = mDNSfalse;
query->qAv6.QuestionCallback = FoundServiceInfo;
query->qAv6.QuestionContext = query;
question->ExpectUnique = mDNSfalse;
question->ForceMCast = mDNSfalse;
question->ReturnIntermed = mDNSfalse;
+ question->SuppressUnusable = mDNSfalse;
question->QuestionCallback = Callback;
question->QuestionContext = Context;
if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr);
mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newttl,
const mDNSu16 newrdlength, RData *const newrdata, mDNSRecordUpdateCallback *Callback)
{
-#ifndef UNICAST_DISABLED
- mDNSBool unicast = !(rr->resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(rr->resrec.name));
-#else
- mDNSBool unicast = mDNSfalse;
-#endif
-
if (!ValidateRData(rr->resrec.rrtype, newrdlength, newrdata))
{
LogMsg("Attempt to update record with invalid rdata: %s", GetRRDisplayString_rdb(&rr->resrec, &newrdata->u, m->MsgBuffer));
// If TTL is unspecified, leave TTL unchanged
if (newttl == 0) newttl = rr->resrec.rroriginalttl;
- // If we already have an update queued up which has not gone through yet,
- // give the client a chance to free that memory
- if (!unicast && rr->NewRData)
+ // If we already have an update queued up which has not gone through yet, give the client a chance to free that memory
+ if (rr->NewRData)
{
RData *n = rr->NewRData;
- rr->NewRData = mDNSNULL; // Clear the NewRData pointer ...
+ rr->NewRData = mDNSNULL; // Clear the NewRData pointer ...
if (rr->UpdateCallback)
- rr->UpdateCallback(m, rr, n); // ...and let the client free this memory, if necessary
+ rr->UpdateCallback(m, rr, n, rr->newrdlength); // ...and let the client free this memory, if necessary
}
rr->NewRData = newrdata;
rr->newrdlength = newrdlength;
rr->UpdateCallback = Callback;
- if (unicast) { mStatus status = uDNS_UpdateRecord(m, rr); mDNS_Unlock(m); return(status); }
+#ifndef UNICAST_DISABLED
+ if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly && rr->resrec.InterfaceID != mDNSInterface_P2P && !IsLocalDomain(rr->resrec.name))
+ {
+ mStatus status = uDNS_UpdateRecord(m, rr);
+ // The caller frees the memory on error, don't retain stale pointers
+ if (status != mStatus_NoError) { rr->NewRData = mDNSNULL; rr->newrdlength = 0; }
+ mDNS_Unlock(m);
+ return(status);
+ }
+#endif
if (rr->resrec.rroriginalttl == newttl &&
rr->resrec.rdlength == newrdlength && mDNSPlatformMemSame(rr->resrec.rdata->u.data, newrdata->u.data, newrdlength))
CompleteRDataUpdate(m, rr);
else
{
- domainlabel name;
- domainname type, domain;
- DeconstructServiceName(rr->resrec.name, &name, &type, &domain);
rr->AnnounceCount = InitialAnnounceCount;
- // iChat often does suprious record updates where no data has changed. For the _presence service type, using
- // name/value pairs, the mDNSPlatformMemSame() check above catches this and correctly suppresses the wasteful
- // update. For the _ichat service type, the XML encoding introduces spurious noise differences into the data
- // 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);
while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
if (!rr->UpdateBlocked && rr->UpdateCredits) rr->UpdateCredits--;
mDNSlocal void RestartRecordGetZoneData(mDNS * const m)
{
AuthRecord *rr;
- ServiceRecordSet *s;
-
+ LogInfo("RestartRecordGetZoneData: ResourceRecords");
for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (AuthRecord_uDNS(rr))
+ if (AuthRecord_uDNS(rr) && rr->state != regState_NoTarget)
{
debugf("RestartRecordGetZoneData: StartGetZoneData for %##s", rr->resrec.name->c);
- if (rr->nta) CancelGetZoneData(m, rr->nta);
+ // Zero out the updateid so that if we have a pending response from the server, it won't
+ // be accepted as a valid response. If we accept the response, we might free the new "nta"
+ if (rr->nta) { rr->updateid = zeroID; 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)
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);
+ if (m->SPSBrowseCallback)
+ {
+ mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback
+ m->SPSBrowseCallback(m, &set->NetWakeBrowse, mDNSNULL, mDNSfalse);
+ mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again
+ }
// 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)
// Assume this interface will be active now, unless we find a duplicate already in the list
set->InterfaceActive = mDNStrue;
- set->IPv4Available = (set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx);
- set->IPv6Available = (set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx);
+ set->IPv4Available = (mDNSu8)(set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx);
+ set->IPv6Available = (mDNSu8)(set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx);
InitializeNetWakeState(m, set);
if (set->McastTxRx && ((m->KnownBugs & mDNS_KnownBug_PhantomInterfaces) || FirstOfType || set->InterfaceActive))
{
DNSQuestion *q;
- // 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;
+ // Normally, after an interface comes up, we pause half a second before beginning probing.
+ // This is to guard against cases where there's rapid interface changes, where we could be confused by
+ // seeing packets we ourselves sent just moments ago (perhaps when this interface had a different address)
+ // which are then echoed back after a short delay by some Ethernet switches and some 802.11 base stations.
+ // We don't want to do a probe, and then see a stale echo of an announcement we ourselves sent,
+ // and think it's a conflicting answer to our probe.
+ // In the case of a flapping interface, we pause for five seconds, and reduce the announcement count to one packet.
+ const mDNSs32 probedelay = flapping ? mDNSPlatformOneSecond * 5 : mDNSPlatformOneSecond / 2;
+ const mDNSu8 numannounce = flapping ? (mDNSu8)1 : InitialAnnounceCount;
// 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.
- 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("RegisterInterface: Frequent transitions for interface %s (%#a)",
- set->ifname, &set->ip);
- if (!m->SuppressProbes ||
- m->SuppressProbes - (m->timenow + delay) < 0)
- m->SuppressProbes = (m->timenow + delay);
- }
+ // We set a random delay of up to InitialQuestionInterval (1/3 second).
+ // We must *never* set m->SuppressSending to more than that (or set it repeatedly in a way
+ // that causes mDNSResponder to remain in a prolonged state of SuppressSending, because
+ // suppressing packet sending for more than about 1/3 second can cause protocol correctness
+ // to start to break down (e.g. we don't answer probes fast enough, and get name conflicts).
+ // See <rdar://problem/4073853> mDNS: m->SuppressSending set too enthusiastically
+ if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval);
+
+ if (flapping) LogMsg("RegisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip);
+
+ LogInfo("RegisterInterface: %s (%#a) probedelay %d", set->ifname, &set->ip, probedelay);
+ if (m->SuppressProbes == 0 ||
+ m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0)
+ m->SuppressProbes = NonZeroTime(m->timenow + probedelay);
for (q = m->Questions; q; q=q->next) // Scan our list of questions
if (mDNSOpaque16IsZero(q->TargetQID))
if (!q->InterfaceID || q->InterfaceID == set->InterfaceID) // If non-specific Q, or Q on this specific interface,
{ // then reactivate this question
+ // If flapping, delay between first and second queries is nine seconds instead of one second
mDNSBool dodelay = flapping && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID);
mDNSs32 initial = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval;
mDNSs32 qdelay = dodelay ? mDNSPlatformOneSecond * 5 : 0;
{
if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType);
- if (rr->AnnounceCount < announce) rr->AnnounceCount = announce;
+ if (rr->AnnounceCount < numannounce) rr->AnnounceCount = numannounce;
+ rr->SendNSECNow = mDNSNULL;
InitializeLastAPTime(m, rr);
}
}
RestartRecordGetZoneData(m);
+ CheckSuppressUnusableQuestions(m);
+
+ mDNS_UpdateAllowSleep(m);
+
mDNS_Unlock(m);
return(mStatus_NoError);
}
LogInfo("mDNS_DeregisterInterface: Last representative of InterfaceID %p %s (%#a) deregistered;"
" marking questions etc. dormant", set->InterfaceID, set->ifname, &set->ip);
- if (flapping)
- LogMsg("DeregisterInterface: Frequent transitions for interface %s (%#a)",
- set->ifname, &set->ip);
+ if (set->McastTxRx && flapping)
+ LogMsg("DeregisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip);
// 1. Deactivate any questions specific to this interface, and tag appropriate questions
// so that mDNS_RegisterInterface() knows how swiftly it needs to reactivate them
{
// If this interface is deemed flapping,
// postpone deleting the cache records in case the interface comes back again
- if (!flapping) mDNS_PurgeCacheResourceRecord(m, rr);
- else
+ if (set->McastTxRx && flapping)
{
- // We want these record to go away in 30 seconds
+ // For a flapping interface we want these record to go away after 30 seconds
+ mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface);
// We set UnansweredQueries = MaxUnansweredQueries so we don't waste time doing any queries for them --
// if the interface does come back, any relevant questions will be reactivated anyway
- mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface);
rr->UnansweredQueries = MaxUnansweredQueries;
}
+ else
+ mDNS_PurgeCacheResourceRecord(m, rr);
}
// 3. Any DNS servers specific to this interface are now unusable
mDNSu32 slot;
CacheGroup *cg;
CacheRecord *rr;
- m->NextCacheCheck = m->timenow;
FORALL_CACHERECORDS(slot, cg, rr)
if (rr->resrec.InterfaceID == set->InterfaceID)
mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface);
}
+ CheckSuppressUnusableQuestions(m);
+
+ mDNS_UpdateAllowSleep(m);
+
mDNS_Unlock(m);
}
// are still in the process of deregistering, don't pass on the NameConflict/MemFree message until
// every record is finished cleaning up.
mDNSu32 i;
+ ExtraResourceRecord *e = sr->Extras;
+
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;
+ while (e)
+ {
+ if (e->r.resrec.RecordType != kDNSRecordTypeUnregistered) return;
+ e = e->next;
+ }
+
// 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;
- }
}
+ LogInfo("ServiceCallback: All records %s for %##s", (result == mStatus_MemFree ? "Unregistered": "Registered"), sr->RR_PTR.resrec.name->c);
// CAUTION: MUST NOT do anything more with sr after calling sr->Callback(), because the client's callback
// function is allowed to do anything, including deregistering this service and freeing its memory.
if (sr->ServiceCallback)
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;
- ServiceRecordSet **p = &m->ServiceRegistrations;
- while (*p && *p != srs) p=&(*p)->uDNS_next;
- if (*p) { LogMsg("uDNS_RegisterService: %p %##s already in list", srs, srs->RR_SRV.resrec.name->c); return(mStatus_AlreadyRegistered); }
-
- srs->uDNS_next = mDNSNULL;
- *p = srs;
-
- srs->RR_SRV.resrec.rroriginalttl = kHostNameTTL;
- srs->RR_TXT.resrec.rroriginalttl = kStandardTTL;
- srs->RR_PTR.resrec.rroriginalttl = kStandardTTL;
- for (i = 0; i < srs->NumSubTypes;i++) srs->SubTypes[i].resrec.rroriginalttl = kStandardTTL;
-
- srs->srs_uselease = mDNStrue;
-
- if (srs->RR_SRV.AutoTarget)
- {
- // For autotunnel services pointing at our IPv6 ULA we don't need or want a NAT mapping, but for all other
- // advertised services referencing our uDNS hostname, we want NAT mappings automatically created as appropriate,
- // with the port number in our advertised SRV record automatically tracking the external mapped port.
- DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name);
- if (!AuthInfo || !AuthInfo->AutoTunnel) srs->RR_SRV.AutoTarget = Target_AutoHostAndNATMAP;
- }
-
- if (!GetServiceTarget(m, &srs->RR_SRV))
- {
- // defer registration until we've got a target
- 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;
- return mStatus_NoError;
- }
-#endif
-
// Note:
// Name is first label of domain name (any dots in the name are actual dots, not label separators)
// Type is service type (e.g. "_ipp._tcp.")
mStatus err;
mDNSu32 i;
- sr->state = regState_Zero;
- sr->srs_uselease = 0;
- sr->TestForSelfConflict = 0;
- sr->Private = 0;
- sr->id = zeroID;
- sr->zone.c[0] = 0;
- 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;
- sr->SRVChanged = 0;
- sr->tcp = mDNSNULL;
-
sr->ServiceCallback = Callback;
sr->ServiceContext = Context;
sr->Conflict = mDNSfalse;
// 2. Set up the PTR record rdata to point to our service name
// We set up two additionals, so when a client asks for this PTR we automatically send the SRV and the TXT too
+ // Note: uDNS registration code assumes that Additional1 points to the SRV record
AssignDomainName(&sr->RR_PTR.resrec.rdata->u.name, sr->RR_SRV.resrec.name);
sr->RR_PTR.Additional1 = &sr->RR_SRV;
sr->RR_PTR.Additional2 = &sr->RR_TXT;
// 4. Set up the TXT record rdata,
// and set DependentOn because we're depending on the SRV record to find and resolve conflicts for us
+ // Note: uDNS registration code assumes that DependentOn points to the SRV record
if (txtinfo == mDNSNULL) sr->RR_TXT.resrec.rdlength = 0;
else if (txtinfo != sr->RR_TXT.resrec.rdata->u.txt.c)
{
}
sr->RR_TXT.DependentOn = &sr->RR_SRV;
- 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)))
- {
- mStatus status;
- mDNS_Lock(m);
- // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
- // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
- // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
- // (We have to duplicate this check here because uDNS_RegisterService() bypasses the usual mDNS_Register_internal() bottleneck)
- if (!sr->RR_TXT.resrec.rdlength) { sr->RR_TXT.resrec.rdlength = 1; sr->RR_TXT.resrec.rdata->u.txt.c[0] = 0; }
-
- status = uDNS_RegisterService(m, sr);
- mDNS_Unlock(m);
- return(status);
- }
-#endif
-
mDNS_Lock(m);
+ // It is important that we register SRV first. uDNS assumes that SRV is registered first so
+ // that if the SRV cannot find a target, rest of the records that belong to this service
+ // will not be activated.
err = mDNS_Register_internal(m, &sr->RR_SRV);
if (!err) err = mDNS_Register_internal(m, &sr->RR_TXT);
// We register the RR_PTR last, because we want to be sure that in the event of a forced call to
return(err);
}
-mDNSlocal void DummyCallback(mDNS *const m, AuthRecord *rr, mStatus result)
- {
- (void)m; // Unused
- (void)rr; // Unused
- (void)result; // Unused
- LogInfo("DummyCallback %d %s", result, ARDisplayString(m, rr));
- }
-
mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr,
ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl)
{
extra->r.resrec.name->c, DNSTypeName(extra->r.resrec.rrtype), extra->r.resrec.rdlength);
status = mDNS_Register_internal(m, &extra->r);
- if (status == mStatus_NoError)
- {
- *e = extra;
-#ifndef UNICAST_DISABLED
- if (AuthRecord_uDNS(&sr->RR_SRV))
- {
- extra->r.resrec.RecordType = kDNSRecordTypeShared; // don't want it to conflict with the service name (???)
- extra->r.RecordCallback = DummyCallback; // don't generate callbacks for extra RRs for unicast services (WHY NOT????)
- if (sr->state != regState_Registered && sr->state != regState_Refresh) extra->r.state = regState_ExtraQueued;
- }
-#endif
- }
+ if (status == mStatus_NoError) *e = extra;
mDNS_Unlock(m);
return(status);
// 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)
- {
- // 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));
-
-#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;
- mDNS_Lock(m);
- status = uDNS_DeregisterService(m, sr);
- mDNS_Unlock(m);
- return(status);
- }
-#endif
+// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
+mDNSexport mStatus mDNS_DeregisterService_drt(mDNS *const m, ServiceRecordSet *sr, mDNS_Dereg_type drt)
+ {
+ // 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));
+
if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeUnregistered)
{
debugf("Service set for %##s already deregistered", sr->RR_SRV.resrec.name->c);
}
else if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeDeregistering)
{
- debugf("Service set for %##s already in the process of deregistering", sr->RR_SRV.resrec.name->c);
+ LogInfo("Service set for %##s already in the process of deregistering", sr->RR_SRV.resrec.name->c);
// Avoid race condition:
// If a service gets a conflict, then we set the Conflict flag to tell us to generate
// an mStatus_NameConflict message when we get the mStatus_MemFree for our PTR record.
mDNS_Deregister_internal(m, &sr->RR_SRV, mDNS_Dereg_repeat);
mDNS_Deregister_internal(m, &sr->RR_TXT, mDNS_Dereg_repeat);
- mDNS_Deregister_internal(m, &sr->RR_ADV, mDNS_Dereg_normal);
+ mDNS_Deregister_internal(m, &sr->RR_ADV, drt);
// We deregister all of the extra records, but we leave the sr->Extras list intact
// in case the client wants to do a RenameAndReregister and reinstate the registration
}
for (i=0; i<sr->NumSubTypes; i++)
- mDNS_Deregister_internal(m, &sr->SubTypes[i], mDNS_Dereg_normal);
-
- // Be sure to deregister the PTR last!
- // Deregistering this record is what triggers the mStatus_MemFree callback to ServiceCallback,
- // which in turn passes on the mStatus_MemFree (or mStatus_NameConflict) back to the client callback,
- // which is then at liberty to free the ServiceRecordSet memory at will. We need to make sure
- // we've deregistered all our records and done any other necessary cleanup before that happens.
- status = mDNS_Deregister_internal(m, &sr->RR_PTR, mDNS_Dereg_normal);
+ mDNS_Deregister_internal(m, &sr->SubTypes[i], drt);
+
+ status = mDNS_Deregister_internal(m, &sr->RR_PTR, drt);
mDNS_Unlock(m);
return(status);
}
return(mDNS_Register(m, rr));
}
+mDNSlocal mDNSBool mDNS_IdUsedInResourceRecordsList(mDNS * const m, mDNSOpaque16 id)
+ {
+ AuthRecord *r;
+ for (r = m->ResourceRecords; r; r=r->next) if (mDNSSameOpaque16(id, r->updateid)) return mDNStrue;
+ return mDNSfalse;
+ }
+
+mDNSlocal mDNSBool mDNS_IdUsedInQuestionsList(mDNS * const m, mDNSOpaque16 id)
+ {
+ DNSQuestion *q;
+ for (q = m->Questions; q; q=q->next) if (mDNSSameOpaque16(id, q->TargetQID)) return mDNStrue;
+ return mDNSfalse;
+ }
+
mDNSexport mDNSOpaque16 mDNS_NewMessageID(mDNS * const m)
{
mDNSOpaque16 id;
int i;
+
for (i=0; i<10; i++)
{
- AuthRecord *r;
- DNSQuestion *q;
- id = mDNSOpaque16fromIntVal(1 + mDNSRandom(0xFFFE));
- 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;
+ id = mDNSOpaque16fromIntVal(1 + (mDNSu16)mDNSRandom(0xFFFE));
+ if (!mDNS_IdUsedInResourceRecordsList(m, id) && !mDNS_IdUsedInQuestionsList(m, id)) break;
}
+
debugf("mDNS_NewMessageID: %5d", mDNSVal16(id));
+
return id;
}
}
}
-mDNSexport void mDNSCoreReceiveRawPacket(mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID)
+mDNSlocal void mDNSCoreReceiveRawARP(mDNS *const m, const ARP_EthIP *const arp, 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;
+ 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);
- mDNS_Lock(m);
+ // Pass 1:
+ // Process ARP Requests and Probes (but not Announcements), and generate an ARP Reply if necessary.
+ // We also process ARPs from our own kernel (and 'answer' them by injecting a local ARP table entry)
+ // We ignore ARP Announcements here -- Announcements are not questions, they're assertions, so we don't need to answer them.
+ // The times we might need to react to an ARP Announcement are:
+ // (i) as an indication that the host in question has not gone to sleep yet (so we should delay beginning to proxy for it) or
+ // (ii) if it's a conflicting Announcement from another host
+ // -- and we check for these 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->resrec.RecordType != kDNSRecordTypeDeregistering &&
+ 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",
+ intf->ifname, msg, &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
+ if (msg == msg1) RestartARPProbing(m, rr);
+ else if (msg == msg3) mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID);
+ else if (msg == msg4) SendARP(m, 2, rr, &arp->tpa, &arp->sha, &arp->spa, &arp->sha);
+ }
+ }
- // Pass 1:
- // Process ARP Requests and Probes (but not Announcements), and generate an ARP Reply if necessary.
- // We also process ARPs from our own kernel (and 'answer' them by injecting a local ARP table entry)
- // We ignore ARP Announcements here -- Announcements are not questions, they're assertions, so we don't need to answer them.
- // The times we might need to react to an ARP Announcement are:
- // (i) as an indication that the host in question has not gone to sleep yet (so we should delay beginning to proxy for it) or
- // (ii) if it's a conflicting Announcement from another host
- // -- and we check for these in Pass 2 below.
- if (mDNSSameOpaque16(arp->op, ARP_op_request) && !mDNSSameIPv4Address(arp->spa, arp->tpa))
+ // 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->tpa))
+ if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
+ rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, arp->spa))
{
- char *ifname = InterfaceNameForID(m, InterfaceID);
- if (!ifname) ifname = "<NULL InterfaceID>";
- 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",
- ifname, msg, &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
- if (msg == msg1) RestartARPProbing(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);
+ RestartARPProbing(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", intf->ifname,
+ 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", intf->ifname,
+ &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
+ ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC);
+ }
}
+ }
- // 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))
+ mDNS_Unlock(m);
+ }
+
+/*
+// Option 1 is Source Link Layer Address Option
+// Option 2 is Target Link Layer Address Option
+mDNSlocal const mDNSEthAddr *GetLinkLayerAddressOption(const IPv6NDP *const ndp, const mDNSu8 *const end, mDNSu8 op)
+ {
+ const mDNSu8 *options = (mDNSu8 *)(ndp+1);
+ while (options < end)
+ {
+ debugf("NDP Option %02X len %2d %d", options[0], options[1], end - options);
+ if (options[0] == op && options[1] == 1) return (const mDNSEthAddr*)(options+2);
+ options += options[1] * 8;
+ }
+ return mDNSNULL;
+ }
+*/
+
+mDNSlocal void mDNSCoreReceiveRawND(mDNS *const m, const mDNSEthAddr *const sha, const mDNSv6Addr *spa,
+ const IPv6NDP *const ndp, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID)
+ {
+ AuthRecord *rr;
+ NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
+ if (!intf) return;
+
+ mDNS_Lock(m);
+
+ // Pass 1: Process Neighbor Solicitations, and generate a Neighbor Advertisement if necessary.
+ if (ndp->type == NDP_Sol)
+ {
+ //const mDNSEthAddr *const sha = GetLinkLayerAddressOption(ndp, end, NDP_SrcLL);
+ (void)end;
+ for (rr = m->ResourceRecords; rr; rr=rr->next)
+ if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
+ rr->AddressProxy.type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->AddressProxy.ip.v6, ndp->target))
+ {
+ static const char msg1[] = "NDP Req from owner -- re-probing";
+ static const char msg2[] = "Ignoring NDP Request from ";
+ static const char msg3[] = "Creating Local NDP Cache entry ";
+ static const char msg4[] = "Answering NDP Request from ";
+ static const char msg5[] = "Answering NDP Probe from ";
+ const char *const msg = sha && mDNSSameEthAddress(sha, &rr->WakeUp.IMAC) ? msg1 :
+ (rr->AnnounceCount == InitialAnnounceCount) ? msg2 :
+ sha && mDNSSameEthAddress(sha, &intf->MAC) ? msg3 :
+ spa && mDNSIPv6AddressIsZero(*spa) ? msg4 : msg5;
+ LogSPS("%-7s %s %.6a %.16a for %.16a -- H-MAC %.6a I-MAC %.6a %s",
+ intf->ifname, msg, sha, spa, &ndp->target, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
+ if (msg == msg1) RestartARPProbing(m, rr);
+ else if (msg == msg3)
+ {
+ if (!(m->KnownBugs & mDNS_KnownBug_LimitedIPv6))
+ mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID);
+ }
+ else if (msg == msg4) SendNDP(m, NDP_Adv, NDP_Solicited, rr, &ndp->target, mDNSNULL, spa, sha );
+ else if (msg == msg5) SendNDP(m, NDP_Adv, 0, rr, &ndp->target, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth);
+ }
+ }
+
+ // Pass 2: For all types of NDP packet we check the Sender IP address to make sure it doesn't conflict with any AddressProxy record we're holding.
+ if (mDNSSameEthAddress(sha, &intf->MAC))
+ debugf("NDP from self for %.16a", &ndp->target);
+ else
+ {
+ // For Neighbor Advertisements we check the Target address field, not the actual IPv6 source address.
+ // When a machine has both link-local and routable IPv6 addresses, it may send NDP packets making assertions
+ // about its routable IPv6 address, using its link-local address as the source address for all NDP packets.
+ // Hence it is the NDP target address we care about, not the actual packet source address.
+ if (ndp->type == NDP_Adv) spa = &ndp->target;
+ if (!mDNSSameIPv6Address(*spa, zerov6Addr))
+ for (rr = m->ResourceRecords; rr; rr=rr->next)
+ if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
+ rr->AddressProxy.type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->AddressProxy.ip.v6, *spa))
+ {
+ RestartARPProbing(m, rr);
+ if (mDNSSameEthAddress(sha, &rr->WakeUp.IMAC))
+ LogSPS("%-7s NDP %s from owner %.6a %.16a for %.16a -- re-starting probing for %s", intf->ifname,
+ ndp->type == NDP_Sol ? "Solicitation " : "Advertisement", sha, spa, &ndp->target, ARDisplayString(m, rr));
+ else
{
- char *ifname = InterfaceNameForID(m, InterfaceID);
- if (!ifname) ifname = "<NULL InterfaceID>";
-
- RestartARPProbing(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",
- ifname,
- 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",
- ifname, &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);
- }
+ LogMsg("%-7s Conflicting NDP from %.6a %.16a for %.16a -- waking H-MAC %.6a I-MAC %.6a %s", intf->ifname,
+ sha, spa, &ndp->target, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
+ ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC);
}
- }
-
- mDNS_Unlock(m);
+ }
}
- else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IP) && (v4->flagsfrags.b[0] & 0x1F) == 0 && v4->flagsfrags.b[1] == 0)
+
+ mDNS_Unlock(m);
+ }
+
+mDNSlocal void mDNSCoreReceiveRawTransportPacket(mDNS *const m, const mDNSEthAddr *const sha, const mDNSAddr *const src, const mDNSAddr *const dst, const mDNSu8 protocol,
+ const mDNSu8 *const p, const TransportLayerPacket *const t, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID, const mDNSu16 len)
+ {
+ const mDNSIPPort port = (protocol == 0x06) ? t->tcp.dst : (protocol == 0x11) ? t->udp.dst : zeroIPPort;
+ mDNSBool wake = mDNSfalse;
+
+ switch (protocol)
{
- 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
- static const mDNSIPPort SSH = { { SSH_AsNumber >> 8, SSH_AsNumber & 0xFF } };
- static const mDNSIPPort ARD = { { ARD_AsNumber >> 8, ARD_AsNumber & 0xFF } };
+ #define XX wake ? "Received" : "Ignoring", end-p
+ case 0x01: LogSPS("Ignoring %d-byte ICMP from %#a to %#a", end-p, src, dst);
+ break;
- 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 0x06: {
+ #define SSH_AsNumber 22
+ static const mDNSIPPort SSH = { { SSH_AsNumber >> 8, SSH_AsNumber & 0xFF } };
- case 17: {
- const UDPHeader *const udp = (const UDPHeader *)trans;
- const mDNSu16 udplen = (mDNSu16)((mDNSu16)trans[4] << 8 | trans[5]); // Length *including* 8-byte UDP header
- if (udplen >= sizeof(UDPHeader))
- {
- const mDNSu16 datalen = udplen - sizeof(UDPHeader);
- port = udp->dst;
- wake = mDNStrue;
+ // 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 = (!(t->tcp.flags & 4) && (t->tcp.flags & 3) != 1);
- // For Back to My Mac UDP port 4500 (IPSEC) packets, we do some special handling
- if (mDNSSameIPPort(port, IPSECPort))
- {
- // Specifically ignore NAT keepalive packets
- if (datalen == 1 && end >= trans + 9 && trans[8] == 0xFF) wake = mDNSfalse;
- else
- {
- // Skip over the Non-ESP Marker if present
- const mDNSBool NonESP = (end >= trans + 12 && trans[8] == 0 && trans[9] == 0 && trans[10] == 0 && trans[11] == 0);
- const IKEHeader *const ike = (IKEHeader *)(trans + (NonESP ? 12 : 8));
- const mDNSu16 ikelen = datalen - (NonESP ? 4 : 0);
- if (ikelen >= sizeof(IKEHeader) && end >= ((mDNSu8 *)ike) + sizeof(IKEHeader))
- if ((ike->Version & 0x10) == 0x10)
- {
- // ExchangeType == 5 means 'Informational' <http://www.ietf.org/rfc/rfc2408.txt>
- // ExchangeType == 34 means 'IKE_SA_INIT' <http://www.iana.org/assignments/ikev2-parameters>
- if (ike->ExchangeType == 5 || ike->ExchangeType == 34) wake = mDNSfalse;
- LogSPS("%s %d-byte IKE ExchangeType %d", XX, ike->ExchangeType);
- }
- }
- }
+ // 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) && !(t->tcp.flags & 2)) wake = mDNSfalse;
- // 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)
- // Payload: 13 88 00 6a 41 4e 41 20 (8 bytes) ffffffffffff (6 bytes) 16xMAC (96 bytes) = 110 bytes total
- if (mDNSSameIPPort(port, ARD)) wake = (datalen >= 110 && end >= trans+10 && trans[8] == 0x13 && trans[9] == 0x88);
+ LogSPS("%s %d-byte TCP from %#a:%d to %#a:%d%s%s%s", XX,
+ src, mDNSVal16(t->tcp.src), dst, mDNSVal16(port),
+ (t->tcp.flags & 2) ? " SYN" : "",
+ (t->tcp.flags & 1) ? " FIN" : "",
+ (t->tcp.flags & 4) ? " RST" : "");
+ }
+ break;
+
+ case 0x11: {
+ #define ARD_AsNumber 3283
+ static const mDNSIPPort ARD = { { ARD_AsNumber >> 8, ARD_AsNumber & 0xFF } };
+ const mDNSu16 udplen = (mDNSu16)((mDNSu16)t->bytes[4] << 8 | t->bytes[5]); // Length *including* 8-byte UDP header
+ if (udplen >= sizeof(UDPHeader))
+ {
+ const mDNSu16 datalen = udplen - sizeof(UDPHeader);
+ wake = mDNStrue;
- LogSPS("%s %d-byte UDP from %.4a:%d to %.4a:%d", XX, &v4->src, mDNSVal16(udp->src), &v4->dst, mDNSVal16(port));
+ // For Back to My Mac UDP port 4500 (IPSEC) packets, we do some special handling
+ if (mDNSSameIPPort(port, IPSECPort))
+ {
+ // Specifically ignore NAT keepalive packets
+ if (datalen == 1 && end >= &t->bytes[9] && t->bytes[8] == 0xFF) wake = mDNSfalse;
+ else
+ {
+ // Skip over the Non-ESP Marker if present
+ const mDNSBool NonESP = (end >= &t->bytes[12] && t->bytes[8] == 0 && t->bytes[9] == 0 && t->bytes[10] == 0 && t->bytes[11] == 0);
+ const IKEHeader *const ike = (IKEHeader *)(t + (NonESP ? 12 : 8));
+ const mDNSu16 ikelen = datalen - (NonESP ? 4 : 0);
+ if (ikelen >= sizeof(IKEHeader) && end >= ((mDNSu8 *)ike) + sizeof(IKEHeader))
+ if ((ike->Version & 0x10) == 0x10)
+ {
+ // ExchangeType == 5 means 'Informational' <http://www.ietf.org/rfc/rfc2408.txt>
+ // ExchangeType == 34 means 'IKE_SA_INIT' <http://www.iana.org/assignments/ikev2-parameters>
+ if (ike->ExchangeType == 5 || ike->ExchangeType == 34) wake = mDNSfalse;
+ LogSPS("%s %d-byte IKE ExchangeType %d", XX, ike->ExchangeType);
+ }
}
}
- break;
- default: LogSPS("%s %d-byte IP packet unknown protocol %d from %.4a to %.4a", XX, v4->protocol, &v4->src, &v4->dst);
- break;
- }
+ // 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)
+ // Payload: 13 88 00 6a 41 4e 41 20 (8 bytes) ffffffffffff (6 bytes) 16xMAC (96 bytes) = 110 bytes total
+ if (mDNSSameIPPort(port, ARD)) wake = (datalen >= 110 && end >= &t->bytes[10] && t->bytes[8] == 0x13 && t->bytes[9] == 0x88);
- if (wake)
- {
- AuthRecord *rr, *r2;
+ LogSPS("%s %d-byte UDP from %#a:%d to %#a:%d", XX, src, mDNSVal16(t->udp.src), dst, mDNSVal16(port));
+ }
+ }
+ break;
- 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))
+ case 0x3A: if (&t->bytes[len] <= end)
{
- const mDNSu8 *const tp = (v4->protocol == 6) ? (const mDNSu8 *)"\x4_tcp" : (const 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(ThirdLabel(r2->resrec.name)->c, tp))
- break;
- if (!r2 && mDNSSameIPPort(port, IPSECPort)) r2 = rr; // So that we wake for BTMM IPSEC packets, even without a matching SRV record
- char *ifname = InterfaceNameForID(m, rr->resrec.InterfaceID);
- if (!ifname) ifname = "<NULL InterfaceID>";
- if (r2)
- {
- rr->AnnounceCount = 0;
- LogMsg("Waking host at %s %.4a H-MAC %.6a I-MAC %.6a for %s",
- ifname, &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",
- ifname, &v4->dst, &rr->WakeUp.HMAC, tp, mDNSVal16(port));
+ mDNSu16 checksum = IPv6CheckSum(&src->ip.v6, &dst->ip.v6, protocol, t->bytes, len);
+ if (!checksum) mDNSCoreReceiveRawND(m, sha, &src->ip.v6, &t->ndp, &t->bytes[len], InterfaceID);
+ else LogInfo("IPv6CheckSum bad %04X %02X%02X from %#a to %#a", checksum, t->bytes[2], t->bytes[3], src, dst);
}
- mDNS_Unlock(m);
- }
- }
+ break;
+
+ default: LogSPS("Ignoring %d-byte IP packet unknown protocol %d from %#a to %#a", end-p, protocol, src, dst);
+ break;
}
- else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IP) && (v4->flagsfrags.b[0] & 0x1F) == 0 && v4->flagsfrags.b[1] == 0)
+
+ if (wake)
{
- debugf("Got IPv6 from %.16a to %.16a", &v4->src, &v6->dst);
- (void)v6;
+ AuthRecord *rr, *r2;
+
+ mDNS_Lock(m);
+ for (rr = m->ResourceRecords; rr; rr=rr->next)
+ if (rr->resrec.InterfaceID == InterfaceID &&
+ rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
+ rr->AddressProxy.type && mDNSSameAddress(&rr->AddressProxy, dst))
+ {
+ const mDNSu8 *const tp = (protocol == 6) ? (const mDNSu8 *)"\x4_tcp" : (const 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.RecordType != kDNSRecordTypeDeregistering &&
+ r2->resrec.rrtype == kDNSType_SRV && mDNSSameIPPort(r2->resrec.rdata->u.srv.port, port) &&
+ SameDomainLabel(ThirdLabel(r2->resrec.name)->c, tp))
+ break;
+ if (!r2 && mDNSSameIPPort(port, IPSECPort)) r2 = rr; // So that we wake for BTMM IPSEC packets, even without a matching SRV record
+ if (r2)
+ {
+ LogMsg("Waking host at %s %#a H-MAC %.6a I-MAC %.6a for %s",
+ InterfaceNameForID(m, rr->resrec.InterfaceID), dst, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, r2));
+ ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC);
+ }
+ else
+ LogSPS("Sleeping host at %s %#a %.6a has no service on %#s %d",
+ InterfaceNameForID(m, rr->resrec.InterfaceID), dst, &rr->WakeUp.HMAC, tp, mDNSVal16(port));
+ }
+ mDNS_Unlock(m);
+ }
+ }
+
+mDNSexport void mDNSCoreReceiveRawPacket(mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID)
+ {
+ static const mDNSOpaque16 Ethertype_ARP = { { 0x08, 0x06 } }; // Ethertype 0x0806 = ARP
+ static const mDNSOpaque16 Ethertype_IPv4 = { { 0x08, 0x00 } }; // Ethertype 0x0800 = IPv4
+ static const mDNSOpaque16 Ethertype_IPv6 = { { 0x86, 0xDD } }; // Ethertype 0x86DD = IPv6
+ static const mDNSOpaque16 ARP_hrd_eth = { { 0x00, 0x01 } }; // Hardware address space (Ethernet = 1)
+ static const mDNSOpaque16 ARP_pro_ip = { { 0x08, 0x00 } }; // Protocol address space (IP = 0x0800)
+
+ // Note: BPF guarantees that the NETWORK LAYER header will be word aligned, not the link-layer header.
+ // In other words, we can safely assume that pkt below (ARP, IPv4 or IPv6) is properly word aligned,
+ // but if pkt is 4-byte aligned, that necessarily means that eth CANNOT also be 4-byte aligned
+ // since it points to a an address 14 bytes before pkt.
+ const EthernetHeader *const eth = (const EthernetHeader *)p;
+ const NetworkLayerPacket *const pkt = (const NetworkLayerPacket *)(eth+1);
+ mDNSAddr src, dst;
+ #define RequiredCapLen(P) ((P)==0x01 ? 4 : (P)==0x06 ? 20 : (P)==0x11 ? 8 : (P)==0x3A ? 24 : 0)
+
+ // Is ARP? Length must be at least 14 + 28 = 42 bytes
+ if (end >= p+42 && mDNSSameOpaque16(eth->ethertype, Ethertype_ARP) && mDNSSameOpaque16(pkt->arp.hrd, ARP_hrd_eth) && mDNSSameOpaque16(pkt->arp.pro, ARP_pro_ip))
+ mDNSCoreReceiveRawARP(m, &pkt->arp, InterfaceID);
+ // Is IPv4 with zero fragmentation offset? Length must be at least 14 + 20 = 34 bytes
+ else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv4) && (pkt->v4.flagsfrags.b[0] & 0x1F) == 0 && pkt->v4.flagsfrags.b[1] == 0)
+ {
+ const mDNSu8 *const trans = p + 14 + (pkt->v4.vlen & 0xF) * 4;
+ debugf("Got IPv4 %02X from %.4a to %.4a", pkt->v4.protocol, &pkt->v4.src, &pkt->v4.dst);
+ src.type = mDNSAddrType_IPv4; src.ip.v4 = pkt->v4.src;
+ dst.type = mDNSAddrType_IPv4; dst.ip.v4 = pkt->v4.dst;
+ if (end >= trans + RequiredCapLen(pkt->v4.protocol))
+ mDNSCoreReceiveRawTransportPacket(m, ð->src, &src, &dst, pkt->v4.protocol, p, (TransportLayerPacket*)trans, end, InterfaceID, 0);
+ }
+ // Is IPv6? Length must be at least 14 + 28 = 42 bytes
+ else if (end >= p+54 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv6))
+ {
+ const mDNSu8 *const trans = p + 54;
+ debugf("Got IPv6 %02X from %.16a to %.16a", pkt->v6.pro, &pkt->v6.src, &pkt->v6.dst);
+ src.type = mDNSAddrType_IPv6; src.ip.v6 = pkt->v6.src;
+ dst.type = mDNSAddrType_IPv6; dst.ip.v6 = pkt->v6.dst;
+ if (end >= trans + RequiredCapLen(pkt->v6.pro))
+ mDNSCoreReceiveRawTransportPacket(m, ð->src, &src, &dst, pkt->v6.pro, p, (TransportLayerPacket*)trans, end, InterfaceID,
+ (mDNSu16)pkt->bytes[4] << 8 | pkt->bytes[5]);
}
}
mDNSlocal void ConstructSleepProxyServerName(mDNS *const m, domainlabel *name)
{
- name->c[0] = mDNS_snprintf((char*)name->c+1, 62, "%d-%d-%d-%d %#s",
+ name->c[0] = (mDNSu8)mDNS_snprintf((char*)name->c+1, 62, "%d-%d-%d-%d %#s",
m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower, &m->nicelabel);
}
m->SPSState = 3;
else
{
- m->SPSState = (m->SPSSocket != mDNSNULL);
+ m->SPSState = (mDNSu8)(m->SPSSocket != mDNSNULL);
if (m->SPSState)
{
domainlabel name;
}
}
-mDNSexport void mDNSCoreBeSleepProxyServer(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower)
+// Called with lock held
+mDNSexport void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower)
{
+ // This routine uses mDNS_DeregisterService and calls SleepProxyServerCallback, so we execute in user callback context
+ mDNS_DropLockBeforeCallback();
+
// 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); }
+ { m->SPSState = 2; mDNS_DeregisterService_drt(m, &m->SPSRecords, sps ? mDNS_Dereg_rapid : mDNS_Dereg_normal); }
// Record our new SPS parameters
m->SPSType = sps;
if (!m->SPSSocket)
{
m->SPSSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
- if (!m->SPSSocket) { LogMsg("mDNSCoreBeSleepProxyServer: Failed to allocate SPSSocket"); return; }
+ if (!m->SPSSocket) { LogMsg("mDNSCoreBeSleepProxyServer: Failed to allocate SPSSocket"); goto fail; }
}
if (m->SPSState == 0) SleepProxyServerCallback(m, &m->SPSRecords, mStatus_MemFree);
}
+ else if (m->SPSState)
+ {
+ LogSPS("mDNSCoreBeSleepProxyServer turning off from state %d; will wake clients", m->SPSState);
+ m->NextScheduledSPS = m->timenow;
+ }
+fail:
+ mDNS_ReclaimLockAfterCallback();
}
// ***************************************************************************
m->RandomQueryDelay = 0;
m->RandomReconfirmDelay = 0;
m->PktNum = 0;
+ m->LocalRemoveEvents = mDNSfalse;
m->SleepState = SleepState_Awake;
m->SleepSeqNum = 0;
m->SystemWakeOnLANEnabled = mDNSfalse;
m->SentSleepProxyRegistration = mDNSfalse;
- m->AnnounceOwner = 0;
+ m->AnnounceOwner = NonZeroTime(timenow + 60 * mDNSPlatformOneSecond);
m->DelaySleep = 0;
m->SleepLimit = 0;
m->rrcache_report = 10;
m->rrcache_free = mDNSNULL;
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) m->rrcache_hash[slot] = mDNSNULL;
+ for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
+ {
+ m->rrcache_hash[slot] = mDNSNULL;
+ m->rrcache_nextcheck[slot] = timenow + 0x78000000;;
+ }
mDNS_GrowCache_internal(m, rrcachestorage, rrcachesize);
#ifndef UNICAST_DISABLED
m->NextuDNSEvent = timenow + 0x78000000;
m->NextSRVUpdate = timenow + 0x78000000;
- m->SuppressStdPort53Queries = 0;
- m->ServiceRegistrations = mDNSNULL;
m->DNSServers = mDNSNULL;
m->Router = zeroAddr;
m->AutoTunnelLabel.c[0] = 0;
m->RegisterSearchDomains = mDNSfalse;
+ m->RegisterAutoTunnel6 = mDNStrue;
// NAT traversal fields
m->NATTraversals = mDNSNULL;
#if APPLE_OSX_mDNSResponder
m->TunnelClients = mDNSNULL;
+
+#if ! NO_WCF
+ CHECK_WCF_FUNCTION(WCFConnectionNew)
+ {
+ m->WCF = WCFConnectionNew();
+ if (!m->WCF) { LogMsg("WCFConnectionNew failed"); return -1; }
+ }
+#endif
+
#endif
result = mDNSPlatformInit(m);
// When SleepProxyServerCallback gets the mStatus_MemFree message,
// it will reregister the service under the new name
m->SPSState = 2;
- mDNS_DeregisterService(m, &m->SPSRecords);
+ mDNS_DeregisterService_drt(m, &m->SPSRecords, mDNS_Dereg_rapid);
}
}
(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));
+ debugf("PurgeOrReconfirmCacheRecord: %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)
+ {
+ LogInfo("PurgeorReconfirmCacheRecord: Purging Resourcerecord %s, RecordType %x", CRDisplayString(m, cr), cr->resrec.RecordType);
+ mDNS_PurgeCacheResourceRecord(m, cr);
+ }
+ else
+ {
+ LogInfo("PurgeorReconfirmCacheRecord: Reconfirming Resourcerecord %s, RecordType %x", CRDisplayString(m, cr), cr->resrec.RecordType);
+ mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
+ }
+ }
+
+mDNSlocal void CacheRecordResetDNSServer(mDNS *const m, DNSQuestion *q, DNSServer *new)
+ {
+ const mDNSu32 slot = HashSlot(&q->qname);
+ CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ CacheRecord *rp;
+ mDNSBool found = mDNSfalse;
+ mDNSBool foundNew = mDNSfalse;
+ DNSServer *old = q->qDNSServer;
+ mDNSBool newQuestion = IsQuestionNew(m, q);
+ DNSQuestion *qptr;
+
+ // This function is called when the DNSServer is updated to the new question. There may already be
+ // some cache entries matching the old DNSServer and/or new DNSServer. There are four cases. In the
+ // following table, "Yes" denotes that a cache entry was found for old/new DNSServer.
+ //
+ // old DNSServer new DNSServer
+ //
+ // Case 1 Yes Yes
+ // Case 2 No Yes
+ // Case 3 Yes No
+ // Case 4 No No
+ //
+ // Case 1: There are cache entries for both old and new DNSServer. We handle this case by simply
+ // expiring the old Cache entries, deliver a RMV event (if an ADD event was delivered before)
+ // followed by the ADD event of the cache entries corresponding to the new server. This
+ // case happens when we pick a DNSServer, issue a query and get a valid response and create
+ // cache entries after which it stops responding. Another query (non-duplicate) picks a different
+ // DNSServer and creates identical cache entries (perhaps through records in Additional records).
+ // Now if the first one expires and tries to pick the new DNSServer (the original DNSServer
+ // is not responding) we will find cache entries corresponding to both DNSServers.
+ //
+ // Case 2: There are no cache entries for the old DNSServer but there are some for the new DNSServer.
+ // This means we should deliver an ADD event. Normally ADD events are delivered by
+ // AnswerNewQuestion if it is a new question. So, we check to see if it is a new question
+ // and if so, leave it to AnswerNewQuestion to deliver it. Otherwise, we use
+ // AnswerQuestionsForDNSServerChanges to deliver the ADD event. This case happens when a
+ // question picks a DNS server for which AnswerNewQuestion could not deliver an answer even
+ // though there were potential cache entries but DNSServer did not match. Now when we
+ // pick a new DNSServer, those cache entries may answer this question.
+ //
+ // Case 3: There are the cache entries for the old DNSServer but none for the new. We just move
+ // the old cache entries to point to the new DNSServer and the caller is expected to
+ // do a purge or reconfirm to delete or validate the RDATA. We don't need to do anything
+ // special for delivering ADD events, as it should have been done/will be done by
+ // AnswerNewQuestion. This case happens when we picked a DNSServer, sent the query and
+ // got a response and the cache is expired now and we are reissuing the question but the
+ // original DNSServer does not respond.
+ //
+ // Case 4: There are no cache entries either for the old or for the new DNSServer. There is nothing
+ // much we can do here.
+ //
+ // Case 2 and 3 are the most common while case 4 is possible when no DNSServers are working. Case 1
+ // is relatively less likely to happen in practice
+
+ // Temporarily set the DNSServer to look for the matching records for the new DNSServer.
+ q->qDNSServer = new;
+ for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next)
+ {
+ if (SameNameRecordAnswersQuestion(&rp->resrec, q))
+ {
+ LogInfo("CacheRecordResetDNSServer: Found cache record %##s for new DNSServer address: %#a", rp->resrec.name->c,
+ (rp->resrec.rDNSServer != mDNSNULL ? &rp->resrec.rDNSServer->addr : mDNSNULL));
+ foundNew = mDNStrue;
+ break;
+ }
+ }
+ q->qDNSServer = old;
+
+ for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next)
+ {
+ if (SameNameRecordAnswersQuestion(&rp->resrec, q))
+ {
+ // Case1
+ found = mDNStrue;
+ if (foundNew)
+ {
+ LogInfo("CacheRecordResetDNSServer: Flushing Resourcerecord %##s, before:%#a, after:%#a", rp->resrec.name->c,
+ (rp->resrec.rDNSServer != mDNSNULL ? &rp->resrec.rDNSServer->addr : mDNSNULL),
+ (new != mDNSNULL ? &new->addr : mDNSNULL));
+ mDNS_PurgeCacheResourceRecord(m, rp);
+ if (newQuestion)
+ {
+ // "q" is not a duplicate question. If it is a newQuestion, then the CRActiveQuestion can't be
+ // possibly set as it is set only when we deliver the ADD event to the question.
+ if (rp->CRActiveQuestion != mDNSNULL)
+ {
+ LogMsg("CacheRecordResetDNSServer: ERROR!!: CRActiveQuestion %p set, current question %p, name %##s", rp->CRActiveQuestion, q, q->qname.c);
+ rp->CRActiveQuestion = mDNSNULL;
+ }
+ // if this is a new question, then we never delivered an ADD yet, so don't deliver the RMV.
+ continue;
+ }
+ }
+ LogInfo("CacheRecordResetDNSServer: resetting cache record %##s DNSServer address before:%#a,"
+ " after:%#a, CRActiveQuestion %p", rp->resrec.name->c, (rp->resrec.rDNSServer != mDNSNULL ?
+ &rp->resrec.rDNSServer->addr : mDNSNULL), (new != mDNSNULL ? &new->addr : mDNSNULL),
+ rp->CRActiveQuestion);
+ // Though we set it to the new DNS server, the caller is *assumed* to do either a purge
+ // or reconfirm or send out questions to the "new" server to verify whether the cached
+ // RDATA is valid
+ rp->resrec.rDNSServer = new;
+ }
+ }
+
+ // Case 1 and Case 2
+ if ((found && foundNew) || (!found && foundNew))
+ {
+ if (newQuestion)
+ LogInfo("CacheRecordResetDNSServer: deliverAddEvents not set for question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+ else if (QuerySuppressed(q))
+ LogInfo("CacheRecordResetDNSServer: deliverAddEvents not set for suppressed question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+ else
+ {
+ LogInfo("CacheRecordResetDNSServer: deliverAddEvents set for %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+ q->deliverAddEvents = mDNStrue;
+ for (qptr = q->next; qptr; qptr = qptr->next)
+ if (qptr->DuplicateOf == q) qptr->deliverAddEvents = mDNStrue;
+ }
+ return;
+ }
+
+ // Case 3 and Case 4
+ return;
+ }
+
+mDNSexport void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *new)
+ {
+ DNSQuestion *qptr;
+
+ // 1. Whenever we change the DNS server, we change the message identifier also so that response
+ // from the old server is not accepted as a response from the new server but only messages
+ // from the new server are accepted as valid responses. We do it irrespective of whether "new"
+ // is NULL or not. It is possible that we send two queries, no responses, pick a new DNS server
+ // which is NULL and now the response comes back and will try to penalize the DNS server which
+ // is NULL. By setting the messageID here, we will not accept that as a valid response.
+
+ q->TargetQID = mDNS_NewMessageID(m);
+
+ // 2. Move the old cache records to point them at the new DNSServer so that we can deliver the ADD/RMV events
+ // appropriately. At any point in time, we want all the cache records point only to one DNSServer for a given
+ // question. "DNSServer" here is the DNSServer object and not the DNS server itself. It is possible to
+ // have the same DNS server address in two objects, one scoped and another not scoped. But, the cache is per
+ // DNSServer object. By maintaining the question and the cache entries point to the same DNSServer
+ // always, the cache maintenance and delivery of ADD/RMV events becomes simpler.
+ //
+ // CacheRecordResetDNSServer should be called only once for the non-duplicate question as once the cache
+ // entries are moved to point to the new DNSServer, we don't need to call it for the duplicate question
+ // and it is wrong to call for the duplicate question as it's decision to mark deliverAddevents will be
+ // incorrect.
+
+ if (q->DuplicateOf)
+ LogMsg("DNSServerChangeForQuestion: ERROR: Called for duplicate question %##s", q->qname.c);
+ else
+ CacheRecordResetDNSServer(m, q, new);
- if (purge) mDNS_PurgeCacheResourceRecord(m, cr);
- else mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
+ // 3. Make sure all the duplicate questions point to the same DNSServer so that delivery
+ // of events for all of them are consistent. Duplicates for a question are always inserted
+ // after in the list.
+ q->qDNSServer = new;
+ for (qptr = q->next ; qptr; qptr = qptr->next)
+ {
+ if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = new; }
+ }
}
mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
mDNSPlatformSetDNSConfig(m, mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL);
+ // Mark the records to be flushed that match a new resolver. We need to do this before
+ // we walk the questions below where we change the DNSServer pointer of the cache
+ // record
+ FORALL_CACHERECORDS(slot, cg, cr)
+ {
+ if (cr->resrec.InterfaceID) continue;
+
+ // We just mark them for purge or reconfirm. We can't affect the DNSServer pointer
+ // here as the code below that calls CacheRecordResetDNSServer relies on this
+ //
+ // The new DNSServer may be a scoped or non-scoped one. We use the active question's
+ // InterfaceID for looking up the right DNS server
+ ptr = GetServerForName(m, cr->resrec.name, cr->CRActiveQuestion ? cr->CRActiveQuestion->InterfaceID : mDNSNULL);
+
+ // Purge or Reconfirm if this cache entry would use the new DNS server
+ if (ptr && (ptr != cr->resrec.rDNSServer))
+ {
+ // As the DNSServers for this cache record is not the same anymore, we don't
+ // want any new questions to pick this old value
+ if (cr->CRActiveQuestion == mDNSNULL)
+ {
+ LogInfo("uDNS_SetupDNSConfig: Purging Resourcerecord %s", CRDisplayString(m, cr));
+ mDNS_PurgeCacheResourceRecord(m, cr);
+ }
+ else
+ PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNSfalse);
+ }
+ }
// Update our qDNSServer pointers before we go and free the DNSServer object memory
for (q = m->Questions; q; q=q->next)
if (!mDNSOpaque16IsZero(q->TargetQID))
{
- DNSServer *s = GetServerForName(m, &q->qname, mDNSNULL);
- DNSServer *t = q->qDNSServer;
+ DNSServer *s, *t;
+ DNSQuestion *qptr;
+ if (q->DuplicateOf) continue;
+ SetValidDNSServers(m, q);
+ q->triedAllServersOnce = 0;
+ s = GetServerForQuestion(m, q);
+ t = q->qDNSServer;
if (t != s)
{
// If DNS Server for this question has changed, reactivate it
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));
- q->qDNSServer = s;
- q->unansweredQueries = 0;
-
- // Change the query ID so that we won't cache responses to any in-flight queries
- q->TargetQID = mDNS_NewMessageID(m);
- ActivateUnicastQuery(m, q, mDNStrue);
+ // After we reset the DNSServer pointer on the cache records here, three things could happen:
+ //
+ // 1) The query gets sent out and when the actual response comes back later it is possible
+ // that the response has the same RDATA, in which case we update our cache entry.
+ // If the response is different, then the entry will expire and a new entry gets added.
+ // For the latter case to generate a RMV followed by ADD events, we need to reset the DNS
+ // server here to match the question and the cache record.
+ //
+ // 2) We might have marked the cache entries for purge above and for us to be able to generate the RMV
+ // events for the questions, the DNSServer on the question should match the Cache Record
+ //
+ // 3) We might have marked the cache entries for reconfirm above, for which we send the query out which is
+ // the same as the first case above.
+
+ DNSServerChangeForQuestion(m, q, s);
+ q->unansweredQueries = 0;
+ // We still need to pick a new DNSServer for the questions that have been
+ // suppressed, but it is wrong to activate the query as DNS server change
+ // could not possibly change the status of SuppressUnusable questions
+ if (!QuerySuppressed(q))
+ {
+ debugf("uDNS_SetupDNSConfig: Activating query %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+ ActivateUnicastQuery(m, q, mDNStrue);
+ // ActivateUnicastQuery is called for duplicate questions also as it does something
+ // special for AutoTunnel questions
+ for (qptr = q->next ; qptr; qptr = qptr->next)
+ {
+ if (qptr->DuplicateOf == q) ActivateUnicastQuery(m, qptr, mDNStrue);
+ }
+ }
+ }
+ else
+ {
+ debugf("uDNS_SetupDNSConfig: Not Updating DNS server question %p %##s (%s) DNS server %#a:%d %p %d",
+ q, q->qname.c, DNSTypeName(q->qtype), t ? &t->addr : mDNSNULL, mDNSVal16(t ? t->port : zeroIPPort), q->DuplicateOf, q->SuppressUnusable);
+ for (qptr = q->next ; qptr; qptr = qptr->next)
+ if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; }
}
}
- // Flush all records that match a new resolver
- FORALL_CACHERECORDS(slot, cg, cr)
- {
- if (cr->resrec.InterfaceID) continue;
- ptr = GetServerForName(m, cr->resrec.name, mDNSNULL);
- if (ptr && (ptr->flags & DNSServer_FlagNew))
- PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNSfalse);
- }
-
while (*p)
{
if (((*p)->flags & DNSServer_FlagDelete) != 0)
// We reconfirm any records that match, because in this world of split DNS, firewalls, etc.
// different DNS servers can give different answers to the same question.
ptr = *p;
- 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, mDNSNULL) == ptr)
+ {
+ if (cr->resrec.InterfaceID) continue;
+ if (cr->resrec.rDNSServer == ptr)
+ {
+ // If we don't have an active question for this cache record, neither Purge can
+ // generate RMV events nor Reconfirm can send queries out. Just set the DNSServer
+ // pointer on the record NULL so that we don't point to freed memory (We might dereference
+ // DNSServer pointers from resource record for logging purposes).
+ //
+ // If there is an active question, point to its DNSServer as long as it does not point to the
+ // freed one. We already went through the questions above and made them point at either the
+ // new server or NULL if there is no server and also affected the cache entries that match
+ // this question. Hence, whenever we hit a resource record with a DNSServer that is just
+ // about to be deleted, we should never have an active question. The code below just tries to
+ // be careful logging messages if we ever hit this case.
+
+ if (cr->CRActiveQuestion)
+ {
+ DNSQuestion *qptr = cr->CRActiveQuestion;
+ if (qptr->qDNSServer == mDNSNULL)
+ LogMsg("uDNS_SetupDNSConfig: Cache Record %s match: Active question %##s (%s) with DNSServer Address NULL, Server to be deleted %#a",
+ CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype), &ptr->addr);
+ else
+ LogMsg("uDNS_SetupDNSConfig: Cache Record %s match: Active question %##s (%s) DNSServer Address %#a, Server to be deleted %#a",
+ CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype), &qptr->qDNSServer->addr, &ptr->addr);
+
+ if (qptr->qDNSServer == ptr)
+ {
+ qptr->validDNSServers = zeroOpaque64;
+ qptr->qDNSServer = mDNSNULL;
+ cr->resrec.rDNSServer = mDNSNULL;
+ }
+ else
+ {
+ cr->resrec.rDNSServer = qptr->qDNSServer;
+ }
+ }
+ else
+ {
+ LogInfo("uDNS_SetupDNSConfig: Cache Record %##s has no Active question, Record's DNSServer Address %#a, Server to be deleted %#a",
+ cr->resrec.name, &cr->resrec.rDNSServer->addr, &ptr->addr);
+ cr->resrec.rDNSServer = mDNSNULL;
+ }
+
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);
+ NumUnicastDNSServers--;
}
else
{
if (m->FQDN.c[0]) mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1); // Set status to 1 to indicate temporary failure
}
+ debugf("uDNS_SetupDNSConfig: number of unicast DNS servers %d", NumUnicastDNSServers);
return mStatus_NoError;
}
}
}
-extern ServiceRecordSet *CurrentServiceRecordSet;
-
mDNSlocal void DeregLoop(mDNS *const m, AuthRecord *const start)
{
m->CurrentRecord = start;
while (m->CurrentRecord)
{
AuthRecord *rr = m->CurrentRecord;
+ LogInfo("DeregLoop: %s deregistration for %p %02X %s",
+ (rr->resrec.RecordType != kDNSRecordTypeDeregistering) ? "Initiating " : "Accelerating",
+ rr, rr->resrec.RecordType, ARDisplayString(m, rr));
if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
+ mDNS_Deregister_internal(m, rr, mDNS_Dereg_rapid);
+ else if (rr->AnnounceCount > 1)
{
- LogInfo("DeregLoop: Deregistering %p %02X %s", rr, rr->resrec.RecordType, ARDisplayString(m, rr));
- mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
+ rr->AnnounceCount = 1;
+ rr->LastAPTime = m->timenow - rr->ThisAPInterval;
}
- // Note: We mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
- // the list may have been changed in that call.
+ // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
+ // new records could have been added to the end of the list as a result of that call.
if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
m->CurrentRecord = rr->next;
}
mDNS_Lock(m);
+ LogInfo("mDNS_StartExit");
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();
+ mDNSCoreBeSleepProxyServer_internal(m, 0, 0, 0, 0);
+
+#if APPLE_OSX_mDNSResponder
+#if ! NO_WCF
+ CHECK_WCF_FUNCTION(WCFConnectionDealloc)
+ {
+ if (m->WCF) WCFConnectionDealloc((WCFConnection *)m->WCF);
+ }
+#endif
+#endif
#ifndef UNICAST_DISABLED
{
SearchListElem *s;
SuspendLLQs(m);
- // Don't need to do SleepRecordRegistrations() or SleepServiceRegistrations() here,
+ // Don't need to do SleepRecordRegistrations() here
// because we deregister all records and services later in this routine
while (m->Hostnames) mDNS_RemoveDynDNSHostName(m, &m->Hostnames->fqdn);
// This has particularly important implications for our AutoTunnel records --
// when we deregister our AutoTunnel records below, we don't want their mStatus_MemFree
// handlers to just turn around and attempt to re-register those same records.
- // Clearing t->ExternalPort will cause the mStatus_MemFree callback handlers to not do this.
+ // Clearing t->ExternalPort/t->RequestedPort will cause the mStatus_MemFree callback handlers
+ // to not do this.
t->ExternalAddress = zerov4Addr;
t->ExternalPort = zeroIPPort;
+ t->RequestedPort = zeroIPPort;
t->Lifetime = 0;
t->Result = mStatus_NoError;
}
m->SuppressSending = 0;
}
-#if !defined(UNICAST_DISABLED) && USE_SEPARATE_UDNS_SERVICE_LIST
- CurrentServiceRecordSet = m->ServiceRegistrations;
- while (CurrentServiceRecordSet)
- {
- ServiceRecordSet *srs = CurrentServiceRecordSet;
- 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->ServiceRegistrations) LogInfo("mDNS_StartExit: Sending final uDNS service deregistrations");
- else LogInfo("mDNS_StartExit: No deregistering uDNS 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));
mDNSu32 rrcache_totalused = 0;
mDNSu32 slot;
AuthRecord *rr;
- ServiceRecordSet *srs;
LogInfo("mDNS_FinalExit: mDNSPlatformClose");
mDNSPlatformClose(m);
for (rr = m->ResourceRecords; rr; rr = rr->next)
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: %p %##s", srs, srs->RR_SRV.resrec.name->c);
-
LogInfo("mDNS_FinalExit: done");
}
* 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: 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
-
-Revision 1.38 2007/12/13 20:27:07 cheshire
-Remove unused VerifySameNameAssumptions symbol
-
-Revision 1.37 2007/12/01 00:33:17 cheshire
-Fixes from Bob Bradley for building on EFI
-
-Revision 1.36 2007/10/01 19:06:19 cheshire
-Defined symbolic constant MDNS_LOG_INITIAL_LEVEL to set the logging level we start out at
-
-Revision 1.35 2007/07/27 20:19:56 cheshire
-For now, comment out unused log levels MDNS_LOG_ERROR, MDNS_LOG_WARN, MDNS_LOG_INFO, MDNS_LOG_DEBUG
-
-Revision 1.34 2007/07/24 17:23:33 cheshire
-<rdar://problem/5357133> Add list validation checks for debugging
-
-Revision 1.33 2007/06/15 21:54:50 cheshire
-<rdar://problem/4883206> Add packet logging to help debugging private browsing over TLS
-
-Revision 1.32 2007/05/25 16:03:03 cheshire
-Remove unused LogMalloc
-
-Revision 1.31 2007/04/06 19:50:05 cheshire
-Add ProgramName declaration
-
-Revision 1.30 2007/03/24 01:22:44 cheshire
-Add validator for uDNS data structures
-
-Revision 1.29 2006/08/14 23:24:23 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.28 2006/07/07 01:09:09 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-Only use mallocL/freeL debugging routines when building mDNSResponder, not dnsextd
-
-Revision 1.27 2006/06/29 07:42:14 cheshire
-<rdar://problem/3922989> Performance: Remove unnecessary SameDomainName() checks
-
-Revision 1.26 2005/07/04 22:40:26 cheshire
-Additional debugging code to help catch memory corruption
-
-Revision 1.25 2004/12/14 21:34:16 cheshire
-Add "#define ANSWER_REMOTE_HOSTNAME_QUERIES 0" and comment
-
-Revision 1.24 2004/09/16 01:58:21 cheshire
-Fix compiler warnings
-
-Revision 1.23 2004/05/18 23:51:25 cheshire
-Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
-
-Revision 1.22 2004/04/22 04:27:42 cheshire
-Spacing tidyup
-
-Revision 1.21 2004/04/14 23:21:41 ksekar
-Removed accidental checkin of MALLOC_DEBUGING flag in 1.20
-
-Revision 1.20 2004/04/14 23:09:28 ksekar
-Support for TSIG signed dynamic updates.
-
-Revision 1.19 2004/03/15 18:57:59 cheshire
-Undo last checkin that accidentally made verbose debugging the default for all targets
-
-Revision 1.18 2004/03/13 01:57:33 ksekar
-<rdar://problem/3192546>: DynDNS: Dynamic update of service records
-
-Revision 1.17 2004/01/28 21:14:23 cheshire
-Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
-
-Revision 1.16 2003/12/09 01:30:06 rpantos
-Fix usage of ARGS... macros to build properly on Windows.
-
-Revision 1.15 2003/12/08 20:55:26 rpantos
-Move some definitions here from mDNSMacOSX.h.
-
-Revision 1.14 2003/08/12 19:56:24 cheshire
-Update to APSL 2.0
-
-Revision 1.13 2003/07/02 21:19:46 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.12 2003/05/26 03:01:27 cheshire
-<rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
-
-Revision 1.11 2003/05/21 17:48:10 cheshire
-Add macro to enable GCC's printf format string checking
-
-Revision 1.10 2003/04/26 02:32:57 cheshire
-Add extern void LogMsg(const char *format, ...);
-
-Revision 1.9 2002/09/21 20:44:49 zarzycki
-Added APSL info
-
-Revision 1.8 2002/09/19 04:20:43 cheshire
-Remove high-ascii characters that confuse some systems
-
-Revision 1.7 2002/09/16 18:41:42 cheshire
-Merge in license terms from Quinn's copy, in preparation for Darwin release
-
-*/
+ */
#ifndef __mDNSDebug_h
#define __mDNSDebug_h
//#define ForceAlerts 1
//#define LogTimeStamps 1
-#define USE_SEPARATE_UDNS_SERVICE_LIST 1
-
// Developer-settings section ends here
#if MDNS_CHECK_PRINTF_STYLE_FUNCTIONS
#if (MDNS_HAS_VA_ARG_MACROS)
#if (MDNS_C99_VA_ARGS)
#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)
+ #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 debug_noop( ARGS... ) ((void)0)
- #define LogMsg( ARGS... ) LogMsgWithLevel(MDNS_LOG_MSG, ARGS)
+ #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)
+ #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
#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 debug_noop 1 ? (void)0 : (void)
#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);
+ #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);
+ 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
extern const char ProgramName[];
extern void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(2,3);
+// LogMsgNoIdent needs to be fixed so that it logs without the ident prefix like it used to
+// (or completely overhauled to use the new "log to a separate file" facility)
#define LogMsgNoIdent LogMsg
#if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
* See the License for the specific language governing permissions and
* limitations under the License.
-
NOTE:
If you're building an application that uses DNS Service Discovery
this is probably NOT the header file you're looking for.
you can still use the exact same client C code as you'd use on a
general-purpose desktop system.
-
- Change History (most recent first):
-
-$Log: mDNSEmbeddedAPI.h,v $
-Revision 1.577 2009/07/16 00:34:18 cheshire
-<rdar://problem/6434656> Sleep Proxy: Put owner OPT records in multicast announcements to avoid conflicts
-Additional refinement: If we didn't register with a Sleep Proxy when going to sleep,
-we don't need to include our OWNER option in our packets when we re-awaken
-
-Revision 1.576 2009/07/15 23:35:37 cheshire
-<rdar://problem/6434656> Sleep Proxy: Put owner OPT records in multicast announcements to avoid conflicts
-
-Revision 1.575 2009/07/11 01:57:00 cheshire
-<rdar://problem/6613674> Sleep Proxy: Add support for using sleep proxy in local network interface hardware
-Added declaration of ActivateLocalProxy
-
-Revision 1.574 2009/07/10 23:03:17 cheshire
-Made SecondLabel(X) more defensive, to guard against the case where the name doesn't have a second label
-
-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.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.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.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
-
-Revision 1.467 2008/02/26 20:48:46 cheshire
-Need parentheses around use of macro argument in mDNS_TimeNow_NoLock(m)
-
-Revision 1.466 2008/02/21 21:36:32 cheshire
-Updated comment about record type values (kDNSRecordTypePacketAns/Auth/Add)
-
-Revision 1.465 2008/02/20 00:39:05 mcguire
-<rdar://problem/5427102> Some device info XML blobs too large
-
-Revision 1.464 2008/01/31 23:33:29 mcguire
-<rdar://problem/5614450> changes to build using gcc 4.2 with -Werror
-
-Revision 1.463 2007/12/17 23:53:25 cheshire
-Added DNSDigest_SignMessageHostByteOrder, for signing messages not yet converted to network byte order
-
-Revision 1.462 2007/12/17 23:48:29 cheshire
-DNSDigest_SignMessage doesn't need to return a result -- it already updates the 'end' parameter
-
-Revision 1.461 2007/12/15 00:18:51 cheshire
-Renamed question->origLease to question->ReqLease
-
-Revision 1.460 2007/12/14 23:55:28 cheshire
-Moved "struct tcpInfo_t" definition from uDNS.c to mDNSEmbeddedAPI.h
-
-Revision 1.459 2007/12/07 22:40:34 cheshire
-Rename 'LocalAnswer' to more descriptive 'AnsweredLocalQ'
-
-Revision 1.458 2007/12/07 00:45:58 cheshire
-<rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
-
-Revision 1.457 2007/12/06 00:22:27 mcguire
-<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
-
-Revision 1.456 2007/12/05 01:45:35 cheshire
-Renamed markedForDeletion -> MarkedForDeletion
-
-Revision 1.455 2007/12/01 01:21:27 jgraessley
-<rdar://problem/5623140> mDNSResponder unicast DNS improvements
-
-Revision 1.454 2007/12/01 00:34:03 cheshire
-Fixes from Bob Bradley for building on EFI
-
-Revision 1.453 2007/10/29 23:51:22 cheshire
-Added comment about NATTraversalInfo ExternalAddress field
-
-Revision 1.452 2007/10/29 18:13:40 cheshire
-Added Question_uDNS macro, analogous to AuthRecord_uDNS macro
-
-Revision 1.451 2007/10/26 23:42:57 cheshire
-Removed unused "mDNSs32 expire" field from ServiceRecordSet_struct
-
-Revision 1.450 2007/10/26 22:24:08 cheshire
-Added AuthRecord_uDNS() macro to determine when a given AuthRecord needs to be registered via unicast DNS
-
-Revision 1.449 2007/10/25 20:48:47 cheshire
-For naming consistency (with AuthRecord's UpdateServer) renamed 'ns' to 'SRSUpdateServer'
-
-Revision 1.448 2007/10/22 22:19:44 cheshire
-Tidied up code alignment
-
-Revision 1.447 2007/10/22 19:40:30 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Made subroutine mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst)
-
-Revision 1.446 2007/10/17 22:49:54 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-
-Revision 1.445 2007/10/17 22:37:23 cheshire
-<rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events
-
-Revision 1.444 2007/09/29 03:14:52 cheshire
-<rdar://problem/5513168> BTMM: mDNSResponder memory corruption in GetAuthInfoForName_internal
-Added AutoTunnelUnregistered macro to check state of DomainAuthInfo AuthRecords
-
-Revision 1.443 2007/09/27 21:21:39 cheshire
-Export CompleteDeregistration so it's callable from other files
-
-Revision 1.442 2007/09/27 00:25:39 cheshire
-Added ttl_seconds parameter to MakeNegativeCacheRecord in preparation for:
-<rdar://problem/4947392> uDNS: Use SOA to determine TTL for negative answers
-
-Revision 1.441 2007/09/26 23:17:49 cheshire
-Get rid of unused kWideAreaTTL constant
-
-Revision 1.440 2007/09/26 22:06:02 cheshire
-<rdar://problem/5507399> BTMM: No immediate failure notifications for BTMM names
-
-Revision 1.439 2007/09/21 21:12:36 cheshire
-DNSDigest_SignMessage does not need separate "mDNSu16 *numAdditionals" parameter
-
-Revision 1.438 2007/09/19 20:32:09 cheshire
-Export GetAuthInfoForName so it's callable from other files
-
-Revision 1.437 2007/09/18 21:42:29 cheshire
-To reduce programming mistakes, renamed ExtPort to RequestedPort
-
-Revision 1.436 2007/09/14 21:26:08 cheshire
-<rdar://problem/5482627> BTMM: Need to manually avoid port conflicts when using UPnP gateways
-
-Revision 1.435 2007/09/13 00:16:41 cheshire
-<rdar://problem/5468706> Miscellaneous NAT Traversal improvements
-
-Revision 1.434 2007/09/12 23:03:07 cheshire
-<rdar://problem/5476978> DNSServiceNATPortMappingCreate callback not giving correct interface index
-
-Revision 1.433 2007/09/12 22:19:28 cheshire
-<rdar://problem/5476977> Need to listen for port 5350 NAT-PMP announcements
-
-Revision 1.432 2007/09/12 19:22:19 cheshire
-Variable renaming in preparation for upcoming fixes e.g. priv/pub renamed to intport/extport
-Made NAT Traversal packet handlers take typed data instead of anonymous "mDNSu8 *" byte pointers
-
-Revision 1.431 2007/09/11 19:19:16 cheshire
-Correct capitalization of "uPNP" to "UPnP"
-
-Revision 1.430 2007/09/10 22:06:50 cheshire
-Rename uptime => upseconds and LastNATUptime => LastNATupseconds to make it clear these time values are in seconds
-
-Revision 1.429 2007/09/07 21:16:58 cheshire
-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 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.
-
-Revision 1.427 2007/09/05 20:47:12 cheshire
-Tidied up alignment of code layout
-
-Revision 1.426 2007/09/04 20:37:06 cheshire
-<rdar://problem/5457287> mDNSResponder taking up 100% CPU in ReissueBlockedQuestions
-Reorder fields into more logical order, with AuthInfo before DuplicateOf
-
-Revision 1.425 2007/08/31 19:53:14 cheshire
-<rdar://problem/5431151> BTMM: IPv6 address lookup should not succeed if autotunnel cannot be setup
-If AutoTunnel setup fails, the code now generates a fake NXDomain error saying that the requested AAAA record does not exist
-
-Revision 1.424 2007/08/31 18:49:49 vazquez
-<rdar://problem/5393719> BTMM: Need to properly deregister when stopping BTMM
-
-Revision 1.423 2007/08/31 00:04:28 cheshire
-Added comment explaining deltime in DomainAuthInfo structure
-
-Revision 1.422 2007/08/28 23:58:42 cheshire
-Rename HostTarget -> AutoTarget
-
-Revision 1.421 2007/08/27 20:30:43 cheshire
-Only include TunnelClients list when building for OS X
-
-Revision 1.420 2007/08/23 21:47:09 vazquez
-<rdar://problem/5427316> BTMM: mDNSResponder sends NAT-PMP packets on public network
-make sure we clean up port mappings on base stations by sending a lease value of 0,
-and only send NAT-PMP packets on private networks; also save some memory by
-not using packet structs in NATTraversals.
-
-Revision 1.419 2007/08/08 21:07:47 vazquez
-<rdar://problem/5244687> BTMM: Need to advertise model information via wide-area bonjour
-
-Revision 1.418 2007/08/01 16:09:13 cheshire
-Removed unused NATTraversalInfo substructure from AuthRecord; reduced structure sizecheck values accordingly
-
-Revision 1.417 2007/08/01 03:04:59 cheshire
-Add NATTraversalInfo structures to HostnameInfo and DomainAuthInfo
-
-Revision 1.416 2007/08/01 00:04:13 cheshire
-<rdar://problem/5261696> Crash in tcpKQSocketCallback
-Half-open TCP connections were not being cancelled properly
-
-Revision 1.415 2007/07/31 02:28:35 vazquez
-<rdar://problem/3734269> NAT-PMP: Detect public IP address changes and base station reboot
-
-Revision 1.414 2007/07/30 23:34:19 cheshire
-Remove unused "udpSock" from DNSQuestion
-
-Revision 1.413 2007/07/28 01:25:56 cheshire
-<rdar://problem/4780038> BTMM: Add explicit UDP event port to LLQ setup request, to fix LLQs not working behind NAT
-
-Revision 1.412 2007/07/27 23:57:23 cheshire
-Added compile-time structure size checks
-
-Revision 1.411 2007/07/27 22:50:08 vazquez
-Allocate memory for UPnP request and reply buffers instead of using arrays
-
-Revision 1.410 2007/07/27 19:37:19 cheshire
-Moved AutomaticBrowseDomainQ into main mDNS object
-
-Revision 1.409 2007/07/27 19:30:39 cheshire
-Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
-to properly reflect tri-state nature of the possible responses
-
-Revision 1.408 2007/07/27 18:44:01 cheshire
-Rename "AnswerQuestionWithResourceRecord" to more informative "AnswerCurrentQuestionWithResourceRecord"
-
-Revision 1.407 2007/07/26 21:19:26 vazquez
-Retry port mapping with incremented port number (up to max) in order to handle
-port mapping conflicts on UPnP gateways
-
-Revision 1.406 2007/07/25 22:19:59 cheshire
-ClientTunnel structure also needs a rmt_outer_port field
-
-Revision 1.405 2007/07/25 03:05:02 vazquez
-Fixes for:
-<rdar://problem/5338913> LegacyNATTraversal: UPnP heap overflow
-<rdar://problem/5338933> LegacyNATTraversal: UPnP stack buffer overflow
-and a myriad of other security problems
-
-Revision 1.404 2007/07/24 20:22:07 cheshire
-Add AutoTunnelHostAddrActive flag
-
-Revision 1.403 2007/07/24 04:14:29 cheshire
-<rdar://problem/5356281> LLQs not working in with NAT Traversal
-
-Revision 1.402 2007/07/21 00:54:44 cheshire
-<rdar://problem/5344576> Delay IPv6 address callback until AutoTunnel route and policy is configured
-
-Revision 1.401 2007/07/20 20:01:38 cheshire
-Rename "mDNS_DomainTypeBrowseLegacy" as "mDNS_DomainTypeBrowseAutomatic"
-
-Revision 1.400 2007/07/20 00:54:18 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
-
-Revision 1.399 2007/07/18 03:22:35 cheshire
-SetupLocalAutoTunnelInterface_internal needs to be callable from uDNS.c
-
-Revision 1.398 2007/07/18 02:26:56 cheshire
-Don't need to declare UpdateTunnels here
-
-Revision 1.397 2007/07/18 01:03:50 cheshire
-<rdar://problem/5303834> Automatically configure IPSec policy when resolving services
-Add list of client tunnels so we can automatically reconfigure when local address changes
-
-Revision 1.396 2007/07/16 23:54:48 cheshire
-<rdar://problem/5338850> Crash when removing or changing DNS keys
-
-Revision 1.395 2007/07/16 20:12:33 vazquez
-<rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite
-
-Revision 1.394 2007/07/12 02:51:27 cheshire
-<rdar://problem/5303834> Automatically configure IPSec policy when resolving services
-
-Revision 1.393 2007/07/11 23:43:42 cheshire
-Rename PurgeCacheResourceRecord to mDNS_PurgeCacheResourceRecord
-
-Revision 1.392 2007/07/11 22:44:40 cheshire
-<rdar://problem/5328801> SIGHUP should purge the cache
-
-Revision 1.391 2007/07/11 20:30:45 cheshire
-<rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
-Added AutoTunnelTarget and AutoTunnelService to DomainAuthInfo structure
-
-Revision 1.390 2007/07/11 18:56:55 cheshire
-Added comments about AutoTunnelHostAddr and AutoTunnelLabel
-
-Revision 1.389 2007/07/11 02:44:03 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-Added AutoTunnel fields to structures
-
-Revision 1.388 2007/07/10 01:53:18 cheshire
-<rdar://problem/5196524> uDNS: mDNSresponder is leaking TCP connections to DNS server
-AuthRecord, ServiceRecordSet, and DNSQuestion structures need tcpInfo_t pointers
-so they can keep track of what TCP connections they open
-
-Revision 1.387 2007/07/06 18:55:15 cheshire
-Add explicit NextScheduledNATOp scheduling variable
-
-Revision 1.386 2007/07/03 20:54:11 cheshire
-Tidied up code layout of NATTraversalInfo_struct fields and comments
-
-Revision 1.385 2007/07/03 00:40:23 vazquez
-More changes for <rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes)
-Safely deal with packet replies and client callbacks
-
-Revision 1.384 2007/06/29 00:08:07 vazquez
-<rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes)
-
-Revision 1.383 2007/06/20 01:10:12 cheshire
-<rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
-
-Revision 1.382 2007/06/19 20:31:59 cheshire
-Add DNSServer_Disabled state
-Add mDNSInterfaceID for DNS servers reachable over specific interfaces
-
-Revision 1.381 2007/06/15 18:11:16 cheshire
-<rdar://problem/5174466> mDNSResponder crashed in memove() near end of MobileSafari stress test
-Made AssignDomainName more defensive when source name is garbage
-
-Revision 1.380 2007/05/25 00:04:51 cheshire
-Added comment explaining rdlength
-
-Revision 1.379 2007/05/21 18:04:40 cheshire
-Updated comments -- port_mapping_create_reply renamed to port_mapping_reply
-
-Revision 1.378 2007/05/17 19:11:46 cheshire
-Tidy up code layout
-
-Revision 1.377 2007/05/15 00:43:33 cheshire
-Remove unused regState_Cancelled
-
-Revision 1.376 2007/05/14 23:51:49 cheshire
-Added constants MAX_REVERSE_MAPPING_NAME_V4 and MAX_REVERSE_MAPPING_NAME_V6
-
-Revision 1.375 2007/05/10 21:19:18 cheshire
-Rate-limit DNS test queries to at most one per three seconds
-(useful when we have a dozen active WAB queries, and then we join a new network)
-
-Revision 1.374 2007/05/07 22:07:47 cheshire
-<rdar://problem/4738025> Enhance GetLargeResourceRecord to decompress more record types
-
-Revision 1.373 2007/05/07 20:43:45 cheshire
-<rdar://problem/4241419> Reduce the number of queries and announcements
-
-Revision 1.372 2007/05/04 22:15:29 cheshire
-Get rid of unused q->RestartTime
-
-Revision 1.371 2007/05/03 22:40:37 cheshire
-<rdar://problem/4669229> mDNSResponder ignores bogus null target in SRV record
-
-Revision 1.370 2007/05/02 22:18:09 cheshire
-Renamed NATTraversalInfo_struct context to NATTraversalContext
-
-Revision 1.369 2007/05/01 21:21:42 cheshire
-Add missing parentheses in LEASE_OPT_RDLEN definition
-
-Revision 1.368 2007/04/30 21:33:38 cheshire
-Fix crash when a callback unregisters a service while the UpdateSRVRecords() loop
-is iterating through the m->ServiceRegistrations list
-
-Revision 1.367 2007/04/28 01:31:59 cheshire
-Improve debugging support for catching memory corruption problems
-
-Revision 1.366 2007/04/27 19:28:02 cheshire
-Any code that calls StartGetZoneData needs to keep a handle to the structure, so
-it can cancel it if necessary. (First noticed as a crash in Apple Remote Desktop
--- it would start a query and then quickly cancel it, and then when
-StartGetZoneData completed, it had a dangling pointer and crashed.)
-
-Revision 1.365 2007/04/26 00:35:15 cheshire
-<rdar://problem/5140339> uDNS: Domain discovery not working over VPN
-Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server
-inside the firewall may give answers where a public one gives none, and vice versa.)
-
-Revision 1.364 2007/04/24 02:07:42 cheshire
-<rdar://problem/4246187> Identical client queries should reference a single shared core query
-Deleted some more redundant code
-
-Revision 1.363 2007/04/24 00:09:47 cheshire
-Remove MappedV4 field from mDNS_struct (not actually used anywhere)
-
-Revision 1.362 2007/04/22 06:02:02 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.361 2007/04/21 19:43:33 cheshire
-Code tidying: represent NAT opcodes as bitwise combinations rather than numerical additions
-
-Revision 1.360 2007/04/20 21:17:24 cheshire
-For naming consistency, kDNSRecordTypeNegative should be kDNSRecordTypePacketNegative
-
-Revision 1.359 2007/04/19 22:50:53 cheshire
-<rdar://problem/4246187> Identical client queries should reference a single shared core query
-
-Revision 1.358 2007/04/19 20:06:41 cheshire
-Rename field 'Private' (sounds like a boolean) to more informative 'AuthInfo' (it's a DomainAuthInfo pointer)
-
-Revision 1.357 2007/04/19 18:14:51 cheshire
-In mDNS_AddSearchDomain_CString check for NULL pointer before calling MakeDomainNameFromDNSNameString()
-
-Revision 1.356 2007/04/18 20:56:46 cheshire
-Added mDNS_AddSearchDomain_CString macro
-
-Revision 1.355 2007/04/17 19:21:29 cheshire
-<rdar://problem/5140339> Domain discovery not working over VPN
-
-Revision 1.354 2007/04/05 22:55:34 cheshire
-<rdar://problem/5077076> Records are ending up in Lighthouse without expiry information
-
-Revision 1.353 2007/04/05 20:40:37 cheshire
-Remove unused mDNSPlatformTCPGetFlags()
-
-Revision 1.352 2007/04/04 21:48:52 cheshire
-<rdar://problem/4720694> Combine unicast authoritative answer list with multicast list
-
-Revision 1.351 2007/04/04 01:27:45 cheshire
-Update comment
-
-Revision 1.350 2007/04/04 00:03:26 cheshire
-<rdar://problem/5089862> DNSServiceQueryRecord is returning kDNSServiceErr_NoSuchRecord for empty rdata
-
-Revision 1.349 2007/04/03 19:37:58 cheshire
-Rename mDNSAddrIsv4Private() to more precise mDNSAddrIsRFC1918()
-
-Revision 1.348 2007/04/03 19:13:39 cheshire
-Added macros mDNSSameIPPort, mDNSSameOpaque16, mDNSIPPortIsZero, mDNSOpaque16IsZero
-
-Revision 1.347 2007/03/28 20:59:26 cheshire
-<rdar://problem/4743285> Remove inappropriate use of IsPrivateV4Addr()
-
-Revision 1.346 2007/03/28 15:56:37 cheshire
-<rdar://problem/5085774> Add listing of NAT port mapping and GetAddrInfo requests in SIGINFO output
-
-Revision 1.345 2007/03/22 19:29:23 cheshire
-Add comment and check to ensure StandardAuthRDSize is at least 256 bytes
-
-Revision 1.344 2007/03/22 18:31:48 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.343 2007/03/22 00:49:20 cheshire
-<rdar://problem/4848295> Advertise model information via Bonjour
-
-Revision 1.342 2007/03/21 23:06:00 cheshire
-Rename uDNS_HostnameInfo to HostnameInfo; deleted some unused fields
-
-Revision 1.341 2007/03/21 20:44:11 cheshire
-Added mDNSAddressIsv4LinkLocal macro
-
-Revision 1.340 2007/03/21 00:30:02 cheshire
-<rdar://problem/4789455> Multiple errors in DNameList-related code
-
-Revision 1.339 2007/03/20 17:07:15 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.338 2007/03/10 02:28:28 cheshire
-Added comment explaining NATResponseHndlr
-
-Revision 1.337 2007/03/10 02:02:58 cheshire
-<rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache
-Eliminate unnecessary "InternalResponseHndlr responseCallback" function pointer
-
-Revision 1.336 2007/02/28 22:12:24 cheshire
-Get rid of unused mDNSVal32 and mDNSOpaque32fromIntVal
-
-Revision 1.335 2007/02/28 21:49:07 cheshire
-Off-by-one error: SameDomainLabelCS (case-sensitive) was stopping one character short of
-the end of the label, e.g. it would fail to detect that "chesh1" and "chesh2" are different.
-
-Revision 1.334 2007/02/28 01:44:26 cheshire
-<rdar://problem/5027863> Byte order bugs in uDNS.c, uds_daemon.c, dnssd_clientstub.c
-
-Revision 1.333 2007/02/27 22:55:22 cheshire
-Get rid of unused AllDNSLinkGroupv4 and AllDNSLinkGroupv6
-
-Revision 1.332 2007/02/27 02:48:24 cheshire
-Parameter to LNT_GetPublicIP function is IPv4 address, not anonymous "mDNSOpaque32" object
-
-Revision 1.331 2007/02/14 03:16:39 cheshire
-<rdar://problem/4789477> Eliminate unnecessary malloc/free in mDNSCore code
-
-Revision 1.330 2007/02/08 21:12:28 cheshire
-<rdar://problem/4386497> Stop reading /etc/mDNSResponder.conf on every sleep/wake
-
-Revision 1.329 2007/02/07 01:19:36 cheshire
-<rdar://problem/4849427> API: Reconcile conflicting error code values
-
-Revision 1.328 2007/01/25 00:19:40 cheshire
-Add CNAMEReferrals field to DNSQuestion_struct
-
-Revision 1.327 2007/01/23 02:56:10 cheshire
-Store negative results in the cache, instead of generating them out of pktResponseHndlr()
-
-Revision 1.326 2007/01/20 01:30:49 cheshire
-Update comments
-
-Revision 1.325 2007/01/19 18:39:11 cheshire
-Fix a bunch of parameters that should have been declared "const"
-
-Revision 1.324 2007/01/19 18:04:04 cheshire
-For naming consistency, use capital letters for RR types: rdataOpt should be rdataOPT
-
-Revision 1.323 2007/01/17 21:46:02 cheshire
-Remove redundant duplicated "isPrivate" field from LLQ_Info
-
-Revision 1.322 2007/01/10 22:51:56 cheshire
-<rdar://problem/4917539> Add support for one-shot private queries as well as long-lived private queries
-
-Revision 1.321 2007/01/09 22:37:18 cheshire
-Provide ten-second grace period for deleted keys, to give mDNSResponder
-time to delete host name before it gives up access to the required key.
-
-Revision 1.320 2007/01/05 08:30:41 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.319 2007/01/04 23:11:11 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-When an automatic browsing domain is removed, generate appropriate "remove" events for legacy queries
-
-Revision 1.318 2007/01/04 20:57:48 cheshire
-Rename ReturnCNAME to ReturnIntermed (for ReturnIntermediates)
-
-Revision 1.317 2007/01/04 02:39:53 cheshire
-<rdar://problem/4030599> Hostname passed into DNSServiceRegister ignored for Wide-Area service registrations
-
-Revision 1.316 2006/12/22 20:59:49 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.315 2006/12/20 04:07:35 cheshire
-Remove uDNS_info substructure from AuthRecord_struct
-
-Revision 1.314 2006/12/19 22:49:23 cheshire
-Remove uDNS_info substructure from ServiceRecordSet_struct
-
-Revision 1.313 2006/12/19 02:38:20 cheshire
-Get rid of unnecessary duplicate query ID field from DNSQuestion_struct
-
-Revision 1.312 2006/12/19 02:18:48 cheshire
-Get rid of unnecessary duplicate "void *context" field from DNSQuestion_struct
-
-Revision 1.311 2006/12/16 01:58:31 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-
-Revision 1.310 2006/12/15 19:09:56 cheshire
-<rdar://problem/4769083> ValidateRData() should be stricter about malformed MX and SRV records
-Made DomainNameLength() more defensive by adding a limit parameter, so it can be
-safely used to inspect potentially malformed data received from external sources.
-Without this, a domain name that starts off apparently valid, but extends beyond the end of
-the received packet data, could have appeared valid if the random bytes are already in memory
-beyond the end of the packet just happened to have reasonable values (e.g. all zeroes).
-
-Revision 1.309 2006/12/14 03:02:37 cheshire
-<rdar://problem/4838433> Tools: dns-sd -G 0 only returns IPv6 when you have a routable IPv6 address
-
-Revision 1.308 2006/11/30 23:07:56 herscher
-<rdar://problem/4765644> uDNS: Sync up with Lighthouse changes for Private DNS
-
-Revision 1.307 2006/11/18 05:01:30 cheshire
-Preliminary support for unifying the uDNS and mDNS code,
-including caching of uDNS answers
-
-Revision 1.306 2006/11/10 07:44:04 herscher
-<rdar://problem/4825493> Fix Daemon locking failures while toggling BTMM
-
-Revision 1.305 2006/11/10 00:54:15 cheshire
-<rdar://problem/4816598> Changing case of Computer Name doesn't work
-
-Revision 1.304 2006/10/20 05:35:05 herscher
-<rdar://problem/4720713> uDNS: Merge unicast active question list with multicast list.
-
-Revision 1.303 2006/10/04 21:37:33 herscher
-Remove uDNS_info substructure from DNSQuestion_struct
-
-Revision 1.302 2006/09/26 01:53:25 herscher
-<rdar://problem/4245016> NAT Port Mapping API (for both NAT-PMP and UPnP Gateway Protocol)
-
-Revision 1.301 2006/09/15 21:20:15 cheshire
-Remove uDNS_info substructure from mDNS_struct
-
-Revision 1.300 2006/08/14 23:24:23 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.299 2006/07/15 02:01:28 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Fix broken "empty string" browsing
-
-Revision 1.298 2006/07/05 22:55:03 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Need Private field in uDNS_RegInfo
-
-Revision 1.297 2006/07/05 22:20:03 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-
-Revision 1.296 2006/06/29 05:28:01 cheshire
-Added comment about mDNSlocal and mDNSexport
-
-Revision 1.295 2006/06/29 03:02:43 cheshire
-<rdar://problem/4607042> mDNSResponder NXDOMAIN and CNAME support
-
-Revision 1.294 2006/06/28 06:50:08 cheshire
-In future we may want to change definition of mDNSs32 from "signed long" to "signed int"
-I doubt anyone is building mDNSResponder on systems where int is 16-bits,
-but lets add a compile-time assertion to make sure.
-
-Revision 1.293 2006/06/12 18:00:43 cheshire
-To make code a little more defensive, check _ILP64 before _LP64,
-in case both are set by mistake on some platforms
-
-Revision 1.292 2006/03/19 17:00:57 cheshire
-Define symbol MaxMsg instead of using hard-coded constant value '80'
-
-Revision 1.291 2006/03/19 02:00:07 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.290 2006/03/08 22:42:23 cheshire
-Fix spelling mistake: LocalReverseMapomain -> LocalReverseMapDomain
-
-Revision 1.289 2006/02/26 00:54:41 cheshire
-Fixes to avoid code generation warning/error on FreeBSD 7
-
-*/
+ */
#ifndef __mDNSClientAPI_h
#define __mDNSClientAPI_h
typedef mDNSOpaque128 mDNSv6Addr; // An IPv6 address is a 16-byte opaque identifier (not an integer)
typedef mDNSOpaque48 mDNSEthAddr; // An Ethernet address is a six-byte opaque identifier (not an integer)
+// Bit operations for opaque 64 bit quantity. Uses the 32 bit quantity(l[2]) to set and clear bits
+#define mDNSNBBY 8
+#define bit_set_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
+#define bit_clr_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
+#define bit_get_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
+
enum
{
mDNSAddrType_None = 0,
#define MAX_DOMAIN_LABEL 63
typedef struct { mDNSu8 c[ 64]; } domainlabel; // One label: length byte and up to 63 characters
-// RFC 1034/1035/2181 specify that a domain name, including length bytes, data bytes, and terminating zero, may be up to 256 bytes long
+// RFC 1034/1035/2181 specify that a domain name (length bytes and data bytes) may be up to 255 bytes long,
+// plus the terminating zero at the end makes 256 bytes total in the on-the-wire format.
#define MAX_DOMAIN_NAME 256
typedef struct { mDNSu8 c[256]; } domainname; // Up to 256 bytes of length-prefixed domainlabels
#define kStandardTTL (3600UL * 100 / 80)
#define kHostNameTTL 120UL
+// Multicast DNS uses announcements (gratuitous responses) to update peer caches.
+// This means it is feasible to use relatively larger TTL values than we might otherwise
+// use, because we have a cache coherency protocol to keep the peer caches up to date.
+// With Unicast DNS, once an authoritative server gives a record with a certain TTL value to a client
+// or caching server, that client or caching server is entitled to hold onto the record until its TTL
+// expires, and has no obligation to contact the authoritative server again until that time arrives.
+// This means that whereas Multicast DNS can use announcements to pre-emptively update stale data
+// before it would otherwise have expired, standard Unicast DNS (not using LLQs) has no equivalent
+// mechanism, and TTL expiry is the *only* mechanism by which stale data gets deleted. Because of this,
+// we currently limit the TTL to ten seconds in such cases where no dynamic cache updating is possible.
+#define kStaticCacheTTL 10
+
#define DefaultTTLforRRType(X) (((X) == kDNSType_A || (X) == kDNSType_AAAA || (X) == kDNSType_SRV) ? kHostNameTTL : kStandardTTL)
typedef struct AuthRecord_struct AuthRecord;
DNSMessage request;
int requestLen;
DNSQuestion *question; // For queries
- ServiceRecordSet *srs; // For service record updates
AuthRecord *rr; // For record updates
mDNSAddr Addr;
mDNSIPPort Port;
+ mDNSIPPort SrcPort;
DNSMessage *reply;
mDNSu16 replylen;
unsigned long nread;
mDNSOpaque16 id;
mDNSOpaque16 flagsfrags;
mDNSu8 ttl;
- mDNSu8 protocol;
+ mDNSu8 protocol; // Payload type: 0x06 = TCP, 0x11 = UDP
mDNSu16 checksum;
mDNSv4Addr src;
mDNSv4Addr dst;
{
mDNSu32 vcf; // Version, Traffic Class, Flow Label
mDNSu16 len; // Payload Length
- mDNSu8 protocol; // Type of next header: 0x06 = TCP, 0x11 = UDP, 0x3A = ICMPv6
+ mDNSu8 pro; // Type of next header: 0x06 = TCP, 0x11 = UDP, 0x3A = ICMPv6
mDNSu8 ttl; // Hop Limit
mDNSv6Addr src;
mDNSv6Addr dst;
typedef packedstruct
{
- mDNSu8 type; // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
- mDNSu8 code;
+ mDNSv6Addr src;
+ mDNSv6Addr dst;
+ mDNSOpaque32 len;
+ mDNSOpaque32 pro;
+ } IPv6PseudoHeader; // 40 bytes
+
+typedef union
+ {
+ mDNSu8 bytes[20];
+ ARP_EthIP arp;
+ IPv4Header v4;
+ IPv6Header v6;
+ } NetworkLayerPacket;
+
+typedef packedstruct
+ {
+ mDNSIPPort src;
+ mDNSIPPort dst;
+ mDNSu32 seq;
+ mDNSu32 ack;
+ mDNSu8 offset;
+ mDNSu8 flags;
+ mDNSu16 window;
mDNSu16 checksum;
- mDNSu32 reserved;
- mDNSv6Addr target;
- } IPv6ND; // 24 bytes
+ mDNSu16 urgent;
+ } TCPHeader; // 20 bytes; IP protocol type 0x06
typedef packedstruct
{
mDNSIPPort src;
mDNSIPPort dst;
- mDNSu16 len; // Length including UDP header (ie. minimum value is 8 bytes)
+ mDNSu16 len; // Length including UDP header (i.e. minimum value is 8 bytes)
mDNSu16 checksum;
- } UDPHeader; // 8 bytes
+ } UDPHeader; // 8 bytes; IP protocol type 0x11
+
+typedef packedstruct
+ {
+ mDNSu8 type; // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
+ mDNSu8 code;
+ mDNSu16 checksum;
+ mDNSu32 flags_res; // R/S/O flags and reserved bits
+ mDNSv6Addr target;
+ // Typically 8 bytes of options are also present
+ } IPv6NDP; // 24 bytes or more; IP protocol type 0x3A
+
+#define NDP_Sol 0x87
+#define NDP_Adv 0x88
+
+#define NDP_Router 0x80
+#define NDP_Solicited 0x40
+#define NDP_Override 0x20
+
+#define NDP_SrcLL 1
+#define NDP_TgtLL 2
+
+typedef union
+ {
+ mDNSu8 bytes[20];
+ TCPHeader tcp;
+ UDPHeader udp;
+ IPv6NDP ndp;
+ } TransportLayerPacket;
typedef packedstruct
{
mDNSu32 Length;
} IKEHeader; // 28 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 -
kDNSRecordTypeKnownUnique = 0x20, // Known Unique means mDNS can assume name is unique without checking
// For Dynamic Update records, Known Unique means the record must already exist on the server.
kDNSRecordTypeUniqueMask = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
- kDNSRecordTypeActiveMask = (kDNSRecordTypeAdvisory | kDNSRecordTypeShared | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
+ kDNSRecordTypeActiveSharedMask = (kDNSRecordTypeAdvisory | kDNSRecordTypeShared),
+ kDNSRecordTypeActiveUniqueMask = (kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
+ kDNSRecordTypeActiveMask = (kDNSRecordTypeActiveSharedMask | kDNSRecordTypeActiveUniqueMask),
kDNSRecordTypePacketAdd = 0x80, // Received in the Additional Section of a DNS Response
kDNSRecordTypePacketAddUnique = 0x90, // Received in the Additional Section of a DNS Response with kDNSClass_UniqueRRSet set
kDNSRecordTypePacketNegative = 0xF0, // Pseudo-RR generated to cache non-existence results like NXDomain
- kDNSRecordTypePacketUniqueMask = 0x10 // True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique
+ kDNSRecordTypePacketUniqueMask = 0x10 // True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique, kDNSRecordTypePacketNegative
};
typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target; } rdataSRV;
(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(A,B) (mDNSSameEthAddress((A),(B)) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space)
#define DNSOpt_Data_Space(O) ( \
// 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
+ #define InlineCacheGroupNameSize 160
#else
- #define InlineCacheGroupNameSize 144
+ #define InlineCacheGroupNameSize 148
#endif
#else
#if defined(_ILP64) || defined(__ILP64__) || defined(_LP64) || defined(__LP64__) || defined(_WIN64)
- #define InlineCacheGroupNameSize 136
+ #define InlineCacheGroupNameSize 144
#else
- #define InlineCacheGroupNameSize 128
+ #define InlineCacheGroupNameSize 132
#endif
#endif
// Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls.
// The intent of this callback is to allow the client to free memory, if necessary.
// The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
-typedef void mDNSRecordUpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData);
+typedef void mDNSRecordUpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData, mDNSu16 OldRDLen);
// ***************************************************************************
#if 0
LNTOp_t op; // operation performed using this connection
mDNSAddr Address; // router address
mDNSIPPort Port; // router port
- mDNSs8 *Request; // xml request to router
+ mDNSu8 *Request; // xml request to router
int requestLen;
- mDNSs8 *Reply; // xml reply from router
+ mDNSu8 *Reply; // xml reply from router
int replyLen;
unsigned long nread; // number of bytes read so far
int retries; // number of times we've tried to do this port mapping
void *clientContext;
};
+enum
+ {
+ DNSServer_Untested = 0,
+ DNSServer_Passed = 1,
+ DNSServer_Failed = 2,
+ DNSServer_Disabled = 3
+ };
+
+enum
+ {
+ DNSServer_FlagDelete = 1,
+ DNSServer_FlagNew = 2
+ };
+
+typedef struct DNSServer
+ {
+ struct DNSServer *next;
+ 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"
+ mDNSs32 penaltyTime; // amount of time this server is penalized
+ mDNSBool scoped; // interface should be matched against question only
+ // if scoped is set
+ } DNSServer;
+
typedef struct // Size is 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
{
mDNSu8 RecordType; // See enum above
// that are interface-specific (e.g. address records, especially linklocal addresses)
const domainname *name;
RData *rdata; // Pointer to storage for this rdata
+ DNSServer *rDNSServer; // Unicast DNS server authoritative for this entry;null for multicast
} ResourceRecord;
// Unless otherwise noted, states may apply to either independent record registrations or service registrations
typedef enum
{
regState_Zero = 0,
- regState_FetchingZoneData = 1, // getting info - update not sent
- regState_Pending = 2, // update sent, reply not received
- regState_Registered = 3, // update sent, reply received
- regState_DeregPending = 4, // dereg sent, reply not received
- regState_DeregDeferred = 5, // dereg requested while in Pending state - send dereg AFTER registration is confirmed
- regState_Unregistered = 8, // not in any list
- regState_Refresh = 9, // outstanding refresh (or target change) message
- regState_NATMap = 10, // establishing NAT port mapping (service registrations only)
- regState_UpdatePending = 11, // update in flight as result of mDNS_Update call
- regState_NoTarget = 12, // service registration pending registration of hostname (ServiceRegistrations only)
- regState_ExtraQueued = 13, // extra record to be registered upon completion of service registration (RecordRegistrations only)
- regState_NATError = 14 // unable to complete NAT traversal
+ regState_Pending = 1, // update sent, reply not received
+ regState_Registered = 2, // update sent, reply received
+ regState_DeregPending = 3, // dereg sent, reply not received
+ regState_Unregistered = 4, // not in any list
+ regState_Refresh = 5, // outstanding refresh (or target change) message
+ regState_NATMap = 6, // establishing NAT port mapping
+ regState_UpdatePending = 7, // update in flight as result of mDNS_Update call
+ regState_NoTarget = 8, // SRV Record registration pending registration of hostname
+ regState_NATError = 9 // unable to complete NAT traversal
} regState_t;
enum
Target_AutoHostAndNATMAP = 2
};
+typedef enum
+ {
+ mergeState_Zero = 0,
+ mergeState_DontMerge = 1 // Set on fatal error conditions to disable merging
+ } mergeState_t;
+
struct AuthRecord_struct
{
// For examples of how to set up this structure for use in mDNS_Register(),
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)
+ OwnerOptData WakeUp; // WakeUp.HMAC.l[0] nonzero indicates that this is a Sleep Proxy record
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
mDNSBool Private; // If zone is private, DNS updates may have to be encrypted to prevent eavesdropping
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
- // SDC Perhaps should keep a reference to the relevant SRV record in the cache?
ZoneData *nta;
struct tcpInfo_t *tcp;
+ NATTraversalInfo NATinfo;
+ mDNSBool SRVChanged; // temporarily deregistered service because its SRV target or port changed
+ mergeState_t mState; // Unicast Record Registrations merge state
+ mDNSu8 refreshCount; // Number of refreshes to the server
+ mStatus updateError; // Record update resulted in Error ?
// uDNS_UpdateRecord support fields
// Do we really need all these in *addition* to NewRData and newrdlength above?
+ void *UpdateContext; // Context parameter for the update callback function
mDNSu16 OrigRDLen; // previously registered, being deleted
mDNSu16 InFlightRDLen; // currently being registered
mDNSu16 QueuedRDLen; // pending operation (re-transmitting if necessary) THEN register the queued update
// DO NOT ADD ANY MORE FIELDS HERE
};
+// IsLocalDomain alone is not sufficient to determine that a record is mDNS or uDNS. By default domain names within
+// the "local" pseudo-TLD (and within the IPv4 and IPv6 link-local reverse mapping domains) are automatically treated
+// as mDNS records, but it is also possible to force any record (even those not within one of the inherently local
+// domains) to be handled as an mDNS record by setting the ForceMCast flag, or by setting a non-zero InterfaceID.
+// For example, the reverse-mapping PTR record created in AdvertiseInterface sets the ForceMCast flag, since it points to
+// a dot-local hostname, and therefore it would make no sense to register this record with a wide-area Unicast DNS server.
+// The same applies to Sleep Proxy records, which we will answer for when queried via mDNS, but we never want to try
+// to register them with a wide-area Unicast DNS server -- and we probably don't have the required credentials anyway.
+// Currently we have no concept of a wide-area uDNS record scoped to a particular interface, so if the InterfaceID is
+// nonzero we treat this the same as ForceMCast.
+// Note: Question_uDNS(Q) is used in *only* one place -- on entry to mDNS_StartQuery_internal, to decide whether to set TargetQID.
+// Everywhere else in the code, the determination of whether a question is unicast is made by checking to see if TargetQID is nonzero.
#define AuthRecord_uDNS(R) ((R)->resrec.InterfaceID == mDNSInterface_Any && !(R)->ForceMCast && !IsLocalDomain((R)->resrec.name))
-#define Question_uDNS(Q) ((Q)->InterfaceID == mDNSInterface_Any && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname))
+#define Question_uDNS(Q) ((Q)->InterfaceID == mDNSInterface_Unicast || \
+ ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
+
+// Question (A or AAAA) that is suppressed currently because IPv4 or IPv6 address
+// is not available locally for A or AAAA question respectively
+#define QuerySuppressed(Q) ((Q)->SuppressUnusable && (Q)->SuppressQuery)
+
+#define PrivateQuery(Q) ((Q)->AuthInfo && (Q)->AuthInfo->AutoTunnel)
// Wrapper struct for Auth Records for higher-level code that cannot use the AuthRecord's ->next pointer field
typedef struct ARListElem
mDNSs32 DelayDelivery; // Set if we want to defer delivery of this answer to local clients
mDNSs32 NextRequiredQuery; // In platform time units
mDNSs32 LastUsed; // In platform time units
- DNSQuestion *CRActiveQuestion; // Points to an active question referencing this answer
+ DNSQuestion *CRActiveQuestion; // Points to an active question referencing this answer. Can never point to a NewQuestion.
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
const void *StatusContext; // Client Context
} HostnameInfo;
-enum
- {
- DNSServer_Untested = 0,
- DNSServer_Passed = 1,
- DNSServer_Failed = 2,
- DNSServer_Disabled = 3
- };
-
-enum
- {
- DNSServer_FlagDelete = 1,
- DNSServer_FlagNew = 2
- };
-
-typedef struct DNSServer
- {
- struct DNSServer *next;
- 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"
- mDNSs32 penaltyTime; // amount of time this server is penalized
- } DNSServer;
-
typedef struct ExtraResourceRecord_struct ExtraResourceRecord;
struct ExtraResourceRecord_struct
{
// Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
typedef void mDNSServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result);
-// A ServiceRecordSet is basically a convenience structure to group together
-// the PTR/SRV/TXT records that make up a standard service registration
-// It contains its own ServiceCallback+ServiceContext to report aggregate results up to the next layer of software above
+// A ServiceRecordSet has no special meaning to the core code of the Multicast DNS protocol engine;
+// it is just a convenience structure to group together the records that make up a standard service
+// registration so that they can be allocted and deallocted together as a single memory object.
+// It contains its own ServiceCallback+ServiceContext to report aggregate results up to the next layer of software above.
// It also contains:
+// * the basic PTR/SRV/TXT triplet used to represent any DNS-SD service
// * the "_services" PTR record for service enumeration
-// * the optional target host name (for proxy registrations)
// * the optional list of SubType PTR records
// * the optional list of additional records attached to the service set (e.g. iChat pictures)
-//
-// ... and a bunch of stuff related to uDNS, some of which could be simplified or eliminated
struct ServiceRecordSet_struct
{
// These internal state fields are used internally by mDNSCore; the client layer needn't be concerned with them.
// No fields need to be set up by the client prior to calling mDNS_RegisterService();
// all required data is passed as parameters to that function.
-
- // Begin uDNS info ****************
- // All of these fields should be eliminated
-
- // 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.
- ServiceRecordSet *uDNS_next;
- regState_t state;
- 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 *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
- mDNSIPPort SRSUpdatePort; // port on which server accepts dynamic updates
- NATTraversalInfo NATinfo;
- mDNSBool ClientCallbackDeferred; // invoke client callback on completion of pending operation(s)
- mStatus DeferredStatus; // status to deliver when above flag is set
- mDNSBool SRVUpdateDeferred; // do we need to change target or port once current operation completes?
- mDNSBool SRVChanged; // temporarily deregistered service because its SRV target or port changed
- struct tcpInfo_t *tcp;
-
- // End uDNS info ****************
-
mDNSServiceCallback *ServiceCallback;
void *ServiceContext;
mDNSBool Conflict; // Set if this record set was forcibly deregistered because of a conflict
#endif
// We record the last eight instances of each duplicate query
-// This gives us v4/v6 on each of Ethernet/AirPort and Firewire, and two free slots "for future expansion"
+// This gives us v4/v6 on each of Ethernet, AirPort and Firewire, and two free slots "for future expansion"
// If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully.
// Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression.
#define DupSuppressInfoSize 8
#define AutoTunnelUnregistered(X) ( \
(X)->AutoTunnelHostRecord.resrec.RecordType == kDNSRecordTypeUnregistered && \
(X)->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered && \
- (X)->AutoTunnelService. resrec.RecordType == kDNSRecordTypeUnregistered )
+ (X)->AutoTunnelService. resrec.RecordType == kDNSRecordTypeUnregistered && \
+ (X)->AutoTunnel6Record. resrec.RecordType == kDNSRecordTypeUnregistered )
// Internal data structure to maintain authentication information
typedef struct DomainAuthInfo
AuthRecord AutoTunnelTarget; // Opaque hostname of tunnel endpoint; used as SRV target for AutoTunnelService record
AuthRecord AutoTunnelDeviceInfo; // Device info of tunnel endpoint
AuthRecord AutoTunnelService; // Service record (possibly NAT-Mapped) of IKE daemon implementing tunnel endpoint
+ AuthRecord AutoTunnel6Record; // AutoTunnel AAAA Record obtained from Connectivityd
NATTraversalInfo AutoTunnelNAT;
domainname domain;
domainname keyname;
// Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
typedef enum { QC_rmv = 0, QC_add = 1, QC_addnocache = 2 } QC_result;
typedef void mDNSQuestionCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
+
+#define NextQSendTime(Q) ((Q)->LastQTime + (Q)->ThisQInterval)
+#define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
+#define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - NextQSendTime(Q) >= 0)
+
struct DNSQuestion_struct
{
// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
mDNSu32 RequestUnicast; // Non-zero if we want to send query with kDNSQClass_UnicastResponse bit set
mDNSs32 LastQTxTime; // Last time this Q was sent on one (but not necessarily all) interfaces
mDNSu32 CNAMEReferrals; // Count of how many CNAME redirections we've done
+ mDNSBool SuppressQuery; // This query should be suppressed and not sent on the wire
// Wide Area fields. These are used internally by the uDNS core
UDPSocket *LocalSocket;
+ mDNSBool deliverAddEvents; // Change in DNSSserver requiring to deliver ADD events
DNSServer *qDNSServer; // Caching server for this query (in the absence of an SRV saying otherwise)
+ mDNSOpaque64 validDNSServers; // Valid DNSServers for this question
+ mDNSu16 noServerResponse; // At least one server did not respond.
+ mDNSu16 triedAllServersOnce; // Tried all DNS servers once
mDNSu8 unansweredQueries;// The number of unanswered queries to this server
ZoneData *nta; // Used for getting zone data for private or LLQ query
mDNSAddr servAddr; // Address and port learned from _dns-llq, _dns-llq-tls or _dns-query-tls SRV query
mDNSIPPort servPort;
struct tcpInfo_t *tcp;
+ mDNSIPPort tcpSrcPort; // Local Port TCP packet received on;need this as tcp struct is disposed
+ // by tcpCallback before calling into mDNSCoreReceive
mDNSu8 NoAnswer; // Set if we want to suppress answers until tunnel setup has completed
// LLQ-specific fields. These fields are only meaningful when LongLived flag is set
mDNSBool ExpectUnique; // Set by client if it's expecting unique RR(s) for this question, not shared RRs
mDNSBool ForceMCast; // Set by client to force mDNS query, even for apparently uDNS names
mDNSBool ReturnIntermed; // Set by client to request callbacks for intermediate CNAME/NXDOMAIN results
+ mDNSBool SuppressUnusable; // Set by client to suppress unusable queries to be sent on the wire
mDNSQuestionCallback *QuestionCallback;
void *QuestionContext;
};
} DNameListElem;
#if APPLE_OSX_mDNSResponder
+// Different states that we go through locating the peer
+#define TC_STATE_AAAA_PEER 0x000000001 /* Peer's BTMM IPv6 address */
+#define TC_STATE_AAAA_PEER_RELAY 0x000000002 /* Peer's IPv6 Relay address */
+#define TC_STATE_SRV_PEER 0x000000003 /* Peer's SRV Record corresponding to IPv4 address */
+#define TC_STATE_ADDR_PEER 0x000000004 /* Peer's IPv4 address */
+
typedef struct ClientTunnel
{
struct ClientTunnel *next;
mDNSBool MarkedForDeletion;
mDNSv6Addr loc_inner;
mDNSv4Addr loc_outer;
+ mDNSv6Addr loc_outer6;
mDNSv6Addr rmt_inner;
mDNSv4Addr rmt_outer;
+ mDNSv6Addr rmt_outer6;
mDNSIPPort rmt_outer_port;
+ mDNSu16 tc_state;
DNSQuestion q;
} ClientTunnel;
#endif
DNSQuestion AutomaticBrowseQ;
DNSQuestion RegisterQ;
DNSQuestion DefRegisterQ;
+ DNSQuestion DirQ;
+ int numDirAnswers;
ARListElem *AuthRecs;
} SearchListElem;
#define CACHE_HASH_SLOTS 499
-enum
+enum // Bit flags -- i.e. values should be 1, 2, 4, 8, etc.
{
mDNS_KnownBug_PhantomInterfaces = 1,
- mDNS_KnownBug_LossySyslog = 2 // <rdar://problem/6561888>
+ mDNS_KnownBug_LimitedIPv6 = 2,
+ mDNS_KnownBug_LossySyslog = 4 // <rdar://problem/6561888>
};
enum
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 SuppressSending; // Don't send *any* packets during this time
+ mDNSs32 SuppressSending; // Don't send local-link mDNS 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 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
+ mDNSu8 LocalRemoveEvents; // Set if we may need to deliver remove events for local-only questions and/or local-only records
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
mDNSu8 SentSleepProxyRegistration;// Set if we registered (or tried to register) with a Sleep Proxy
+ mDNSu8 SystemSleepOnlyIfWakeOnLAN;// Set if we may only sleep if we managed to register with a Sleep Proxy
mDNSs32 AnnounceOwner; // After waking from sleep, include OWNER option in packets until this time
mDNSs32 DelaySleep; // To inhibit re-sleeping too quickly right after wake
mDNSs32 SleepLimit; // Time window to allow deregistrations, etc.,
DNSQuestion *Questions; // List of all registered questions, active and inactive
DNSQuestion *NewQuestions; // Fresh questions not yet answered from cache
DNSQuestion *CurrentQuestion; // Next question about to be examined in AnswerLocalQuestions()
- DNSQuestion *LocalOnlyQuestions; // Questions with InterfaceID set to mDNSInterface_LocalOnly
- DNSQuestion *NewLocalOnlyQuestions; // Fresh local-only questions not yet answered
+ DNSQuestion *LocalOnlyQuestions; // Questions with InterfaceID set to mDNSInterface_LocalOnly or mDNSInterface_P2P
+ DNSQuestion *NewLocalOnlyQuestions; // Fresh local-only or P2P questions not yet answered
mDNSu32 rrcache_size; // Total number of available cache entries
mDNSu32 rrcache_totalused; // Number of cache entries currently occupied
mDNSu32 rrcache_active; // Number of cache entries currently occupied by records that answer active questions
mDNSu32 rrcache_report;
CacheEntity *rrcache_free;
CacheGroup *rrcache_hash[CACHE_HASH_SLOTS];
+ mDNSs32 rrcache_nextcheck[CACHE_HASH_SLOTS];
// Fields below only required for mDNS Responder...
domainlabel nicelabel; // Rich text label encoded using canonically precomposed UTF-8
AuthRecord DeviceInfo;
AuthRecord *ResourceRecords;
AuthRecord *DuplicateRecords; // Records currently 'on hold' because they are duplicates of existing records
- AuthRecord *NewLocalRecords; // Fresh local-only records not yet delivered to local-only questions
+ AuthRecord *NewLocalRecords; // Fresh AuthRecords (both local-only and public) not yet delivered to our local-only questions
AuthRecord *CurrentRecord; // Next AuthRecord about to be examined
NetworkInterfaceInfo *HostInterfaces;
mDNSs32 ProbeFailTime;
// 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
- ServiceRecordSet *ServiceRegistrations;
DNSServer *DNSServers; // list of DNS servers
mDNSAddr Router;
HostnameInfo *Hostnames; // List of registered hostnames + hostname metadata
mDNSv6Addr AutoTunnelHostAddr; // IPv6 address advertised for AutoTunnel services on this machine
mDNSBool AutoTunnelHostAddrActive;
+ mDNSv6Addr AutoTunnelRelayAddr; // IPv6 address advertised for AutoTunnel Relay services on this machine
domainlabel AutoTunnelLabel; // Used to construct hostname for *IPv4* address of tunnel endpoints
mDNSBool RegisterSearchDomains;
+ mDNSBool RegisterAutoTunnel6;
// NAT-Traversal fields
NATTraversalInfo LLQNAT; // Single shared NAT Traversal to receive inbound LLQ notifications
#if APPLE_OSX_mDNSResponder
ClientTunnel *TunnelClients;
uuid_t asl_uuid; // uuid for ASL logging
+ void *WCF;
#endif
// Fixed storage, to avoid creating large objects on the stack
#pragma mark - Useful Static Constants
#endif
-extern const mDNSIPPort zeroIPPort;
-extern const mDNSv4Addr zerov4Addr;
-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 mDNSInterfaceID mDNSInterfaceMark; // Special value
+extern const mDNSInterfaceID mDNSInterface_P2P; // Special value
extern const mDNSIPPort DiscardPort;
extern const mDNSIPPort SSHPort;
extern const mDNSIPPort LoopbackIPCPort;
extern const mDNSIPPort PrivateDNSPort;
+extern const OwnerOptData zeroOwner;
+
+extern const mDNSIPPort zeroIPPort;
+extern const mDNSv4Addr zerov4Addr;
+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 mDNSv4Addr AllDNSAdminGroup;
-extern const mDNSv4Addr AllSystemsMcast;
+extern const mDNSv4Addr AllHosts_v4;
+extern const mDNSv6Addr AllHosts_v6;
+extern const mDNSv6Addr NDP_prefix;
+extern const mDNSEthAddr AllHosts_v6_Eth;
extern const mDNSAddr AllDNSLinkGroup_v4;
extern const mDNSAddr AllDNSLinkGroup_v6;
extern const mDNSOpaque64 zeroOpaque64;
extern mDNSBool StrictUnicastOrdering;
+extern mDNSu8 NumUnicastDNSServers;
#define localdomain (*(const domainname *)"\x5" "local")
#define DeviceInfoName (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp")
extern void mDNS_StartExit (mDNS *const m);
extern void mDNS_FinalExit (mDNS *const m);
#define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0)
-#define mDNS_ExitNow(m, now) ((now) - (m)->ShutdownTime >= 0 || (!(m)->ResourceRecords && !(m)->ServiceRegistrations))
+#define mDNS_ExitNow(m, now) ((now) - (m)->ShutdownTime >= 0 || (!(m)->ResourceRecords))
extern mDNSs32 mDNS_Execute (mDNS *const m);
extern DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const name);
+extern void mDNS_UpdateAllowSleep(mDNS *const m);
+
// ***************************************************************************
#if 0
#pragma mark -
#pragma mark - General utility and helper functions
#endif
+// mDNS_Dereg_normal is used for most calls to mDNS_Deregister_internal
+// mDNS_Dereg_rapid is used to send one goodbye instead of three, when we want the memory available for reuse sooner
+// mDNS_Dereg_conflict is used to indicate that this record is being forcibly deregistered because of a conflict
+// mDNS_Dereg_repeat is used when cleaning up, for records that may have already been forcibly deregistered
+typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_Dereg_repeat } mDNS_Dereg_type;
+
// mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
//
// mDNS_StartResolveService is single call which is equivalent to multiple calls to mDNS_StartQuery,
extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl);
extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, mDNSRecordCallback MemFreeCallback, void *Context);
extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname);
-extern mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr);
+extern mStatus mDNS_DeregisterService_drt(mDNS *const m, ServiceRecordSet *sr, mDNS_Dereg_type drt);
+#define mDNS_DeregisterService(M,S) mDNS_DeregisterService_drt((M), (S), mDNS_Dereg_normal)
extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
const domainlabel *const name, const domainname *const type, const domainname *const domain,
#define mDNS_StopAdvertiseDomains mDNS_Deregister
extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m);
-
-extern DNSServer *GetServerForName(mDNS *m, const domainname *name, DNSServer *current);
+extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr);
+
+extern DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID);
+extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question);
+extern void SetValidDNSServers(mDNS *m, DNSQuestion *question);
// ***************************************************************************
#if 0
extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
extern mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2);
extern mDNSBool SameDomainNameCS(const domainname *const d1, const domainname *const d2);
+typedef mDNSBool DomainNameComparisonFn(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 StripFirstLabel(X) ((const domainname *)&(X)->c[(X)->c[0] ? 1 + (X)->c[0] : 0])
((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLinkLocal(&(X)->ip.v4) : \
((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLinkLocal(&(X)->ip.v6) : mDNSfalse)
+#define mDNSv4AddressIsLoopback(X) ((X)->b[0] == 127 && (X)->b[1] == 0 && (X)->b[2] == 0 && (X)->b[3] == 1)
+#define mDNSv6AddressIsLoopback(X) ((((X)->l[0] | (X)->l[1] | (X)->l[2]) == 0) && ((X)->b[12] == 0 && (X)->b[13] == 0 && (X)->b[14] == 0 && (X)->b[15] == 1))
+
+#define mDNSAddressIsLoopback(X) ( \
+ ((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLoopback(&(X)->ip.v4) : \
+ ((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLoopback(&(X)->ip.v6) : mDNSfalse)
// ***************************************************************************
#if 0
#pragma mark -
extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext);
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 PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSBool QueryFail);
+extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped);
+extern void PenalizeDNSServer(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
extern TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port); // creates a TCP socket
extern TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd);
extern int mDNSPlatformTCPGetFD(TCPSocket *sock);
-extern mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID,
- TCPConnectionCallback callback, void *context);
+extern mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname,
+ mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context);
extern void mDNSPlatformTCPCloseConnection(TCPSocket *sock);
extern long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed);
extern long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len);
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 mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID);
extern void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst);
// mDNSPlatformTLSSetupCerts/mDNSPlatformTLSTearDownCerts used by dnsextd
extern mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router);
extern void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status);
+extern void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep);
+
#ifdef _LEGACY_NAT_TRAVERSAL_
// Support for legacy NAT traversal protocols, implemented by the platform layer and callable by the core.
extern void LNT_SendDiscoveryMsg(mDNS *m);
-extern void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 *data, mDNSu16 len);
+extern void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, const mDNSu8 *const data, const mDNSu16 len);
extern mStatus LNT_GetExternalAddress(mDNS *m);
extern mStatus LNT_MapPort(mDNS *m, NATTraversalInfo *n);
extern mStatus LNT_UnmapPort(mDNS *m, NATTraversalInfo *n);
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);
+ const mDNSAddr *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, mDNSs32 now);
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 CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay);
+extern void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event);
extern void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease);
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);
+ const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds,
+ mDNSInterfaceID InterfaceID, DNSServer *dnsserver);
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);
extern char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID);
+extern void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *new);
+extern void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr);
+extern void CheckSuppressUnusableQuestions(mDNS *const m);
// For now this AutoTunnel stuff is specific to Mac OS X.
// In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
#if APPLE_OSX_mDNSResponder
extern void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
extern void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q);
-extern void SetupLocalAutoTunnelInterface_internal(mDNS *const m);
+extern void SetupLocalAutoTunnelInterface_internal(mDNS *const m, mDNSBool servicesStarting);
extern void UpdateAutoTunnelDomainStatuses(const mDNS *const m);
extern mStatus ActivateLocalProxy(mDNS *const m, char *ifname);
+extern void RemoveAutoTunnel6Record(mDNS *const m);
+extern void SetupConndConfigChanges(mDNS *const m);
+extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr);
+#endif
+
+// ***************************************************************************
+#if 0
+#pragma mark -
+#pragma mark - Sleep Proxy
#endif
+// Sleep Proxy Server Property Encoding
+//
+// Sleep Proxy Servers are advertised using a structured service name, consisting of four
+// metrics followed by a human-readable name. The metrics assist clients in deciding which
+// Sleep Proxy Server(s) to use when multiple are available on the network. Each metric
+// is a two-digit decimal number in the range 10-99. Lower metrics are generally better.
+//
+// AA-BB-CC-DD Name
+//
+// Metrics:
+//
+// AA = Intent
+// BB = Portability
+// CC = Marginal Power
+// DD = Total Power
+//
+//
+// ** Intent Metric **
+//
+// 20 = Dedicated Sleep Proxy Server -- a device, permanently powered on,
+// installed for the express purpose of providing Sleep Proxy Service.
+//
+// 30 = Primary Network Infrastructure Hardware -- a router, DHCP server, NAT gateway,
+// or similar permanently installed device which is permanently powered on.
+// This is hardware designed for the express purpose of being network
+// infrastructure, and for most home users is typically a single point
+// of failure for the local network -- e.g. most home users only have
+// a single NAT gateway / DHCP server. Even though in principle the
+// hardware might technically be capable of running different software,
+// a typical user is unlikely to do that. e.g. AirPort base station.
+//
+// 40 = Primary Network Infrastructure Software -- a general-purpose computer
+// (e.g. Mac, Windows, Linux, etc.) which is currently running DHCP server
+// or NAT gateway software, but the user could choose to turn that off
+// fairly easily. e.g. iMac running Internet Sharing
+//
+// 50 = Secondary Network Infrastructure Hardware -- like primary infrastructure
+// hardware, except not a single point of failure for the entire local network.
+// For example, an AirPort base station in bridge mode. This may have clients
+// associated with it, and if it goes away those clients will be inconvenienced,
+// but unlike the NAT gateway / DHCP server, the entire local network is not
+// dependent on it.
+//
+// 60 = Secondary Network Infrastructure Software -- like 50, but in a general-
+// purpose CPU.
+//
+// 70 = Incidentally Available Hardware -- a device which has no power switch
+// and is generally left powered on all the time. Even though it is not a
+// part of what we conventionally consider network infrastructure (router,
+// DHCP, NAT, DNS, etc.), and the rest of the network can operate fine
+// without it, since it's available and unlikely to be turned off, it is a
+// reasonable candidate for providing Sleep Proxy Service e.g. Apple TV,
+// or an AirPort base station in client mode, associated with an existing
+// wireless network (e.g. AirPort Express connected to a music system, or
+// being used to share a USB printer).
+//
+// 80 = Incidentally Available Software -- a general-purpose computer which
+// happens at this time to be set to "never sleep", and as such could be
+// useful as a Sleep Proxy Server, but has not been intentionally provided
+// for this purpose. Of all the Intent Metric categories this is the
+// one most likely to be shut down or put to sleep without warning.
+// However, if nothing else is availalable, it may be better than nothing.
+// e.g. Office computer in the workplace which has been set to "never sleep"
+//
+//
+// ** Portability Metric **
+//
+// Inversely related to mass of device, on the basis that, all other things
+// being equal, heavier devices are less likely to be moved than lighter devices.
+// E.g. A MacBook running Internet Sharing is probably more likely to be
+// put to sleep and taken away than a Mac Pro running Internet Sharing.
+// The Portability Metric is a logarithmic decibel scale, computed by taking the
+// (approximate) mass of the device in milligrammes, taking the base 10 logarithm
+// of that, multiplying by 10, and subtracting the result from 100:
+//
+// Portability Metric = 100 - (log10(mg) * 10)
+//
+// The Portability Metric is not necessarily computed literally from the actual
+// mass of the device; the intent is just that lower numbers indicate more
+// permanent devices, and higher numbers indicate devices more likely to be
+// removed from the network, e.g., in order of increasing portability:
+//
+// Mac Pro < iMac < Laptop < iPhone
+//
+// Example values:
+//
+// 10 = 1 metric tonne
+// 40 = 1kg
+// 70 = 1g
+// 90 = 10mg
+//
+//
+// ** Marginal Power and Total Power Metrics **
+//
+// The Marginal Power Metric is the power difference between sleeping and staying awake
+// to be a Sleep Proxy Server.
+//
+// The Total Power Metric is the total power consumption when being Sleep Proxy Server.
+//
+// The Power Metrics use a logarithmic decibel scale, computed as ten times the
+// base 10 logarithm of the (approximate) power in microwatts:
+//
+// Power Metric = log10(uW) * 10
+//
+// Higher values indicate higher power consumption. Example values:
+//
+// 10 = 10 uW
+// 20 = 100 uW
+// 30 = 1 mW
+// 60 = 1 W
+// 90 = 1 kW
+
+extern void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower);
+#define mDNSCoreBeSleepProxyServer(M,S,P,MP,TP) \
+ do { mDNS_Lock(m); mDNSCoreBeSleepProxyServer_internal((M),(S),(P),(MP),(TP)); mDNS_Unlock(m); } while(0)
+
+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'))
+
// ***************************************************************************
#if 0
#pragma mark -
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 assertJ[(sizeof(IPv6NDP ) == 24 ) ? 1 : -1];
char assertK[(sizeof(UDPHeader ) == 8 ) ? 1 : -1];
char assertL[(sizeof(IKEHeader ) == 28 ) ? 1 : -1];
char assertM[(sizeof(TCPHeader ) == 20 ) ? 1 : -1];
// 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) <= 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_ResourceRecord [(sizeof(ResourceRecord) <= 64) ? 1 : -1];
+ char sizecheck_AuthRecord [(sizeof(AuthRecord) <= 1208) ? 1 : -1];
+ char sizecheck_CacheRecord [(sizeof(CacheRecord) <= 184) ? 1 : -1];
+ char sizecheck_CacheGroup [(sizeof(CacheGroup) <= 184) ? 1 : -1];
+ char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 752) ? 1 : -1];
+ char sizecheck_ZoneData [(sizeof(ZoneData) <= 1588) ? 1 : -1];
char sizecheck_NATTraversalInfo [(sizeof(NATTraversalInfo) <= 192) ? 1 : -1];
- char sizecheck_HostnameInfo [(sizeof(HostnameInfo) <= 2800) ? 1 : -1];
- char sizecheck_DNSServer [(sizeof(DNSServer) <= 312) ? 1 : -1];
- char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 5968) ? 1 : -1];
+ char sizecheck_HostnameInfo [(sizeof(HostnameInfo) <= 3050) ? 1 : -1];
+ char sizecheck_DNSServer [(sizeof(DNSServer) <= 320) ? 1 : -1];
+ char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 6750) ? 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];
+ char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 7550) ? 1 : -1];
+ char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3050) ? 1 : -1];
#if APPLE_OSX_mDNSResponder
- char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1072) ? 1 : -1];
+ char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1104) ? 1 : -1];
#endif
};
* Elimate all mDNSPlatformMemAllocate/mDNSPlatformMemFree from this code -- the core code
* is supposed to be malloc-free so that it runs in constant memory determined at compile-time.
* Any dynamic run-time requirements should be handled by the platform layer below or client layer above
-
- Change History (most recent first):
-
-$Log: uDNS.c,v $
-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.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.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.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
-
-Revision 1.552 2008/03/05 01:56:42 cheshire
-<rdar://problem/5687667> BTMM: Don't fallback to unencrypted operations when SRV lookup fails
-
-Revision 1.551 2008/03/01 01:43:04 cheshire
-<rdar://problem/5631565> BTMM: Lots of "Error getting external address 3" when double-NATed prevents sleep
-Added code to suppress logging of multiple identical error results
-
-Revision 1.550 2008/03/01 01:34:47 cheshire
-<rdar://problem/5736313> BTMM: Double-NAT'd machines register all but AutoTunnel v4 address records
-Further refinements
-
-Revision 1.549 2008/02/29 01:35:37 mcguire
-<rdar://problem/5736313> BTMM: Double-NAT'd machines register all but AutoTunnel v4 address records
-
-Revision 1.548 2008/02/20 23:54:18 cheshire
-<rdar://problem/5661518> "Failed to obtain NAT port mapping" syslog messages
-Improved log message so it tells us more about what's going on
-
-Revision 1.547 2008/02/20 00:41:09 cheshire
-Change "PrivateQueryGotZoneData ... invoked with error code" from LogMsg to LogOperation
-
-Revision 1.546 2008/02/19 23:26:50 cheshire
-<rdar://problem/5661661> BTMM: Too many members.mac.com SOA queries
-
-Revision 1.545 2007/12/22 02:25:29 cheshire
-<rdar://problem/5661128> Records and Services sometimes not re-registering on wake from sleep
-
-Revision 1.544 2007/12/18 00:40:11 cheshire
-<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
-Reordered code to avoid double-TSIGs in some cases
-
-Revision 1.543 2007/12/17 23:57:43 cheshire
-<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
-Need to include TSIG signature when sending LLQ cancellations over TLS
-
-Revision 1.542 2007/12/15 01:12:27 cheshire
-<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
-
-Revision 1.541 2007/12/15 00:18:51 cheshire
-Renamed question->origLease to question->ReqLease
-
-Revision 1.540 2007/12/14 23:55:28 cheshire
-Moved "struct tcpInfo_t" definition from uDNS.c to mDNSEmbeddedAPI.h
-
-Revision 1.539 2007/12/14 20:44:24 cheshire
-<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
-SleepRecordRegistrations/WakeRecordRegistrations should only operate on uDNS records
-
-Revision 1.538 2007/12/14 01:13:40 cheshire
-<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
-Additional fixes (existing code to deregister private records and services didn't work at all)
-
-Revision 1.537 2007/12/11 00:18:25 cheshire
-<rdar://problem/5569316> BTMM: My iMac has a "ghost" ID associated with it
-There were cases where the code was incorrectly clearing the "uselease" flag, and never resetting it.
-
-Revision 1.536 2007/12/10 23:07:00 cheshire
-Removed some unnecessary log messages
-
-Revision 1.535 2007/12/06 00:22:27 mcguire
-<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
-
-Revision 1.534 2007/12/04 00:49:37 cheshire
-<rdar://problem/5607082> BTMM: mDNSResponder taking 100 percent CPU after upgrading to 10.5.1
-
-Revision 1.533 2007/12/01 01:21:27 jgraessley
-<rdar://problem/5623140> mDNSResponder unicast DNS improvements
-
-Revision 1.532 2007/11/30 20:16:44 cheshire
-Fixed compile warning: declaration of 'end' shadows a previous local
-
-Revision 1.531 2007/11/28 22:00:09 cheshire
-In StartSRVNatMap, change "mDNSu8 *p" to "const mDNSu8 *p"
-
-Revision 1.530 2007/11/16 22:19:40 cheshire
-<rdar://problem/5547474> mDNSResponder leaks on network changes
-The "connection failed" code path in MakeTCPConn was not disposing of the TCPSocket it had created
-
-Revision 1.529 2007/11/15 22:52:29 cheshire
-<rdar://problem/5589039> ERROR: mDNSPlatformWriteTCP - send Broken pipe
-
-Revision 1.528 2007/11/02 21:32:30 cheshire
-<rdar://problem/5575593> BTMM: Deferring deregistration of record log messages on sleep/wake
-
-Revision 1.527 2007/11/01 16:08:51 cheshire
-Tidy up alignment of "SetRecordRetry refresh" log messages
-
-Revision 1.526 2007/10/31 19:26:55 cheshire
-Don't need to log "Permanently abandoning service registration" message when we're intentionally deleting a service
-
-Revision 1.525 2007/10/30 23:58:59 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-After failure, double retry interval up to maximum of 30 minutes
-
-Revision 1.524 2007/10/30 20:10:47 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-
-Revision 1.523 2007/10/30 00:54:31 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-Fixed timing logic to double retry interval properly
-
-Revision 1.522 2007/10/30 00:04:43 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-Made the code not give up and abandon the record when it gets an error in regState_UpdatePending state
-
-Revision 1.521 2007/10/29 23:58:52 cheshire
-<rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events
-Use standard "if (mDNSIPv4AddressIsOnes(....ExternalAddress))" mechanism to determine whether callback has been invoked yet
-
-Revision 1.520 2007/10/29 21:48:36 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Added 10% random variation on LLQ renewal time, to reduce unintended timing correlation between multiple machines
-
-Revision 1.519 2007/10/29 21:37:00 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-Added 10% random variation on record refresh time, to reduce accidental timing correlation between multiple machines
-
-Revision 1.518 2007/10/26 23:41:29 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-
-Revision 1.517 2007/10/25 23:30:12 cheshire
-Private DNS registered records now deregistered on sleep and re-registered on wake
-
-Revision 1.516 2007/10/25 22:53:52 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-Don't unlinkSRS and permanently give up at the first sign of trouble
-
-Revision 1.515 2007/10/25 21:08:07 cheshire
-Don't try to send record registrations/deletions before we have our server address
-
-Revision 1.514 2007/10/25 20:48:47 cheshire
-For naming consistency (with AuthRecord's UpdateServer) renamed 'ns' to 'SRSUpdateServer'
-
-Revision 1.513 2007/10/25 20:06:13 cheshire
-Don't try to do SOA queries using private DNS (TLS over TCP) queries
-
-Revision 1.512 2007/10/25 18:25:15 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-Don't need a NAT mapping for autotunnel services
-
-Revision 1.511 2007/10/25 00:16:23 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-Fixed retry timing logic; when DNS server returns an error code, we should retry later,
-instead of just deleting our record ("UnlinkAuthRecord") and completely giving up
-
-Revision 1.510 2007/10/24 22:40:06 cheshire
-Renamed: RecordRegistrationCallback -> RecordRegistrationGotZoneData
-Renamed: ServiceRegistrationZoneDataComplete -> ServiceRegistrationGotZoneData
-
-Revision 1.509 2007/10/24 00:54:07 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-
-Revision 1.508 2007/10/24 00:05:03 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-When sending TLS/TCP LLQ setup request over VPN, need to set EventPort to 5353, not zero
-
-Revision 1.507 2007/10/23 00:33:36 cheshire
-Improved debugging messages
-
-Revision 1.506 2007/10/22 19:54:13 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Only put EventPort in LLQ request when sending from an RFC 1918 source address, not when sending over VPN
-
-Revision 1.505 2007/10/19 22:08:49 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Additional fixes and refinements
-
-Revision 1.504 2007/10/18 23:06:43 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Additional fixes and refinements
-
-Revision 1.503 2007/10/18 20:23:17 cheshire
-Moved SuspendLLQs into mDNS.c, since it's only called from one place
-
-Revision 1.502 2007/10/17 22:49:54 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-
-Revision 1.501 2007/10/17 22:37:23 cheshire
-<rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events
-
-Revision 1.500 2007/10/17 21:53:51 cheshire
-Improved debugging messages; renamed startLLQHandshakeCallback to LLQGotZoneData
-
-Revision 1.499 2007/10/16 21:16:50 cheshire
-Get rid of unused uDNS_Sleep() routine
-
-Revision 1.498 2007/10/16 20:59:41 cheshire
-Export SuspendLLQs/SleepServiceRegistrations/SleepRecordRegistrations so they're callable from other files
-
-Revision 1.497 2007/10/05 18:09:44 cheshire
-<rdar://problem/5524841> Services advertised with wrong target host
-
-Revision 1.496 2007/10/04 22:38:59 cheshire
-Added LogOperation message showing new q->ThisQInterval after sending uDNS query packet
-
-Revision 1.495 2007/10/03 00:16:19 cheshire
-In PrivateQueryGotZoneData, need to grab lock before calling SetNextQueryTime
-
-Revision 1.494 2007/10/02 21:11:08 cheshire
-<rdar://problem/5518270> LLQ refreshes don't work, which breaks BTMM browsing
-
-Revision 1.493 2007/10/02 19:50:23 cheshire
-Improved debugging message
-
-Revision 1.492 2007/09/29 03:15:43 cheshire
-<rdar://problem/5513168> BTMM: mDNSResponder memory corruption in GetAuthInfoForName_internal
-Use AutoTunnelUnregistered macro instead of checking record state directly
-
-Revision 1.491 2007/09/29 01:33:45 cheshire
-<rdar://problem/5513168> BTMM: mDNSResponder memory corruption in GetAuthInfoForName_internal
-
-Revision 1.490 2007/09/29 01:06:17 mcguire
-<rdar://problem/5507862> 9A564: mDNSResponder crash in mDNS_Execute
-
-Revision 1.489 2007/09/27 22:02:33 cheshire
-<rdar://problem/5464941> BTMM: Registered records in BTMM don't get removed from server after calling RemoveRecord
-
-Revision 1.488 2007/09/27 21:20:17 cheshire
-Improved debugging syslog messages
-
-Revision 1.487 2007/09/27 18:55:11 cheshire
-<rdar://problem/5477165> BTMM: Multiple SRV records get registered after changing Computer Name
-
-Revision 1.486 2007/09/27 17:42:49 cheshire
-Fix naming: for consistency, "kDNSFlag1_RC" should be "kDNSFlag1_RC_Mask"
-
-Revision 1.485 2007/09/27 02:16:30 cheshire
-<rdar://problem/5500111> BTMM: LLQ refreshes being sent in the clear to the wrong port
-
-Revision 1.484 2007/09/27 00:25:39 cheshire
-Added ttl_seconds parameter to MakeNegativeCacheRecord in preparation for:
-<rdar://problem/4947392> uDNS: Use SOA to determine TTL for negative answers
-
-Revision 1.483 2007/09/26 23:16:58 cheshire
-<rdar://problem/5496399> BTMM: Leopard sending excessive LLQ registration requests to .Mac
-
-Revision 1.482 2007/09/26 22:06:02 cheshire
-<rdar://problem/5507399> BTMM: No immediate failure notifications for BTMM names
-
-Revision 1.481 2007/09/26 00:49:46 cheshire
-Improve packet logging to show sent and received packets,
-transport protocol (UDP/TCP/TLS) and source/destination address:port
-
-Revision 1.480 2007/09/21 21:08:52 cheshire
-Get rid of unnecessary DumpPacket() calls -- it makes more sense
-to do this in mDNSSendDNSMessage and mDNSCoreReceive instead
-
-Revision 1.479 2007/09/21 20:01:17 cheshire
-<rdar://problem/5496750> BTMM: Skip directly to member name in SOA queries to avoid sending names in the clear
-
-Revision 1.478 2007/09/21 19:29:14 cheshire
-Added dump of uDNS questions when in MDNS_LOG_VERBOSE_DEBUG mode
-
-Revision 1.477 2007/09/20 02:29:37 cheshire
-<rdar://problem/4038277> BTMM: Not getting LLQ remove events when logging out of VPN or disconnecting from network
-
-Revision 1.476 2007/09/20 01:19:49 cheshire
-Improve debugging messages: report startLLQHandshake errors; show state in uDNS_StopLongLivedQuery message
-
-Revision 1.475 2007/09/19 23:51:26 cheshire
-<rdar://problem/5480517> BTMM: Need to log a message when NAT port mapping fails
-
-Revision 1.474 2007/09/19 20:32:09 cheshire
-Export GetAuthInfoForName so it's callable from other files
-
-Revision 1.473 2007/09/18 21:42:29 cheshire
-To reduce programming mistakes, renamed ExtPort to RequestedPort
-
-Revision 1.472 2007/09/14 21:26:08 cheshire
-<rdar://problem/5482627> BTMM: Need to manually avoid port conflicts when using UPnP gateways
-
-Revision 1.471 2007/09/14 01:07:10 cheshire
-If UPnP NAT gateway returns 0.0.0.0 as external address (e.g. because it hasn't
-got a DHCP address yet) then retry periodically until it gives us a real address.
-
-Revision 1.470 2007/09/13 00:36:26 cheshire
-<rdar://problem/5477360> NAT Reboot detection logic incorrect
-
-Revision 1.469 2007/09/13 00:28:50 cheshire
-<rdar://problem/5477354> Host records not updated on NAT address change
-
-Revision 1.468 2007/09/13 00:16:41 cheshire
-<rdar://problem/5468706> Miscellaneous NAT Traversal improvements
-
-Revision 1.467 2007/09/12 23:03:08 cheshire
-<rdar://problem/5476978> DNSServiceNATPortMappingCreate callback not giving correct interface index
-
-Revision 1.466 2007/09/12 22:19:29 cheshire
-<rdar://problem/5476977> Need to listen for port 5350 NAT-PMP announcements
-
-Revision 1.465 2007/09/12 19:22:19 cheshire
-Variable renaming in preparation for upcoming fixes e.g. priv/pub renamed to intport/extport
-Made NAT Traversal packet handlers take typed data instead of anonymous "mDNSu8 *" byte pointers
-
-Revision 1.464 2007/09/12 01:22:13 cheshire
-Improve validatelists() checking to detect when 'next' pointer gets smashed to ~0
-
-Revision 1.463 2007/09/11 20:23:28 vazquez
-<rdar://problem/5466719> CrashTracer: 3 crashes in mDNSResponder at mDNSResponder: natTraversalHandlePortMapReply + 107
-Make sure we clean up NATTraversals before free'ing HostnameInfo
-
-Revision 1.462 2007/09/11 19:19:16 cheshire
-Correct capitalization of "uPNP" to "UPnP"
-
-Revision 1.461 2007/09/10 22:08:17 cheshire
-Rename uptime => upseconds and LastNATUptime => LastNATupseconds to make it clear these time values are in seconds
-
-Revision 1.460 2007/09/07 21:47:43 vazquez
-<rdar://problem/5460210> BTMM: SetupSocket 5351 failed; Can't allocate UDP multicast socket spew on wake from sleep with internet sharing on
-Try to allocate using port 5350 if we get a failure, and only log message if that fails too.
-
-Revision 1.459 2007/09/07 01:01:05 cheshire
-<rdar://problem/5464844> BTMM: Services being registered and deregistered in a loop
-In hndlServiceUpdateReply, need to clear SRVUpdateDeferred
-
-Revision 1.458 2007/09/06 19:14:33 cheshire
-Fixed minor error introduced in 1.379 (an "if" statement was deleted but the "else" following it was left there)
-
-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 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.
-
-Revision 1.456 2007/09/05 21:00:17 cheshire
-<rdar://problem/5457287> mDNSResponder taking up 100% CPU in ReissueBlockedQuestions
-Additional refinement: ThisQInterval needs to be restored in tcpCallback, not in PrivateQueryGotZoneData
-
-Revision 1.455 2007/09/05 20:53:06 cheshire
-Tidied up alignment of code layout; code was clearing m->tcpAddrInfo.sock instead of m->tcpDeviceInfo.sock
-
-Revision 1.454 2007/09/05 02:32:55 cheshire
-Fixed posix build error (mixed declarations and code)
-
-Revision 1.453 2007/09/05 02:26:57 cheshire
-<rdar://problem/5457287> mDNSResponder taking up 100% CPU in ReissueBlockedQuestions
-In PrivateQueryGotZoneData, restore q->ThisQInterval to non-zero value after GetZoneData completes
-
-Revision 1.452 2007/08/31 22:58:22 cheshire
-If we have an existing TCP connection we should re-use it instead of just bailing out
-After receiving dnsbugtest response, need to set m->NextScheduledQuery to cause queries to be re-issued
-
-Revision 1.451 2007/08/31 18:49:49 vazquez
-<rdar://problem/5393719> BTMM: Need to properly deregister when stopping BTMM
-
-Revision 1.450 2007/08/30 22:50:04 mcguire
-<rdar://problem/5430628> BTMM: Tunneled services are registered when autotunnel can't be setup
-
-Revision 1.449 2007/08/30 00:43:17 cheshire
-Need to clear m->rec.r.resrec.RecordType before returning from uDNS_recvLLQResponse
-
-Revision 1.448 2007/08/30 00:18:46 cheshire
-<rdar://problem/5448804> Error messages: "SendServiceRegistration: Already have TCP connection..."
-
-Revision 1.447 2007/08/29 01:18:33 cheshire
-<rdar://problem/5400181> BTMM: Tunneled services do not need NAT port mappings
-Only create NAT mappings for SRV records with AutoTarget set to Target_AutoHostAndNATMAP
-
-Revision 1.446 2007/08/28 23:58:42 cheshire
-Rename HostTarget -> AutoTarget
-
-Revision 1.445 2007/08/28 23:53:21 cheshire
-Rename serviceRegistrationCallback -> ServiceRegistrationZoneDataComplete
-
-Revision 1.444 2007/08/27 20:29:20 cheshire
-Additional debugging messages
-
-Revision 1.443 2007/08/24 23:18:28 cheshire
-mDNS_SetSecretForDomain is called with lock held; needs to use
-GetAuthInfoForName_internal() instead of external version GetAuthInfoForName()
-
-Revision 1.442 2007/08/24 22:43:06 cheshire
-Tidied up coded layout
-
-Revision 1.441 2007/08/24 01:20:55 cheshire
-<rdar://problem/5434381> BTMM: Memory corruption in KeychainChanged event handling
-
-Revision 1.440 2007/08/24 00:15:20 cheshire
-Renamed GetAuthInfoForName() to GetAuthInfoForName_internal() to make it clear that it may only be called with the lock held
-
-Revision 1.439 2007/08/23 21:47:09 vazquez
-<rdar://problem/5427316> BTMM: mDNSResponder sends NAT-PMP packets on public network
-make sure we clean up port mappings on base stations by sending a lease value of 0,
-and only send NAT-PMP packets on private networks; also save some memory by
-not using packet structs in NATTraversals.
-
-Revision 1.438 2007/08/22 17:50:08 vazquez
-<rdar://problem/5399276> Need to handle errors returned by NAT-PMP routers properly
-Propagate router errors to clients, and stop logging spurious "message too short" logs.
-
-Revision 1.437 2007/08/18 00:54:15 mcguire
-<rdar://problem/5413147> BTMM: Should not register private addresses or zeros
-
-Revision 1.436 2007/08/08 21:07:48 vazquez
-<rdar://problem/5244687> BTMM: Need to advertise model information via wide-area bonjour
-
-Revision 1.435 2007/08/03 02:04:09 vazquez
-<rdar://problem/5371843> BTMM: Private LLQs never fall back to polling
-Fix case where NAT-PMP returns an external address but does not support
-port mappings. Undo previous change and now, if the router returns an
-error in the reply packet we respect it.
-
-Revision 1.434 2007/08/02 21:03:05 vazquez
-Change NAT logic to fix case where base station with port mapping turned off
-returns an external address but does not make port mappings.
-
-Revision 1.433 2007/08/02 03:30:11 vazquez
-<rdar://problem/5371843> BTMM: Private LLQs never fall back to polling
-
-Revision 1.432 2007/08/01 18:15:19 cheshire
-Fixed crash in tcpCallback; fixed some problems with LLQ setup behind NAT
-
-Revision 1.431 2007/08/01 16:11:06 cheshire
-Fixed "mixed declarations and code" compiler error in Posix build
-
-Revision 1.430 2007/08/01 16:09:13 cheshire
-Removed unused NATTraversalInfo substructure from AuthRecord; reduced structure sizecheck values accordingly
-
-Revision 1.429 2007/08/01 03:09:22 cheshire
-<rdar://problem/5344587> BTMM: Create NAT port mapping for autotunnel port
-
-Revision 1.428 2007/08/01 01:43:36 cheshire
-Need to do mDNS_DropLockBeforeCallback/ReclaimLock around invokation of NAT client callback
-
-Revision 1.427 2007/08/01 01:31:13 cheshire
-Need to initialize traversal->tcpInfo fields or code may crash
-
-Revision 1.426 2007/08/01 01:15:57 cheshire
-<rdar://problem/5375791> Need to invoke NAT client callback when not on RFC1918 private network
-
-Revision 1.425 2007/08/01 00:04:14 cheshire
-<rdar://problem/5261696> Crash in tcpKQSocketCallback
-Half-open TCP connections were not being cancelled properly
-
-Revision 1.424 2007/07/31 02:28:35 vazquez
-<rdar://problem/3734269> NAT-PMP: Detect public IP address changes and base station reboot
-
-Revision 1.423 2007/07/30 23:31:26 cheshire
-Code for respecting TTL received in uDNS responses should exclude LLQ-type responses
-
-Revision 1.422 2007/07/28 01:25:57 cheshire
-<rdar://problem/4780038> BTMM: Add explicit UDP event port to LLQ setup request, to fix LLQs not working behind NAT
-
-Revision 1.421 2007/07/28 00:04:14 cheshire
-Various fixes for comments and debugging messages
-
-Revision 1.420 2007/07/27 23:59:18 cheshire
-Added compile-time structure size checks
-
-Revision 1.419 2007/07/27 20:52:29 cheshire
-Made uDNS_recvLLQResponse() return tri-state result: LLQ_Not, LLQ_First, or LLQ_Events
-
-Revision 1.418 2007/07/27 20:32:05 vazquez
-Flag a UPnP NAT traversal before starting a UPnP port mapping, and make sure all
-calls to mDNS_StopNATOperation() go through the UPnP code
-
-Revision 1.417 2007/07/27 20:19:42 cheshire
-Use MDNS_LOG_VERBOSE_DEBUG for dumping out packets instead of MDNS_LOG_DEBUG
-
-Revision 1.416 2007/07/27 19:59:28 cheshire
-MUST NOT touch m->CurrentQuestion (or q) after calling AnswerCurrentQuestionWithResourceRecord()
-
-Revision 1.415 2007/07/27 19:51:01 cheshire
-Use symbol QC_addnocache instead of literal constant "2"
-
-Revision 1.414 2007/07/27 19:30:39 cheshire
-Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
-to properly reflect tri-state nature of the possible responses
-
-Revision 1.413 2007/07/27 18:44:01 cheshire
-Rename "AnswerQuestionWithResourceRecord" to more informative "AnswerCurrentQuestionWithResourceRecord"
-
-Revision 1.412 2007/07/27 18:38:56 cheshire
-Rename "uDNS_CheckQuery" to more informative "uDNS_CheckCurrentQuestion"
-
-Revision 1.411 2007/07/27 00:57:13 cheshire
-Create hostname address records using standard kHostNameTTL (2 minutes) instead of 1 second
-
-Revision 1.410 2007/07/25 21:41:00 vazquez
-Make sure we clean up opened sockets when there are network transitions and when changing
-port mappings
-
-Revision 1.409 2007/07/25 03:05:02 vazquez
-Fixes for:
-<rdar://problem/5338913> LegacyNATTraversal: UPnP heap overflow
-<rdar://problem/5338933> LegacyNATTraversal: UPnP stack buffer overflow
-and a myriad of other security problems
-
-Revision 1.408 2007/07/24 21:47:51 cheshire
-Don't do mDNS_StopNATOperation() for operations we never started
-
-Revision 1.407 2007/07/24 17:23:33 cheshire
-<rdar://problem/5357133> Add list validation checks for debugging
-
-Revision 1.406 2007/07/24 04:14:30 cheshire
-<rdar://problem/5356281> LLQs not working in with NAT Traversal
-
-Revision 1.405 2007/07/24 01:29:03 cheshire
-<rdar://problem/5356026> DNSServiceNATPortMappingCreate() returns stale external address information
-
-Revision 1.404 2007/07/20 23:10:51 cheshire
-Fix code layout
-
-Revision 1.403 2007/07/20 20:12:37 cheshire
-Rename "mDNS_DomainTypeBrowseLegacy" as "mDNS_DomainTypeBrowseAutomatic"
-
-Revision 1.402 2007/07/20 00:54:20 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
-
-Revision 1.401 2007/07/18 03:23:33 cheshire
-In GetServiceTarget, need to call SetupLocalAutoTunnelInterface_internal to bring up tunnel on demand, if necessary
-
-Revision 1.400 2007/07/18 02:30:25 cheshire
-Defer AutoTunnel server record advertising until we have at least one service to advertise
-Do AutoTunnel target host selection in GetServiceTarget (instead of uDNS_RegisterService)
-
-Revision 1.399 2007/07/18 01:02:28 cheshire
-<rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
-Declare records as kDNSRecordTypeKnownUnique so we don't get name conflicts with ourselves
-
-Revision 1.398 2007/07/16 23:54:48 cheshire
-<rdar://problem/5338850> Crash when removing or changing DNS keys
-
-Revision 1.397 2007/07/16 20:13:31 vazquez
-<rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite
-
-Revision 1.396 2007/07/14 00:33:04 cheshire
-Remove temporary IPv4LL tunneling mode now that IPv6-over-IPv4 is working
-
-Revision 1.395 2007/07/12 23:56:23 cheshire
-Change "GetZoneData GOT SRV" message to debugf to reduce verbosity in syslog
-
-Revision 1.394 2007/07/12 23:36:08 cheshire
-Changed some 'LogOperation' calls to 'debugf' to reduce verbosity in syslog
-
-Revision 1.393 2007/07/12 22:15:10 cheshire
-Modified mDNS_SetSecretForDomain() so it can be called to update an existing entry
-
-Revision 1.392 2007/07/12 02:51:27 cheshire
-<rdar://problem/5303834> Automatically configure IPSec policy when resolving services
-
-Revision 1.391 2007/07/11 23:16:31 cheshire
-<rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
-Need to prepend _autotunnel._udp to start of AutoTunnel SRV record name
-
-Revision 1.390 2007/07/11 22:47:55 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for services
-In mDNS_SetSecretForDomain(), don't register records until after we've validated the parameters
-
-Revision 1.389 2007/07/11 21:33:10 cheshire
-<rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
-Set up and register AutoTunnelTarget and AutoTunnelService DNS records
-
-Revision 1.388 2007/07/11 19:27:10 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for services
-For temporary testing fake up an IPv4LL address instead of IPv6 ULA
-
-Revision 1.387 2007/07/11 03:04:08 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-Add AutoTunnel parameter to mDNS_SetSecretForDomain; Set up AutoTunnel information for domains that require it
-
-Revision 1.386 2007/07/10 01:57:28 cheshire
-<rdar://problem/5196524> uDNS: mDNSresponder is leaking TCP connections to DNS server
-Turned vast chunks of replicated code into a subroutine MakeTCPConn(...);
-Made routines hold on to the reference it returns instead of leaking it
-
-Revision 1.385 2007/07/09 23:50:18 cheshire
-unlinkSRS needs to call mDNS_StopNATOperation_internal(), not mDNS_StopNATOperation()
-
-Revision 1.384 2007/07/06 21:20:21 cheshire
-Fix scheduling error (was causing "Task Scheduling Error: Continuously busy for more than a second")
-
-Revision 1.383 2007/07/06 18:59:59 cheshire
-Avoid spinning in an infinite loop when uDNS_SendNATMsg() returns an error
-
-Revision 1.382 2007/07/04 00:49:43 vazquez
-Clean up extraneous comments
-
-Revision 1.381 2007/07/03 00:41:14 vazquez
- More changes for <rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes)
- Safely deal with packet replies and client callbacks
-
-Revision 1.380 2007/07/02 22:08:47 cheshire
-Fixed crash in "Received public IP address" message
-
-Revision 1.379 2007/06/29 00:08:49 vazquez
-<rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes)
-
-Revision 1.378 2007/06/27 20:25:10 cheshire
-Expanded dnsbugtest comment, explaining requirement that we also need these
-test queries to black-hole before they get to the root name servers.
-
-Revision 1.377 2007/06/22 21:27:21 cheshire
-Modified "could not convert shared secret from base64" log message
-
-Revision 1.376 2007/06/20 01:10:12 cheshire
-<rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
-
-Revision 1.375 2007/06/15 21:54:51 cheshire
-<rdar://problem/4883206> Add packet logging to help debugging private browsing over TLS
-
-Revision 1.374 2007/06/12 02:15:26 cheshire
-Fix incorrect "DNS Server passed" LogOperation message
-
-Revision 1.373 2007/05/31 00:25:43 cheshire
-<rdar://problem/5238688> Only send dnsbugtest query for questions where it's warranted
-
-Revision 1.372 2007/05/25 17:03:45 cheshire
-lenptr needs to be declared unsigned, otherwise sign extension can mess up the shifting and ORing operations
-
-Revision 1.371 2007/05/24 00:11:44 cheshire
-Remove unnecessary lenbuf field from tcpInfo_t
-
-Revision 1.370 2007/05/23 00:30:59 cheshire
-Don't change question->TargetQID when repeating query over TCP
-
-Revision 1.369 2007/05/21 18:04:40 cheshire
-Updated comments -- port_mapping_create_reply renamed to port_mapping_reply
-
-Revision 1.368 2007/05/17 19:12:16 cheshire
-Updated comment about finding matching pair of sockets
-
-Revision 1.367 2007/05/15 23:38:00 cheshire
-Need to grab lock before calling SendRecordRegistration();
-
-Revision 1.366 2007/05/15 00:43:05 cheshire
-<rdar://problem/4983538> uDNS serviceRegistrationCallback locking failures
-
-Revision 1.365 2007/05/10 21:19:18 cheshire
-Rate-limit DNS test queries to at most one per three seconds
-(useful when we have a dozen active WAB queries, and then we join a new network)
-
-Revision 1.364 2007/05/07 20:43:45 cheshire
-<rdar://problem/4241419> Reduce the number of queries and announcements
-
-Revision 1.363 2007/05/04 22:12:48 cheshire
-Work towards solving <rdar://problem/5176892> "uDNS_CheckQuery: LastQTime" log messages
-When code gets in this invalid state, double ThisQInterval each time, to avoid excessive logging
-
-Revision 1.362 2007/05/04 21:23:05 cheshire
-<rdar://problem/5167263> Private DNS always returns no answers in the initial LLQ setup response
-Preparatory work to enable us to do a four-way LLQ handshake over TCP, if we decide that's what we want
-
-Revision 1.361 2007/05/03 23:50:48 cheshire
-<rdar://problem/4669229> mDNSResponder ignores bogus null target in SRV record
-In the case of negative answers for the address record, set the server address to zerov4Addr
-
-Revision 1.360 2007/05/03 22:40:38 cheshire
-<rdar://problem/4669229> mDNSResponder ignores bogus null target in SRV record
-
-Revision 1.359 2007/05/02 22:21:33 cheshire
-<rdar://problem/5167331> RegisterRecord and RegisterService need to cancel StartGetZoneData
-
-Revision 1.358 2007/05/01 21:46:31 cheshire
-Move GetLLQOptData/GetPktLease from uDNS.c into DNSCommon.c so that dnsextd can use them
-
-Revision 1.357 2007/05/01 01:33:49 cheshire
-Removed "#define LLQ_Info DNSQuestion" and manually reconciled code that was still referring to "LLQ_Info"
-
-Revision 1.356 2007/04/30 21:51:06 cheshire
-Updated comments
-
-Revision 1.355 2007/04/30 21:33:38 cheshire
-Fix crash when a callback unregisters a service while the UpdateSRVRecords() loop
-is iterating through the m->ServiceRegistrations list
-
-Revision 1.354 2007/04/30 01:30:04 cheshire
-GetZoneData_QuestionCallback needs to call client callback function on error, so client knows operation is finished
-RecordRegistrationCallback and serviceRegistrationCallback need to clear nta reference when they're invoked
-
-Revision 1.353 2007/04/28 01:28:25 cheshire
-Fixed memory leak on error path in FoundDomain
-
-Revision 1.352 2007/04/27 19:49:53 cheshire
-In uDNS_ReceiveTestQuestionResponse, also check that srcport matches
-
-Revision 1.351 2007/04/27 19:28:02 cheshire
-Any code that calls StartGetZoneData needs to keep a handle to the structure, so
-it can cancel it if necessary. (First noticed as a crash in Apple Remote Desktop
--- it would start a query and then quickly cancel it, and then when
-StartGetZoneData completed, it had a dangling pointer and crashed.)
-
-Revision 1.350 2007/04/26 22:47:14 cheshire
-Defensive coding: tcpCallback only needs to check "if (closed)", not "if (!n && closed)"
-
-Revision 1.349 2007/04/26 16:04:06 cheshire
-In mDNS_AddDNSServer, check whether port matches
-In uDNS_CheckQuery, handle case where startLLQHandshake changes q->llq->state to LLQ_Poll
-
-Revision 1.348 2007/04/26 04:01:59 cheshire
-Copy-and-paste error: Test should be "if (result == DNSServer_Passed)" not "if (result == DNSServer_Failed)"
-
-Revision 1.347 2007/04/26 00:35:15 cheshire
-<rdar://problem/5140339> uDNS: Domain discovery not working over VPN
-Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server
-inside the firewall may give answers where a public one gives none, and vice versa.)
-
-Revision 1.346 2007/04/25 19:16:59 cheshire
-Don't set SuppressStdPort53Queries unless we do actually send a DNS packet
-
-Revision 1.345 2007/04/25 18:05:11 cheshire
-Don't try to restart inactive (duplicate) queries
-
-Revision 1.344 2007/04/25 17:54:07 cheshire
-Don't cancel Private LLQs using a clear-text UDP packet
-
-Revision 1.343 2007/04/25 16:40:08 cheshire
-Add comment explaining uDNS_recvLLQResponse logic
-
-Revision 1.342 2007/04/25 02:14:38 cheshire
-<rdar://problem/4246187> uDNS: Identical client queries should reference a single shared core query
-Additional fixes to make LLQs work properly
-
-Revision 1.341 2007/04/24 02:07:42 cheshire
-<rdar://problem/4246187> Identical client queries should reference a single shared core query
-Deleted some more redundant code
-
-Revision 1.340 2007/04/23 22:01:23 cheshire
-<rdar://problem/5094009> IPv6 filtering in AirPort base station breaks Wide-Area Bonjour
-As of March 2007, AirPort base stations now block incoming IPv6 connections by default, so there's no point
-advertising IPv6 addresses in DNS any more -- we have to assume that most of the time a host's IPv6 address
-probably won't work for incoming connections (but its IPv4 address probably will, using NAT-PMP).
-
-Revision 1.339 2007/04/22 06:02:03 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.338 2007/04/21 19:44:11 cheshire
-Improve uDNS_HandleNATPortMapReply log message
-
-Revision 1.337 2007/04/21 02:03:00 cheshire
-Also need to set AddressRec->resrec.RecordType in the NAT case too
-
-Revision 1.336 2007/04/20 21:16:12 cheshire
-Fixed bogus double-registration of host name -- was causing these warning messages in syslog:
-Error! Tried to register AuthRecord 0181FB0C host.example.com. (Addr) that's already in the list
-
-Revision 1.335 2007/04/19 23:57:20 cheshire
-Temporary workaround for some AirPort base stations that don't seem to like us requesting public port zero
-
-Revision 1.334 2007/04/19 23:21:51 cheshire
-Fixed a couple of places where the StartGetZoneData check was backwards
-
-Revision 1.333 2007/04/19 22:50:53 cheshire
-<rdar://problem/4246187> Identical client queries should reference a single shared core query
-
-Revision 1.332 2007/04/19 20:34:32 cheshire
-Add debugging log message in uDNS_CheckQuery()
-
-Revision 1.331 2007/04/19 20:06:41 cheshire
-Rename field 'Private' (sounds like a boolean) to more informative 'AuthInfo' (it's a DomainAuthInfo pointer)
-
-Revision 1.330 2007/04/19 19:51:54 cheshire
-Get rid of unnecessary initializeQuery() routine
-
-Revision 1.329 2007/04/19 18:03:52 cheshire
-Improved "mDNS_AddSearchDomain" log message
-
-Revision 1.328 2007/04/18 20:57:20 cheshire
-Commented out "GetAuthInfoForName none found" debugging message
-
-Revision 1.327 2007/04/17 19:21:29 cheshire
-<rdar://problem/5140339> Domain discovery not working over VPN
-
-Revision 1.326 2007/04/16 20:49:39 cheshire
-Fix compile errors for mDNSPosix build
-
-Revision 1.325 2007/04/05 22:55:35 cheshire
-<rdar://problem/5077076> Records are ending up in Lighthouse without expiry information
-
-Revision 1.324 2007/04/05 20:43:30 cheshire
-Collapse sprawling code onto one line -- this is part of a bigger block of identical
-code that has been copied-and-pasted into six different places in the same file.
-This really needs to be turned into a subroutine.
-
-Revision 1.323 2007/04/04 21:48:52 cheshire
-<rdar://problem/4720694> Combine unicast authoritative answer list with multicast list
-
-Revision 1.322 2007/04/03 19:53:06 cheshire
-Use mDNSSameIPPort (and similar) instead of accessing internal fields directly
-
-Revision 1.321 2007/04/02 23:44:09 cheshire
-Minor code tidying
-
-Revision 1.320 2007/03/31 01:26:13 cheshire
-Take out GetAuthInfoForName syslog message
-
-Revision 1.319 2007/03/31 01:10:53 cheshire
-Add debugging
-
-Revision 1.318 2007/03/31 00:17:11 cheshire
-Remove some LogMsgs
-
-Revision 1.317 2007/03/29 00:09:31 cheshire
-Improve "uDNS_InitLongLivedQuery" log message
-
-Revision 1.316 2007/03/28 21:16:27 cheshire
-Remove DumpPacket() call now that OPT pseudo-RR rrclass bug is fixed
-
-Revision 1.315 2007/03/28 21:02:18 cheshire
-<rdar://problem/3810563> Wide-Area Bonjour should work on multi-subnet private network
-
-Revision 1.314 2007/03/28 15:56:37 cheshire
-<rdar://problem/5085774> Add listing of NAT port mapping and GetAddrInfo requests in SIGINFO output
-
-Revision 1.313 2007/03/28 01:27:32 cheshire
-<rdar://problem/4996439> Unicast DNS polling server every three seconds
-StartLLQPolling was using INIT_UCAST_POLL_INTERVAL instead of LLQ_POLL_INTERVAL for the retry interval
-
-Revision 1.312 2007/03/27 23:48:21 cheshire
-Use mDNS_StopGetDomains(), not mDNS_StopQuery()
-
-Revision 1.311 2007/03/27 22:47:51 cheshire
-Remove unnecessary "*(long*)0 = 0;" to generate crash and stack trace
-
-Revision 1.310 2007/03/24 01:24:13 cheshire
-Add validator for uDNS data structures; fixed crash in RegisterSearchDomains()
-
-Revision 1.309 2007/03/24 00:47:53 cheshire
-<rdar://problem/4983538> serviceRegistrationCallback: Locking Failure! mDNS_busy (1) != mDNS_reentrancy (2)
-Locking in this file is all messed up. For now we'll just work around the issue.
-
-Revision 1.308 2007/03/24 00:41:33 cheshire
-Minor code cleanup (move variable declarations to minimum enclosing scope)
-
-Revision 1.307 2007/03/21 23:06:00 cheshire
-Rename uDNS_HostnameInfo to HostnameInfo; deleted some unused fields
-
-Revision 1.306 2007/03/21 00:30:03 cheshire
-<rdar://problem/4789455> Multiple errors in DNameList-related code
-
-Revision 1.305 2007/03/20 17:07:15 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.304 2007/03/17 00:02:11 cheshire
-<rdar://problem/5067013> NAT-PMP: Lease TTL is being ignored
-
-Revision 1.303 2007/03/10 03:26:44 cheshire
-<rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache
-
-Revision 1.302 2007/03/10 02:29:58 cheshire
-Added comments about NAT-PMP response functions
-
-Revision 1.301 2007/03/10 02:02:58 cheshire
-<rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache
-Eliminate unnecessary "InternalResponseHndlr responseCallback" function pointer
-
-Revision 1.300 2007/03/08 18:56:00 cheshire
-Fixed typo: "&v4.ip.v4.b[0]" is always non-zero (ampersand should not be there)
-
-Revision 1.299 2007/02/28 01:45:47 cheshire
-<rdar://problem/4683261> NAT-PMP: Port mapping refreshes should contain actual public port
-<rdar://problem/5027863> Byte order bugs in uDNS.c, uds_daemon.c, dnssd_clientstub.c
-
-Revision 1.298 2007/02/14 03:16:39 cheshire
-<rdar://problem/4789477> Eliminate unnecessary malloc/free in mDNSCore code
-
-Revision 1.297 2007/02/08 21:12:28 cheshire
-<rdar://problem/4386497> Stop reading /etc/mDNSResponder.conf on every sleep/wake
-
-Revision 1.296 2007/01/29 16:03:22 cheshire
-Fix unused parameter warning
-
-Revision 1.295 2007/01/27 03:34:27 cheshire
-Made GetZoneData use standard queries (and cached results);
-eliminated GetZoneData_Callback() packet response handler
-
-Revision 1.294 2007/01/25 00:40:16 cheshire
-Unified CNAME-following functionality into cache management code (which means CNAME-following
-should now also work for mDNS queries too); deleted defunct pktResponseHndlr() routine.
-
-Revision 1.293 2007/01/23 02:56:11 cheshire
-Store negative results in the cache, instead of generating them out of pktResponseHndlr()
-
-Revision 1.292 2007/01/20 01:32:40 cheshire
-Update comments and debugging messages
-
-Revision 1.291 2007/01/20 00:07:02 cheshire
-When we have credentials in the keychain for a domain, we attempt private queries, but
-if the authoritative server is not set up for private queries (i.e. no _dns-query-tls
-or _dns-llq-tls record) then we need to fall back to conventional non-private queries.
-
-Revision 1.290 2007/01/19 23:41:45 cheshire
-Need to clear m->rec.r.resrec.RecordType after calling GetLLQOptData()
-
-Revision 1.289 2007/01/19 23:32:07 cheshire
-Eliminate pointless timenow variable
-
-Revision 1.288 2007/01/19 23:26:08 cheshire
-Right now tcpCallback does not run holding the lock, so no need to drop the lock before invoking callbacks
-
-Revision 1.287 2007/01/19 22:55:41 cheshire
-Eliminate redundant identical parameters to GetZoneData_StartQuery()
-
-Revision 1.286 2007/01/19 21:17:33 cheshire
-StartLLQPolling needs to call SetNextQueryTime() to cause query to be done in a timely fashion
-
-Revision 1.285 2007/01/19 18:39:11 cheshire
-Fix a bunch of parameters that should have been declared "const"
-
-Revision 1.284 2007/01/19 18:28:28 cheshire
-Improved debugging messages
-
-Revision 1.283 2007/01/19 18:09:33 cheshire
-Fixed getLLQAtIndex (now called GetLLQOptData):
-1. It incorrectly assumed all EDNS0 OPT records are the same size (it ignored optlen)
-2. It used inefficient memory copying instead of just returning a pointer
-
-Revision 1.282 2007/01/17 22:06:01 cheshire
-Replace duplicated literal constant "{ { 0 } }" with symbol "zeroIPPort"
-
-Revision 1.281 2007/01/17 21:58:13 cheshire
-For clarity, rename ntaContext field "isPrivate" to "ntaPrivate"
-
-Revision 1.280 2007/01/17 21:46:02 cheshire
-Remove redundant duplicated "isPrivate" field from LLQ_Info
-
-Revision 1.279 2007/01/17 21:35:31 cheshire
-For clarity, rename zoneData_t field "isPrivate" to "zonePrivate"
-
-Revision 1.278 2007/01/16 03:04:16 cheshire
-<rdar://problem/4917539> Add support for one-shot private queries as well as long-lived private queries
-Don't cache result of ntaContextSRV(context) in a local variable --
-the macro evaluates to a different result after we clear "context->isPrivate"
-
-Revision 1.277 2007/01/10 22:51:58 cheshire
-<rdar://problem/4917539> Add support for one-shot private queries as well as long-lived private queries
-
-Revision 1.276 2007/01/10 02:09:30 cheshire
-Better LogOperation record of keys read from System Keychain
-
-Revision 1.275 2007/01/09 22:37:18 cheshire
-Provide ten-second grace period for deleted keys, to give mDNSResponder
-time to delete host name before it gives up access to the required key.
-
-Revision 1.274 2007/01/09 01:16:32 cheshire
-Improve "ERROR m->CurrentQuestion already set" debugging messages
-
-Revision 1.273 2007/01/08 23:58:00 cheshire
-Don't request regDomain and browseDomains in uDNS_SetupDNSConfig() -- it just ignores those results
-
-Revision 1.272 2007/01/05 08:30:42 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.271 2007/01/05 06:34:03 cheshire
-Improve "ERROR m->CurrentQuestion already set" debugging messages
-
-Revision 1.270 2007/01/05 05:44:33 cheshire
-Move automatic browse/registration management from uDNS.c to mDNSShared/uds_daemon.c,
-so that mDNSPosix embedded clients will compile again
-
-Revision 1.269 2007/01/04 23:11:13 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-When an automatic browsing domain is removed, generate appropriate "remove" events for legacy queries
-
-Revision 1.268 2007/01/04 22:06:38 cheshire
-Fixed crash in LLQNatMapComplete()
-
-Revision 1.267 2007/01/04 21:45:20 cheshire
-Added mDNS_DropLockBeforeCallback/mDNS_ReclaimLockAfterCallback macros,
-to do additional lock sanity checking around callback invocations
-
-Revision 1.266 2007/01/04 21:01:20 cheshire
-<rdar://problem/4607042> mDNSResponder NXDOMAIN and CNAME support
-Only return NXDOMAIN results to clients that request them using kDNSServiceFlagsReturnIntermediates
-
-Revision 1.265 2007/01/04 20:47:17 cheshire
-Fixed crash in CheckForUnreferencedLLQMapping()
-
-Revision 1.264 2007/01/04 20:39:27 cheshire
-Fix locking mismatch
-
-Revision 1.263 2007/01/04 02:39:53 cheshire
-<rdar://problem/4030599> Hostname passed into DNSServiceRegister ignored for Wide-Area service registrations
-
-Revision 1.262 2007/01/04 00:29:25 cheshire
-Covert LogMsg() in GetAuthInfoForName to LogOperation()
-
-Revision 1.261 2006/12/22 20:59:49 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.260 2006/12/21 00:06:07 cheshire
-Don't need to do mDNSPlatformMemZero() -- mDNS_SetupResourceRecord() does it for us
-
-Revision 1.259 2006/12/20 04:07:36 cheshire
-Remove uDNS_info substructure from AuthRecord_struct
-
-Revision 1.258 2006/12/19 22:49:24 cheshire
-Remove uDNS_info substructure from ServiceRecordSet_struct
-
-Revision 1.257 2006/12/19 02:38:20 cheshire
-Get rid of unnecessary duplicate query ID field from DNSQuestion_struct
-
-Revision 1.256 2006/12/19 02:18:48 cheshire
-Get rid of unnecessary duplicate "void *context" field from DNSQuestion_struct
-
-Revision 1.255 2006/12/16 01:58:31 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-
-Revision 1.254 2006/12/15 19:23:39 cheshire
-Use new DomainNameLengthLimit() function, to be more defensive against malformed
-data received from the network.
-
-Revision 1.253 2006/12/01 07:43:34 herscher
-Fix byte ordering problem for one-shot TCP queries.
-Iterate more intelligently over duplicates in uDNS_ReceiveMsg to avoid spin loops.
-
-Revision 1.252 2006/11/30 23:07:57 herscher
-<rdar://problem/4765644> uDNS: Sync up with Lighthouse changes for Private DNS
-
-Revision 1.251 2006/11/28 21:42:11 mkrochma
-Work around a crashing bug that was introduced by uDNS and mDNS code unification
-
-Revision 1.250 2006/11/18 05:01:30 cheshire
-Preliminary support for unifying the uDNS and mDNS code,
-including caching of uDNS answers
-
-Revision 1.249 2006/11/10 07:44:04 herscher
-<rdar://problem/4825493> Fix Daemon locking failures while toggling BTMM
-
-Revision 1.248 2006/11/08 04:26:53 cheshire
-Fix typo in debugging message
-
-Revision 1.247 2006/10/20 05:35:04 herscher
-<rdar://problem/4720713> uDNS: Merge unicast active question list with multicast list.
-
-Revision 1.246 2006/10/11 19:29:41 herscher
-<rdar://problem/4744553> uDNS: mDNSResponder-111 using 100% CPU
-
-Revision 1.245 2006/10/04 22:21:15 herscher
-Tidy up references to mDNS_struct introduced when the embedded uDNS_info struct was removed.
-
-Revision 1.244 2006/10/04 21:51:27 herscher
-Replace calls to mDNSPlatformTimeNow(m) with m->timenow
-
-Revision 1.243 2006/10/04 21:38:59 herscher
-Remove uDNS_info substructure from DNSQuestion_struct
-
-Revision 1.242 2006/09/27 00:51:46 herscher
-Fix compile error when _LEGACY_NAT_TRAVERSAL_ is not defined
-
-Revision 1.241 2006/09/26 01:54:47 herscher
-<rdar://problem/4245016> NAT Port Mapping API (for both NAT-PMP and UPnP Gateway Protocol)
-
-Revision 1.240 2006/09/15 21:20:15 cheshire
-Remove uDNS_info substructure from mDNS_struct
-
-Revision 1.239 2006/08/16 02:52:56 mkrochma
-<rdar://problem/4104154> Actually fix it this time
-
-Revision 1.238 2006/08/16 00:31:50 mkrochma
-<rdar://problem/4386944> Get rid of NotAnInteger references
-
-Revision 1.237 2006/08/15 23:38:17 mkrochma
-<rdar://problem/4104154> Requested Public Port field should be set to zero on mapping deletion
-
-Revision 1.236 2006/08/14 23:24:23 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.235 2006/07/30 05:45:36 cheshire
-<rdar://problem/4304215> Eliminate MIN_UCAST_PERIODIC_EXEC
-
-Revision 1.234 2006/07/22 02:58:36 cheshire
-Code was clearing namehash twice instead of namehash and rdatahash
-
-Revision 1.233 2006/07/20 19:46:51 mkrochma
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Fix Private DNS
-
-Revision 1.232 2006/07/15 02:01:29 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Fix broken "empty string" browsing
-
-Revision 1.231 2006/07/05 23:28:22 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-
-Revision 1.230 2006/06/29 03:02:44 cheshire
-<rdar://problem/4607042> mDNSResponder NXDOMAIN and CNAME support
-
-Revision 1.229 2006/03/02 22:03:41 cheshire
-<rdar://problem/4395331> Spurious warning "GetLargeResourceRecord: m->rec appears to be already in use"
-Refinement: m->rec.r.resrec.RecordType needs to be cleared *every* time around for loop, not just once at the end
-
-Revision 1.228 2006/02/26 00:54:42 cheshire
-Fixes to avoid code generation warning/error on FreeBSD 7
-
-Revision 1.227 2006/01/09 20:47:05 cheshire
-<rdar://problem/4395331> Spurious warning "GetLargeResourceRecord: m->rec appears to be already in use"
-
-*/
+ */
#include "uDNS.h"
// default registration) and possibly one or more recommended automatic browsing domains.
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
-// -- it should just be a grouping of records that are treated the same as any other registered records.
-// In that case it may no longer be necessary to keep an explicit list of ServiceRecordSets, which in turn
-// would avoid the perils of modifying that list cleanly while some other piece of code is iterating through it.
-ServiceRecordSet *CurrentServiceRecordSet = mDNSNULL;
-
// The value can be set to true by the Platform code e.g., MacOSX uses the plist mechanism
mDNSBool StrictUnicastOrdering = mDNSfalse;
+// We keep track of the number of unicast DNS servers and log a message when we exceed 64.
+// Currently the unicast queries maintain a 64 bit map to track the valid DNS servers for that
+// question. Bit position is the index into the DNS server list. This is done so to try all
+// the servers exactly once before giving up. If we could allocate memory in the core, then
+// arbitrary limitation of 64 DNSServers can be removed.
+mDNSu8 NumUnicastDNSServers = 0;
+#define MAX_UNICAST_DNS_SERVERS 64
+
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark - General Utility Functions
#endif
-// Unlink an AuthRecord from the m->ResourceRecords list.
-// This seems risky. Probably some (or maybe all) of the places calling UnlinkAuthRecord to directly
-// remove a record from the list should actually be using mDNS_Deregister/mDNS_Deregister_internal.
-mDNSlocal mStatus UnlinkAuthRecord(mDNS *const m, AuthRecord *const rr)
- {
- AuthRecord **list = &m->ResourceRecords;
- if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next;
- if (m->CurrentRecord == rr) m->CurrentRecord = rr->next;
- while (*list && *list != rr) list = &(*list)->next;
- if (!*list)
- {
- list = &m->DuplicateRecords;
- while (*list && *list != rr) list = &(*list)->next;
- }
- if (*list) { *list = rr->next; rr->next = mDNSNULL; return(mStatus_NoError); }
- LogMsg("ERROR: UnlinkAuthRecord - no such active record %##s", rr->resrec.name->c);
- return(mStatus_NoSuchRecord);
- }
-
-// unlinkSRS is an internal routine (i.e. must be called with the lock already held)
-mDNSlocal void unlinkSRS(mDNS *const m, ServiceRecordSet *srs)
- {
- ServiceRecordSet **p;
-
- if (srs->NATinfo.clientContext)
- {
- mDNS_StopNATOperation_internal(m, &srs->NATinfo);
- srs->NATinfo.clientContext = mDNSNULL;
- }
-
- for (p = &m->ServiceRegistrations; *p; p = &(*p)->uDNS_next)
- if (*p == srs)
- {
- ExtraResourceRecord *e;
- *p = srs->uDNS_next;
- if (CurrentServiceRecordSet == srs)
- CurrentServiceRecordSet = srs->uDNS_next;
- srs->uDNS_next = mDNSNULL;
- for (e=srs->Extras; e; e=e->next)
- if (UnlinkAuthRecord(m, &e->r))
- LogMsg("unlinkSRS: extra record %##s not found", e->r.resrec.name->c);
- return;
- }
- LogMsg("ERROR: unlinkSRS - SRS not found in ServiceRegistrations list %##s", srs->RR_SRV.resrec.name->c);
- }
-
// set retry timestamp for record with exponential backoff
-// (for service record sets, use RR_SRV as representative for time checks
-mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mStatus SendErr)
+mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mDNSu32 random)
{
- mDNSs32 elapsed = m->timenow - rr->LastAPTime;
rr->LastAPTime = m->timenow;
-#if 0
- // Code for stress-testing registration renewal code
- if (rr->expire && rr->expire - m->timenow > mDNSPlatformOneSecond * 120)
- {
- LogInfo("Adjusting expiry from %d to 120 seconds for %s",
- (rr->expire - m->timenow) / mDNSPlatformOneSecond, ARDisplayString(m, rr));
- rr->expire = m->timenow + mDNSPlatformOneSecond * 120;
- }
-#endif
-
- if (rr->expire && rr->expire - m->timenow > mDNSPlatformOneSecond)
+ if (rr->expire && rr->refreshCount < MAX_UPDATE_REFRESH_COUNT)
{
mDNSs32 remaining = rr->expire - m->timenow;
- rr->ThisAPInterval = remaining/2 + mDNSRandom(remaining/10);
- debugf("SetRecordRetry refresh in %4d of %4d for %s",
- rr->ThisAPInterval / mDNSPlatformOneSecond, (rr->expire - m->timenow) / mDNSPlatformOneSecond, ARDisplayString(m, rr));
+ rr->refreshCount++;
+ if (remaining > MIN_UPDATE_REFRESH_TIME)
+ {
+ // Refresh at 70% + random (currently it is 0 to 10%)
+ rr->ThisAPInterval = 7 * (remaining/10) + (random ? random : mDNSRandom(remaining/10));
+ // Don't update more often than 5 minutes
+ if (rr->ThisAPInterval < MIN_UPDATE_REFRESH_TIME)
+ rr->ThisAPInterval = MIN_UPDATE_REFRESH_TIME;
+ LogInfo("SetRecordRetry refresh in %d of %d for %s",
+ rr->ThisAPInterval/mDNSPlatformOneSecond, (rr->expire - m->timenow)/mDNSPlatformOneSecond, ARDisplayString(m, rr));
+ }
+ else
+ {
+ rr->ThisAPInterval = MIN_UPDATE_REFRESH_TIME;
+ LogInfo("SetRecordRetry clamping to min refresh in %d of %d for %s",
+ rr->ThisAPInterval/mDNSPlatformOneSecond, (rr->expire - m->timenow)/mDNSPlatformOneSecond, ARDisplayString(m, rr));
+ }
return;
}
rr->expire = 0;
- // If at least half our our time interval has elapsed, it's time to double rr->ThisAPInterval
- // If resulting interval is too small, set to at least INIT_UCAST_POLL_INTERVAL (3 seconds)
- // If resulting interval is too large, set to at most 30 minutes
- if (rr->ThisAPInterval / 2 <= elapsed) rr->ThisAPInterval *= 2;
- if (rr->ThisAPInterval < INIT_UCAST_POLL_INTERVAL || SendErr == mStatus_TransientErr)
- rr->ThisAPInterval = INIT_UCAST_POLL_INTERVAL;
- rr->ThisAPInterval += mDNSRandom(rr->ThisAPInterval/20);
- if (rr->ThisAPInterval > 30 * 60 * mDNSPlatformOneSecond)
- rr->ThisAPInterval = 30 * 60 * mDNSPlatformOneSecond;
-
- LogInfo("SetRecordRetry retry in %4d for %s", rr->ThisAPInterval / mDNSPlatformOneSecond, ARDisplayString(m, rr));
+ rr->ThisAPInterval = rr->ThisAPInterval * QuestionIntervalStep; // Same Retry logic as Unicast Queries
+ if (rr->ThisAPInterval < INIT_RECORD_REG_INTERVAL)
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ if (rr->ThisAPInterval > MAX_RECORD_REG_INTERVAL)
+ rr->ThisAPInterval = MAX_RECORD_REG_INTERVAL;
+
+ LogInfo("SetRecordRetry retry in %d ms for %s", rr->ThisAPInterval, ARDisplayString(m, rr));
}
// ***************************************************************************
#pragma mark - Name Server List Management
#endif
-mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port)
+mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped)
{
DNSServer **p = &m->DNSServers;
DNSServer *tmp = mDNSNULL;
+ if ((NumUnicastDNSServers + 1) > MAX_UNICAST_DNS_SERVERS)
+ {
+ LogMsg("mDNS_AddDNSServer: DNS server limit of %d reached, not adding this server", MAX_UNICAST_DNS_SERVERS);
+ return mDNSNULL;
+ }
+
if (!d) d = (const domainname *)"";
- LogInfo("mDNS_AddDNSServer: Adding %#a for %##s", addr, d->c);
+ LogInfo("mDNS_AddDNSServer: Adding %#a for %##s, InterfaceID %p, scoped %d", addr, d->c, interface, scoped);
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 {interface,address,port,domain} tuple registered
{
- if ((*p)->interface == interface && (*p)->teststate != DNSServer_Disabled &&
+ if ((*p)->scoped == scoped && (*p)->interface == interface && (*p)->teststate != DNSServer_Disabled &&
mDNSSameAddress(&(*p)->addr, addr) && mDNSSameIPPort((*p)->port, port) && SameDomainName(&(*p)->domain, d))
{
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);
if (!*p) LogMsg("Error: mDNS_AddDNSServer - malloc");
else
{
+ NumUnicastDNSServers++;
+ (*p)->scoped = scoped;
(*p)->interface = interface;
(*p)->addr = *addr;
(*p)->port = port;
// PenalizeDNSServer is called when the number of queries to the unicast
// DNS server exceeds MAX_UCAST_UNANSWERED_QUERIES or when we receive an
-// error e.g., SERV_FAIL from DNS server. QueryFail is TRUE if this function
-// is called when we exceed MAX_UCAST_UNANSWERED_QUERIES
-
-mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSBool QueryFail)
+// error e.g., SERV_FAIL from DNS server.
+mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q)
{
+ DNSServer *new;
DNSServer *orig = q->qDNSServer;
if (m->mDNS_busy != m->mDNS_reentrancy+1)
LogMsg("PenalizeDNSServer: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
+ // This should never happen. Whenever we change DNS server, we change the ID on the question and hence
+ // we should never accept a response after we penalize a DNS server e.g., send two queries, no response,
+ // penalize DNS server and no new servers to pick for the question and hence qDNSServer is NULL. If we
+ // receive a response now, the DNS server can be NULL. But we won't because the ID already has been
+ // changed.
if (!q->qDNSServer)
{
- LogMsg("PenalizeDNSServer: Null DNS server for %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), q->unansweredQueries);
+ LogMsg("PenalizeDNSServer: ERROR!! Null DNS server for %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), q->unansweredQueries);
goto end;
}
- if (QueryFail)
- {
- LogInfo("PenalizeDNSServer: DNS server %#a:%d (%##s) %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));
- }
- else
- {
- LogInfo("PenalizeDNSServer: DNS server %#a:%d (%##s) Server Error for %##s (%s)",
- &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c, q->qname.c, DNSTypeName(q->qtype));
- }
-
+ LogInfo("PenalizeDNSServer: Penalizing DNS server %#a:%d question (%##s) for question %p %##s (%s) SuppressUnusable %d",
+ &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c, q, q->qname.c, DNSTypeName(q->qtype),
+ q->SuppressUnusable);
// If strict ordering of unicast servers needs to be preserved, we just lookup
// the next best match server below
}
end:
- q->qDNSServer = GetServerForName(m, &q->qname, q->qDNSServer);
+ new = GetServerForQuestion(m, q);
- if ((q->qDNSServer != orig) && (QueryFail))
+
+ if (new == orig)
{
- // We picked a new server. In the case where QueryFail is true, the code has already incremented the interval
- // and to compensate that we decrease it here. When two queries are sent, the QuestionIntervalStep is at 9. We just
- // move it back to 3 here when we pick a new server. We can't start at 1 because if we have two servers failing, we will never
- // backoff
- //
- q->ThisQInterval = q->ThisQInterval / QuestionIntervalStep;
- if (q->qDNSServer) LogInfo("PenalizeDNSServer: Server for %##s (%s) changed to %#a:%d (%##s), Question Interval %u", q->qname.c, DNSTypeName(q->qtype), &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c, q->ThisQInterval);
- else LogInfo("PenalizeDNSServer: Server for %##s (%s) changed to <null>, Question Interval %u", q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval);
-
+ if (new)
+ LogMsg("PenalizeDNSServer: ERROR!! GetServerForQuestion returned the same server %#a:%d", &new->addr,
+ mDNSVal16(new->port));
+ else
+ LogMsg("PenalizeDNSServer: ERROR!! GetServerForQuestion returned the same server NULL");
+ q->ThisQInterval = 0; // Inactivate this question so that we dont bombard the network
}
- else
+ else
{
- // if we are here it means,
- //
- // 1) We picked the same server, QueryFail = false
- // 2) We picked the same server, QueryFail = true
- // 3) We picked a different server, QueryFail = false
- //
- // For all these three cases, ThisQInterval is already set properly
+ // The new DNSServer is set in DNSServerChangeForQuestion
+ DNSServerChangeForQuestion(m, q, new);
- if (q->qDNSServer)
+ if (new)
{
- if (q->qDNSServer != orig)
- {
- LogInfo("PenalizeDNSServer: 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("PenalizeDNSServer: 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);
+ // We want to try the next server immediately. As the question may already have backed off, reset
+ // the interval. We do this only the first time when we try all the DNS servers. Once we reached the end of
+ // list and retrying all the servers again e.g., at least one server failed to respond in the previous try, we
+ // use the normal backoff which is done in uDNS_CheckCurrentQuestion when we send the packet out.
+ if (!q->triedAllServersOnce)
{
- LogInfo("PenalizeDNSServer: Server for %##s (%s) remains the same at %#a:%d (%##s)", q->qname.c, DNSTypeName(q->qtype), &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c);
+ q->ThisQInterval = InitialQuestionInterval;
+ q->LastQTime = m->timenow - q->ThisQInterval;
+ SetNextQueryTime(m, q);
}
}
else
- {
- LogInfo("PenalizeDNSServer: Server for %##s (%s) changed to <null>", q->qname.c, DNSTypeName(q->qtype));
+ {
+ // We don't have any more DNS servers for this question. If some server in the list did not return
+ // any response, we need to keep retrying till we get a response. uDNS_CheckCurrentQuestion handles
+ // this case.
+ //
+ // If all servers responded with a negative response, We need to do two things. First, generate a
+ // negative response so that applications get a reply. We also need to reinitialize the DNS servers
+ // so that when the cache expires, we can restart the query.
+ //
+ // Negative response may be generated in two ways.
+ //
+ // 1. AnswerQuestionForDNSServerChanges (called from DNSServerChangedForQuestion) might find some
+ // cache entries and answer this question.
+ // 2. uDNS_CheckCurrentQuestion will create a new cache entry and answer this question
+ //
+ // For (1), it might be okay to reinitialize the DNS servers here. But for (2), we can't do it here
+ // because uDNS_CheckCurrentQuestion will try resending the queries. Hence, to be consistent, we
+ // defer reintializing the DNS servers up until generating a negative cache response.
+ //
+ // Be careful not to touch the ThisQInterval here. For a normal question, when we answer the question
+ // in AnswerCurrentQuestionWithResourceRecord will set ThisQInterval to MaxQuestionInterval and hence
+ // the next query will not happen until cache expiry. If it is a long lived question,
+ // AnswerCurrentQuestionWithResourceRecord will not set it to MaxQuestionInterval. In that case,
+ // we want the normal backoff to work.
+ LogInfo("PenalizeDNSServer: Server for %p, %##s (%s) changed to NULL, Interval %d", q, q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval);
}
+ q->unansweredQueries = 0;
+
}
- q->unansweredQueries = 0;
}
// ***************************************************************************
info->deltime = 0;
while (*p && (*p) != info) p=&(*p)->next;
- if (*p) return(mStatus_AlreadyRegistered);
+ if (*p) {LogInfo("mDNS_SetSecretForDomain: Domain %##s Already in list", (*p)->domain.c); return(mStatus_AlreadyRegistered);}
// Caution: Only zero AutoTunnelHostRecord.namestorage and AutoTunnelNAT.clientContext AFTER we've determined that this is a NEW DomainAuthInfo
// being added to the list. Otherwise we risk smashing our AutoTunnel host records and NATOperation that are already active and in use.
info->AutoTunnelTarget .resrec.RecordType = kDNSRecordTypeUnregistered;
info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeUnregistered;
info->AutoTunnelService .resrec.RecordType = kDNSRecordTypeUnregistered;
+ info->AutoTunnel6Record .resrec.RecordType = kDNSRecordTypeUnregistered;
info->AutoTunnelNAT.clientContext = mDNSNULL;
info->next = mDNSNULL;
*p = info;
{
NATTraversalInfo **n;
- LogInfo("mDNS_StartNATOperation_internal Protocol %d IntPort %d RequestedPort %d NATLease %d",
+ LogInfo("mDNS_StartNATOperation_internal %p Protocol %d IntPort %d RequestedPort %d NATLease %d", traversal,
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
if (*ptr) *ptr = (*ptr)->next; // If we found it, cut this NATTraversalInfo struct from our list
else
{
- LogMsg("mDNS_StopNATOperation: NATTraversalInfo %p not found in list", traversal);
+ LogMsg("mDNS_StopNATOperation_internal: NATTraversalInfo %p not found in list", traversal);
return(mStatus_BadReferenceErr);
}
- LogInfo("mDNS_StopNATOperation_internal %d %d %d %d",
+ LogInfo("mDNS_StopNATOperation_internal %p %d %d %d %d", traversal,
traversal->Protocol, mDNSVal16(traversal->IntPort), mDNSVal16(traversal->RequestedPort), traversal->NATLease);
if (m->CurrentNATTraversal == traversal)
return(mStatus_NoError);
}
-mDNSexport mStatus mDNS_StartNATOperation(mDNS *m, NATTraversalInfo *traversal)
+mDNSexport mStatus mDNS_StartNATOperation(mDNS *const m, NATTraversalInfo *traversal)
{
mStatus status;
mDNS_Lock(m);
return(status);
}
-mDNSexport mStatus mDNS_StopNATOperation(mDNS *m, NATTraversalInfo *traversal)
+mDNSexport mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traversal)
{
mStatus status;
mDNS_Lock(m);
mDNSu8 *responsePtr = m->omsg.data;
LLQOptData llqBuf;
+ if (q->tcp) { LogMsg("sendChallengeResponse: ERROR!!: question %##s (%s) tcp non-NULL", q->qname.c, DNSTypeName(q->qtype)); return; }
+
+ if (PrivateQuery(q)) { LogMsg("sendChallengeResponse: ERROR!!: Private Query %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; }
+
if (q->ntries++ == kLLQ_MAX_TRIES)
{
LogMsg("sendChallengeResponse: %d failed attempts for LLQ %##s", kLLQ_MAX_TRIES, q->qname.c);
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);
- if (err)
- {
- LogMsg("sendChallengeResponse: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err);
- if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
- }
+ mStatus err = mDNSSendDNSMessage(m, &m->omsg, responsePtr, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, mDNSNULL, mDNSNULL);
+ if (err) { LogMsg("sendChallengeResponse: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err); }
}
else StartLLQPolling(m,q);
}
// an issue for private LLQs, because we skip parts 2 and 3 of the handshake. This is related to a bigger
// problem of the current implementation of TCP LLQ setup: we're not handling state transitions correctly
// if the server sends back SERVFULL or STATIC.
- if (q->AuthInfo)
+ if (PrivateQuery(q))
{
LogInfo("Private LLQ_SecondaryRequest; copying id %08X%08X", llq->id.l[0], llq->id.l[1]);
q->id = llq->id;
}
}
-mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport)
+mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
+ const mDNSAddr *const srcaddr, const mDNSIPPort srcport, DNSQuestion **matchQuestion)
{
DNSQuestion pktQ, *q;
if (msg->h.numQuestions && getQuestion(msg, msg->data, end, 0, &pktQ))
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
- debugf("uDNS_recvLLQResponse got poll response; moving to LLQ_InitialRequest for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- q->state = LLQ_InitialRequest;
+
+ // Don't reset the state to IntialRequest as we may write that to the dynamic store
+ // and PrefPane might wrongly think that we are "Starting" instead of "Polling". If
+ // we are in polling state because of NAT-PMP disabled or DoubleNAT, next LLQNATCallback
+ // would kick us back to LLQInitialRequest. So, resetting the state here may not be useful.
+ //
+ // If we have a good NAT (neither NAT-PMP disabled nor Double-NAT), then we should not be
+ // possibly in polling state. To be safe, we want to retry from the start in that case
+ // as there may not be another LLQNATCallback
+ //
+ // NOTE: We can be in polling state if we cannot resolve the SOA record i.e, servAddr is set to
+ // all ones. In that case, we would set it in LLQ_InitialRequest as it overrides the NAT-PMP or
+ // Double-NAT state.
+ if (!mDNSAddressIsOnes(&q->servAddr) && !mDNSIPPortIsZero(m->LLQNAT.ExternalPort) &&
+ !m->LLQNAT.Result)
+ {
+ 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
q->LastQTime = m->timenow;
SetNextQueryTime(m, q);
+ *matchQuestion = q;
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
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));
+ *matchQuestion = q;
return uDNS_LLQ_Events;
}
if (opt && mDNSSameOpaque16(msg->h.id, q->TargetQID))
q->ntries = 0;
}
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
+ *matchQuestion = q;
return uDNS_LLQ_Ignore;
}
if (q->state < LLQ_Established && mDNSSameAddress(srcaddr, &q->servAddr))
// are still valid, so this packet should not cause us to do anything that messes with our cache.
// The ack+answers packet gives us the whole truth, so we should handle it by updating our cache
// to match the answers in the packet, and only the answers in the packet.
+ *matchQuestion = q;
return (oldstate == LLQ_SecondaryRequest ? uDNS_LLQ_Entire : uDNS_LLQ_Ignore);
}
}
}
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
}
+ *matchQuestion = mDNSNULL;
return uDNS_LLQ_Not;
}
DNSQuestion *const q = tcpInfo->question;
tcpInfo_t **backpointer =
q ? &q ->tcp :
- tcpInfo->srs ? &tcpInfo->srs->tcp :
tcpInfo->rr ? &tcpInfo->rr ->tcp : mDNSNULL;
if (backpointer && *backpointer != tcpInfo)
- LogMsg("tcpCallback: %d backpointer %p incorrect tcpInfo %p question %p srs %p rr %p",
- mDNSPlatformTCPGetFD(tcpInfo->sock), *backpointer, tcpInfo, q, tcpInfo->srs, tcpInfo->rr);
+ LogMsg("tcpCallback: %d backpointer %p incorrect tcpInfo %p question %p rr %p",
+ mDNSPlatformTCPGetFD(tcpInfo->sock), *backpointer, tcpInfo, q, tcpInfo->rr);
if (err) goto exit;
// Defensive coding for <rdar://problem/5546824> Crash in mDNSResponder at GetAuthInfoForName_internal + 366
// Don't know yet what's causing this, but at least we can be cautious and try to avoid crashing if we find our pointers in an unexpected state
- if (tcpInfo->srs && tcpInfo->srs->RR_SRV.resrec.name != &tcpInfo->srs->RR_SRV.namestorage)
- LogMsg("tcpCallback: ERROR: tcpInfo->srs->RR_SRV.resrec.name %p != &tcpInfo->srs->RR_SRV.namestorage %p",
- tcpInfo->srs->RR_SRV.resrec.name, &tcpInfo->srs->RR_SRV.namestorage);
if (tcpInfo->rr && tcpInfo->rr->resrec.name != &tcpInfo->rr->namestorage)
LogMsg("tcpCallback: ERROR: tcpInfo->rr->resrec.name %p != &tcpInfo->rr->namestorage %p",
tcpInfo->rr->resrec.name, &tcpInfo->rr->namestorage);
- if (tcpInfo->srs && tcpInfo->srs->RR_SRV.resrec.name != &tcpInfo->srs->RR_SRV.namestorage) return;
if (tcpInfo->rr && tcpInfo->rr-> resrec.name != &tcpInfo->rr-> namestorage) return;
- AuthInfo = tcpInfo->srs ? GetAuthInfoForName(m, tcpInfo->srs->RR_SRV.resrec.name) :
- tcpInfo->rr ? GetAuthInfoForName(m, tcpInfo->rr->resrec.name) : mDNSNULL;
+ AuthInfo = tcpInfo->rr ? GetAuthInfoForName(m, tcpInfo->rr->resrec.name) : mDNSNULL;
// connection is established - send the message
if (q && q->LongLived && q->state == LLQ_Established)
if ((tcpInfo->nread - 2) == tcpInfo->replylen)
{
- AuthRecord *rr = tcpInfo->rr;
+ mDNSBool tls;
DNSMessage *reply = tcpInfo->reply;
mDNSu8 *end = (mDNSu8 *)tcpInfo->reply + tcpInfo->replylen;
mDNSAddr Addr = tcpInfo->Addr;
mDNSIPPort Port = tcpInfo->Port;
+ mDNSIPPort srcPort = zeroIPPort;
tcpInfo->numReplies++;
tcpInfo->reply = mDNSNULL; // Detach reply buffer from tcpInfo_t, to make sure client callback can't cause it to be disposed
tcpInfo->nread = 0;
tcpInfo->replylen = 0;
// If we're going to dispose this connection, do it FIRST, before calling client callback
- // Note: Sleep code depends on us clearing *backpointer here -- it uses the clearing of rr->tcp and srs->tcp
+ // Note: Sleep code depends on us clearing *backpointer here -- it uses the clearing of rr->tcp
// as the signal that the DNS deregistration operation with the server has completed, and the machine may now sleep
+ // If we clear the tcp pointer in the question, mDNSCoreReceiveResponse cannot find a matching question. Hence
+ // we store the minimal information i.e., the source port of the connection in the question itself.
+ // Dereference sock before it is disposed in DisposeTCPConn below.
+
+ if (sock->flags & kTCPSocketFlags_UseTLS) tls = mDNStrue;
+ else tls = mDNSfalse;
+
+ if (q && q->tcp) {srcPort = q->tcp->SrcPort; q->tcpSrcPort = srcPort;}
+
if (backpointer)
if (!q || !q->LongLived || m->SleepState)
{ *backpointer = mDNSNULL; DisposeTCPConn(tcpInfo); }
- if (rr && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
- {
- mDNS_Lock(m);
- LogInfo("tcpCallback: CompleteDeregistration %s", ARDisplayString(m, rr));
- CompleteDeregistration(m, rr); // Don't touch rr after this
- mDNS_Unlock(m);
- }
- else
- mDNSCoreReceive(m, reply, end, &Addr, Port, (sock->flags & kTCPSocketFlags_UseTLS) ? (mDNSAddr *)1 : mDNSNULL, zeroIPPort, 0);
+ mDNSCoreReceive(m, reply, end, &Addr, Port, tls ? (mDNSAddr *)1 : mDNSNULL, srcPort, 0);
// USE CAUTION HERE: Invoking mDNSCoreReceive may have caused the environment to change, including canceling this operation itself
mDNSPlatformMemFree(reply);
}
SetNextQueryTime(m, q);
}
- else if (q->LastQTime + q->ThisQInterval - m->timenow > (q->LongLived ? LLQ_POLL_INTERVAL : MAX_UCAST_POLL_INTERVAL))
+ else if (NextQSendTime(q) - m->timenow > (q->LongLived ? LLQ_POLL_INTERVAL : MAX_UCAST_POLL_INTERVAL))
{
// If we get an error and our next scheduled query for this question is more than the max interval from now,
// reset the next query to ensure we wait no longer the maximum interval from now before trying again.
}
}
- if (tcpInfo->rr) SetRecordRetry(m, tcpInfo->rr, mStatus_NoError);
-
- if (tcpInfo->srs) SetRecordRetry(m, &tcpInfo->srs->RR_SRV, mStatus_NoError);
-
mDNS_Unlock(m);
DisposeTCPConn(tcpInfo);
}
mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
- TCPSocketFlags flags, const mDNSAddr *const Addr, const mDNSIPPort Port,
- DNSQuestion *const question, ServiceRecordSet *const srs, AuthRecord *const rr)
+ TCPSocketFlags flags, const mDNSAddr *const Addr, const mDNSIPPort Port, domainname *hostname,
+ DNSQuestion *const question, AuthRecord *const rr)
{
mStatus err;
mDNSIPPort srcport = zeroIPPort;
- tcpInfo_t *info = (tcpInfo_t *)mDNSPlatformMemAllocate(sizeof(tcpInfo_t));
+ tcpInfo_t *info;
+
+ if ((flags & kTCPSocketFlags_UseTLS) && (!hostname || !hostname->c[0]))
+ { LogMsg("MakeTCPConn: TLS connection being setup with NULL hostname"); return mDNSNULL; }
+
+ info = (tcpInfo_t *)mDNSPlatformMemAllocate(sizeof(tcpInfo_t));
if (!info) { LogMsg("ERROR: MakeTCP - memallocate failed"); return(mDNSNULL); }
mDNSPlatformMemZero(info, sizeof(tcpInfo_t));
info->sock = mDNSPlatformTCPSocket(m, flags, &srcport);
info->requestLen = 0;
info->question = question;
- info->srs = srs;
info->rr = rr;
info->Addr = *Addr;
info->Port = Port;
info->replylen = 0;
info->nread = 0;
info->numReplies = 0;
+ info->SrcPort = srcport;
if (msg)
{
mDNSPlatformMemCopy(&info->request, msg, info->requestLen);
}
- if (!info->sock) { LogMsg("SendServiceRegistration: unable to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); }
- err = mDNSPlatformTCPConnect(info->sock, Addr, Port, 0, tcpCallback, info);
+ if (!info->sock) { LogMsg("MakeTCPConn: unable to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); }
+ err = mDNSPlatformTCPConnect(info->sock, Addr, Port, hostname, (question ? question->InterfaceID : mDNSNULL), tcpCallback, info);
// Probably suboptimal here.
// Instead of returning mDNSNULL here on failure, we should probably invoke the callback with an error code.
// 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 ) { LogInfo("MakeTCPConnection: connection failed"); DisposeTCPConn(info); return(mDNSNULL); }
+ else if (err != mStatus_ConnPending ) { LogInfo("MakeTCPConn: connection failed"); DisposeTCPConn(info); return(mDNSNULL); }
return(info);
}
return;
}
- if (mDNSIPPortIsZero(m->LLQNAT.ExternalPort))
+ // Either we don't have NAT-PMP support (ExternalPort is zero) or behind a Double NAT that may or
+ // may not have NAT-PMP support (NATResult is non-zero)
+ if (mDNSIPPortIsZero(m->LLQNAT.ExternalPort) || m->LLQNAT.Result)
{
- LogInfo("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) External Port %d, NAT Result %d",
+ q->qname.c, DNSTypeName(q->qtype), mDNSVal16(m->LLQNAT.ExternalPort), m->LLQNAT.Result);
StartLLQPolling(m, q);
return;
}
return;
}
- if (q->AuthInfo)
+ if (PrivateQuery(q))
{
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) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
+ if (!q->nta)
+ {
+ // Normally we lookup the zone data and then call this function. And we never free the zone data
+ // for "PrivateQuery". But sometimes this can happen due to some race conditions. When we
+ // switch networks, we might end up "Polling" the network e.g., we are behind a Double NAT.
+ // When we poll, we free the zone information as we send the query to the server (See
+ // PrivateQueryGotZoneData). The NAT callback (LLQNATCallback) may happen soon after that. If we
+ // are still behind Double NAT, we would have returned early in this function. But we could
+ // have switched to a network with no NATs and we should get the zone data again.
+ LogInfo("startLLQHandshake: nta is NULL for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ q->nta = StartGetZoneData(m, &q->qname, ZoneServiceLLQ, LLQGotZoneData, q);
+ return;
+ }
+ else if (!q->nta->Host.c[0])
+ {
+ // This should not happen. If it happens, we print a log and MakeTCPConn will fail if it can't find a hostname
+ LogMsg("startLLQHandshake: ERROR!!: nta non NULL for %##s (%s) but HostName %d NULL, LongLived %d", q->qname.c, DNSTypeName(q->qtype), q->nta->Host.c[0], q->LongLived);
+ }
+ q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_UseTLS, &q->servAddr, q->servPort, &q->nta->Host, q, mDNSNULL);
if (!q->tcp)
q->ThisQInterval = mDNSPlatformOneSecond * 5; // If TCP failed (transient networking glitch) try again in five seconds
else
// If this AutoTunnel is not yet active, start it now (which entails activating its NAT Traversal request,
// which will subsequently advertise the appropriate records when the NAT Traversal returns a result)
if (!AuthInfo->AutoTunnelNAT.clientContext && m->AutoTunnelHostAddr.b[0])
- SetupLocalAutoTunnelInterface_internal(m);
+ {
+ LogInfo("GetServiceTarget: Calling SetupLocalAutoTunnelInterface_internal");
+ SetupLocalAutoTunnelInterface_internal(m, mDNStrue);
+ }
if (AuthInfo->AutoTunnelHostRecord.namestorage.c[0] == 0) return(mDNSNULL);
+ debugf("GetServiceTarget: Returning %##s", AuthInfo->AutoTunnelHostRecord.namestorage.c);
return(&AuthInfo->AutoTunnelHostRecord.namestorage);
}
else
}
if (m->StaticHostname.c[0]) return(&m->StaticHostname);
else GetStaticHostname(m); // asynchronously do reverse lookup for primary IPv4 address
+ LogInfo("GetServiceTarget: Returning NULL for %s", ARDisplayString(m, rr));
return(mDNSNULL);
}
}
-// Called with lock held
-mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs)
- {
- mDNSu8 *ptr = m->omsg.data;
- mDNSu8 *end = (mDNSu8 *)&m->omsg + sizeof(DNSMessage);
- mDNSOpaque16 id;
- mStatus err = mStatus_NoError;
- const domainname *target;
- mDNSu32 i;
-
- if (m->mDNS_busy != m->mDNS_reentrancy+1)
- LogMsg("SendServiceRegistration: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
-
- if (mDNSIPv4AddressIsZero(srs->SRSUpdateServer.ip.v4)) // Don't know our UpdateServer yet
- {
- srs->RR_SRV.LastAPTime = m->timenow;
- if (srs->RR_SRV.ThisAPInterval < mDNSPlatformOneSecond * 5)
- srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 5;
- return;
- }
-
- if (srs->state == regState_Registered) srs->state = regState_Refresh;
-
- id = mDNS_NewMessageID(m);
- InitializeDNSMessage(&m->omsg.h, id, UpdateReqFlags);
-
- // setup resource records
- SetNewRData(&srs->RR_PTR.resrec, mDNSNULL, 0); // Update rdlength, rdestimate, rdatahash
- SetNewRData(&srs->RR_TXT.resrec, mDNSNULL, 0); // Update rdlength, rdestimate, rdatahash
-
- // replace port w/ NAT mapping if necessary
- if (srs->RR_SRV.AutoTarget == Target_AutoHostAndNATMAP && !mDNSIPPortIsZero(srs->NATinfo.ExternalPort))
- srs->RR_SRV.resrec.rdata->u.srv.port = srs->NATinfo.ExternalPort;
-
- // construct update packet
- // set zone
- ptr = putZone(&m->omsg, ptr, end, &srs->zone, mDNSOpaque16fromIntVal(srs->RR_SRV.resrec.rrclass));
- if (!ptr) { err = mStatus_UnknownErr; goto exit; }
-
- if (srs->TestForSelfConflict)
- {
- // update w/ prereq that SRV already exist to make sure previous registration was ours, and delete any stale TXT records
- if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numPrereqs, &srs->RR_SRV.resrec, 0))) { err = mStatus_UnknownErr; goto exit; }
- if (!(ptr = putDeleteRRSet(&m->omsg, ptr, srs->RR_TXT.resrec.name, srs->RR_TXT.resrec.rrtype))) { err = mStatus_UnknownErr; goto exit; }
- }
-
- else if (srs->state != regState_Refresh && srs->state != regState_UpdatePending)
- {
- // use SRV name for prereq
- //ptr = putPrereqNameNotInUse(srs->RR_SRV.resrec.name, &m->omsg, ptr, end);
-
- // For now, until we implement RFC 4701 (DHCID RR) to detect whether an existing record is someone else using the name, or just a
- // stale echo of our own previous registration before we changed our host name, we just overwrite whatever may have already been there
- ptr = putDeleteRRSet(&m->omsg, ptr, srs->RR_SRV.resrec.name, kDNSQType_ANY);
- if (!ptr) { err = mStatus_UnknownErr; goto exit; }
- }
-
- //!!!KRS Need to do bounds checking and use TCP if it won't fit!!!
- if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &srs->RR_PTR.resrec, srs->RR_PTR.resrec.rroriginalttl))) { err = mStatus_UnknownErr; goto exit; }
-
- for (i = 0; i < srs->NumSubTypes; i++)
- if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &srs->SubTypes[i].resrec, srs->SubTypes[i].resrec.rroriginalttl))) { err = mStatus_UnknownErr; goto exit; }
-
- if (srs->state == regState_UpdatePending) // we're updating the txt record
- {
- AuthRecord *txt = &srs->RR_TXT;
- // delete old RData
- SetNewRData(&txt->resrec, txt->OrigRData, txt->OrigRDLen);
- if (!(ptr = putDeletionRecord(&m->omsg, ptr, &srs->RR_TXT.resrec))) { err = mStatus_UnknownErr; goto exit; } // delete old rdata
-
- // add new RData
- SetNewRData(&txt->resrec, txt->InFlightRData, txt->InFlightRDLen);
- 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; }
- }
- 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->RR_SRV);
- if (!target || target->c[0] == 0)
- {
- debugf("SendServiceRegistration - no target for %##s", srs->RR_SRV.resrec.name->c);
- srs->state = regState_NoTarget;
- return;
- }
-
- if (!SameDomainName(target, &srs->RR_SRV.resrec.rdata->u.srv.target))
- {
- AssignDomainName(&srs->RR_SRV.resrec.rdata->u.srv.target, target);
- SetNewRData(&srs->RR_SRV.resrec, mDNSNULL, 0); // Update rdlength, rdestimate, rdatahash
- }
-
- ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &srs->RR_SRV.resrec, srs->RR_SRV.resrec.rroriginalttl);
- if (!ptr) { err = mStatus_UnknownErr; goto exit; }
-
- if (srs->srs_uselease)
- { ptr = putUpdateLease(&m->omsg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) { err = mStatus_UnknownErr; goto exit; } }
-
- if (srs->state != regState_Refresh && srs->state != regState_DeregDeferred && srs->state != regState_UpdatePending)
- srs->state = regState_Pending;
-
- srs->id = id;
-
- if (srs->Private)
- {
- 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)
- else if (srs->RR_SRV.ThisAPInterval < mDNSPlatformOneSecond * 30) srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 30;
- }
- 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 - %d", err);
- }
-
- SetRecordRetry(m, &srs->RR_SRV, err);
- return;
-
-exit:
- if (err)
- {
- LogMsg("SendServiceRegistration ERROR formatting message %d!! Permanently abandoning service registration %##s", err, srs->RR_SRV.resrec.name->c);
- unlinkSRS(m, srs);
- srs->state = regState_Unregistered;
-
- mDNS_DropLockBeforeCallback();
- srs->ServiceCallback(m, srs, err);
- mDNS_ReclaimLockAfterCallback();
- // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
- // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
- }
- }
-
mDNSlocal const domainname *PUBLIC_UPDATE_SERVICE_TYPE = (const domainname*)"\x0B_dns-update" "\x04_udp";
mDNSlocal const domainname *PUBLIC_LLQ_SERVICE_TYPE = (const domainname*)"\x08_dns-llq" "\x04_udp";
{
debugf("GetZoneData GOT SOA %s", RRDisplayString(m, answer));
mDNS_StopQuery(m, question);
+ if (question->ThisQInterval != -1)
+ LogMsg("GetZoneData_QuestionCallback: Question %##s (%s) ThisQInterval %d not -1", question->qname.c, DNSTypeName(question->qtype), question->ThisQInterval);
if (answer->rdlength)
{
AssignDomainName(&zd->ZoneName, answer->name);
}
else if (zd->CurrentSOA->c[0])
{
- zd->CurrentSOA = (domainname *)(zd->CurrentSOA->c + zd->CurrentSOA->c[0]+1);
- AssignDomainName(&zd->question.qname, zd->CurrentSOA);
- GetZoneData_StartQuery(m, zd, kDNSType_SOA);
+ DomainAuthInfo *AuthInfo = GetAuthInfoForName(m, zd->CurrentSOA);
+ if (AuthInfo && AuthInfo->AutoTunnel)
+ {
+ // To keep the load on the server down, we don't chop down on
+ // SOA lookups for AutoTunnels
+ LogInfo("GetZoneData_QuestionCallback: not chopping labels for %##s", zd->CurrentSOA->c);
+ zd->ZoneDataCallback(m, mStatus_NoSuchNameErr, zd);
+ }
+ else
+ {
+ zd->CurrentSOA = (domainname *)(zd->CurrentSOA->c + zd->CurrentSOA->c[0]+1);
+ AssignDomainName(&zd->question.qname, zd->CurrentSOA);
+ GetZoneData_StartQuery(m, zd, kDNSType_SOA);
+ }
}
else
{
LogInfo("GetZoneData recursed to root label of %##s without finding SOA", zd->ChildName.c);
zd->ZoneDataCallback(m, mStatus_NoSuchNameErr, zd);
- mDNSPlatformMemFree(zd);
}
}
else if (answer->rrtype == kDNSType_SRV)
{
debugf("GetZoneData GOT SRV %s", RRDisplayString(m, answer));
mDNS_StopQuery(m, question);
+ if (question->ThisQInterval != -1)
+ LogMsg("GetZoneData_QuestionCallback: Question %##s (%s) ThisQInterval %d not -1", question->qname.c, DNSTypeName(question->qtype), question->ThisQInterval);
// Right now we don't want to fail back to non-encrypted operations
// If the AuthInfo has the AutoTunnel field set, then we want private or nothing
// <rdar://problem/5687667> BTMM: Don't fallback to unencrypted operations when SRV lookup fails
zd->Port = zeroIPPort;
zd->Addr = zeroAddr;
zd->ZoneDataCallback(m, mStatus_NoError, zd);
- mDNSPlatformMemFree(zd);
}
}
}
{
debugf("GetZoneData GOT A %s", RRDisplayString(m, answer));
mDNS_StopQuery(m, question);
+ if (question->ThisQInterval != -1)
+ LogMsg("GetZoneData_QuestionCallback: Question %##s (%s) ThisQInterval %d not -1", question->qname.c, DNSTypeName(question->qtype), question->ThisQInterval);
zd->Addr.type = mDNSAddrType_IPv4;
zd->Addr.ip.v4 = (answer->rdlength == 4) ? answer->rdata->u.ipv4 : zerov4Addr;
// In order to simulate firewalls blocking our outgoing TCP connections, returning immediate ICMP errors or TCP resets,
zd->Addr.ip.v4.b[2] = 0;
zd->Addr.ip.v4.b[3] = 1;
#endif
+ // The caller needs to free the memory when done with zone data
zd->ZoneDataCallback(m, mStatus_NoError, zd);
- mDNSPlatformMemFree(zd);
}
}
debugf("lookupDNSPort %##s", zd->question.qname.c);
}
- zd->question.ThisQInterval = -1; // So that GetZoneData_QuestionCallback() knows whether to cancel this question (Is this necessary?)
+ // CancelGetZoneData can get called at any time. We should stop the question if it has not been
+ // stopped already. A value of -1 for ThisQInterval indicates that the question is not active
+ // yet.
+ zd->question.ThisQInterval = -1;
zd->question.InterfaceID = mDNSInterface_Any;
zd->question.Target = zeroAddr;
//zd->question.qname.c[0] = 0; // Already set
zd->question.ExpectUnique = mDNStrue;
zd->question.ForceMCast = mDNSfalse;
zd->question.ReturnIntermed = mDNStrue;
+ zd->question.SuppressUnusable = mDNSfalse;
zd->question.QuestionCallback = GetZoneData_QuestionCallback;
zd->question.QuestionContext = zd;
#pragma mark - host name and interface management
#endif
-// Called in normal client context (lock not held)
-mDNSlocal void CompleteSRVNatMap(mDNS *m, NATTraversalInfo *n)
+mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr);
+mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr);
+mDNSlocal mDNSBool IsRecordMergeable(mDNS *const m, AuthRecord *rr, mDNSs32 time);
+
+// When this function is called, service record is already deregistered. We just
+// have to deregister the PTR and TXT records.
+mDNSlocal void UpdateAllServiceRecords(mDNS *const m, AuthRecord *rr, mDNSBool reg)
{
- ServiceRecordSet *srs = (ServiceRecordSet *)n->clientContext;
- debugf("SRVNatMap complete %.4a IntPort %u ExternalPort %u NATLease %u", &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), n->NATLease);
+ AuthRecord *r, *srvRR;
- if (!srs) { LogMsg("CompleteSRVNatMap called with unknown ServiceRecordSet object"); return; }
- if (!n->NATLease) return;
+ if (rr->resrec.rrtype != kDNSType_SRV) { LogMsg("UpdateAllServiceRecords:ERROR!! ResourceRecord not a service record %s", ARDisplayString(m, rr)); return; }
- mDNS_Lock(m);
- if (!mDNSIPv4AddressIsZero(srs->SRSUpdateServer.ip.v4))
- SendServiceRegistration(m, srs); // non-zero server address means we already have necessary zone data to send update
- else
+ if (reg && rr->state == regState_NoTarget) { LogMsg("UpdateAllServiceRecords:ERROR!! SRV record %s in noTarget state during registration", ARDisplayString(m, rr)); return; }
+
+ LogInfo("UpdateAllServiceRecords: ResourceRecord %s", ARDisplayString(m, rr));
+
+ for (r = m->ResourceRecords; r; r=r->next)
{
- // SHOULD NEVER HAPPEN!
- LogInfo("ERROR: CompleteSRVNatMap called but srs->SRSUpdateServer.ip.v4 is zero!");
- srs->state = regState_FetchingZoneData;
- 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);
+ if (!AuthRecord_uDNS(r)) continue;
+ srvRR = mDNSNULL;
+ if (r->resrec.rrtype == kDNSType_PTR)
+ srvRR = r->Additional1;
+ else if (r->resrec.rrtype == kDNSType_TXT)
+ srvRR = r->DependentOn;
+ if (srvRR && srvRR->resrec.rrtype != kDNSType_SRV)
+ LogMsg("UpdateAllServiceRecords: ERROR!! Resource record %s wrong, expecting SRV type", ARDisplayString(m, srvRR));
+ if (srvRR == rr)
+ {
+ if (!reg)
+ {
+ LogInfo("UpdateAllServiceRecords: deregistering %s", ARDisplayString(m, r));
+ r->SRVChanged = mDNStrue;
+ r->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ r->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
+ r->state = regState_DeregPending;
+ }
+ else
+ {
+ // Clearing SRVchanged is a safety measure. If our pewvious dereg never
+ // came back and we had a target change, we are starting fresh
+ r->SRVChanged = mDNSfalse;
+ // if it is already registered or in the process of registering, then don't
+ // bother re-registering. This happens today for non-BTMM domains where the
+ // TXT and PTR get registered before SRV records because of the delay in
+ // getting the port mapping. There is no point in re-registering the TXT
+ // and PTR records.
+ if ((r->state == regState_Registered) ||
+ (r->state == regState_Pending && r->nta && !mDNSIPv4AddressIsZero(r->nta->Addr.ip.v4)))
+ LogInfo("UpdateAllServiceRecords: not registering %s, state %d", ARDisplayString(m, r), r->state);
+ else
+ {
+ LogInfo("UpdateAllServiceRecords: registering %s, state %d", ARDisplayString(m, r), r->state);
+ ActivateUnicastRegistration(m, r);
+ }
+ }
+ }
}
- mDNS_Unlock(m);
- }
-
-mDNSlocal void StartSRVNatMap(mDNS *m, ServiceRecordSet *srs)
- {
- const mDNSu8 *p = srs->RR_PTR.resrec.name->c;
- if (p[0]) p += 1 + p[0];
- if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) srs->NATinfo.Protocol = NATOp_MapTCP;
- else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) srs->NATinfo.Protocol = NATOp_MapUDP;
- 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);
- // 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;
- srs->NATinfo.clientContext = srs;
- mDNS_StartNATOperation_internal(m, &srs->NATinfo);
}
-// Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1)
-mDNSexport void ServiceRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData)
+// Called in normal client context (lock not held)
+// Currently only supports SRV records for nat mapping
+mDNSlocal void CompleteRecordNatMap(mDNS *m, NATTraversalInfo *n)
{
- ServiceRecordSet *srs = (ServiceRecordSet *)zoneData->ZoneDataContext;
-
- if (m->mDNS_busy != m->mDNS_reentrancy)
- LogMsg("ServiceRegistrationGotZoneData: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
-
- 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
- srs->srs_uselease = mDNStrue;
-
- if (err || !zoneData) return;
+ const domainname *target;
+ domainname *srvt;
+ AuthRecord *rr = (AuthRecord *)n->clientContext;
+ debugf("SRVNatMap complete %.4a IntPort %u ExternalPort %u NATLease %u", &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), n->NATLease);
- if (mDNSIPPortIsZero(zoneData->Port) || mDNSAddressIsZero(&zoneData->Addr)) return;
+ if (!rr) { LogMsg("CompleteRecordNatMap called with unknown AuthRecord object"); return; }
+ if (!n->NATLease) { LogMsg("CompleteRecordNatMap No NATLease for %s", ARDisplayString(m, rr)); return; }
- // cache zone data
- AssignDomainName(&srs->zone, &zoneData->ZoneName);
- srs->SRSUpdateServer.type = mDNSAddrType_IPv4;
- srs->SRSUpdateServer = zoneData->Addr;
- srs->SRSUpdatePort = zoneData->Port;
- srs->Private = zoneData->ZonePrivate;
+ if (rr->resrec.rrtype != kDNSType_SRV) {LogMsg("CompleteRecordNatMap: Not a service record %s", ARDisplayString(m, rr)); return; }
- srs->RR_SRV.LastAPTime = m->timenow;
- srs->RR_SRV.ThisAPInterval = 0;
+ if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) { LogInfo("CompleteRecordNatMap called for %s, Service deregistering", ARDisplayString(m, rr)); return; }
- 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 (rr->state == regState_DeregPending) { LogInfo("CompleteRecordNatMap called for %s, record in DeregPending", ARDisplayString(m, rr)); return; }
- // 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)
+ // As we free the zone info after registering/deregistering with the server (See hndlRecordUpdateReply),
+ // we need to restart the get zone data and nat mapping request to get the latest mapping result as we can't handle it
+ // at this moment. Restart from the beginning.
+ if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
{
- srs->state = regState_NATMap;
- debugf("ServiceRegistrationGotZoneData StartSRVNatMap");
- StartSRVNatMap(m, srs);
+ LogInfo("CompleteRecordNatMap called for %s but no zone information!", ARDisplayString(m, rr));
+ // We need to clear out the NATinfo state so that it will result in re-acuqiring the mapping
+ // and hence this callback called again.
+ if (rr->NATinfo.clientContext)
+ {
+ mDNS_StopNATOperation_internal(m, &rr->NATinfo);
+ rr->NATinfo.clientContext = mDNSNULL;
+ }
+ rr->state = regState_Pending;
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
+ return;
}
- else
- {
- mDNS_Lock(m);
- SendServiceRegistration(m, srs);
+
+ mDNS_Lock(m);
+ // Reevaluate the target always as Target could have changed while
+ // we were getting the port mapping (See UpdateOneSRVRecord)
+ target = GetServiceTarget(m, rr);
+ srvt = GetRRDomainNameTarget(&rr->resrec);
+ if (!target || target->c[0] == 0 || mDNSIPPortIsZero(n->ExternalPort))
+ {
+ if (target && target->c[0])
+ LogInfo("CompleteRecordNatMap - Target %##s for ResourceRecord %##s, ExternalPort %d", target->c, rr->resrec.name->c, mDNSVal16(n->ExternalPort));
+ else
+ LogInfo("CompleteRecordNatMap - no target for %##s, ExternalPort %d", rr->resrec.name->c, mDNSVal16(n->ExternalPort));
+ if (srvt) srvt->c[0] = 0;
+ rr->state = regState_NoTarget;
+ rr->resrec.rdlength = rr->resrec.rdestimate = 0;
mDNS_Unlock(m);
+ UpdateAllServiceRecords(m, rr, mDNSfalse);
+ return;
+ }
+ LogInfo("CompleteRecordNatMap - Target %##s for ResourceRecord %##s, ExternalPort %d", target->c, rr->resrec.name->c, mDNSVal16(n->ExternalPort));
+ // This function might get called multiple times during a network transition event. Previosuly, we could
+ // have put the SRV record in NoTarget state above and deregistered all the other records. When this
+ // function gets called again with a non-zero ExternalPort, we need to set the target and register the
+ // other records again.
+ if (srvt && !SameDomainName(srvt, target))
+ {
+ AssignDomainName(srvt, target);
+ SetNewRData(&rr->resrec, mDNSNULL, 0); // Update rdlength, rdestimate, rdatahash
}
+
+ // SRVChanged is set when when the target of the SRV record changes (See UpdateOneSRVRecord).
+ // As a result of the target change, we might register just that SRV Record if it was
+ // previously registered and we have a new target OR deregister SRV (and the associated
+ // PTR/TXT records) if we don't have a target anymore. When we get a response from the server,
+ // SRVChanged state tells that we registered/deregistered because of a target change
+ // and hence handle accordingly e.g., if we deregistered, put the records in NoTarget state OR
+ // if we registered then put it in Registered state.
+ //
+ // Here, we are registering all the records again from the beginning. Treat this as first time
+ // registration rather than a temporary target change.
+ rr->SRVChanged = mDNSfalse;
+
+ // We want IsRecordMergeable to check whether it is a record whose update can be
+ // sent with others. We set the time before we call IsRecordMergeable, so that
+ // it does not fail this record based on time. We are interested in other checks
+ // at this time
+ rr->state = regState_Pending;
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
+ if (IsRecordMergeable(m, rr, m->timenow + MERGE_DELAY_TIME))
+ // Delay the record registration by MERGE_DELAY_TIME so that we can merge them
+ // into one update
+ rr->LastAPTime += MERGE_DELAY_TIME;
+ mDNS_Unlock(m);
+ // We call this always even though it may not be necessary always e.g., normal registration
+ // process where TXT and PTR gets registered followed by the SRV record after it gets
+ // the port mapping. In that case, UpdateAllServiceRecords handles the optimization. The
+ // update of TXT and PTR record is required if we entered noTargetState before as explained
+ // above.
+ UpdateAllServiceRecords(m, rr, mDNStrue);
}
-mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs)
+mDNSlocal void StartRecordNatMap(mDNS *m, AuthRecord *rr)
{
- mDNSOpaque16 id;
- mDNSu8 *ptr = m->omsg.data;
- mDNSu8 *end = (mDNSu8 *)&m->omsg + sizeof(DNSMessage);
- mStatus err = mStatus_UnknownErr;
- mDNSu32 i;
+ const mDNSu8 *p;
+ mDNSu8 protocol;
- if (mDNSIPv4AddressIsZero(srs->SRSUpdateServer.ip.v4)) // Don't know our UpdateServer yet
+ if (rr->resrec.rrtype != kDNSType_SRV)
{
- srs->RR_SRV.LastAPTime = m->timenow;
- if (srs->RR_SRV.ThisAPInterval < mDNSPlatformOneSecond * 5)
- srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 5;
+ LogInfo("StartRecordNatMap: Resource Record %##s type %d, not supported", rr->resrec.name->c, rr->resrec.rrtype);
return;
}
+ p = rr->resrec.name->c;
+ //Assume <Service Instance>.<App Protocol>.<Transport protocol>.<Name>
+ // Skip the first two labels to get to the transport protocol
+ if (p[0]) p += 1 + p[0];
+ if (p[0]) p += 1 + p[0];
+ if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) protocol = NATOp_MapTCP;
+ else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) protocol = NATOp_MapUDP;
+ else { LogMsg("StartRecordNatMap: could not determine transport protocol of service %##s", rr->resrec.name->c); return; }
+
+ if (rr->NATinfo.clientContext) mDNS_StopNATOperation_internal(m, &rr->NATinfo);
+ rr->NATinfo.Protocol = protocol;
+ rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port;
+ rr->NATinfo.RequestedPort = rr->resrec.rdata->u.srv.port;
+ rr->NATinfo.NATLease = 0; // Request default lease
+ rr->NATinfo.clientCallback = CompleteRecordNatMap;
+ rr->NATinfo.clientContext = rr;
+ mDNS_StartNATOperation_internal(m, &rr->NATinfo);
+ }
- id = mDNS_NewMessageID(m);
- InitializeDNSMessage(&m->omsg.h, id, UpdateReqFlags);
-
- // put zone
- ptr = putZone(&m->omsg, ptr, end, &srs->zone, mDNSOpaque16fromIntVal(srs->RR_SRV.resrec.rrclass));
- if (!ptr) { LogMsg("ERROR: SendServiceDeregistration - putZone"); err = mStatus_UnknownErr; goto exit; }
-
- if (!(ptr = putDeleteAllRRSets(&m->omsg, ptr, srs->RR_SRV.resrec.name))) { err = mStatus_UnknownErr; goto exit; } // this deletes SRV, TXT, and Extras
- if (!(ptr = putDeletionRecord(&m->omsg, ptr, &srs->RR_PTR.resrec))) { err = mStatus_UnknownErr; goto exit; }
- for (i = 0; i < srs->NumSubTypes; i++)
- if (!(ptr = putDeletionRecord(&m->omsg, ptr, &srs->SubTypes[i].resrec))) { err = mStatus_UnknownErr; goto exit; }
-
- srs->id = id;
- srs->state = regState_DeregPending;
- srs->RR_SRV.expire = 0; // Indicate that we have no active registration any more
-
- if (srs->Private)
- {
- 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)
- else if (srs->RR_SRV.ThisAPInterval < mDNSPlatformOneSecond * 30) srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 30;
- }
- else
+// Unlink an Auth Record from the m->ResourceRecords list.
+// When a resource record enters regState_NoTarget initially, mDNS_Register_internal
+// does not initialize completely e.g., it cannot check for duplicates etc. The resource
+// record is temporarily left in the ResourceRecords list so that we can initialize later
+// when the target is resolvable. Similarly, when host name changes, we enter regState_NoTarget
+// and we do the same.
+mDNSlocal mStatus UnlinkResourceRecord(mDNS *const m, AuthRecord *const rr)
+ {
+ AuthRecord **list = &m->ResourceRecords;
+ while (*list && *list != rr) list = &(*list)->next;
+ if (*list)
{
- 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 - %d", err); goto exit; }
+ *list = rr->next;
+ rr->next = mDNSNULL;
+ return(mStatus_NoError);
}
+ LogMsg("UnlinkResourceRecord:ERROR!! - no such active record %##s", rr->resrec.name->c);
+ return(mStatus_NoSuchRecord);
+ }
- SetRecordRetry(m, &srs->RR_SRV, err);
- return;
-
-exit:
- if (err)
- {
- LogMsg("SendServiceDeregistration ERROR formatting message %d!! Permanently abandoning service registration %##s", err, srs->RR_SRV.resrec.name->c);
- unlinkSRS(m, srs);
- srs->state = regState_Unregistered;
- }
+// We need to go through mDNS_Register again as we did not complete the
+// full initialization last time e.g., duplicate checks.
+// After we register, we will be in regState_GetZoneData.
+mDNSlocal void RegisterAllServiceRecords(mDNS *const m, AuthRecord *rr)
+ {
+ LogInfo("RegisterAllServiceRecords: Service Record %##s", rr->resrec.name->c);
+ // First Register the service record, we do this differently from other records because
+ // when it entered NoTarget state, it did not go through complete initialization
+ rr->SRVChanged = mDNSfalse;
+ UnlinkResourceRecord(m, rr);
+ mDNS_Register_internal(m, rr);
+ // Register the other records
+ UpdateAllServiceRecords(m, rr, mDNStrue);
}
// Called with lock held
-mDNSlocal void UpdateSRV(mDNS *m, ServiceRecordSet *srs)
+mDNSlocal void UpdateOneSRVRecord(mDNS *m, AuthRecord *rr)
{
- ExtraResourceRecord *e;
-
// Target change if:
// We have a target and were previously waiting for one, or
// We had a target and no longer do, or
// The target has changed
- domainname *curtarget = &srs->RR_SRV.resrec.rdata->u.srv.target;
- const domainname *const nt = GetServiceTarget(m, &srs->RR_SRV);
+ domainname *curtarget = &rr->resrec.rdata->u.srv.target;
+ const domainname *const nt = GetServiceTarget(m, rr);
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);
+ mDNSBool TargetChanged = (newtarget->c[0] && rr->state == regState_NoTarget) || !SameDomainName(curtarget, newtarget);
+ mDNSBool HaveZoneData = rr->nta && !mDNSIPv4AddressIsZero(rr->nta->Addr.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 external port
// We were not behind a NAT and now we are
- mDNSIPPort port = srs->RR_SRV.resrec.rdata->u.srv.port;
- mDNSBool NowNeedNATMAP = (srs->RR_SRV.AutoTarget == Target_AutoHostAndNATMAP && !mDNSIPPortIsZero(port) && mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) && !mDNSAddrIsRFC1918(&srs->SRSUpdateServer));
- mDNSBool WereBehindNAT = (srs->NATinfo.clientContext != mDNSNULL);
- mDNSBool PortWasMapped = (srs->NATinfo.clientContext && !mDNSSameIPPort(srs->NATinfo.RequestedPort, port)); // I think this is always false -- SC Sept 07
+ mDNSIPPort port = rr->resrec.rdata->u.srv.port;
+ mDNSBool NowNeedNATMAP = (rr->AutoTarget == Target_AutoHostAndNATMAP && !mDNSIPPortIsZero(port) && mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) && rr->nta && !mDNSAddrIsRFC1918(&rr->nta->Addr));
+ mDNSBool WereBehindNAT = (rr->NATinfo.clientContext != mDNSNULL);
+ mDNSBool PortWasMapped = (rr->NATinfo.clientContext && !mDNSSameIPPort(rr->NATinfo.RequestedPort, port)); // I think this is always false -- SC Sept 07
mDNSBool NATChanged = (!WereBehindNAT && NowNeedNATMAP) || (!NowNeedNATMAP && PortWasMapped);
- 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,
+ (void)HaveZoneData; //unused
+
+ LogInfo("UpdateOneSRVRecord: Resource Record %s TargetChanged %d, NewTarget %##s", ARDisplayString(m, rr), TargetChanged, nt->c);
+
+ debugf("UpdateOneSRVRecord: %##s newtarget %##s TargetChanged %d HaveZoneData %d port %d NowNeedNATMAP %d WereBehindNAT %d PortWasMapped %d NATChanged %d",
+ rr->resrec.name->c, newtarget,
TargetChanged, HaveZoneData, mDNSVal16(port), NowNeedNATMAP, WereBehindNAT, PortWasMapped, NATChanged);
if (m->mDNS_busy != m->mDNS_reentrancy+1)
- LogMsg("UpdateSRV: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
+ LogMsg("UpdateOneSRVRecord: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
if (!TargetChanged && !NATChanged) return;
- switch(srs->state)
+ // If we are deregistering the record, then ignore any NAT/Target change.
+ if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
+ {
+ LogInfo("UpdateOneSRVRecord: Deregistering record, Ignoring TargetChanged %d, NATChanged %d for %##s, state %d", TargetChanged, NATChanged,
+ rr->resrec.name->c, rr->state);
+ return;
+ }
+
+ if (newtarget)
+ LogInfo("UpdateOneSRVRecord: TargetChanged %d, NATChanged %d for %##s, state %d, newtarget %##s", TargetChanged, NATChanged, rr->resrec.name->c, rr->state, newtarget->c);
+ else
+ LogInfo("UpdateOneSRVRecord: TargetChanged %d, NATChanged %d for %##s, state %d, null newtarget", TargetChanged, NATChanged, rr->resrec.name->c, rr->state);
+ switch(rr->state)
{
- case regState_FetchingZoneData:
- case regState_DeregPending:
- case regState_DeregDeferred:
- case regState_Unregistered:
case regState_NATMap:
- case regState_ExtraQueued:
// In these states, the SRV has either not yet been registered (it will get up-to-date information when it is)
- // or is in the process of, or has already been, deregistered
+ // or is in the process of, or has already been, deregistered. This assumes that whenever we transition out
+ // of this state, we need to look at the target again.
return;
- case regState_Pending:
- case regState_Refresh:
case regState_UpdatePending:
- // let the in-flight operation complete before updating
- srs->SRVUpdateDeferred = mDNStrue;
+ // We are getting a Target change/NAT change while the SRV record is being updated ?
+ // let us not do anything for now.
return;
case regState_NATError:
// if nat changed, register if we have a target (below)
case regState_NoTarget:
- if (newtarget->c[0])
+ if (!newtarget->c[0])
{
- debugf("UpdateSRV: %s service %##s", HaveZoneData ? (NATChanged && NowNeedNATMAP ? "Starting Port Map for" : "Registering") : "Getting Zone Data for", srs->RR_SRV.resrec.name->c);
- if (!HaveZoneData)
- {
- srs->state = regState_FetchingZoneData;
- 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
- {
- if (srs->NATinfo.clientContext && (NATChanged || !NowNeedNATMAP))
- {
- mDNS_StopNATOperation_internal(m, &srs->NATinfo);
- srs->NATinfo.clientContext = mDNSNULL;
- }
- if (NATChanged && NowNeedNATMAP && srs->RR_SRV.AutoTarget == Target_AutoHostAndNATMAP)
- { srs->state = regState_NATMap; StartSRVNatMap(m, srs); }
- else SendServiceRegistration(m, srs);
- }
+ LogInfo("UpdateOneSRVRecord: No target yet for Resource Record %s", ARDisplayString(m, rr));
+ return;
}
+ RegisterAllServiceRecords(m , rr);
return;
-
+ case regState_DeregPending:
+ // We are in DeregPending either because the service was deregistered from above or we handled
+ // a NAT/Target change before and sent the deregistration below. There are a few race conditions
+ // possible
+ //
+ // 1. We are handling a second NAT/Target change while the first dereg is in progress. It is possible
+ // that first dereg never made it through because there was no network connectivity e.g., disconnecting
+ // from network triggers this function due to a target change and later connecting to the network
+ // retriggers this function but the deregistration never made it through yet. Just fall through.
+ // If there is a target register otherwise deregister.
+ //
+ // 2. While we sent the dereg during a previous NAT/Target change, uDNS_DeregisterRecord gets
+ // called as part of service deregistration. When the response comes back, we call
+ // CompleteDeregistration rather than handle NAT/Target change because the record is in
+ // kDNSRecordTypeDeregistering state.
+ //
+ // 3. If the upper layer deregisters the service, we check for kDNSRecordTypeDeregistering both
+ // here in this function to avoid handling NAT/Target change and in hndlRecordUpdateReply to call
+ // CompleteDeregistration instead of handling NAT/Target change. Hence, we are not concerned
+ // about that case here.
+ //
+ // We just handle case (1) by falling through
+ case regState_Pending:
+ case regState_Refresh:
case regState_Registered:
// target or nat changed. deregister service. upon completion, we'll look for a new target
- debugf("UpdateSRV: SRV record changed for service %##s - deregistering (will re-register with new SRV)", srs->RR_SRV.resrec.name->c);
- for (e = srs->Extras; e; e = e->next) e->r.state = regState_ExtraQueued; // extra will be re-registed if the service is re-registered
- srs->SRVChanged = mDNStrue;
- SendServiceDeregistration(m, srs);
+ rr->SRVChanged = mDNStrue;
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
+ if (newtarget->c[0])
+ {
+ LogInfo("UpdateOneSRVRecord: SRV record changed for service %##s, registering with new target %##s",
+ rr->resrec.name->c, newtarget->c);
+ rr->state = regState_Pending;
+ }
+ else
+ {
+ LogInfo("UpdateOneSRVRecord: SRV record changed for service %##s de-registering", rr->resrec.name->c);
+ rr->state = regState_DeregPending;
+ UpdateAllServiceRecords(m, rr, mDNSfalse);
+ }
return;
-
- default: LogMsg("UpdateSRV: Unknown state %d for %##s", srs->state, srs->RR_SRV.resrec.name->c);
+ case regState_Unregistered:
+ default: LogMsg("UpdateOneSRVRecord: Unknown state %d for %##s", rr->state, rr->resrec.name->c);
}
}
-// Called with lock held
-mDNSlocal void UpdateSRVRecords(mDNS *m)
+mDNSexport void UpdateAllSRVRecords(mDNS *m)
{
- debugf("UpdateSRVRecords%s", m->SleepState ? " (ignored due to SleepState)" : "");
- if (m->SleepState) return;
+ m->NextSRVUpdate = 0;
+ LogInfo("UpdateAllSRVRecords %d", m->SleepState);
- if (CurrentServiceRecordSet)
- LogMsg("UpdateSRVRecords ERROR CurrentServiceRecordSet already set");
- CurrentServiceRecordSet = m->ServiceRegistrations;
-
- while (CurrentServiceRecordSet)
+ if (m->CurrentRecord)
+ LogMsg("UpdateAllSRVRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
+ m->CurrentRecord = m->ResourceRecords;
+ while (m->CurrentRecord)
{
- ServiceRecordSet *s = CurrentServiceRecordSet;
- CurrentServiceRecordSet = CurrentServiceRecordSet->uDNS_next;
- UpdateSRV(m, s);
+ AuthRecord *rptr = m->CurrentRecord;
+ m->CurrentRecord = m->CurrentRecord->next;
+ if (AuthRecord_uDNS(rptr) && rptr->resrec.rrtype == kDNSType_SRV)
+ UpdateOneSRVRecord(m, rptr);
}
-
- 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
if (h->arv4.resrec.RecordType)
{
if (mDNSSameIPv4Address(h->arv4.resrec.rdata->u.ipv4, n->ExternalAddress)) return; // If address unchanged, do nothing
- LogInfo("Updating hostname %##s IPv4 from %.4a to %.4a (NAT gateway's external address)",
+ LogInfo("Updating hostname %p %##s IPv4 from %.4a to %.4a (NAT gateway's external address)",n,
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
}
// register any pending services that require a target
mDNS_Lock(m);
- UpdateSRVRecords(m);
+ m->NextSRVUpdate = NonZeroTime(m->timenow);
mDNS_Unlock(m);
// Deliver success to client
(void)question;
- debugf("FoundStaticHostname: %##s -> %##s (%s)", question->qname.c, answer->rdata->u.name.c, AddRecord ? "added" : "removed");
- if (AddRecord && !SameDomainName(pktname, storedname))
+ if (answer->rdlength != 0)
+ LogInfo("FoundStaticHostname: question %##s -> answer %##s (%s)", question->qname.c, answer->rdata->u.name.c, AddRecord ? "ADD" : "RMV");
+ else
+ LogInfo("FoundStaticHostname: question %##s -> answer NULL (%s)", question->qname.c, AddRecord ? "ADD" : "RMV");
+
+ if (AddRecord && answer->rdlength != 0 && !SameDomainName(pktname, storedname))
{
AssignDomainName(storedname, pktname);
while (h)
{
- if (h->arv4.state == regState_FetchingZoneData || h->arv4.state == regState_Pending || h->arv4.state == regState_NATMap ||
- h->arv6.state == regState_FetchingZoneData || h->arv6.state == regState_Pending)
+ if (h->arv4.state == regState_Pending || h->arv4.state == regState_NATMap || h->arv6.state == regState_Pending)
{
// if we're in the process of registering a dynamic hostname, delay SRV update so we don't have to reregister services if the dynamic name succeeds
m->NextSRVUpdate = NonZeroTime(m->timenow + 5 * mDNSPlatformOneSecond);
+ debugf("FoundStaticHostname: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
return;
}
h = h->next;
}
mDNS_Lock(m);
- UpdateSRVRecords(m);
+ m->NextSRVUpdate = NonZeroTime(m->timenow);
mDNS_Unlock(m);
}
else if (!AddRecord && SameDomainName(pktname, storedname))
{
mDNS_Lock(m);
storedname->c[0] = 0;
- UpdateSRVRecords(m);
+ m->NextSRVUpdate = NonZeroTime(m->timenow);
mDNS_Unlock(m);
}
}
q->ExpectUnique = mDNSfalse;
q->ForceMCast = mDNSfalse;
q->ReturnIntermed = mDNStrue;
+ q->SuppressUnusable = mDNSfalse;
q->QuestionCallback = FoundStaticHostname;
q->QuestionContext = mDNSNULL;
if (f6) mDNS_Deregister_internal(m, &hi->arv6, mDNS_Dereg_normal);
// When both deregistrations complete we'll free the memory in the mStatus_MemFree callback
}
- UpdateSRVRecords(m);
+ if (!m->mDNS_busy) LogMsg("mDNS_RemoveDynDNSHostName: ERROR: Lock not held");
+ m->NextSRVUpdate = NonZeroTime(m->timenow);
}
// Currently called without holding the lock
mDNS_Lock(m);
- if (v4addr && !mDNSv4AddressIsLinkLocal(&v4addr->ip.v4)) v6addr = mDNSNULL;
-
v4Changed = !mDNSSameIPv4Address(m->AdvertisedV4.ip.v4, v4addr ? v4addr->ip.v4 : zerov4Addr);
v6Changed = !mDNSSameIPv6Address(m->AdvertisedV6.ip.v6, v6addr ? v6addr->ip.v6 : zerov6Addr);
RouterChanged = !mDNSSameIPv4Address(m->Router.ip.v4, router ? router->ip.v4 : zerov4Addr);
if (m->ReverseMap.ThisQInterval != -1) mDNS_StopQuery_internal(m, &m->ReverseMap);
m->StaticHostname.c[0] = 0;
- UpdateSRVRecords(m); // Will call GetStaticHostname if needed
+ m->NextSRVUpdate = NonZeroTime(m->timenow);
#if APPLE_OSX_mDNSResponder
if (RouterChanged) uuid_generate(m->asl_uuid);
{
ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
if (!ptr) goto finish;
- if (m->rec.r.resrec.rrtype == kDNSType_TSIG)
+ if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_TSIG)
{
mDNSu32 macsize;
mDNSu8 *rd = m->rec.r.resrec.rdata->u.data;
}
else
{
- LogMsg("Update %##s failed with rcode %d", displayname->c, rcode);
- return mStatus_UnknownErr;
+ LogMsg("Update %##s failed with rcode %d", displayname->c, rcode);
+ return mStatus_UnknownErr;
+ }
+ }
+
+// We add three Additional Records for unicast resource record registrations
+// which is a function of AuthInfo and AutoTunnel properties
+mDNSlocal mDNSu32 RRAdditionalSize(mDNS *const m, DomainAuthInfo *AuthInfo)
+ {
+ mDNSu32 leaseSize, hinfoSize, tsigSize;
+ mDNSu32 rr_base_size = 10; // type (2) class (2) TTL (4) rdlength (2)
+
+ // OPT RR : Emptyname(.) + base size + rdataOPT
+ leaseSize = 1 + rr_base_size + sizeof(rdataOPT);
+
+ // HINFO: Resource Record Name + base size + RDATA
+ // HINFO is added only for autotunnels
+ hinfoSize = 0;
+ if (AuthInfo && AuthInfo->AutoTunnel)
+ hinfoSize = (m->hostlabel.c[0] + 1) + DomainNameLength(&AuthInfo->domain) +
+ rr_base_size + (2 + m->HIHardware.c[0] + m->HISoftware.c[0]);
+
+ //TSIG: Resource Record Name + base size + RDATA
+ // RDATA:
+ // Algorithm name: hmac-md5.sig-alg.reg.int (8+7+3+3 + 5 bytes for length = 26 bytes)
+ // Time: 6 bytes
+ // Fudge: 2 bytes
+ // Mac Size: 2 bytes
+ // Mac: 16 bytes
+ // ID: 2 bytes
+ // Error: 2 bytes
+ // Len: 2 bytes
+ // Total: 58 bytes
+ tsigSize = 0;
+ if (AuthInfo) tsigSize = DomainNameLength(&AuthInfo->keyname) + rr_base_size + 58;
+
+ return (leaseSize + hinfoSize + tsigSize);
+ }
+
+//Note: Make sure that RREstimatedSize is updated accordingly if anything that is done here
+//would modify rdlength/rdestimate
+mDNSlocal mDNSu8* BuildUpdateMessage(mDNS *const m, mDNSu8 *ptr, AuthRecord *rr, mDNSu8 *limit)
+ {
+ //If this record is deregistering, then just send the deletion record
+ if (rr->state == regState_DeregPending)
+ {
+ rr->expire = 0; // Indicate that we have no active registration any more
+ ptr = putDeletionRecordWithLimit(&m->omsg, ptr, &rr->resrec, limit);
+ if (!ptr) goto exit;
+ return ptr;
+ }
+
+ // This is a common function to both sending an update in a group or individual
+ // records separately. Hence, we change the state here.
+ if (rr->state == regState_Registered) rr->state = regState_Refresh;
+ if (rr->state != regState_Refresh && rr->state != regState_UpdatePending)
+ rr->state = regState_Pending;
+
+ // For Advisory records like e.g., _services._dns-sd, which is shared, don't send goodbyes as multiple
+ // host might be registering records and deregistering from one does not make sense
+ if (rr->resrec.RecordType != kDNSRecordTypeAdvisory) rr->RequireGoodbye = mDNStrue;
+
+ if ((rr->resrec.rrtype == kDNSType_SRV) && (rr->AutoTarget == Target_AutoHostAndNATMAP) &&
+ !mDNSIPPortIsZero(rr->NATinfo.ExternalPort))
+ {
+ rr->resrec.rdata->u.srv.port = rr->NATinfo.ExternalPort;
+ }
+
+ if (rr->state == regState_UpdatePending)
+ {
+ // delete old RData
+ SetNewRData(&rr->resrec, rr->OrigRData, rr->OrigRDLen);
+ if (!(ptr = putDeletionRecordWithLimit(&m->omsg, ptr, &rr->resrec, limit))) goto exit; // delete old rdata
+
+ // add new RData
+ SetNewRData(&rr->resrec, rr->InFlightRData, rr->InFlightRDLen);
+ if (!(ptr = PutResourceRecordTTLWithLimit(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit))) goto exit;
+ }
+ else
+ {
+ if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique || rr->resrec.RecordType == kDNSRecordTypeVerified)
+ {
+ // KnownUnique : Delete any previous value
+ // For Unicast registrations, we don't verify that it is unique, but set to verified and hence we want to
+ // delete any previous value
+ ptr = putDeleteRRSetWithLimit(&m->omsg, ptr, rr->resrec.name, rr->resrec.rrtype, limit);
+ if (!ptr) goto exit;
+ }
+ else if (rr->resrec.RecordType != kDNSRecordTypeShared)
+ {
+ // For now don't do this, until we have the logic for intelligent grouping of individual records into logical service record sets
+ //ptr = putPrereqNameNotInUse(rr->resrec.name, &m->omsg, ptr, end);
+ if (!ptr) goto exit;
+ }
+
+ ptr = PutResourceRecordTTLWithLimit(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit);
+ if (!ptr) goto exit;
}
+
+ return ptr;
+exit:
+ LogMsg("BuildUpdateMessage: Error formatting message for %s", ARDisplayString(m, rr));
+ return mDNSNULL;
}
// Called with lock held
mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr)
{
mDNSu8 *ptr = m->omsg.data;
- mDNSu8 *end = (mDNSu8 *)&m->omsg + sizeof(DNSMessage);
mStatus err = mStatus_UnknownErr;
+ mDNSu8 *limit;
+ DomainAuthInfo *AuthInfo;
+
+ // For the ability to register large TXT records, we limit the single record registrations
+ // to AbsoluteMaxDNSMessageData
+ limit = ptr + AbsoluteMaxDNSMessageData;
+
+ AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name);
+ limit -= RRAdditionalSize(m, AuthInfo);
if (m->mDNS_busy != m->mDNS_reentrancy+1)
LogMsg("SendRecordRegistration: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
- if (mDNSIPv4AddressIsZero(rr->UpdateServer.ip.v4)) // Don't know our UpdateServer yet
+ if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
{
- rr->LastAPTime = m->timenow;
- if (rr->ThisAPInterval < mDNSPlatformOneSecond * 5)
- rr->ThisAPInterval = mDNSPlatformOneSecond * 5;
+ // We never call this function when there is no zone information . Log a message if it ever happens.
+ LogMsg("SendRecordRegistration: No Zone information, should not happen %s", ARDisplayString(m, rr));
return;
}
- rr->RequireGoodbye = mDNStrue;
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));
- if (!ptr) { err = mStatus_UnknownErr; goto exit; }
+ ptr = putZone(&m->omsg, ptr, limit, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
+ if (!ptr) goto exit;
- if (rr->state == regState_UpdatePending)
- {
- // delete old RData
- SetNewRData(&rr->resrec, rr->OrigRData, rr->OrigRDLen);
- if (!(ptr = putDeletionRecord(&m->omsg, ptr, &rr->resrec))) { err = mStatus_UnknownErr; goto exit; } // delete old rdata
+ if (!(ptr = BuildUpdateMessage(m, ptr, rr, limit))) goto exit;
- // add new RData
- SetNewRData(&rr->resrec, rr->InFlightRData, rr->InFlightRDLen);
- if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl))) { err = mStatus_UnknownErr; goto exit; }
+ if (rr->uselease)
+ {
+ ptr = putUpdateLeaseWithLimit(&m->omsg, ptr, DEFAULT_UPDATE_LEASE, limit);
+ if (!ptr) goto exit;
+ }
+ if (rr->Private)
+ {
+ 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 = mDNSNULL; }
+ if (!rr->nta) { LogMsg("SendRecordRegistration:Private:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; }
+ rr->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &rr->nta->Addr, rr->nta->Port, &rr->nta->Host, mDNSNULL, rr);
}
-
else
{
- if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique)
- {
- // KnownUnique: Delete any previous value
- ptr = putDeleteRRSet(&m->omsg, ptr, rr->resrec.name, rr->resrec.rrtype);
- if (!ptr) { err = mStatus_UnknownErr; goto exit; }
- }
+ LogInfo("SendRecordRegistration UDP %s", ARDisplayString(m, rr));
+ if (!rr->nta) { LogMsg("SendRecordRegistration:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; }
+ err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->nta->Addr, rr->nta->Port, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name));
+ if (err) debugf("ERROR: SendRecordRegistration - mDNSSendDNSMessage - %d", err);
+ }
- else if (rr->resrec.RecordType != kDNSRecordTypeShared)
- {
- // 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; }
- }
+ SetRecordRetry(m, rr, 0);
+ return;
+exit:
+ LogMsg("SendRecordRegistration: Error formatting message for %s, disabling further updates", ARDisplayString(m, rr));
+ // Disable this record from future updates
+ rr->state = regState_NoTarget;
+ }
+
+// Is the given record "rr" eligible for merging ?
+mDNSlocal mDNSBool IsRecordMergeable(mDNS *const m, AuthRecord *rr, mDNSs32 time)
+ {
+ DomainAuthInfo *info;
+ (void) m; //unused
+ // A record is eligible for merge, if the following properties are met.
+ //
+ // 1. uDNS Resource Record
+ // 2. It is time to send them now
+ // 3. It is in proper state
+ // 4. Update zone has been resolved
+ // 5. if DomainAuthInfo exists for the zone, it should not be soon deleted
+ // 6. Zone information is present
+ // 7. Update server is not zero
+ // 8. It has a non-null zone
+ // 9. It uses a lease option
+ // 10. DontMerge is not set
+ //
+ // Following code is implemented as separate "if" statements instead of one "if" statement
+ // is for better debugging purposes e.g., we know exactly what failed if debugging turned on.
+
+ if (!AuthRecord_uDNS(rr)) return mDNSfalse;
+
+ if (rr->LastAPTime + rr->ThisAPInterval - time > 0)
+ { debugf("IsRecordMergeable: Time %d not reached for %s", rr->LastAPTime + rr->ThisAPInterval - m->timenow, ARDisplayString(m, rr)); return mDNSfalse; }
+
+ if (!rr->zone) return mDNSfalse;
+
+ info = GetAuthInfoForName_internal(m, rr->zone);
+
+ if (info && info->deltime && m->timenow - info->deltime >= 0) {debugf("IsRecordMergeable: Domain %##s will be deleted soon", info->domain.c); return mDNSfalse;}
+
+ if (rr->state != regState_DeregPending && rr->state != regState_Pending && rr->state != regState_Registered && rr->state != regState_Refresh && rr->state != regState_UpdatePending)
+ { debugf("IsRecordMergeable: state %d not right %s", rr->state, ARDisplayString(m, rr)); return mDNSfalse; }
+
+ if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4)) return mDNSfalse;
+
+ if (!rr->uselease) return mDNSfalse;
+
+ if (rr->mState == mergeState_DontMerge) {debugf("IsRecordMergeable Dontmerge true %s", ARDisplayString(m, rr));return mDNSfalse;}
+ debugf("IsRecordMergeable: Returning true for %s", ARDisplayString(m, rr));
+ return mDNStrue;
+ }
+
+// Is the resource record "rr" eligible to merge to with "currentRR" ?
+mDNSlocal mDNSBool AreRecordsMergeable(mDNS *const m, AuthRecord *currentRR, AuthRecord *rr, mDNSs32 time)
+ {
+ // A record is eligible to merge with another record as long it is eligible for merge in itself
+ // and it has the same zone information as the other record
+ if (!IsRecordMergeable(m, rr, time)) return mDNSfalse;
- ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl);
- if (!ptr) { err = mStatus_UnknownErr; goto exit; }
+ if (!SameDomainName(currentRR->zone, rr->zone))
+ { debugf("AreRecordMergeable zone mismatch current rr Zone %##s, rr zone %##s", currentRR->zone->c, rr->zone->c); return mDNSfalse; }
+
+ if (!mDNSSameIPv4Address(currentRR->nta->Addr.ip.v4, rr->nta->Addr.ip.v4)) return mDNSfalse;
+
+ if (!mDNSSameIPPort(currentRR->nta->Port, rr->nta->Port)) return mDNSfalse;
+
+ debugf("AreRecordsMergeable: Returning true for %s", ARDisplayString(m, rr));
+ return mDNStrue;
+ }
+
+// If we can't build the message successfully because of problems in pre-computing
+// the space, we disable merging for all the current records
+mDNSlocal void RRMergeFailure(mDNS *const m)
+ {
+ AuthRecord *rr;
+ for (rr = m->ResourceRecords; rr; rr = rr->next)
+ {
+ rr->mState = mergeState_DontMerge;
+ rr->SendRNow = mDNSNULL;
+ // Restarting the registration is much simpler than saving and restoring
+ // the exact time
+ ActivateUnicastRegistration(m, rr);
}
+ }
- if (rr->uselease)
+mDNSlocal void SendGroupRRMessage(mDNS *const m, AuthRecord *anchorRR, mDNSu8 *ptr, DomainAuthInfo *info)
+ {
+ mDNSu8 *limit;
+ if (!anchorRR) {debugf("SendGroupRRMessage: Could not merge records"); return;}
+
+ if (info && info->AutoTunnel) limit = m->omsg.data + AbsoluteMaxDNSMessageData;
+ else limit = m->omsg.data + NormalMaxDNSMessageData;
+
+ // This has to go in the additional section and hence need to be done last
+ ptr = putUpdateLeaseWithLimit(&m->omsg, ptr, DEFAULT_UPDATE_LEASE, limit);
+ if (!ptr)
+ {
+ LogMsg("SendGroupRRMessage: ERROR: Could not put lease option, failing the group registration");
+ // if we can't put the lease, we need to undo the merge
+ RRMergeFailure(m);
+ return;
+ }
+ if (anchorRR->Private)
+ {
+ if (anchorRR->tcp) debugf("SendGroupRRMessage: Disposing existing TCP connection for %s", ARDisplayString(m, anchorRR));
+ if (anchorRR->tcp) { DisposeTCPConn(anchorRR->tcp); anchorRR->tcp = mDNSNULL; }
+ if (!anchorRR->nta) { LogMsg("SendGroupRRMessage:ERROR!! nta is NULL for %s", ARDisplayString(m, anchorRR)); return; }
+ anchorRR->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &anchorRR->nta->Addr, anchorRR->nta->Port, &anchorRR->nta->Host, mDNSNULL, anchorRR);
+ if (!anchorRR->tcp) LogInfo("SendGroupRRMessage: Cannot establish TCP connection for %s", ARDisplayString(m, anchorRR));
+ else LogInfo("SendGroupRRMessage: Sent a group update ID: %d start %p, end %p, limit %p", mDNSVal16(m->omsg.h.id), m->omsg.data, ptr, limit);
+ }
+ else
{
- ptr = putUpdateLease(&m->omsg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) { err = mStatus_UnknownErr; goto exit; }
+ mStatus err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &anchorRR->nta->Addr, anchorRR->nta->Port, mDNSNULL, info);
+ if (err) LogInfo("SendGroupRRMessage: Cannot send UDP message for %s", ARDisplayString(m, anchorRR));
+ else LogInfo("SendGroupRRMessage: Sent a group UDP update ID: %d start %p, end %p, limit %p", mDNSVal16(m->omsg.h.id), m->omsg.data, ptr, limit);
}
+ return;
+ }
- if (rr->Private)
+// As we always include the zone information and the resource records contain zone name
+// at the end, it will get compressed. Hence, we subtract zoneSize and add two bytes for
+// the compression pointer
+mDNSlocal mDNSu32 RREstimatedSize(AuthRecord *rr, int zoneSize)
+ {
+ int rdlength;
+
+ // Note: Estimation of the record size has to mirror the logic in BuildUpdateMessage, otherwise estimation
+ // would be wrong. Currently BuildUpdateMessage calls SetNewRData in UpdatePending case. Hence, we need
+ // to account for that here. Otherwise, we might under estimate the size.
+ if (rr->state == regState_UpdatePending)
+ // old RData that will be deleted
+ // new RData that will be added
+ rdlength = rr->OrigRDLen + rr->InFlightRDLen;
+ else
+ rdlength = rr->resrec.rdestimate;
+
+ if (rr->state == regState_DeregPending)
{
- 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)
- else if (rr->ThisAPInterval < mDNSPlatformOneSecond * 30) rr->ThisAPInterval = mDNSPlatformOneSecond * 30;
+ debugf("RREstimatedSize: ResourceRecord %##s (%s), DomainNameLength %d, zoneSize %d, rdestimate %d",
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), DomainNameLength(rr->resrec.name), zoneSize, rdlength);
+ return DomainNameLength(rr->resrec.name) - zoneSize + 2 + 10 + rdlength;
+ }
+
+ // For SRV, TXT, AAAA etc. that are Unique/Verified, we also send a Deletion Record
+ if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique || rr->resrec.RecordType == kDNSRecordTypeVerified)
+ {
+ // Deletion Record: Resource Record Name + Base size (10) + 0
+ // Record: Resource Record Name (Compressed = 2) + Base size (10) + rdestimate
+
+ debugf("RREstimatedSize: ResourceRecord %##s (%s), DomainNameLength %d, zoneSize %d, rdestimate %d",
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), DomainNameLength(rr->resrec.name), zoneSize, rdlength);
+ return DomainNameLength(rr->resrec.name) - zoneSize + 2 + 10 + 2 + 10 + rdlength;
}
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 - %d", err);
+ return DomainNameLength(rr->resrec.name) - zoneSize + 2 + 10 + rdlength;
}
+ }
- SetRecordRetry(m, rr, err);
+mDNSlocal AuthRecord *MarkRRForSending(mDNS *const m)
+ {
+ AuthRecord *rr;
+ AuthRecord *firstRR = mDNSNULL;
- if (rr->state != regState_Refresh && rr->state != regState_DeregDeferred && rr->state != regState_UpdatePending)
- rr->state = regState_Pending;
+ // Look for records that needs to be sent in the next two seconds (MERGE_DELAY_TIME is set to 1 second).
+ // The logic is as follows.
+ //
+ // 1. Record 1 finishes getting zone data and its registration gets delayed by 1 second
+ // 2. Record 2 comes 0.1 second later, finishes getting its zone data and its registration is also delayed by
+ // 1 second which is now scheduled at 1.1 second
+ //
+ // By looking for 1 second into the future (m->timenow + MERGE_DELAY_TIME below does that) we have merged both
+ // of the above records. Note that we can't look for records too much into the future as this will affect the
+ // retry logic. The first retry is scheduled at 3 seconds. Hence, we should always look smaller than that.
+ // Anything more than one second will affect the first retry to happen sooner.
+ //
+ // Note: As a side effect of looking one second into the future to facilitate merging, the retries happen
+ // one second sooner.
+ for (rr = m->ResourceRecords; rr; rr = rr->next)
+ {
+ if (!firstRR)
+ {
+ if (!IsRecordMergeable(m, rr, m->timenow + MERGE_DELAY_TIME)) continue;
+ firstRR = rr;
+ }
+ else if (!AreRecordsMergeable(m, firstRR, rr, m->timenow + MERGE_DELAY_TIME)) continue;
- return;
+ if (rr->SendRNow) LogMsg("MarkRRForSending: Resourcerecord %s already marked for sending", ARDisplayString(m, rr));
+ rr->SendRNow = mDNSInterfaceMark;
+ }
-exit:
- LogMsg("SendRecordRegistration: Error formatting message for %s", ARDisplayString(m, rr));
+ // We parsed through all records and found something to send. The services/records might
+ // get registered at different times but we want the refreshes to be all merged and sent
+ // as one update. Hence, we accelerate some of the records so that they will sync up in
+ // the future. Look at the records excluding the ones that we have already sent in the
+ // previous pass. If it half way through its scheduled refresh/retransmit, merge them
+ // into this packet.
+ //
+ // Note that we only look at Registered/Refresh state to keep it simple. As we don't know
+ // whether the current update will fit into one or more packets, merging a resource record
+ // (which is in a different state) that has been scheduled for retransmit would trigger
+ // sending more packets.
+ if (firstRR)
+ {
+ int acc = 0;
+ for (rr = m->ResourceRecords; rr; rr = rr->next)
+ {
+ if ((rr->state != regState_Registered && rr->state != regState_Refresh) ||
+ (rr->SendRNow == mDNSInterfaceMark) ||
+ (!AreRecordsMergeable(m, firstRR, rr, m->timenow + rr->ThisAPInterval/2)))
+ continue;
+ rr->SendRNow = mDNSInterfaceMark;
+ acc++;
+ }
+ if (acc) LogInfo("MarkRRForSending: Accelereated %d records", acc);
+ }
+ return firstRR;
}
-// Called with lock held
-mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs, mStatus err)
+mDNSlocal mDNSBool SendGroupUpdates(mDNS *const m)
{
- mDNSBool InvokeCallback = mDNSfalse;
- ExtraResourceRecord **e = &srs->Extras;
- AuthRecord *txt = &srs->RR_TXT;
-
- 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);
+ mDNSOpaque16 msgid;
+ mDNSs32 spaceleft = 0;
+ mDNSs32 zoneSize, rrSize;
+ mDNSu8 *oldnext; // for debugging
+ mDNSu8 *next = m->omsg.data;
+ AuthRecord *rr;
+ AuthRecord *anchorRR = mDNSNULL;
+ int nrecords = 0;
+ AuthRecord *startRR = m->ResourceRecords;
+ mDNSu8 *limit = mDNSNULL;
+ DomainAuthInfo *AuthInfo = mDNSNULL;
+ mDNSBool sentallRecords = mDNStrue;
- debugf("hndlServiceUpdateReply: err %d state %d %##s", err, srs->state, srs->RR_SRV.resrec.name->c);
- SetRecordRetry(m, &srs->RR_SRV, mStatus_NoError);
+ // We try to fit as many ResourceRecords as possible in AbsoluteNormal/MaxDNSMessageData. Before we start
+ // putting in resource records, we need to reserve space for a few things. Every group/packet should
+ // have the following.
+ //
+ // 1) Needs space for the Zone information (which needs to be at the beginning)
+ // 2) Additional section MUST have space for lease option, HINFO and TSIG option (which needs to
+ // to be at the end)
+ //
+ // In future we need to reserve space for the pre-requisites which also goes at the beginning.
+ // To accomodate pre-requisites in the future, first we walk the whole list marking records
+ // that can be sent in this packet and computing the space needed for these records.
+ // For TXT and SRV records, we delete the previous record if any by sending the same
+ // resource record with ANY RDATA and zero rdlen. Hence, we need to have space for both of them.
+
+ while (startRR)
+ {
+ AuthInfo = mDNSNULL;
+ anchorRR = mDNSNULL;
+ nrecords = 0;
+ zoneSize = 0;
+ for (rr = startRR; rr; rr = rr->next)
+ {
+ if (rr->SendRNow != mDNSInterfaceMark) continue;
+
+ rr->SendRNow = mDNSNULL;
- switch (srs->state)
- {
- case regState_Pending:
- if (err == mStatus_NameConflict && !srs->TestForSelfConflict)
+ if (!anchorRR)
{
- srs->TestForSelfConflict = mDNStrue;
- debugf("checking for self-conflict of service %##s", srs->RR_SRV.resrec.name->c);
- SendServiceRegistration(m, srs);
- return;
- }
- else if (srs->TestForSelfConflict)
- {
- srs->TestForSelfConflict = mDNSfalse;
- if (err == mStatus_NoSuchRecord) err = mStatus_NameConflict; // NoSuchRecord implies that our prereq was not met, so we actually have a name conflict
- if (!err) srs->state = regState_Registered;
- InvokeCallback = mDNStrue;
- break;
- }
- else if (srs->srs_uselease && err == mStatus_UnknownErr && mDNSSameIPPort(srs->SRSUpdatePort, UnicastDNSPort))
- {
- LogMsg("Re-trying update of service %##s without lease option", srs->RR_SRV.resrec.name->c);
- srs->srs_uselease = mDNSfalse;
- SendServiceRegistration(m, srs);
- return;
- }
- else
- {
- //!!!KRS make sure all structs will still get cleaned up when client calls DeregisterService with this state
- 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;
- }
- case regState_Refresh:
- if (err)
- {
- 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 %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
- break;
- }
- err = mStatus_MemFree;
- InvokeCallback = mDNStrue;
- if (srs->NATinfo.clientContext)
- {
- // deletion completed
- mDNS_StopNATOperation_internal(m, &srs->NATinfo);
- srs->NATinfo.clientContext = mDNSNULL;
- }
- srs->state = regState_Unregistered;
- break;
- case regState_DeregDeferred:
- if (err)
- {
- 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;
- break;
- }
- else
- {
- debugf("Performing deferred deregistration of %##s", srs->RR_SRV.resrec.name->c);
- srs->state = regState_Registered;
- SendServiceDeregistration(m, srs);
- return;
+ AuthInfo = GetAuthInfoForName_internal(m, rr->zone);
+
+ // Though we allow single record registrations for UDP to be AbsoluteMaxDNSMessageData (See
+ // SendRecordRegistration) to handle large TXT records, to avoid fragmentation we limit UDP
+ // message to NormalMaxDNSMessageData
+ if (AuthInfo && AuthInfo->AutoTunnel) spaceleft = AbsoluteMaxDNSMessageData;
+ else spaceleft = NormalMaxDNSMessageData;
+
+ next = m->omsg.data;
+ spaceleft -= RRAdditionalSize(m, AuthInfo);
+ if (spaceleft <= 0)
+ {
+ LogMsg("SendGroupUpdates: ERROR!!: spaceleft is zero at the beginning");
+ RRMergeFailure(m);
+ return mDNSfalse;
+ }
+ limit = next + spaceleft;
+
+ // Build the initial part of message before putting in the other records
+ msgid = mDNS_NewMessageID(m);
+ InitializeDNSMessage(&m->omsg.h, msgid, UpdateReqFlags);
+
+ // We need zone information at the beginning of the packet. Length: ZNAME, ZTYPE(2), ZCLASS(2)
+ // zone has to be non-NULL for a record to be mergeable, hence it is safe to set/ examine zone
+ //without checking for NULL.
+ zoneSize = DomainNameLength(rr->zone) + 4;
+ spaceleft -= zoneSize;
+ if (spaceleft <= 0)
+ {
+ LogMsg("SendGroupUpdates: ERROR no space for zone information, disabling merge");
+ RRMergeFailure(m);
+ return mDNSfalse;
+ }
+ next = putZone(&m->omsg, next, limit, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
+ if (!next)
+ {
+ LogMsg("SendGroupUpdates: ERROR! Cannot put zone, disabling merge");
+ RRMergeFailure(m);
+ return mDNSfalse;
+ }
+ anchorRR = rr;
}
- case regState_UpdatePending:
- if (err)
+
+ rrSize = RREstimatedSize(rr, zoneSize - 4);
+
+ if ((spaceleft - rrSize) < 0)
{
- LogMsg("hndlServiceUpdateReply: error updating TXT record for service %##s", srs->RR_SRV.resrec.name->c);
- InvokeCallback = mDNStrue;
+ // If we can't fit even a single message, skip it, it will be sent separately
+ // in CheckRecordUpdates
+ if (!nrecords)
+ {
+ LogInfo("SendGroupUpdates: Skipping message %s, spaceleft %d, rrSize %d", ARDisplayString(m, rr), spaceleft, rrSize);
+ // Mark this as not sent so that the caller knows about it
+ rr->SendRNow = mDNSInterfaceMark;
+ // We need to remove the merge delay so that we can send it immediately
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
+ rr = rr->next;
+ anchorRR = mDNSNULL;
+ sentallRecords = mDNSfalse;
+ }
+ else
+ {
+ LogInfo("SendGroupUpdates:1: Parsed %d records and sending using %s, spaceleft %d, rrSize %d", nrecords, ARDisplayString(m, anchorRR), spaceleft, rrSize);
+ SendGroupRRMessage(m, anchorRR, next, AuthInfo);
+ }
+ break; // breaks out of for loop
}
- else
+ spaceleft -= rrSize;
+ oldnext = next;
+ LogInfo("SendGroupUpdates: Building a message with resource record %s, next %p, state %d", ARDisplayString(m, rr), next, rr->state);
+ if (!(next = BuildUpdateMessage(m, next, rr, limit)))
{
- srs->state = regState_Registered;
- // deallocate old RData
- if (txt->UpdateCallback) txt->UpdateCallback(m, txt, txt->OrigRData);
- SetNewRData(&txt->resrec, txt->InFlightRData, txt->InFlightRDLen);
- txt->OrigRData = mDNSNULL;
- txt->InFlightRData = mDNSNULL;
+ // We calculated the space and if we can't fit in, we had some bug in the calculation,
+ // disable merge completely.
+ LogMsg("SendGroupUpdates: ptr NULL while building message with %s", ARDisplayString(m, rr));
+ RRMergeFailure(m);
+ return mDNSfalse;
}
- break;
- case regState_NoTarget:
- // This state is used when using SendServiceDeregistration() when going to sleep -- no further action required
- return;
- case regState_FetchingZoneData:
- case regState_Registered:
- case regState_Unregistered:
- case regState_NATMap:
- case regState_ExtraQueued:
- case regState_NATError:
- 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);
+ // If our estimate was higher, adjust to the actual size
+ if ((next - oldnext) > rrSize)
+ LogMsg("SendGroupUpdates: ERROR!! Record size estimation is wrong for %s, Estimate %d, Actual %d, state %d", ARDisplayString(m, rr), rrSize, next - oldnext, rr->state);
+ else { spaceleft += rrSize; spaceleft -= (next - oldnext); }
+
+ nrecords++;
+ // We could have sent an update earlier with this "rr" as anchorRR for which we never got a response.
+ // To preserve ordering, we blow away the previous connection before sending this.
+ if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL;}
+ rr->updateid = msgid;
+
+ // By setting the retry time interval here, we will not be looking at these records
+ // again when we return to CheckGroupRecordUpdates.
+ SetRecordRetry(m, rr, 0);
+ }
+ // Either we have parsed all the records or stopped at "rr" above due to lack of space
+ startRR = rr;
}
- if ((srs->SRVChanged || srs->SRVUpdateDeferred) && (srs->state == regState_NoTarget || srs->state == regState_Registered))
+ if (anchorRR)
{
- debugf("hndlServiceUpdateReply: SRVChanged %d SRVUpdateDeferred %d state %d", srs->SRVChanged, srs->SRVUpdateDeferred, srs->state);
- if (InvokeCallback)
- {
- srs->ClientCallbackDeferred = mDNStrue;
- srs->DeferredStatus = err;
- }
- srs->SRVChanged = srs->SRVUpdateDeferred = mDNSfalse;
- UpdateSRV(m, srs);
- return;
+ LogInfo("SendGroupUpdates: Parsed %d records and sending using %s", nrecords, ARDisplayString(m, anchorRR));
+ SendGroupRRMessage(m, anchorRR, next, AuthInfo);
}
+ return sentallRecords;
+ }
- while (*e)
+// Merge the record registrations and send them as a group only if they
+// have same DomainAuthInfo and hence the same key to put the TSIG
+mDNSlocal void CheckGroupRecordUpdates(mDNS *const m)
+ {
+ AuthRecord *rr, *nextRR;
+ // Keep sending as long as there is at least one record to be sent
+ while (MarkRRForSending(m))
{
- if ((*e)->r.state == regState_ExtraQueued)
+ if (!SendGroupUpdates(m))
{
- if (srs->state == regState_Registered && !err)
+ // if everything that was marked was not sent, send them out individually
+ for (rr = m->ResourceRecords; rr; rr = nextRR)
{
- // extra resource record queued for this service - copy zone srs and register
- (*e)->r.zone = &srs->zone;
- (*e)->r.UpdateServer = srs->SRSUpdateServer;
- (*e)->r.UpdatePort = srs->SRSUpdatePort;
- (*e)->r.uselease = srs->srs_uselease;
- SendRecordRegistration(m, &(*e)->r);
- e = &(*e)->next;
- }
- else if (err && (*e)->r.state != regState_Unregistered)
- {
- // unlink extra from list
- (*e)->r.state = regState_Unregistered;
- *e = (*e)->next;
+ // SendRecordRegistrtion might delete the rr from list, hence
+ // dereference nextRR before calling the function
+ nextRR = rr->next;
+ if (rr->SendRNow == mDNSInterfaceMark)
+ {
+ // Any records marked for sending should be eligible to be sent out
+ // immediately. Just being cautious
+ if (rr->LastAPTime + rr->ThisAPInterval - m->timenow > 0)
+ { LogMsg("CheckGroupRecordUpdates: ERROR!! Resourcerecord %s not ready", ARDisplayString(m, rr)); continue; }
+ rr->SendRNow = mDNSNULL;
+ SendRecordRegistration(m, rr);
+ }
}
- else e = &(*e)->next;
}
- else e = &(*e)->next;
}
+
+ debugf("CheckGroupRecordUpdates: No work, returning");
+ return;
+ }
- if (srs->state == regState_Unregistered)
- {
- if (err != mStatus_MemFree)
- LogMsg("hndlServiceUpdateReply ERROR! state == regState_Unregistered but err != mStatus_MemFree. Permanently abandoning service registration %##s",
- srs->RR_SRV.resrec.name->c);
- unlinkSRS(m, srs);
- }
- else if (txt->QueuedRData && srs->state == regState_Registered)
+mDNSlocal void hndlSRVChanged(mDNS *const m, AuthRecord *rr)
+ {
+ // Reevaluate the target always as NAT/Target could have changed while
+ // we were registering/deeregistering
+ domainname *dt;
+ const domainname *target = GetServiceTarget(m, rr);
+ if (!target || target->c[0] == 0)
{
- if (InvokeCallback)
+ // we don't have a target, if we just derregistered, then we don't have to do anything
+ if (rr->state == regState_DeregPending)
{
- // if we were supposed to give a client callback, we'll do it after we update the primary txt record
- srs->ClientCallbackDeferred = mDNStrue;
- srs->DeferredStatus = err;
+ LogInfo("hndlSRVChanged: SRVChanged, No Target, SRV Deregistered for %##s, state %d", rr->resrec.name->c,
+ rr->state);
+ rr->SRVChanged = mDNSfalse;
+ dt = GetRRDomainNameTarget(&rr->resrec);
+ if (dt) dt->c[0] = 0;
+ rr->state = regState_NoTarget; // Wait for the next target change
+ rr->resrec.rdlength = rr->resrec.rdestimate = 0;
+ return;
}
- srs->state = regState_UpdatePending;
- txt->InFlightRData = txt->QueuedRData;
- txt->InFlightRDLen = txt->QueuedRDLen;
- txt->OrigRData = txt->resrec.rdata;
- txt->OrigRDLen = txt->resrec.rdlength;
- txt->QueuedRData = mDNSNULL;
- SendServiceRegistration(m, srs);
- return;
+
+ // we don't have a target, if we just registered, we need to deregister
+ if (rr->state == regState_Pending)
+ {
+ LogInfo("hndlSRVChanged: SRVChanged, No Target, Deregistering again %##s, state %d", rr->resrec.name->c, rr->state);
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
+ rr->state = regState_DeregPending;
+ return;
+ }
+ LogInfo("hndlSRVChanged: Not in DeregPending or RegPending state %##s, state %d", rr->resrec.name->c, rr->state);
}
-
- mDNS_DropLockBeforeCallback();
- if (InvokeCallback)
- srs->ServiceCallback(m, srs, err);
- else if (srs->ClientCallbackDeferred)
+ else
{
- srs->ClientCallbackDeferred = mDNSfalse;
- srs->ServiceCallback(m, srs, srs->DeferredStatus);
+ // If we were in registered state and SRV changed to NULL, we deregister and come back here
+ // if we have a target, we need to register again.
+ //
+ // if we just registered check to see if it is same. If it is different just re-register the
+ // SRV and its assoicated records
+ //
+ // UpdateOneSRVRecord takes care of re-registering all service records
+ if ((rr->state == regState_DeregPending) ||
+ (rr->state == regState_Pending && !SameDomainName(target, &rr->resrec.rdata->u.srv.target)))
+ {
+ dt = GetRRDomainNameTarget(&rr->resrec);
+ if (dt) dt->c[0] = 0;
+ rr->state = regState_NoTarget; // NoTarget will allow us to pick up new target OR nat traversal state
+ rr->resrec.rdlength = rr->resrec.rdestimate = 0;
+ LogInfo("hndlSRVChanged: SRVChanged, Valid Target %##s, Registering all records for %##s, state %d",
+ target->c, rr->resrec.name->c, rr->state);
+ rr->SRVChanged = mDNSfalse;
+ UpdateOneSRVRecord(m, rr);
+ return;
+ }
+ // Target did not change while this record was registering. Hence, we go to
+ // Registered state - the state we started from.
+ if (rr->state == regState_Pending) rr->state = regState_Registered;
}
- mDNS_ReclaimLockAfterCallback();
- // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
- // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
+
+ rr->SRVChanged = mDNSfalse;
}
// Called with lock held
-mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err)
+mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err, mDNSu32 random)
{
mDNSBool InvokeCallback = mDNStrue;
+ mDNSIPPort UpdatePort = zeroIPPort;
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);
- LogInfo("hndlRecordUpdateReply: err %d state %d %s", err, rr->state, ARDisplayString(m, rr));
+ LogInfo("hndlRecordUpdateReply: err %d ID %d state %d %s(%p)", err, mDNSVal16(rr->updateid), rr->state, ARDisplayString(m, rr), rr);
+
+ rr->updateError = err;
+#if APPLE_OSX_mDNSResponder
+ if (err == mStatus_BadSig) UpdateAutoTunnelDomainStatuses(m);
+#endif
+
+ SetRecordRetry(m, rr, random);
- if (m->SleepState) return; // If we just sent a deregister on going to sleep, no further action required
+ rr->updateid = zeroID; // Make sure that this is not considered as part of a group anymore
+ // Later when need to send an update, we will get the zone data again. Thus we avoid
+ // using stale information.
+ //
+ // Note: By clearing out the zone info here, it also helps better merging of records
+ // in some cases. For example, when we get out regState_NoTarget state e.g., move out
+ // of Double NAT, we want all the records to be in one update. Some BTMM records like
+ // _autotunnel6 and host records are registered/deregistered when NAT state changes.
+ // As they are re-registered the zone information is cleared out. To merge with other
+ // records that might be possibly going out, clearing out the information here helps
+ // as all of them try to get the zone data.
+ if (rr->nta)
+ {
+ // We always expect the question to be stopped when we get a valid response from the server.
+ // If the zone info tries to change during this time, updateid would be different and hence
+ // this response should not have been accepted.
+ if (rr->nta->question.ThisQInterval != -1)
+ LogMsg("hndlRecordUpdateReply: ResourceRecord %s, zone info question %##s (%s) interval %d not -1",
+ ARDisplayString(m, rr), rr->nta->question.qname.c, DNSTypeName(rr->nta->question.qtype), rr->nta->question.ThisQInterval);
+ UpdatePort = rr->nta->Port;
+ CancelGetZoneData(m, rr->nta);
+ rr->nta = mDNSNULL;
+ }
+
+ // If we are deregistering the record, then complete the deregistration. Ignore any NAT/SRV change
+ // that could have happened during that time.
+ if (rr->resrec.RecordType == kDNSRecordTypeDeregistering && rr->state == regState_DeregPending)
+ {
+ debugf("hndlRecordUpdateReply: 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 %d",
+ rr->resrec.name->c, rr->resrec.rrtype, err);
+ rr->state = regState_Unregistered;
+ CompleteDeregistration(m, rr);
+ return;
+ }
- SetRecordRetry(m, rr, mStatus_NoError);
+ // We are returning early without updating the state. When we come back from sleep we will re-register after
+ // re-initializing all the state as though it is a first registration. If the record can't be registered e.g.,
+ // no target, it will be deregistered. Hence, the updating to the right state should not matter when going
+ // to sleep.
+ if (m->SleepState)
+ {
+ // Need to set it to NoTarget state so that RecordReadyForSleep knows that
+ // we are done
+ if (rr->resrec.rrtype == kDNSType_SRV && rr->state == regState_DeregPending)
+ rr->state = regState_NoTarget;
+ return;
+ }
if (rr->state == regState_UpdatePending)
{
if (err) LogMsg("Update record failed for %##s (err %d)", rr->resrec.name->c, err);
rr->state = regState_Registered;
// deallocate old RData
- if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->OrigRData);
+ if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->OrigRData, rr->OrigRDLen);
SetNewRData(&rr->resrec, rr->InFlightRData, rr->InFlightRDLen);
rr->OrigRData = mDNSNULL;
rr->InFlightRData = mDNSNULL;
}
- 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 %d",
- rr->resrec.name->c, rr->resrec.rrtype, err);
- err = mStatus_MemFree;
- rr->state = regState_Unregistered;
- }
-
- if (rr->state == regState_DeregDeferred)
+ if (rr->SRVChanged)
{
- if (err)
+ if (rr->resrec.rrtype == kDNSType_SRV)
+ hndlSRVChanged(m, rr);
+ else
{
- 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;
+ LogInfo("hndlRecordUpdateReply: Deregistered %##s (%s), state %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->state);
+ rr->SRVChanged = mDNSfalse;
+ if (rr->state != regState_DeregPending) LogMsg("hndlRecordUpdateReply: ResourceRecord %s not in DeregPending state %d", ARDisplayString(m, rr), rr->state);
+ rr->state = regState_NoTarget; // Wait for the next target change
}
- debugf("Calling deferred deregistration of record %##s type %d", rr->resrec.name->c, rr->resrec.rrtype);
- rr->state = regState_Registered;
- mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
return;
}
-
+
if (rr->state == regState_Pending || rr->state == regState_Refresh)
{
if (!err)
}
else
{
- if (rr->uselease && err == mStatus_UnknownErr && mDNSSameIPPort(rr->UpdatePort, UnicastDNSPort))
+ // Retry without lease only for non-Private domains
+ LogMsg("hndlRecordUpdateReply: Registration of record %##s type %d failed with error %d", rr->resrec.name->c, rr->resrec.rrtype, err);
+ if (!rr->Private && rr->uselease && err == mStatus_UnknownErr && mDNSSameIPPort(UpdatePort, UnicastDNSPort))
{
- LogMsg("Re-trying update of record %##s without lease option", rr->resrec.name->c);
+ LogMsg("hndlRecordUpdateReply: Will retry update of record %##s without lease option", rr->resrec.name->c);
rr->uselease = mDNSfalse;
- SendRecordRegistration(m, rr);
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
return;
}
- LogMsg("hndlRecordUpdateReply: Registration of record %##s type %d failed with error %d", rr->resrec.name->c, rr->resrec.rrtype, err);
- return;
+ // Communicate the error to the application in the callback below
}
}
- if (rr->state == regState_Unregistered) // Should never happen
- {
- LogMsg("hndlRecordUpdateReply rr->state == regState_Unregistered %s", ARDisplayString(m, rr));
- return;
- }
-
if (rr->QueuedRData && rr->state == regState_Registered)
{
rr->state = regState_UpdatePending;
rr->OrigRData = rr->resrec.rdata;
rr->OrigRDLen = rr->resrec.rdlength;
rr->QueuedRData = mDNSNULL;
- SendRecordRegistration(m, rr);
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
return;
}
- if (InvokeCallback && rr->RecordCallback)
+ // Don't invoke the callback on error as this may not be useful to the client.
+ // The client may potentially delete the resource record on error which we normally
+ // delete during deregistration
+ if (!err && InvokeCallback && rr->RecordCallback)
{
+ LogInfo("hndlRecordUpdateReply: Calling record callback on %##s", rr->resrec.name->c);
mDNS_DropLockBeforeCallback();
rr->RecordCallback(m, rr, err);
mDNS_ReclaimLockAfterCallback();
// 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
- // 2. We add a two-second safety margin to allow for rounding errors:
- // -- e.g. if NAT gateway sends a packet at t=2.00 seconds, then one at t=7.99, that's virtually 6 seconds,
- // but based on the values in the packet (2,7) the apparent difference is only 5 seconds
- // -- similarly, if we're slow handling packets and/or we have coarse clock granularity, we could over-estimate the true interval
- // (e.g. t=1.99 seconds rounded to 1, and t=8.01 rounded to 8, gives an apparent difference of 7 seconds)
+ // 2. We add a two-second safety margin to allow for rounding errors: e.g.
+ // -- if NAT gateway sends a packet at t=2.000 seconds, then one at t=7.999, that's approximately 6 real seconds,
+ // but based on the values in the packet (2,7) the apparent difference according to the packet is only 5 seconds
+ // -- if we're slow handling packets and/or we have coarse clock granularity,
+ // we could receive the t=2 packet at our t=1.999 seconds, which we round down to 1
+ // and the t=7.999 packet at our t=8.000 seconds, which we record as 8,
+ // giving an apparent local time difference of 7 seconds
+ // The two-second safety margin coves this possible calculation discrepancy
if (AddrReply->upseconds < m->LastNATupseconds || nat_elapsed + 2 < our_elapsed - our_elapsed/8)
{ LogMsg("NAT gateway %#a rebooted", &m->Router); RecreateNATMappings(m); }
(void)srcport; // Unused
debugf("uDNS_ReceiveMsg from %#-15a with "
- "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s",
+ "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes",
srcaddr,
- msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,",
- msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,",
+ 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");
+ msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s", end - msg->data);
if (QR_OP == StdR)
{
if (msg->h.flags.b[0] & kDNSFlag0_TC && mDNSSameOpaque16(qptr->TargetQID, msg->h.id) && m->timenow - qptr->LastQTime < RESPONSE_WINDOW)
{
if (!srcaddr) LogMsg("uDNS_ReceiveMsg: TCP DNS response had TC bit set: ignoring");
- else if (qptr->tcp)
+ else
{
- // 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
- 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();
+ // Don't reuse TCP connections. We might have failed over to a different DNS server
+ // while the first TCP connection is in progress. We need a new TCP connection to the
+ // new DNS server. So, always try to establish a new connection.
+ if (qptr->tcp) { DisposeTCPConn(qptr->tcp); qptr->tcp = mDNSNULL; }
+ qptr->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_Zero, srcaddr, srcport, mDNSNULL, qptr, mDNSNULL);
}
- else qptr->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_Zero, srcaddr, srcport, qptr, mDNSNULL, mDNSNULL);
}
}
if (QR_OP == UpdateR)
{
mDNSu32 lease = GetPktLease(m, msg, end);
- mDNSs32 expire = m->timenow + (mDNSs32)lease * mDNSPlatformOneSecond;
-
- //rcode = kDNSFlag1_RC_ServFail; // Simulate server failure (rcode 2)
-
- if (CurrentServiceRecordSet)
- LogMsg("uDNS_ReceiveMsg ERROR CurrentServiceRecordSet already set");
- CurrentServiceRecordSet = m->ServiceRegistrations;
-
- while (CurrentServiceRecordSet)
- {
- ServiceRecordSet *sptr = CurrentServiceRecordSet;
- CurrentServiceRecordSet = CurrentServiceRecordSet->uDNS_next;
-
- if (mDNSSameOpaque16(sptr->id, msg->h.id))
- {
- err = checkUpdateResult(m, sptr->RR_SRV.resrec.name, rcode, msg, end);
- if (!err && sptr->srs_uselease && lease)
- if (sptr->RR_SRV.expire - expire >= 0 || sptr->state != regState_UpdatePending)
- sptr->RR_SRV.expire = expire;
- hndlServiceUpdateReply(m, sptr, err);
- CurrentServiceRecordSet = mDNSNULL;
- return;
- }
- }
+ mDNSs32 expire = m->timenow + (mDNSs32)lease * mDNSPlatformOneSecond;
+ mDNSu32 random = mDNSRandom((mDNSs32)lease * mDNSPlatformOneSecond/10);
+
+ //rcode = kDNSFlag1_RC_ServFail; // Simulate server failure (rcode 2)
+ // Walk through all the records that matches the messageID. There could be multiple
+ // records if we had sent them in a group
if (m->CurrentRecord)
LogMsg("uDNS_ReceiveMsg ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
m->CurrentRecord = m->ResourceRecords;
err = checkUpdateResult(m, rptr->resrec.name, rcode, msg, end);
if (!err && rptr->uselease && lease)
if (rptr->expire - expire >= 0 || rptr->state != regState_UpdatePending)
+ {
rptr->expire = expire;
- hndlRecordUpdateReply(m, rptr, err);
- m->CurrentRecord = mDNSNULL;
- return;
+ rptr->refreshCount = 0;
+ }
+ // We pass the random value to make sure that if we update multiple
+ // records, they all get the same random value
+ hndlRecordUpdateReply(m, rptr, err, random);
}
}
}
{
mDNSu8 *end;
LLQOptData llq;
+ mDNSu8 *limit = m->omsg.data + AbsoluteMaxDNSMessageData;
if (q->ReqLease)
if ((q->state == LLQ_Established && q->ntries >= kLLQ_MAX_TRIES) || q->expire - m->timenow < 0)
// Note that we (conditionally) add HINFO and TSIG here, since the question might be going away,
// so we may not be able to reference it (most importantly it's AuthInfo) when we actually send the message
- end = putHINFO(m, &m->omsg, end, q->AuthInfo);
+ end = putHINFO(m, &m->omsg, end, q->AuthInfo, limit);
if (!end) { LogMsg("sendLLQRefresh: putHINFO failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; }
- if (q->AuthInfo)
+ if (PrivateQuery(q))
{
DNSDigest_SignMessageHostByteOrder(&m->omsg, &end, q->AuthInfo);
if (!end) { LogMsg("sendLLQRefresh: DNSDigest_SignMessage failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; }
}
- if (q->AuthInfo && !q->tcp)
+ if (PrivateQuery(q) && !q->tcp)
{
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);
+ if (!q->nta) { LogMsg("sendLLQRefresh:ERROR!! q->nta is NULL for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; }
+ q->tcp = MakeTCPConn(m, &m->omsg, end, kTCPSocketFlags_UseTLS, &q->servAddr, q->servPort, &q->nta->Host, q, mDNSNULL);
}
else
{
- mStatus err = mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, mDNSNULL);
+ mStatus err;
+
+ // if AuthInfo and AuthInfo->AutoTunnel is set, we use the TCP socket but don't need to pass the AuthInfo as
+ // we already protected the message above.
+ LogInfo("sendLLQRefresh: using existing %s session %##s (%s)", PrivateQuery(q) ? "TLS" : "UDP",
+ q->qname.c, DNSTypeName(q->qtype));
+
+ err = mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, mDNSNULL);
if (err)
{
LogMsg("sendLLQRefresh: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err);
mDNS_Lock(m);
- // 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
- // we use for cleaning up if our LLQ is cancelled *before* the GetZoneData operation has completes).
- q->nta = mDNSNULL;
+ // If we get here it means that the GetZoneData operation has completed.
+ // We hold on to the zone data if it is AutoTunnel as we use the hostname
+ // in zoneInfo during the TLS connection setup.
q->servAddr = zeroAddr;
q->servPort = zeroIPPort;
- if (!err && zoneInfo && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr))
+ if (!err && zoneInfo && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr) && zoneInfo->Host.c[0])
{
q->servAddr = zoneInfo->Addr;
q->servPort = zoneInfo->Port;
- q->AuthInfo = zoneInfo->ZonePrivate ? GetAuthInfoForName_internal(m, &q->qname) : mDNSNULL;
+ if (!PrivateQuery(q))
+ {
+ // We don't need the zone data as we use it only for the Host information which we
+ // don't need if we are not going to use TLS connections.
+ if (q->nta)
+ {
+ if (q->nta != zoneInfo) LogMsg("LLQGotZoneData: nta (%p) != zoneInfo (%p) %##s (%s)", q->nta, zoneInfo, q->qname.c, DNSTypeName(q->qtype));
+ CancelGetZoneData(m, q->nta);
+ q->nta = mDNSNULL;
+ }
+ }
q->ntries = 0;
debugf("LLQGotZoneData %#a:%d", &q->servAddr, mDNSVal16(q->servPort));
startLLQHandshake(m, q);
}
else
{
+ if (q->nta)
+ {
+ if (q->nta != zoneInfo) LogMsg("LLQGotZoneData: nta (%p) != zoneInfo (%p) %##s (%s)", q->nta, zoneInfo, q->qname.c, DNSTypeName(q->qtype));
+ CancelGetZoneData(m, q->nta);
+ q->nta = mDNSNULL;
+ }
StartLLQPolling(m,q);
if (err == mStatus_NoSuchNameErr)
{
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
- // we use for cleaning up if our LLQ is cancelled *before* the GetZoneData operation has completes).
- q->nta = mDNSNULL;
+ if (q->nta != zoneInfo) LogMsg("PrivateQueryGotZoneData:ERROR!!: nta (%p) != zoneInfo (%p) %##s (%s)", q->nta, zoneInfo, q->qname.c, DNSTypeName(q->qtype));
- if (err || !zoneInfo || mDNSAddressIsZero(&zoneInfo->Addr) || mDNSIPPortIsZero(zoneInfo->Port))
+ if (err || !zoneInfo || mDNSAddressIsZero(&zoneInfo->Addr) || mDNSIPPortIsZero(zoneInfo->Port) || !zoneInfo->Host.c[0])
{
- LogInfo("ERROR: PrivateQueryGotZoneData %##s (%s) invoked with error code %d %p %#a:%d",
+ LogInfo("PrivateQueryGotZoneData: ERROR!! %##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);
+ CancelGetZoneData(m, q->nta);
+ q->nta = mDNSNULL;
return;
}
q->AuthInfo = mDNSNULL; // Clear AuthInfo so we try again non-private
q->ThisQInterval = InitialQuestionInterval;
q->LastQTime = m->timenow - q->ThisQInterval;
+ CancelGetZoneData(m, q->nta);
+ q->nta = mDNSNULL;
mDNS_Lock(m);
SetNextQueryTime(m, q);
mDNS_Unlock(m);
// Next call to uDNS_CheckCurrentQuestion() will do this as a non-private query
}
- if (!q->AuthInfo)
+ if (!PrivateQuery(q))
{
- LogMsg("ERROR: PrivateQueryGotZoneData: cannot find credentials for q %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ LogMsg("PrivateQueryGotZoneData: ERROR!! Not a private query %##s (%s) AuthInfo %p", q->qname.c, DNSTypeName(q->qtype), q->AuthInfo);
+ CancelGetZoneData(m, q->nta);
+ q->nta = mDNSNULL;
return;
}
q->TargetQID = mDNS_NewMessageID(m);
- if (q->tcp) DisposeTCPConn(q->tcp);
- q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_UseTLS, &zoneInfo->Addr, zoneInfo->Port, q, mDNSNULL, mDNSNULL);
+ if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
+ if (!q->nta) { LogMsg("PrivateQueryGotZoneData:ERROR!! nta is NULL for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; }
+ q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_UseTLS, &zoneInfo->Addr, zoneInfo->Port, &q->nta->Host, q, mDNSNULL);
+ if (q->nta) { CancelGetZoneData(m, q->nta); q->nta = mDNSNULL; }
}
// ***************************************************************************
AuthRecord *ptr;
int c1, c2;
+ if (newRR->nta != zoneData)
+ LogMsg("RecordRegistrationGotZoneData: nta (%p) != zoneData (%p) %##s (%s)", newRR->nta, zoneData, newRR->resrec.name->c, DNSTypeName(newRR->resrec.rrtype));
+
if (m->mDNS_busy != m->mDNS_reentrancy)
LogMsg("RecordRegistrationGotZoneData: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
- newRR->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
- newRR->uselease = mDNStrue;
-
// make sure record is still in list (!!!)
for (ptr = m->ResourceRecords; ptr; ptr = ptr->next) if (ptr == newRR) break;
- if (!ptr) { LogMsg("RecordRegistrationGotZoneData - RR no longer in list. Discarding."); return; }
+ if (!ptr)
+ {
+ LogMsg("RecordRegistrationGotZoneData - RR no longer in list. Discarding.");
+ CancelGetZoneData(m, newRR->nta);
+ newRR->nta = mDNSNULL;
+ return;
+ }
// check error/result
if (err)
{
if (err != mStatus_NoSuchNameErr) LogMsg("RecordRegistrationGotZoneData: error %d", err);
+ CancelGetZoneData(m, newRR->nta);
+ newRR->nta = mDNSNULL;
return;
}
if (newRR->resrec.rrclass != zoneData->ZoneClass)
{
LogMsg("ERROR: New resource record's class (%d) does not match zone class (%d)", newRR->resrec.rrclass, zoneData->ZoneClass);
+ CancelGetZoneData(m, newRR->nta);
+ newRR->nta = mDNSNULL;
return;
}
if (zoneData->ZoneName.c[0] == 0)
{
LogInfo("RecordRegistrationGotZoneData: No name server found claiming responsibility for \"%##s\"!", newRR->resrec.name->c);
+ CancelGetZoneData(m, newRR->nta);
+ newRR->nta = mDNSNULL;
return;
}
if (c2 > c1)
{
LogMsg("RecordRegistrationGotZoneData: Zone \"%##s\" is longer than \"%##s\"", zoneData->ZoneName.c, newRR->resrec.name->c);
+ CancelGetZoneData(m, newRR->nta);
+ newRR->nta = mDNSNULL;
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);
+ CancelGetZoneData(m, newRR->nta);
+ newRR->nta = mDNSNULL;
return;
}
- newRR->UpdateServer = zoneData->Addr;
- newRR->UpdatePort = zoneData->Port;
- newRR->Private = zoneData->ZonePrivate;
- debugf("RecordRegistrationGotZoneData: Set newRR->UpdateServer %##s %##s to %#a:%d",
- newRR->resrec.name->c, zoneData->ZoneName.c, &newRR->UpdateServer, mDNSVal16(newRR->UpdatePort));
- if (mDNSIPPortIsZero(zoneData->Port) || mDNSAddressIsZero(&zoneData->Addr))
+ if (mDNSIPPortIsZero(zoneData->Port) || mDNSAddressIsZero(&zoneData->Addr) || !zoneData->Host.c[0])
{
LogInfo("RecordRegistrationGotZoneData: No _dns-update._udp service found for \"%##s\"!", newRR->resrec.name->c);
+ CancelGetZoneData(m, newRR->nta);
+ newRR->nta = mDNSNULL;
return;
}
- newRR->ThisAPInterval = 5 * mDNSPlatformOneSecond; // After doubling, first retry will happen after ten seconds
+ newRR->Private = zoneData->ZonePrivate;
+ debugf("RecordRegistrationGotZoneData: Set zone information for %##s %##s to %#a:%d",
+ newRR->resrec.name->c, zoneData->ZoneName.c, &zoneData->Addr, mDNSVal16(zoneData->Port));
+
+ // If we are deregistering, uDNS_DeregisterRecord will do that as it has the zone data now.
+ if (newRR->state == regState_DeregPending)
+ {
+ mDNS_Lock(m);
+ uDNS_DeregisterRecord(m, newRR);
+ mDNS_Unlock(m);
+ return;
+ }
- mDNS_Lock(m); // SendRecordRegistration expects to be called with the lock held
- SendRecordRegistration(m, newRR);
+ if (newRR->resrec.rrtype == kDNSType_SRV)
+ {
+ const domainname *target;
+ // Reevaluate the target always as NAT/Target could have changed while
+ // we were fetching zone data.
+ mDNS_Lock(m);
+ target = GetServiceTarget(m, newRR);
+ mDNS_Unlock(m);
+ if (!target || target->c[0] == 0)
+ {
+ domainname *t = GetRRDomainNameTarget(&newRR->resrec);
+ LogInfo("RecordRegistrationGotZoneData - no target for %##s", newRR->resrec.name->c);
+ if (t) t->c[0] = 0;
+ newRR->resrec.rdlength = newRR->resrec.rdestimate = 0;
+ newRR->state = regState_NoTarget;
+ CancelGetZoneData(m, newRR->nta);
+ newRR->nta = mDNSNULL;
+ return;
+ }
+ }
+ // 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 SendRecordRegistration() for us
+ if (newRR->resrec.rrtype == kDNSType_SRV && !mDNSIPPortIsZero(newRR->resrec.rdata->u.srv.port) &&
+ mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) && newRR->nta && !mDNSAddrIsRFC1918(&newRR->nta->Addr) &&
+ newRR->AutoTarget == Target_AutoHostAndNATMAP)
+ {
+ DomainAuthInfo *AuthInfo;
+ AuthInfo = GetAuthInfoForName(m, newRR->resrec.name);
+ if (AuthInfo && AuthInfo->AutoTunnel)
+ {
+ domainname *t = GetRRDomainNameTarget(&newRR->resrec);
+ LogMsg("RecordRegistrationGotZoneData: ERROR!! AutoTunnel has Target_AutoHostAndNATMAP for %s", ARDisplayString(m, newRR));
+ if (t) t->c[0] = 0;
+ newRR->resrec.rdlength = newRR->resrec.rdestimate = 0;
+ newRR->state = regState_NoTarget;
+ CancelGetZoneData(m, newRR->nta);
+ newRR->nta = mDNSNULL;
+ return;
+ }
+ // During network transitions, we are called multiple times in different states. Setup NAT
+ // state just once for this record.
+ if (!newRR->NATinfo.clientContext)
+ {
+ LogInfo("RecordRegistrationGotZoneData StartRecordNatMap %s", ARDisplayString(m, newRR));
+ newRR->state = regState_NATMap;
+ StartRecordNatMap(m, newRR);
+ return;
+ }
+ else LogInfo("RecordRegistrationGotZoneData: StartRecordNatMap for %s, state %d, context %p", ARDisplayString(m, newRR), newRR->state, newRR->NATinfo.clientContext);
+ }
+ mDNS_Lock(m);
+ // We want IsRecordMergeable to check whether it is a record whose update can be
+ // sent with others. We set the time before we call IsRecordMergeable, so that
+ // it does not fail this record based on time. We are interested in other checks
+ // at this time. If a previous update resulted in error, then don't reset the
+ // interval. Preserve the back-off so that we don't keep retrying aggressively.
+ if (newRR->updateError == mStatus_NoError)
+ {
+ newRR->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ newRR->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
+ }
+ if (IsRecordMergeable(m, newRR, m->timenow + MERGE_DELAY_TIME))
+ {
+ // Delay the record registration by MERGE_DELAY_TIME so that we can merge them
+ // into one update
+ LogInfo("RecordRegistrationGotZoneData: Delayed registration for %s", ARDisplayString(m, newRR));
+ newRR->LastAPTime += MERGE_DELAY_TIME;
+ }
mDNS_Unlock(m);
}
mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr)
{
mDNSu8 *ptr = m->omsg.data;
- mDNSu8 *end = (mDNSu8 *)&m->omsg + sizeof(DNSMessage);
+ mDNSu8 *limit;
+ DomainAuthInfo *AuthInfo;
+
+ if (m->mDNS_busy != m->mDNS_reentrancy+1)
+ LogMsg("SendRecordDeRegistration: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
- if (mDNSIPv4AddressIsZero(rr->UpdateServer.ip.v4)) // Don't know our UpdateServer yet
+ if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
{
- rr->LastAPTime = m->timenow;
- if (rr->ThisAPInterval < mDNSPlatformOneSecond * 5)
- rr->ThisAPInterval = mDNSPlatformOneSecond * 5;
+ LogMsg("SendRecordDeRegistration: No zone info for Resource record %s RecordType %d", ARDisplayString(m, rr), rr->resrec.RecordType);
return;
}
+ limit = ptr + AbsoluteMaxDNSMessageData;
+ AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name);
+ limit -= RRAdditionalSize(m, AuthInfo);
+
+ rr->updateid = mDNS_NewMessageID(m);
InitializeDNSMessage(&m->omsg.h, rr->updateid, UpdateReqFlags);
- ptr = putZone(&m->omsg, ptr, end, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
- if (ptr) ptr = putDeletionRecord(&m->omsg, ptr, &rr->resrec);
- if (!ptr)
+ // set zone
+ ptr = putZone(&m->omsg, ptr, limit, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
+ if (!ptr) goto exit;
+
+ ptr = BuildUpdateMessage(m, ptr, rr, limit);
+
+ if (!ptr) goto exit;
+
+ if (rr->Private)
{
- LogMsg("SendRecordDeregistration Error: could not contruct deregistration packet for %s", ARDisplayString(m, rr));
- if (rr->state == regState_DeregPending) CompleteDeregistration(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 = mDNSNULL; }
+ if (!rr->nta) { LogMsg("SendRecordDeregistration:Private:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; }
+ rr->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &rr->nta->Addr, rr->nta->Port, &rr->nta->Host, mDNSNULL, rr);
}
else
{
- rr->expire = 0; // Indicate that we have no active registration any more
- if (rr->Private)
- {
- 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)
- else if (rr->ThisAPInterval < mDNSPlatformOneSecond * 30) rr->ThisAPInterval = mDNSPlatformOneSecond * 30;
- SetRecordRetry(m, rr, mStatus_NoError);
- }
- 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 - %d", err);
- if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr); // Don't touch rr after this
- }
+ mStatus err;
+ LogInfo("SendRecordDeregistration UDP %s", ARDisplayString(m, rr));
+ if (!rr->nta) { LogMsg("SendRecordDeregistration:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; }
+ err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->nta->Addr, rr->nta->Port, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name));
+ if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %d", err);
+ //if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr); // Don't touch rr after this
}
+ SetRecordRetry(m, rr, 0);
+ return;
+exit:
+ LogMsg("SendRecordDeregistration: Error formatting message for %s", ARDisplayString(m, rr));
}
mDNSexport mStatus uDNS_DeregisterRecord(mDNS *const m, AuthRecord *const rr)
{
+ DomainAuthInfo *info;
+
+ LogInfo("uDNS_DeregisterRecord: Resource Record %s, state %d", ARDisplayString(m, rr), rr->state);
+
switch (rr->state)
{
- case regState_NATMap: LogMsg("regState_NATMap %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError;
- case regState_ExtraQueued: rr->state = regState_Unregistered; break;
case regState_Refresh:
case regState_Pending:
case regState_UpdatePending:
- case regState_FetchingZoneData:
case regState_Registered: break;
case regState_DeregPending: break;
- case regState_DeregDeferred: LogMsg("regState_DeregDeferred %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError;
- case regState_Unregistered: LogMsg("regState_Unregistered %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError;
- case regState_NATError: LogMsg("regState_NATError %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError;
- case regState_NoTarget: LogMsg("regState_NoTarget %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError;
- default: LogMsg("uDNS_DeregisterRecord: State %d for %##s type %s", rr->state, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError;
- }
-
- if (rr->state != regState_Unregistered) { rr->state = regState_DeregPending; SendRecordDeregistration(m, rr); }
- return mStatus_NoError;
- }
-// Called with lock held
-mDNSexport mStatus uDNS_DeregisterService(mDNS *const m, ServiceRecordSet *srs)
- {
- char *errmsg = "Unknown State";
-
- if (m->mDNS_busy != m->mDNS_reentrancy+1)
- LogMsg("uDNS_DeregisterService: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
-
- // don't re-register with a new target following deregistration
- srs->SRVChanged = srs->SRVUpdateDeferred = mDNSfalse;
+ case regState_NATError:
+ case regState_NATMap:
+ // A record could be in NoTarget to start with if the corresponding SRV record could not find a target.
+ // It is also possible to reenter the NoTarget state when we move to a network with a NAT that has
+ // no NAT-PMP/UPnP support. In that case before we entered NoTarget, we already deregistered with
+ // the server.
+ case regState_NoTarget:
+ case regState_Unregistered:
+ case regState_Zero:
+ default:
+ LogInfo("uDNS_DeregisterRecord: State %d for %##s type %s", rr->state, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+ // This function may be called during sleep when there are no sleep proxy servers
+ if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) CompleteDeregistration(m, rr);
+ return mStatus_NoError;
+ }
- if (srs->srs_nta) { CancelGetZoneData(m, srs->srs_nta); srs->srs_nta = mDNSNULL; }
+ // If a current group registration is pending, we can't send this deregisration till that registration
+ // has reached the server i.e., the ordering is important. Previously, if we did not send this
+ // registration in a group, then the previous connection will be torn down as part of sending the
+ // deregistration. If we send this in a group, we need to locate the resource record that was used
+ // to send this registration and terminate that connection. This means all the updates on that might
+ // be lost (assuming the response is not waiting for us at the socket) and the retry will send the
+ // update again sometime in the near future.
+ //
+ // NOTE: SSL handshake failures normally free the TCP connection immediately. Hence, you may not
+ // find the TCP below there. This case can happen only when tcp is trying to actively retransmit
+ // the request or SSL negotiation taking time i.e resource record is actively trying to get the
+ // message to the server. During that time a deregister has to happen.
- if (srs->NATinfo.clientContext)
+ if (!mDNSOpaque16IsZero(rr->updateid))
{
- mDNS_StopNATOperation_internal(m, &srs->NATinfo);
- srs->NATinfo.clientContext = mDNSNULL;
+ AuthRecord *anchorRR;
+ mDNSBool found = mDNSfalse;
+ for (anchorRR = m->ResourceRecords; anchorRR; anchorRR = anchorRR->next)
+ {
+ if (AuthRecord_uDNS(rr) && mDNSSameOpaque16(anchorRR->updateid, rr->updateid) && anchorRR->tcp)
+ {
+ LogInfo("uDNS_DeregisterRecord: Found Anchor RR %s terminated", ARDisplayString(m, anchorRR));
+ if (found)
+ LogMsg("uDNS_DeregisterRecord: ERROR: Another anchorRR %s found", ARDisplayString(m, anchorRR));
+ DisposeTCPConn(anchorRR->tcp);
+ anchorRR->tcp = mDNSNULL;
+ found = mDNStrue;
+ }
+ }
+ if (!found) LogInfo("uDNSDeregisterRecord: Cannot find the anchor Resource Record for %s, not an error", ARDisplayString(m, rr));
}
- switch (srs->state)
+ // Retry logic for deregistration should be no different from sending registration the first time.
+ // Currently ThisAPInterval most likely is set to the refresh interval
+ rr->state = regState_DeregPending;
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
+ info = GetAuthInfoForName_internal(m, rr->resrec.name);
+ if (IsRecordMergeable(m, rr, m->timenow + MERGE_DELAY_TIME))
{
- case regState_Unregistered:
- debugf("uDNS_DeregisterService - service %##s not registered", srs->RR_SRV.resrec.name->c);
- return mStatus_BadReferenceErr;
- case regState_DeregPending:
- case regState_DeregDeferred:
- debugf("Double deregistration of service %##s", srs->RR_SRV.resrec.name->c);
- return mStatus_NoError;
- case regState_NATError: // not registered
- case regState_NATMap: // not registered
- case regState_NoTarget: // not registered
- unlinkSRS(m, srs);
- srs->state = regState_Unregistered;
- mDNS_DropLockBeforeCallback();
- srs->ServiceCallback(m, srs, mStatus_MemFree);
- mDNS_ReclaimLockAfterCallback();
- return mStatus_NoError;
- case regState_Pending:
- case regState_Refresh:
- case regState_UpdatePending:
- case regState_FetchingZoneData:
- case regState_Registered:
- srs->state = regState_DeregPending;
- SendServiceDeregistration(m, srs);
- return mStatus_NoError;
- case regState_ExtraQueued: // only for record registrations
- errmsg = "bad state (regState_ExtraQueued)";
- goto error;
- default: LogMsg("uDNS_DeregisterService: Unknown state %d for %##s", srs->state, srs->RR_SRV.resrec.name->c);
+ // Delay the record deregistration by MERGE_DELAY_TIME so that we can merge them
+ // into one update. If the domain is being deleted, delay by 2 * MERGE_DELAY_TIME
+ // so that we can merge all the AutoTunnel records and the service records in
+ // one update (they get deregistered a little apart)
+ if (info && info->deltime) rr->LastAPTime += (2 * MERGE_DELAY_TIME);
+ else rr->LastAPTime += MERGE_DELAY_TIME;
}
+ // IsRecordMergeable could have returned false for several reasons e.g., DontMerge is set or
+ // no zone information. Most likely it is the latter, CheckRecordUpdates will fetch the zone
+ // data when it encounters this record.
+
+ if (m->NextuDNSEvent - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
+ m->NextuDNSEvent = (rr->LastAPTime + rr->ThisAPInterval);
- error:
- LogMsg("Error, uDNS_DeregisterService: %s", errmsg);
- return mStatus_BadReferenceErr;
+ return mStatus_NoError;
}
mDNSexport mStatus uDNS_UpdateRecord(mDNS *m, AuthRecord *rr)
{
- ServiceRecordSet *parent = mDNSNULL;
- AuthRecord *rptr;
- regState_t *stateptr = mDNSNULL;
-
- // find the record in registered service list
- for (parent = m->ServiceRegistrations; parent; parent = parent->uDNS_next)
- if (&parent->RR_TXT == rr) { stateptr = &parent->state; break; }
-
- if (!parent)
- {
- // record not part of a service - check individual record registrations
- for (rptr = m->ResourceRecords; rptr; rptr = rptr->next)
- if (rptr == rr) { stateptr = &rr->state; break; }
- if (!rptr) goto unreg_error;
- }
-
- switch(*stateptr)
+ LogInfo("uDNS_UpdateRecord: Resource Record %##s, state %d", rr->resrec.name->c, rr->state);
+ switch(rr->state)
{
case regState_DeregPending:
- case regState_DeregDeferred:
case regState_Unregistered:
// not actively registered
goto unreg_error;
- case regState_FetchingZoneData:
case regState_NATMap:
- case regState_ExtraQueued:
case regState_NoTarget:
// change rdata directly since it hasn't been sent yet
- if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->resrec.rdata);
+ if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->resrec.rdata, rr->resrec.rdlength);
SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);
rr->NewRData = mDNSNULL;
return mStatus_NoError;
// registration in-flight. queue rdata and return
if (rr->QueuedRData && rr->UpdateCallback)
// if unsent rdata is already queued, free it before we replace it
- rr->UpdateCallback(m, rr, rr->QueuedRData);
+ rr->UpdateCallback(m, rr, rr->QueuedRData, rr->QueuedRDLen);
rr->QueuedRData = rr->NewRData;
rr->QueuedRDLen = rr->newrdlength;
rr->NewRData = mDNSNULL;
rr->InFlightRData = rr->NewRData;
rr->InFlightRDLen = rr->newrdlength;
rr->NewRData = mDNSNULL;
- *stateptr = regState_UpdatePending;
- if (parent) SendServiceRegistration(m, parent);
- else SendRecordRegistration(m, rr);
+ rr->state = regState_UpdatePending;
+ rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
+ rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
return mStatus_NoError;
case regState_NATError:
LogMsg("ERROR: uDNS_UpdateRecord called for record %##s with bad state regState_NATError", rr->resrec.name->c);
return mStatus_UnknownErr; // states for service records only
- default: LogMsg("uDNS_UpdateRecord: Unknown state %d for %##s", *stateptr, rr->resrec.name->c);
+ default: LogMsg("uDNS_UpdateRecord: Unknown state %d for %##s", rr->state, rr->resrec.name->c);
}
unreg_error:
- LogMsg("Requested update of record %##s type %d, part of service not currently registered",
- rr->resrec.name->c, rr->resrec.rrtype);
+ LogMsg("uDNS_UpdateRecord: Requested update of record %##s type %d, in erroneous state %d",
+ rr->resrec.name->c, rr->resrec.rrtype, rr->state);
return mStatus_Invalid;
}
#pragma mark - Periodic Execution Routines
#endif
+mDNSlocal const mDNSu8 *mDNS_WABLabels[] =
+ {
+ (const mDNSu8 *)"\001b",
+ (const mDNSu8 *)"\002db",
+ (const mDNSu8 *)"\002lb",
+ (const mDNSu8 *)"\001r",
+ (const mDNSu8 *)"\002dr",
+ (const mDNSu8 *)"\002cf",
+ (const mDNSu8 *)mDNSNULL,
+ };
+
+// Returns true if it is a WAB question
+mDNSlocal mDNSBool WABQuestion(const domainname *qname)
+ {
+ const mDNSu8 *sd = (const mDNSu8 *)"\007_dns-sd";
+ const mDNSu8 *prot = (const mDNSu8 *)"\004_udp";
+ const domainname *d = qname;
+ const mDNSu8 *label;
+ int i = 0;
+
+ // We need at least 3 labels (WAB prefix) + one more label to make
+ // a meaningful WAB query
+ if (CountLabels(qname) < 4) { debugf("WABQuestion: question %##s, not enough labels", qname->c); return mDNSfalse; }
+
+ label = (const mDNSu8 *)d;
+ while (mDNS_WABLabels[i] != (const mDNSu8 *)mDNSNULL)
+ {
+ if (SameDomainLabel(mDNS_WABLabels[i], label)) {debugf("WABquestion: WAB question %##s, label1 match", qname->c); break;}
+ i++;
+ }
+ if (mDNS_WABLabels[i] == (const mDNSu8 *)mDNSNULL)
+ {
+ debugf("WABquestion: Not a WAB question %##s, label1 mismatch", qname->c);
+ return mDNSfalse;
+ }
+ // CountLabels already verified the number of labels
+ d = (const domainname *)(d->c + 1 + d->c[0]); // Second Label
+ label = (const mDNSu8 *)d;
+ if (!SameDomainLabel(label, sd)){ debugf("WABquestion: Not a WAB question %##s, label2 mismatch", qname->c);return(mDNSfalse); }
+ debugf("WABquestion: WAB question %##s, label2 match", qname->c);
+
+ d = (const domainname *)(d->c + 1 + d->c[0]); // Third Label
+ label = (const mDNSu8 *)d;
+ if (!SameDomainLabel(label, prot)){ debugf("WABquestion: Not a WAB question %##s, label3 mismatch", qname->c);return(mDNSfalse); }
+ debugf("WABquestion: WAB question %##s, label3 match", qname->c);
+
+ LogInfo("WABquestion: Question %##s is a WAB question", qname->c);
+
+ return mDNStrue;
+ }
+
// The question to be checked is not passed in as an explicit parameter;
// instead it is implicit that the question to be checked is m->CurrentQuestion.
mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
{
DNSQuestion *q = m->CurrentQuestion;
- mDNSs32 sendtime = q->LastQTime + q->ThisQInterval;
- // Don't allow sendtime to be earlier than SuppressStdPort53Queries
- if (!q->LongLived && m->SuppressStdPort53Queries && sendtime - m->SuppressStdPort53Queries < 0)
- sendtime = m->SuppressStdPort53Queries;
- if (m->timenow - sendtime < 0) return;
+ if (m->timenow - NextQSendTime(q) < 0) return;
if (q->LongLived)
{
switch (q->state)
{
case LLQ_InitialRequest: startLLQHandshake(m, q); break;
- case LLQ_SecondaryRequest: sendChallengeResponse(m, q, mDNSNULL); break;
+ case LLQ_SecondaryRequest:
+ // For PrivateQueries, we need to start the handshake again as we don't do the Challenge/Response step
+ if (PrivateQuery(q))
+ startLLQHandshake(m, q);
+ else
+ sendChallengeResponse(m, q, mDNSNULL);
+ break;
case LLQ_Established: sendLLQRefresh(m, q); break;
case LLQ_Poll: break; // Do nothing (handled below)
}
if (q->unansweredQueries >= MAX_UCAST_UNANSWERED_QUERIES)
{
DNSServer *orig = q->qDNSServer;
- 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);
+ if (orig)
+ LogInfo("uDNS_CheckCurrentQuestion: 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);
- PenalizeDNSServer(m, q, mDNStrue);
+ PenalizeDNSServer(m, q);
+ q->noServerResponse = 1;
+ }
+ // There are two cases here.
+ //
+ // 1. We have only one DNS server for this question. It is not responding even after we sent MAX_UCAST_UNANSWERED_QUERIES.
+ // In that case, we need to keep retrying till we get a response. But we need to backoff as we retry. We set
+ // noServerResponse in the block above and below we do not touch the question interval. When we come here, we
+ // already waited for the response. We need to send another query right at this moment. We do that below by
+ // reinitializing dns servers and reissuing the query.
+ //
+ // 2. We have more than one DNS server. If at least one server did not respond, we would have set noServerResponse
+ // either now (the last server in the list) or before (non-last server in the list). In either case, if we have
+ // reached the end of DNS server list, we need to try again from the beginning. Ideally we should try just the
+ // servers that did not respond, but for simplicity we try all the servers. Once we reached the end of list, we
+ // set triedAllServersOnce so that we don't try all the servers aggressively. See PenalizeDNSServer.
+ if (!q->qDNSServer && q->noServerResponse)
+ {
+ DNSServer *new;
+ DNSQuestion *qptr;
+ q->triedAllServersOnce = 1;
+ // Re-initialize all DNS servers for this question. If we have a DNSServer, DNSServerChangeForQuestion will
+ // handle all the work including setting the new DNS server.
+ SetValidDNSServers(m, q);
+ new = GetServerForQuestion(m, q);
+ if (new)
+ {
+ LogInfo("uDNS_checkCurrentQuestion: Retrying question %p %##s (%s) DNS Server %#a:%d ThisQInterval %d",
+ q, q->qname.c, DNSTypeName(q->qtype), new ? &new->addr : mDNSNULL, mDNSVal16(new ? new->port : zeroIPPort), q->ThisQInterval);
+ DNSServerChangeForQuestion(m, q, new);
+ }
+ for (qptr = q->next ; qptr; qptr = qptr->next)
+ if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; }
}
-
if (q->qDNSServer && q->qDNSServer->teststate != DNSServer_Disabled)
{
mDNSu8 *end = m->omsg.data;
if (q->qDNSServer->teststate != DNSServer_Untested || NoTestQuery(q))
{
end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
- private = (q->AuthInfo && q->AuthInfo->AutoTunnel);
+ private = PrivateQuery(q);
}
else if (m->timenow - q->qDNSServer->lasttest >= INIT_UCAST_POLL_INTERVAL) // Make sure at least three seconds has elapsed since last test query
{
if (end > m->omsg.data && (q->qDNSServer->teststate != DNSServer_Failed || NoTestQuery(q)))
{
- //LogMsg("uDNS_CheckCurrentQuestion %p %d %p %##s (%s)", q, sendtime - m->timenow, private, q->qname.c, DNSTypeName(q->qtype));
+ //LogMsg("uDNS_CheckCurrentQuestion %p %d %p %##s (%s)", q, NextQSendTime(q) - m->timenow, private, q->qname.c, DNSTypeName(q->qtype));
if (private)
{
if (q->nta) CancelGetZoneData(m, q->nta);
}
else
{
+ debugf("uDNS_CheckCurrentQuestion sending %p %##s (%s) %#a:%d UnansweredQueries %d",
+ q, q->qname.c, DNSTypeName(q->qtype),
+ q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort), q->unansweredQueries);
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);
}
}
for (rr = cg->members; rr; rr=rr->next)
if (SameNameRecordAnswersQuestion(&rr->resrec, q)) mDNS_PurgeCacheResourceRecord(m, rr);
- if (!q->qDNSServer) LogInfo("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);
+ if (!q->qDNSServer)
+ {
+ if (!mDNSOpaque64IsZero(&q->validDNSServers))
+ LogMsg("uDNS_CheckCurrentQuestion: ERROR!!: valid DNSServer bits not zero 0x%x, 0x%x for question %##s (%s)",
+ q->validDNSServers.l[1], q->validDNSServers.l[0], q->qname.c, DNSTypeName(q->qtype));
+ // If we reached the end of list while picking DNS servers, then we don't want to deactivate the
+ // question. Try after 60 seconds. We find this by looking for valid DNSServers for this question,
+ // if we find any, then we must have tried them before we came here. This avoids maintaining
+ // another state variable to see if we had valid DNS servers for this question.
+ SetValidDNSServers(m, q);
+ if (mDNSOpaque64IsZero(&q->validDNSServers))
+ {
+ LogInfo("uDNS_CheckCurrentQuestion: no DNS server for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ q->ThisQInterval = 0;
+ }
+ else
+ {
+ DNSQuestion *qptr;
+ // Pretend that we sent this question. As this is an ActiveQuestion, the NextScheduledQuery should
+ // be set properly. Also, we need to properly backoff in cases where we don't set the question to
+ // MaxQuestionInterval when we answer the question e.g., LongLived, we need to keep backing off
+ q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep;
+ q->LastQTime = m->timenow;
+ SetNextQueryTime(m, q);
+ // Pick a new DNS server now. Otherwise, when the cache is 80% of its expiry, we will try
+ // to send a query and come back to the same place here and log the above message.
+ q->qDNSServer = GetServerForQuestion(m, q);
+ for (qptr = q->next ; qptr; qptr = qptr->next)
+ if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; }
+ LogInfo("uDNS_checkCurrentQuestion: Tried all DNS servers, retry question %p SuppressUnusable %d %##s (%s) with DNS Server %#a:%d after 60 seconds, ThisQInterval %d",
+ q, q->SuppressUnusable, q->qname.c, DNSTypeName(q->qtype),
+ q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort), q->ThisQInterval);
+ }
+ }
+ else
+ {
+ q->ThisQInterval = 0;
+ LogMsg("uDNS_CheckCurrentQuestion DNS server %#a:%d for %##s is disabled", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qname.c);
+ }
- 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;
+ // For some of the WAB queries that we generate form within the mDNSResponder, most of the home routers
+ // don't understand and return ServFail/NXDomain. In those cases, we don't want to try too often. We try
+ // every fifteen minutes in that case
+ MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, (WABQuestion(&q->qname) ? 60 * 15 : 60), mDNSInterface_Any, q->qDNSServer);
q->unansweredQueries = 0;
- CreateNewCacheEntry(m, slot, cg);
+ // We're already using the m->CurrentQuestion pointer, so CacheRecordAdd can't use it to walk the question list.
+ // To solve this problem we set rr->DelayDelivery to a nonzero value (which happens to be 'now') so that we
+ // momentarily defer generating answer callbacks until mDNS_Execute time.
+ CreateNewCacheEntry(m, slot, cg, NonZeroTime(m->timenow));
+ ScheduleNextCacheCheckTime(m, slot, NonZeroTime(m->timenow));
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
// MUST NOT touch m->CurrentQuestion (or q) after this -- client callback could have deleted it
}
}
}
-mDNSlocal void CheckNATMappings(mDNS *m)
+mDNSexport void CheckNATMappings(mDNS *m)
{
mStatus err = mStatus_NoError;
mDNSBool rfc1918 = mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4);
if (m->SSDPSocket) { debugf("CheckNATMappings destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
}
- if (m->NATTraversals)
+ if (!m->NATTraversals)
+ m->retryGetAddr = m->timenow + 0x78000000;
+ else
{
if (m->timenow - m->retryGetAddr >= 0)
{
// (1) we have an ExternalAddress, or we've tried and failed a couple of times to discover it
// and (2) the client doesn't want a mapping, or the client won't need a mapping, or the client has a successful mapping, or we've tried and failed a couple of times
// and (3) we have new data to give the client that's changed since the last callback
+ // Time line is: Send, Wait 500ms, Send, Wait 1sec, Send, Wait 2sec, Send
+ // At this point we've sent three requests without an answer, we've just sent our fourth request,
+ // retryIntervalGetAddr is now 4 seconds, which is greater than NATMAP_INIT_RETRY * 8 (2 seconds),
+ // so we return an error result to the caller.
if (!mDNSIPv4AddressIsZero(m->ExternalAddress) || m->retryIntervalGetAddr > NATMAP_INIT_RETRY * 8)
{
const mStatus EffectiveResult = cur->NewResult ? cur->NewResult : mDNSv4AddrIsRFC1918(&m->ExternalAddress) ? mStatus_DoubleNAT : mStatus_NoError;
if (cur->Protocol && mDNSIPPortIsZero(ExternalPort) && !mDNSIPv4AddressIsZero(m->Router.ip.v4))
{
if (!EffectiveResult)
- LogInfo("Failed to obtain NAT port mapping %p from router %#a external address %.4a internal port %5d interval %d error %d",
+ LogInfo("CheckNATMapping: 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",
+ LogMsg("CheckNATMapping: 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);
}
}
}
-mDNSlocal mDNSs32 CheckRecordRegistrations(mDNS *m)
+mDNSlocal mDNSs32 CheckRecordUpdates(mDNS *m)
{
AuthRecord *rr;
mDNSs32 nextevent = m->timenow + 0x3FFFFFFF;
+ CheckGroupRecordUpdates(m);
+
for (rr = m->ResourceRecords; rr; rr = rr->next)
{
- if (rr->state == regState_FetchingZoneData ||
- rr->state == regState_Pending || rr->state == regState_DeregPending || rr->state == regState_UpdatePending ||
- rr->state == regState_DeregDeferred || rr->state == regState_Refresh || rr->state == regState_Registered)
+ if (!AuthRecord_uDNS(rr)) continue;
+ if (rr->state == regState_NoTarget) {debugf("CheckRecordUpdates: Record %##s in NoTarget", rr->resrec.name->c); continue;}
+ // While we are waiting for the port mapping, we have nothing to do. The port mapping callback
+ // will take care of this
+ if (rr->state == regState_NATMap) {debugf("CheckRecordUpdates: Record %##s in NATMap", rr->resrec.name->c); continue;}
+ if (rr->state == regState_Pending || rr->state == regState_DeregPending || rr->state == regState_UpdatePending ||
+ rr->state == regState_Refresh || rr->state == regState_Registered)
{
- if (rr->LastAPTime + rr->ThisAPInterval - m->timenow < 0)
+ if (rr->LastAPTime + rr->ThisAPInterval - m->timenow <= 0)
{
if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
- if (rr->state == regState_FetchingZoneData)
+ if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
{
- if (rr->nta) CancelGetZoneData(m, rr->nta);
+ // Zero out the updateid so that if we have a pending response from the server, it won't
+ // be accepted as a valid response. If we accept the response, we might free the new "nta"
+ if (rr->nta) { rr->updateid = zeroID; CancelGetZoneData(m, rr->nta); }
rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr);
- SetRecordRetry(m, rr, mStatus_NoError);
+
+ // We have just started the GetZoneData. We need to wait for it to finish. SetRecordRetry here
+ // schedules the update timer to fire in the future.
+ //
+ // There are three cases.
+ //
+ // 1) When the updates are sent the first time, the first retry is intended to be at three seconds
+ // in the future. But by calling SetRecordRetry here we set it to nine seconds. But it does not
+ // matter because when the answer comes back, RecordRegistrationGotZoneData resets the interval
+ // back to INIT_RECORD_REG_INTERVAL. This also gives enough time for the query.
+ //
+ // 2) In the case of update errors (updateError), this causes further backoff as
+ // RecordRegistrationGotZoneData does not reset the timer. This is intentional as in the case of
+ // errors, we don't want to update aggressively.
+ //
+ // 3) We might be refreshing the update. This is very similar to case (1). RecordRegistrationGotZoneData
+ // resets it back to INIT_RECORD_REG_INTERVAL.
+ //
+ SetRecordRetry(m, rr, 0);
}
else if (rr->state == regState_DeregPending) SendRecordDeregistration(m, rr);
else SendRecordRegistration(m, rr);
}
- if (nextevent - (rr->LastAPTime + rr->ThisAPInterval) > 0)
- nextevent = (rr->LastAPTime + rr->ThisAPInterval);
}
+ if (nextevent - (rr->LastAPTime + rr->ThisAPInterval) > 0)
+ nextevent = (rr->LastAPTime + rr->ThisAPInterval);
}
return nextevent;
}
-mDNSlocal mDNSs32 CheckServiceRegistrations(mDNS *m)
+mDNSexport void uDNS_Tasks(mDNS *const m)
{
- mDNSs32 nextevent = m->timenow + 0x3FFFFFFF;
+ mDNSs32 nexte;
+ DNSServer *d;
- if (CurrentServiceRecordSet)
- LogMsg("CheckServiceRegistrations ERROR CurrentServiceRecordSet already set");
- CurrentServiceRecordSet = m->ServiceRegistrations;
+ m->NextuDNSEvent = m->timenow + 0x3FFFFFFF;
- // Note: ServiceRegistrations list is in the order they were created; important for in-order event delivery
- while (CurrentServiceRecordSet)
- {
- ServiceRecordSet *srs = CurrentServiceRecordSet;
- CurrentServiceRecordSet = CurrentServiceRecordSet->uDNS_next;
- if (srs->state == regState_FetchingZoneData ||
- srs->state == regState_Pending || srs->state == regState_DeregPending || srs->state == regState_DeregDeferred ||
- srs->state == regState_Refresh || srs->state == regState_UpdatePending || srs->state == regState_Registered)
- {
- if (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval - m->timenow <= 0)
- {
- if (srs->tcp) { DisposeTCPConn(srs->tcp); srs->tcp = mDNSNULL; }
- if (srs->state == regState_FetchingZoneData)
- {
- 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);
- else SendServiceRegistration(m, srs);
- }
- if (nextevent - (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval) > 0)
- nextevent = (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval);
- }
- }
- return nextevent;
- }
+ nexte = CheckRecordUpdates(m);
+ if (m->NextuDNSEvent - nexte > 0)
+ m->NextuDNSEvent = nexte;
-// This function is called early on in mDNS_Execute before any uDNS questions are
-// dispatched so that if there are some good servers, the uDNS questions can now
-// use it
-mDNSexport void ResetDNSServerPenalties(mDNS *m)
- {
- DNSServer *d;
for (d = m->DNSServers; d; d=d->next)
- {
- if (d->penaltyTime != 0)
+ if (d->penaltyTime)
{
- if (d->penaltyTime - m->timenow <= 0)
+ if (m->timenow - d->penaltyTime >= 0)
{
- LogInfo("ResetDNSServerPenalties: DNS server %#a:%d out of penalty box", &d->addr, mDNSVal16(d->port));
+ LogInfo("DNS server %#a:%d out of penalty box", &d->addr, mDNSVal16(d->port));
d->penaltyTime = 0;
}
+ else
+ if (m->NextuDNSEvent - d->penaltyTime > 0)
+ m->NextuDNSEvent = d->penaltyTime;
}
- }
- }
-mDNSlocal mDNSs32 CheckDNSServerPenalties(mDNS *m)
- {
- mDNSs32 nextevent = m->timenow + 0x3FFFFFFF;
- DNSServer *d;
- for (d = m->DNSServers; d; d=d->next)
+ if (m->CurrentQuestion)
+ LogMsg("uDNS_Tasks ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
+ m->CurrentQuestion = m->Questions;
+ while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
{
- if (d->penaltyTime != 0)
+ DNSQuestion *const q = m->CurrentQuestion;
+ if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID))
{
- if ((nextevent - d->penaltyTime) > 0)
- nextevent = d->penaltyTime;
+ uDNS_CheckCurrentQuestion(m);
+ if (q == m->CurrentQuestion)
+ if (m->NextuDNSEvent - NextQSendTime(q) > 0)
+ m->NextuDNSEvent = NextQSendTime(q);
}
+ // If m->CurrentQuestion wasn't modified out from under us, advance it now
+ // We can't do this at the start of the loop because uDNS_CheckCurrentQuestion()
+ // depends on having m->CurrentQuestion point to the right question
+ if (m->CurrentQuestion == q)
+ m->CurrentQuestion = q->next;
}
- return nextevent;
- }
-
-mDNSexport void uDNS_Execute(mDNS *const m)
- {
- mDNSs32 nexte;
-
- m->NextuDNSEvent = m->timenow + 0x3FFFFFFF;
-
- if (m->NextSRVUpdate && m->NextSRVUpdate - m->timenow < 0)
- { m->NextSRVUpdate = 0; UpdateSRVRecords(m); }
-
- CheckNATMappings(m);
-
- if (m->SuppressStdPort53Queries && m->timenow - m->SuppressStdPort53Queries >= 0)
- m->SuppressStdPort53Queries = 0; // If suppression time has passed, clear it
-
- nexte = CheckRecordRegistrations(m);
- if (nexte - m->NextuDNSEvent < 0) m->NextuDNSEvent = nexte;
-
- nexte = CheckServiceRegistrations(m);
- if (nexte - m->NextuDNSEvent < 0) m->NextuDNSEvent = nexte;
-
- nexte = CheckDNSServerPenalties(m);
- if (nexte - m->NextuDNSEvent < 0) m->NextuDNSEvent = nexte;
+ m->CurrentQuestion = mDNSNULL;
}
// ***************************************************************************
#pragma mark - Startup, Shutdown, and Sleep
#endif
-// simplest sleep logic - rather than having sleep states that must be dealt with explicitly in all parts of
-// the code, we simply send a deregistration, and put the service in Refresh state, with a timeout far enough
-// in the future that we'll sleep (or the sleep will be cancelled) before it is retransmitted. Then to wake,
-// we just move up the timers.
-
mDNSexport void SleepRecordRegistrations(mDNS *m)
{
AuthRecord *rr;
for (rr = m->ResourceRecords; rr; rr=rr->next)
+ {
if (AuthRecord_uDNS(rr))
- if (rr->state == regState_Registered ||
- rr->state == regState_Refresh)
+ {
+ // Zero out the updateid so that if we have a pending response from the server, it won't
+ // be accepted as a valid response.
+ if (rr->nta) { rr->updateid = zeroID; CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
+
+ if (rr->NATinfo.clientContext)
{
- SendRecordDeregistration(m, rr);
- rr->state = regState_Refresh;
- rr->LastAPTime = m->timenow;
- rr->ThisAPInterval = 300 * mDNSPlatformOneSecond;
+ mDNS_StopNATOperation_internal(m, &rr->NATinfo);
+ rr->NATinfo.clientContext = mDNSNULL;
+ }
+ // We are waiting to update the resource record. The original data of the record is
+ // in OrigRData and the updated value is in InFlightRData. Free the old and the new
+ // one will be registered when we come back.
+ if (rr->state == regState_UpdatePending)
+ {
+ // act as if the update succeeded, since we're about to delete the name anyway
+ rr->state = regState_Registered;
+ // deallocate old RData
+ if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->OrigRData, rr->OrigRDLen);
+ SetNewRData(&rr->resrec, rr->InFlightRData, rr->InFlightRDLen);
+ rr->OrigRData = mDNSNULL;
+ rr->InFlightRData = mDNSNULL;
}
- }
-
-mDNSexport void SleepServiceRegistrations(mDNS *m)
- {
- ServiceRecordSet *srs = m->ServiceRegistrations;
- while (srs)
- {
- 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)
- {
- mDNS_StopNATOperation_internal(m, &srs->NATinfo);
- srs->NATinfo.clientContext = mDNSNULL;
- }
- if (srs->state == regState_UpdatePending)
- {
- // act as if the update succeeded, since we're about to delete the name anyway
- AuthRecord *txt = &srs->RR_TXT;
- srs->state = regState_Registered;
- // deallocate old RData
- if (txt->UpdateCallback) txt->UpdateCallback(m, txt, txt->OrigRData);
- SetNewRData(&txt->resrec, txt->InFlightRData, txt->InFlightRDLen);
- txt->OrigRData = mDNSNULL;
- txt->InFlightRData = mDNSNULL;
+ // If we have not begun the registration process i.e., never sent a registration packet,
+ // then uDNS_DeregisterRecord will not send a deregistration
+ uDNS_DeregisterRecord(m, rr);
+
+ // When we wake, we call ActivateUnicastRegistration which starts at StartGetZoneData
}
-
- if (srs->state == regState_Registered || srs->state == regState_Refresh)
- SendServiceDeregistration(m, srs);
-
- srs->state = regState_NoTarget; // when we wake, we'll re-register (and optionally nat-map) once our address record completes
- srs->RR_SRV.resrec.rdata->u.srv.target.c[0] = 0;
- srs->SRSUpdateServer = zeroAddr; // This will cause UpdateSRV to do a new StartGetZoneData
- srs->RR_SRV.ThisAPInterval = 5 * mDNSPlatformOneSecond; // After doubling, first retry will happen after ten seconds
-
- srs = srs->uDNS_next;
}
}
if (result == mStatus_MemFree) mDNSPlatformMemFree(rr->RecordContext);
}
+#if APPLE_OSX_mDNSResponder
+mDNSlocal void CheckAutoTunnel6Registration(mDNS *const m, mDNSBool RegisterAutoTunnel6)
+ {
+ LogInfo("CheckAutoTunnel6Registration: Current value RegisterAutoTunnel6 %d, New value %d", m->RegisterAutoTunnel6, RegisterAutoTunnel6);
+ if (!RegisterAutoTunnel6)
+ {
+ // We are not supposed to register autotunnel6. If we had previously registered
+ // autotunnel6, deregister it now.
+ if (m->RegisterAutoTunnel6)
+ {
+ m->RegisterAutoTunnel6 = mDNSfalse;
+ LogInfo("CheckAutoTunnel6Registration: Removing AutoTunnel6");
+ RemoveAutoTunnel6Record(m);
+ }
+ else LogInfo("CheckAutoTunnel6Registration: Already Removed AutoTunnel6");
+ }
+ else
+ {
+ // We are supposed to register autotunnel6. If we had previously de-registered
+ // autotunnel6, re-register it now.
+ if (!m->RegisterAutoTunnel6)
+ {
+ m->RegisterAutoTunnel6 = mDNStrue;
+ LogInfo("CheckAutoTunnel6Registration: Adding AutoTunnel6");
+ SetupConndConfigChanges(m);
+ }
+ else LogInfo("CheckAutoTunnel6Registration: already Added AutoTunnel6");
+ }
+ }
+#endif
+
+mDNSlocal void FoundDirDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
+ {
+ SearchListElem *slElem = question->QuestionContext;
+ mDNSBool RegisterAutoTunnel6 = mDNStrue;
+ char *res = "DisableInboundRelay";
+
+ LogInfo("FoundDirDomain: InterfaceID %p %s Question %##s Answer %s", answer->InterfaceID, AddRecord ? "Add" : "Rmv", question->qname.c, RRDisplayString(m, answer));
+ if (answer->rrtype != kDNSType_TXT)
+ {
+ LogMsg("FoundDirDomain: answer type is not TXT %s for question %##s", DNSTypeName(answer->rrtype), question->qname.c);
+ return;
+ }
+ if (answer->RecordType == kDNSRecordTypePacketNegative)
+ {
+ LogInfo("FoundDirDomain: Negative answer for %##s", question->qname.c);
+ return;
+ }
+ if (answer->InterfaceID == mDNSInterface_LocalOnly)
+ {
+ LogInfo("FoundDirDomain: LocalOnly interfaceID for %##s", question->qname.c);
+ return;
+ }
+
+ // TXT record is encoded as <len><data>
+ if (answer->rdlength != mDNSPlatformStrLen(res) + 1)
+ {
+ LogInfo("FoundDirDomain: Invalid TXT record to disable %##s, length %d", question->qname.c, answer->rdlength);
+ return;
+ }
+
+ // Compare the data (excluding the len byte)
+ if (!mDNSPlatformMemSame(&answer->rdata->u.txt.c[1], res, answer->rdlength - 1))
+ {
+ LogInfo("FoundDirDomain: Invalid TXT record to disable %##s", question->qname.c);
+ return;
+ }
+
+ // It is sufficient for one answer to disable registration of autotunnel6. But we should
+ // have zero answers across all domains to register autotunnel6.
+ if (AddRecord)
+ {
+ slElem->numDirAnswers++;
+ RegisterAutoTunnel6 = mDNSfalse;
+ }
+ else
+ {
+ const SearchListElem *s;
+ slElem->numDirAnswers--;
+ if (slElem->numDirAnswers < 0) LogMsg("FoundDirDomain: numDirAnswers less than zero %d", slElem->numDirAnswers);
+ // See if any domain (including the slElem) has any answers
+ for (s=SearchList; s; s=s->next)
+ if (s->numDirAnswers) { RegisterAutoTunnel6 = mDNSfalse; break; }
+ }
+#if APPLE_OSX_mDNSResponder
+ CheckAutoTunnel6Registration(m, RegisterAutoTunnel6);
+#endif
+ }
+
mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
SearchListElem *slElem = question->QuestionContext;
{
mDNS *const m = v;
- ServiceRecordSet *s;
- for (s = m->ServiceRegistrations; s; s=s->uDNS_next)
- if (s->uDNS_next == (ServiceRecordSet*)~0)
- LogMemCorruption("m->ServiceRegistrations: %p is garbage (%lX)", s, s->uDNS_next);
-
NATTraversalInfo *n;
for (n = m->NATTraversals; n; n=n->next)
if (n->next == (NATTraversalInfo *)~0 || n->clientCallback == (NATTraversalClientCallback)~0)
}
#endif
+mDNSlocal void mDNS_StartDirQuestion(mDNS *const m, DNSQuestion *question, domainname *domain, void *context)
+ {
+ AssignDomainName (&question->qname, (const domainname*)"\002cf" "\007_dns-sd" "\x04_udp");
+ AppendDomainName (&question->qname, domain);
+ question->InterfaceID = mDNSInterface_Any;
+ question->Target = zeroAddr;
+ question->qtype = kDNSType_TXT;
+ question->qclass = kDNSClass_IN;
+ question->LongLived = mDNSfalse;
+ question->ExpectUnique = mDNStrue;
+ question->ForceMCast = mDNSfalse;
+ question->ReturnIntermed = mDNSfalse;
+ question->SuppressUnusable = mDNSfalse;
+ question->QuestionCallback = FoundDirDomain;
+ question->QuestionContext = context;
+ LogInfo("mDNS_StartDirQuestion: Start DIR domain question %##s", question->qname.c);
+ if (mDNS_StartQuery(m, question))
+ LogMsg("mDNS_StartDirQuestion: ERROR!! cannot start _dir._dns-sd query");
+ }
+
// This should probably move to the UDS daemon -- the concept of legacy clients and automatic registration / automatic browsing
// is really a UDS API issue, not something intrinsic to uDNS
-
mDNSexport mStatus uDNS_RegisterSearchDomains(mDNS *const m)
{
SearchListElem **p = &SearchList, *ptr;
+ const SearchListElem *s;
+ mDNSBool RegisterAutoTunnel6 = mDNStrue;
mStatus err;
// step 1: mark each element for removal (-1)
*p = ptr->next;
// If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries
+ // Note: Stopping a question will not generate the RMV events for the question (handled in FoundDirDomain)
+ // and hence we need to recheck all the domains to see if we need to register/deregister _autotunnel6.
+ // This is done at the end.
if (!SameDomainName(&ptr->domain, &localdomain))
{
mDNS_StopGetDomains(m, &ptr->BrowseQ);
mDNS_StopGetDomains(m, &ptr->DefBrowseQ);
mDNS_StopGetDomains(m, &ptr->DefRegisterQ);
mDNS_StopGetDomains(m, &ptr->AutomaticBrowseQ);
+ mDNS_StopGetDomains(m, &ptr->DirQ);
}
mDNSPlatformMemFree(ptr);
arList = arList->next;
debugf("Deregistering PTR %##s -> %##s", dereg->ar.resrec.name->c, dereg->ar.resrec.rdata->u.name.c);
err = mDNS_Deregister(m, &dereg->ar);
- if (err) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err);
+ if (err) LogMsg("uDNS_RegisterSearchDomains ERROR!! mDNS_Deregister returned %d", err);
// Memory will be freed in the FreeARElemCallback
}
continue;
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"
+ LogMsg("uDNS_RegisterSearchDomains: 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);
+ mDNS_StartDirQuestion(m, &ptr->DirQ, &ptr->domain, ptr);
}
ptr->flag = 0;
}
- if (ptr->flag) { LogMsg("RegisterSearchDomains - unknown flag %d. Skipping.", ptr->flag); }
+ if (ptr->flag) { LogMsg("uDNS_RegisterSearchDomains - unknown flag %d. Skipping.", ptr->flag); }
p = &ptr->next;
}
-
+ // if there is any domain has answers, need to deregister autotunnel6
+ for (s=SearchList; s; s=s->next)
+ if (s->numDirAnswers) { RegisterAutoTunnel6 = mDNSfalse; break; }
+#if APPLE_OSX_mDNSResponder
+ CheckAutoTunnel6Registration(m, RegisterAutoTunnel6);
+#endif
return mStatus_NoError;
}
// 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) <= 3920) ? 1 : -1];
+ char sizecheck_SearchListElem[(sizeof(SearchListElem) <= 4800) ? 1 : -1];
};
* 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: 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
-
-Revision 1.91 2008/06/19 01:20:50 mcguire
-<rdar://problem/4206534> Use all configured DNS servers
-
-Revision 1.90 2007/12/22 02:25:30 cheshire
-<rdar://problem/5661128> Records and Services sometimes not re-registering on wake from sleep
-
-Revision 1.89 2007/12/15 01:12:27 cheshire
-<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
-
-Revision 1.88 2007/10/25 20:06:13 cheshire
-Don't try to do SOA queries using private DNS (TLS over TCP) queries
-
-Revision 1.87 2007/10/24 22:40:06 cheshire
-Renamed: RecordRegistrationCallback -> RecordRegistrationGotZoneData
-Renamed: ServiceRegistrationZoneDataComplete -> ServiceRegistrationGotZoneData
-
-Revision 1.86 2007/10/18 23:06:42 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Additional fixes and refinements
-
-Revision 1.85 2007/10/18 20:23:17 cheshire
-Moved SuspendLLQs into mDNS.c, since it's only called from one place
-
-Revision 1.84 2007/10/17 22:49:54 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-
-Revision 1.83 2007/10/17 22:37:23 cheshire
-<rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events
-
-Revision 1.82 2007/10/17 21:53:51 cheshire
-Improved debugging messages; renamed startLLQHandshakeCallback to LLQGotZoneData
-
-Revision 1.81 2007/10/16 21:16:50 cheshire
-Get rid of unused uDNS_Sleep() routine
-
-Revision 1.80 2007/10/16 20:59:41 cheshire
-Export SuspendLLQs/SleepServiceRegistrations/SleepRecordRegistrations so they're callable from other files
-
-Revision 1.79 2007/09/20 01:13:19 cheshire
-Export CacheGroupForName so it's callable from other files
-
-Revision 1.78 2007/09/14 21:26:09 cheshire
-<rdar://problem/5482627> BTMM: Need to manually avoid port conflicts when using UPnP gateways
-
-Revision 1.77 2007/09/12 23:03:08 cheshire
-<rdar://problem/5476978> DNSServiceNATPortMappingCreate callback not giving correct interface index
-
-Revision 1.76 2007/09/12 19:22:19 cheshire
-Variable renaming in preparation for upcoming fixes e.g. priv/pub renamed to intport/extport
-Made NAT Traversal packet handlers take typed data instead of anonymous "mDNSu8 *" byte pointers
-
-Revision 1.75 2007/08/28 23:53:21 cheshire
-Rename serviceRegistrationCallback -> ServiceRegistrationZoneDataComplete
-
-Revision 1.74 2007/08/24 00:15:20 cheshire
-Renamed GetAuthInfoForName() to GetAuthInfoForName_internal() to make it clear that it may only be called with the lock held
-
-Revision 1.73 2007/08/01 03:09:22 cheshire
-<rdar://problem/5344587> BTMM: Create NAT port mapping for autotunnel port
-
-Revision 1.72 2007/08/01 00:04:13 cheshire
-<rdar://problem/5261696> Crash in tcpKQSocketCallback
-Half-open TCP connections were not being cancelled properly
-
-Revision 1.71 2007/07/30 23:31:26 cheshire
-Code for respecting TTL received in uDNS responses should exclude LLQ-type responses
-
-Revision 1.70 2007/07/27 20:52:29 cheshire
-Made uDNS_recvLLQResponse() return tri-state result: LLQ_Not, LLQ_First, or LLQ_Events
-
-Revision 1.69 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
-
-Revision 1.68 2007/07/27 18:38:56 cheshire
-Rename "uDNS_CheckQuery" to more informative "uDNS_CheckCurrentQuestion"
-
-Revision 1.67 2007/07/20 23:11:12 cheshire
-Fix code layout
-
-Revision 1.66 2007/07/16 23:54:48 cheshire
-<rdar://problem/5338850> Crash when removing or changing DNS keys
-
-Revision 1.65 2007/07/16 20:14:22 vazquez
-<rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite
-
-Revision 1.64 2007/07/11 02:53:36 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-Add ServiceRecordSet parameter in GetServiceTarget
-
-Revision 1.63 2007/06/29 00:09:24 vazquez
-<rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes)
-
-Revision 1.62 2007/05/14 23:53:00 cheshire
-Export mDNS_StartQuery_internal and mDNS_StopQuery_internal so they can be called from uDNS.c
-
-Revision 1.61 2007/05/07 20:43:45 cheshire
-<rdar://problem/4241419> Reduce the number of queries and announcements
-
-Revision 1.60 2007/05/04 21:46:10 cheshire
-Get rid of uDNS_Close (synonym for uDNS_Sleep)
-
-Revision 1.59 2007/05/03 22:40:38 cheshire
-<rdar://problem/4669229> mDNSResponder ignores bogus null target in SRV record
-
-Revision 1.58 2007/05/02 22:21:33 cheshire
-<rdar://problem/5167331> RegisterRecord and RegisterService need to cancel StartGetZoneData
-
-Revision 1.57 2007/04/27 19:28:02 cheshire
-Any code that calls StartGetZoneData needs to keep a handle to the structure, so
-it can cancel it if necessary. (First noticed as a crash in Apple Remote Desktop
--- it would start a query and then quickly cancel it, and then when
-StartGetZoneData completed, it had a dangling pointer and crashed.)
-
-Revision 1.56 2007/04/25 02:14:38 cheshire
-<rdar://problem/4246187> uDNS: Identical client queries should reference a single shared core query
-Additional fixes to make LLQs work properly
-
-Revision 1.55 2007/04/22 06:02:03 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.54 2007/04/04 21:48:53 cheshire
-<rdar://problem/4720694> Combine unicast authoritative answer list with multicast list
-
-Revision 1.53 2007/03/28 15:56:37 cheshire
-<rdar://problem/5085774> Add listing of NAT port mapping and GetAddrInfo requests in SIGINFO output
-
-Revision 1.52 2007/02/28 01:44:26 cheshire
-<rdar://problem/5027863> Byte order bugs in uDNS.c, uds_daemon.c, dnssd_clientstub.c
-
-Revision 1.51 2007/01/27 03:34:27 cheshire
-Made GetZoneData use standard queries (and cached results);
-eliminated GetZoneData_Callback() packet response handler
-
-Revision 1.50 2007/01/19 21:17:32 cheshire
-StartLLQPolling needs to call SetNextQueryTime() to cause query to be done in a timely fashion
-
-Revision 1.49 2007/01/17 21:35:31 cheshire
-For clarity, rename zoneData_t field "isPrivate" to "zonePrivate"
-
-Revision 1.48 2007/01/10 22:51:57 cheshire
-<rdar://problem/4917539> Add support for one-shot private queries as well as long-lived private queries
-
-Revision 1.47 2007/01/05 08:30:43 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.46 2007/01/04 01:41:47 cheshire
-Use _dns-update-tls/_dns-query-tls/_dns-llq-tls instead of creating a new "_tls" subdomain
-
-Revision 1.45 2006/12/22 20:59:49 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.44 2006/12/20 04:07:35 cheshire
-Remove uDNS_info substructure from AuthRecord_struct
-
-Revision 1.43 2006/12/16 01:58:32 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-
-Revision 1.42 2006/11/30 23:07:56 herscher
-<rdar://problem/4765644> uDNS: Sync up with Lighthouse changes for Private DNS
-
-Revision 1.41 2006/11/18 05:01:30 cheshire
-Preliminary support for unifying the uDNS and mDNS code,
-including caching of uDNS answers
-
-Revision 1.40 2006/11/10 07:44:04 herscher
-<rdar://problem/4825493> Fix Daemon locking failures while toggling BTMM
-
-Revision 1.39 2006/10/20 05:35:05 herscher
-<rdar://problem/4720713> uDNS: Merge unicast active question list with multicast list.
-
-Revision 1.38 2006/09/26 01:54:02 herscher
-<rdar://problem/4245016> NAT Port Mapping API (for both NAT-PMP and UPnP Gateway Protocol)
-
-Revision 1.37 2006/09/15 21:20:15 cheshire
-Remove uDNS_info substructure from mDNS_struct
-
-Revision 1.36 2006/08/14 23:24:23 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.35 2006/07/30 05:45:36 cheshire
-<rdar://problem/4304215> Eliminate MIN_UCAST_PERIODIC_EXEC
-
-Revision 1.34 2006/07/15 02:01:29 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Fix broken "empty string" browsing
-
-Revision 1.33 2006/07/05 22:53:28 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-
-*/
+ */
#ifndef __UDNS_H_
#define __UDNS_H_
#define QuestionIntervalStep3 (QuestionIntervalStep*QuestionIntervalStep*QuestionIntervalStep)
#define InitialQuestionInterval ((mDNSPlatformOneSecond + QuestionIntervalStep-1) / QuestionIntervalStep)
+// For Unicast record registrations, we initialize the interval to 1 second. When we send any query for
+// the record registration e.g., GetZoneData, we always back off by QuestionIntervalStep
+// so that the first retry does not happen until 3 seconds which should be enough for TCP/TLS to be done.
+#define INIT_RECORD_REG_INTERVAL (1 * mDNSPlatformOneSecond)
+#define MAX_RECORD_REG_INTERVAL (15 * 60 * mDNSPlatformOneSecond)
+#define MERGE_DELAY_TIME (1 * mDNSPlatformOneSecond)
+
+// If we are refreshing, we do it at least 5 times with a min update frequency of
+// 5 minutes
+#define MAX_UPDATE_REFRESH_COUNT 5
+#define MIN_UPDATE_REFRESH_TIME (5 * 60 * mDNSPlatformOneSecond)
// Entry points into unicast-specific routines
extern void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo);
extern void startLLQHandshake(mDNS *m, DNSQuestion *q);
extern void sendLLQRefresh(mDNS *m, DNSQuestion *q);
-extern void SleepServiceRegistrations(mDNS *m);
extern void SleepRecordRegistrations(mDNS *m);
// uDNS_UpdateRecord
// rr->newrdlength
// rr->UpdateCallback
-extern mStatus uDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra);
extern mStatus uDNS_UpdateRecord(mDNS *m, AuthRecord *rr);
extern void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q);
extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name);
extern mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr);
-// mDNS_Dereg_normal is used for most calls to mDNS_Deregister_internal
-// mDNS_Dereg_conflict is used to indicate that this record is being forcibly deregistered because of a conflict
-// mDNS_Dereg_repeat is used when cleaning up, for records that may have already been forcibly deregistered
-typedef enum { mDNS_Dereg_normal, mDNS_Dereg_conflict, mDNS_Dereg_repeat } mDNS_Dereg_type;
extern mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt);
extern mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question);
extern mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question);
extern void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData);
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, AuthRecord *const rr);
-extern mStatus uDNS_DeregisterService(mDNS *const m, ServiceRecordSet *srs);
-
extern void uDNS_CheckCurrentQuestion(mDNS *const m);
// integer fields of msg header must be in HOST byte order before calling this routine
extern void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
const mDNSAddr *const srcaddr, const mDNSIPPort srcport);
-// returns time of next scheduled event
-extern void uDNS_Execute(mDNS *const m);
-extern void ResetDNSServerPenalties(mDNS *m);
+extern void uDNS_Tasks(mDNS *const m);
+extern void UpdateAllSRVRecords(mDNS *m);
+extern void CheckNATMappings(mDNS *m);
extern mStatus uDNS_SetupDNSConfig(mDNS *const m);
extern mStatus uDNS_RegisterSearchDomains(mDNS *const m);
uDNS_LLQ_Events // LLQ event packet: don't flush cache; assume TTL is 2 x LLQ refresh interval
} uDNS_LLQType;
-extern uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport);
+extern uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, DNSQuestion **matchQuestion);
extern DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname *const name);
extern DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *const q);
extern void DisposeTCPConn(struct tcpInfo_t *tcp);
* 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: CarbonResource.r,v $
-Revision 1.6 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.5 2003/08/12 19:56:24 cheshire
-Update to APSL 2.0
-
*/
data 'carb' (0) { };
* 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: 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
-
-Revision 1.24 2004/12/16 20:49:34 cheshire
-<rdar://problem/3324626> Cache memory management improvements
-
-Revision 1.23 2004/09/17 01:08:50 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.22 2004/08/13 23:25:01 cheshire
-Now that we do both uDNS and mDNS, global replace "m->hostname" with
-"m->MulticastHostname" for clarity
-
-Revision 1.21 2004/03/12 21:30:25 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
-Revision 1.20 2004/02/09 23:23:32 cheshire
-Advertise "IL 2\4th Floor.apple.com." as another test "browse domain"
-
-Revision 1.19 2004/01/24 23:55:15 cheshire
-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 (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
-
-Revision 1.16 2003/08/12 19:56:24 cheshire
-Update to APSL 2.0
-
*/
#include <stdio.h> // For printf()
* 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: 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
-
-Revision 1.22 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.21 2004/12/16 20:49:34 cheshire
-<rdar://problem/3324626> Cache memory management improvements
-
-Revision 1.20 2004/10/19 21:33:18 cheshire
-<rdar://problem/3844991> Cannot resolve non-local registrations using the mach API
-Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name
-doesn't force multicast unless you set this flag to indicate explicitly that this is what you want
-
-Revision 1.19 2004/09/17 01:08:50 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.18 2004/09/16 21:59:16 cheshire
-For consistency with zerov6Addr, rename zeroIPAddr to zerov4Addr
-
-Revision 1.17 2004/06/10 04:37:27 cheshire
-Add new parameter in mDNS_GetDomains()
-
-Revision 1.16 2004/03/12 21:30:25 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
-Revision 1.15 2004/01/24 23:55:15 cheshire
-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 (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
-
-Revision 1.12 2003/08/12 19:56:24 cheshire
-Update to APSL 2.0
-
*/
#include <stdio.h> // For printf()
* 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: Responder.c,v $
-Revision 1.3 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/05/20 18:38:31 cheshire
-Fix build broken by removal of 'kDNSServiceFlagsAutoRename' from dns_sd.h
-
-Revision 1.1 2004/03/12 21:30:25 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
*/
#include <stdio.h> // For printf()
* 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: Searcher.c,v $
-Revision 1.4 2006/12/19 22:43:54 cheshire
-Fix compiler warnings
-
-Revision 1.3 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/05/27 06:30:21 cheshire
-Add code to test DNSServiceQueryRecord()
-
-Revision 1.1 2004/03/12 21:30:25 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
*/
#include <stdio.h> // For printf()
* 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: SubTypeTester.c,v $
-Revision 1.7 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.6 2004/12/16 20:49:35 cheshire
-<rdar://problem/3324626> Cache memory management improvements
-
-Revision 1.5 2004/09/17 01:08:50 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.4 2004/09/16 00:24:49 cheshire
-<rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
-
-Revision 1.3 2004/08/13 23:25:01 cheshire
-Now that we do both uDNS and mDNS, global replace "m->hostname" with
-"m->MulticastHostname" for clarity
-
-Revision 1.2 2004/08/04 22:11:30 cheshire
-<rdar://problem/3588761> Current method of doing subtypes causes name collisions
-Change to use "._sub." instead of ".s." to mark subtypes.
-
-Revision 1.1 2004/06/11 00:03:28 cheshire
-Add code for testing avail/busy subtypes
-
-
*/
#include <stdio.h> // For printf()
* 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: mDNSLibrary.c,v $
-Revision 1.4 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2004/12/16 20:49:35 cheshire
-<rdar://problem/3324626> Cache memory management improvements
-
-Revision 1.2 2004/09/17 01:08:50 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.1 2004/03/12 21:30:26 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
*/
// Define the required CFM Shared Library entry and exit points
* 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: mDNSLibraryLoader.c,v $
-Revision 1.2 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2004/03/12 21:30:26 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
*/
#include <Resources.h>
* 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: mDNSLibraryResources.r,v $
-Revision 1.54 2007/06/27 21:59:08 cheshire
-mDNSResponder-130
-
-Revision 1.53 2007/05/29 23:47:57 cheshire
-mDNSResponder-129
-
-Revision 1.52 2007/05/25 23:45:39 jvidrine
-Update version numbers to reflect the submission number. (Thanks, Marc!)
-
-Revision 1.51 2007/05/25 22:10:19 cheshire
-mDNSResponder-127
-
-Revision 1.50 2007/05/23 00:57:23 cheshire
-mDNSResponder-126
-
-Revision 1.49 2007/05/15 00:47:50 cheshire
-mDNSResponder-125
-
-Revision 1.48 2007/05/14 20:49:54 cheshire
-mDNSResponder-124
-
-Revision 1.47 2007/05/10 21:43:12 cheshire
-mDNSResponder-123
-
-Revision 1.46 2007/04/27 19:33:07 cheshire
-mDNSResponder-122
-
-Revision 1.45 2007/04/08 03:04:00 cheshire
-mDNSResponder-121
-
-Revision 1.44 2007/03/30 23:30:04 cheshire
-mDNSResponder-120
-
-Revision 1.43 2007/02/28 22:09:24 cheshire
-mDNSResponder-119
-
-Revision 1.42 2007/01/09 01:58:20 cheshire
-mDNSResponder-116
-
-Revision 1.41 2006/11/08 04:29:02 cheshire
-mDNSResponder-115
-
-Revision 1.40 2006/10/27 01:46:40 cheshire
-mDNSResponder-114
-
-Revision 1.39 2006/09/30 01:38:53 cheshire
-mDNSResponder-113
-
-Revision 1.38 2006/09/21 23:38:13 cheshire
-mDNSResponder-112
-
-Revision 1.37 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.36 2006/07/14 00:52:00 cheshire
-mDNSResponder-111
-
-Revision 1.35 2006/06/20 23:05:10 cheshire
-mDNSResponder-110
-
-Revision 1.34 2006/02/09 22:24:53 cheshire
-mDNSResponder-109
-
-Revision 1.33 2005/12/12 17:48:36 cheshire
-mDNSResponder-108
-
-Revision 1.32 2005/05/05 00:06:58 ksekar
-Update version string to 1.0a107.1
-
-Revision 1.31 2005/03/15 02:14:14 cheshire
-mDNSResponder-107
-
-Revision 1.30 2005/03/10 01:32:37 cheshire
-mDNSResponder-105
-
-Revision 1.29 2005/02/26 05:20:13 cheshire
-mDNSResponder-102
-
-Revision 1.28 2005/02/19 00:42:58 cheshire
-mDNSResponder-101
-
-Revision 1.27 2005/02/10 21:56:38 cheshire
-mDNSResponder-100
-
-Revision 1.26 2005/02/04 03:25:10 cheshire
-mDNSResponder-99
-
-Revision 1.25 2005/01/28 00:04:16 cheshire
-mDNSResponder-98
-
-Revision 1.24 2005/01/22 01:15:14 ksekar
-Update version string to 1.0a97
-
-Revision 1.23 2005/01/13 19:50:17 ksekar
-Update version string to 1.0a94
-
-Revision 1.22 2005/01/10 16:33:26 ksekar
-Update version string to 1.0a93
-
-Revision 1.21 2004/12/23 23:50:59 ksekar
-Update version string to 1.0a92
-
-Revision 1.20 2004/12/20 23:26:47 cheshire
-mDNSResponder-90
-
-Revision 1.19 2004/12/16 20:52:38 cheshire
-mDNSResponder-89
-
-Revision 1.18 2004/12/15 20:25:49 cheshire
-mDNSResponder-88
-
-Revision 1.17 2004/12/13 21:54:30 cheshire
-mDNSResponder-87
-
-Revision 1.16 2004/12/06 19:09:47 cheshire
-mDNSResponder-86
-
-Revision 1.15 2004/11/29 23:36:15 cheshire
-mDNSResponder-85
-
-Revision 1.14 2004/11/23 03:46:31 cheshire
-mDNSResponder-84
-
-Revision 1.13 2004/10/26 20:30:30 cheshire
-mDNSResponder-82
-
-Revision 1.12 2004/10/14 23:38:04 cheshire
-mDNSResponder-80
-
-Revision 1.11 2004/10/07 21:49:15 cheshire
-mDNSResponder-79
-
-Revision 1.10 2004/09/25 02:52:09 cheshire
-mDNSResponder-78
-
-Revision 1.9 2004/09/22 22:52:07 cheshire
-mDNSResponder-77
-
-Revision 1.8 2004/09/21 00:20:52 cheshire
-mDNSResponder-76
-
-Revision 1.7 2004/09/15 19:45:06 cheshire
-mDNSResponder-75
-
-Revision 1.6 2004/09/09 23:32:35 cheshire
-mDNSResponder-74
-
-Revision 1.5 2004/08/10 21:51:45 cheshire
-mDNSResponder-69
-
-Revision 1.4 2004/06/10 20:28:16 cheshire
-Update version string to 1.0a66
-
-Revision 1.3 2004/06/05 00:37:12 cheshire
-Update version string to 1.0a65
-
-Revision 1.2 2004/05/27 06:24:21 cheshire
-Update version string to 1.0a64
-
-Revision 1.1 2004/03/12 21:30:26 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
*/
#ifndef __TYPES.R__
* 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: mDNSMacOS9.c,v $
-Revision 1.51 2007/09/12 19:23:17 cheshire
-Get rid of unnecessary mDNSPlatformTCPIsConnected() routine
-
-Revision 1.50 2007/04/05 20:40:37 cheshire
-Remove unused mDNSPlatformTCPGetFlags()
-
-Revision 1.49 2007/03/22 18:31:48 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.48 2007/03/20 17:07:15 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.47 2006/12/19 22:43:54 cheshire
-Fix compiler warnings
-
-Revision 1.46 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.45 2006/03/19 02:00:14 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.44 2005/09/16 21:06:50 cheshire
-Use mDNS_TimeNow_NoLock macro, instead of writing "mDNSPlatformRawTime() + m->timenow_adjust" all over the place
-
-Revision 1.43 2004/12/17 23:37:49 cheshire
-<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
-(and other repetitive configuration changes)
-
-Revision 1.42 2004/12/16 20:43:39 cheshire
-interfaceinfo.fMask should be interfaceinfo.fNetmask
-
-Revision 1.41 2004/10/16 00:17:00 cheshire
-<rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
-
-Revision 1.40 2004/09/27 23:56:27 cheshire
-Fix infinite loop where mDNSPlatformUnlock() called mDNS_TimeNow(),
-and then mDNS_TimeNow() called mDNSPlatformUnlock()
-
-Revision 1.39 2004/09/21 21:02:54 cheshire
-Set up ifname before calling mDNS_RegisterInterface()
-
-Revision 1.38 2004/09/17 01:08:50 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.37 2004/09/17 00:19:10 cheshire
-For consistency with AllDNSLinkGroupv6, rename AllDNSLinkGroup to AllDNSLinkGroupv4
-
-Revision 1.36 2004/09/16 21:59:16 cheshire
-For consistency with zerov6Addr, rename zeroIPAddr to zerov4Addr
-
-Revision 1.35 2004/09/16 00:24:49 cheshire
-<rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
-
-Revision 1.34 2004/09/14 23:42:36 cheshire
-<rdar://problem/3801296> Need to seed random number generator from platform-layer data
-
-Revision 1.33 2004/09/14 23:16:31 cheshire
-Fix compile error: mDNS_SetFQDNs has been renamed to mDNS_SetFQDN
-
-Revision 1.32 2004/09/14 21:03:16 cheshire
-Fix spacing
-
-Revision 1.31 2004/08/14 03:22:42 cheshire
-<rdar://problem/3762579> Dynamic DNS UI <-> mDNSResponder glue
-Add GetUserSpecifiedDDNSName() routine
-Convert ServiceRegDomain to domainname instead of C string
-Replace mDNS_GenerateFQDN/mDNS_GenerateGlobalFQDN with mDNS_SetFQDNs
-
-Revision 1.30 2004/07/29 19:26:03 ksekar
-Plaform-level changes for NAT-PMP support
-
-Revision 1.29 2004/05/26 20:53:16 cheshire
-Remove unncecessary "return( -1 );" at the end of mDNSPlatformUTC()
-
-Revision 1.28 2004/05/20 18:39:06 cheshire
-Fix build broken by addition of mDNSPlatformUTC requirement
-
-Revision 1.27 2004/04/21 02:49:11 cheshire
-To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
-
-Revision 1.26 2004/04/09 17:43:03 cheshire
-Make sure to set the McastTxRx field so that duplicate suppression works correctly
-
-Revision 1.25 2004/03/15 18:55:38 cheshire
-Comment out debugging message
-
-Revision 1.24 2004/03/12 21:30:26 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
-Revision 1.23 2004/02/09 23:24:43 cheshire
-Need to set TTL 255 to interoperate with peers that check TTL (oops!)
-
-Revision 1.22 2004/01/27 20:15:23 cheshire
-<rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
-
-Revision 1.21 2004/01/24 04:59:16 cheshire
-Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
-
-Revision 1.20 2003/11/14 20:59:09 cheshire
-Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
-Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
-
-Revision 1.19 2003/08/18 23:09:20 cheshire
-<rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformRawTime()
-
-Revision 1.18 2003/08/12 19:56:24 cheshire
-Update to APSL 2.0
-
*/
#include <stdio.h>
* 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: mDNSMacOS9.h,v $
-Revision 1.11 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.10 2004/03/12 21:30:26 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
-Revision 1.9 2004/02/09 23:25:35 cheshire
-Need to set TTL 255 to interoperate with peers that check TTL (oops!)
-
-Revision 1.8 2003/08/12 19:56:24 cheshire
-Update to APSL 2.0
-
*/
// ***************************************************************************
* 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: mDNSPrefix.h,v $
-Revision 1.4 2006/08/14 23:24:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2004/06/11 00:03:28 cheshire
-Add code for testing avail/busy subtypes
-
-Revision 1.2 2004/05/21 01:57:08 cheshire
-Add macros for malloc() and free() so that dnssd_clientlib.c can use them
-
-Revision 1.1 2004/03/12 21:30:26 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
*/
// Global definitions that apply to all source files
* 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: DNSServiceDiscoveryDefines.h,v $
-Revision 1.8 2006/10/27 00:35:36 cheshire
-DNS_SERVICE_DISCOVERY_SERVER is now com.apple.mDNSResponder, not DNSServiceDiscoveryServer
-
-Revision 1.7 2006/08/14 23:24:39 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.6 2004/09/20 21:45:27 ksekar
-Mach IPC cleanup
-
-Revision 1.5 2003/08/12 19:56:25 cheshire
-Update to APSL 2.0
-
*/
#ifndef __DNS_SERVICE_DISCOVERY_DEFINES_H
* 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: LegacyNATTraversal.c,v $
-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
-
-Revision 1.47 2008/07/18 21:37:46 mcguire
-<rdar://problem/5736845> BTMM: alternate SSDP queries between multicast & unicast
-
-Revision 1.46 2008/05/13 01:51:12 mcguire
-<rdar://problem/5839161> UPnP compatibility workaround for Netgear WGT624
-
-Revision 1.45 2007/12/06 00:22:27 mcguire
-<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
-
-Revision 1.44 2007/11/02 20:45:40 cheshire
-Don't log "connection failed" in customer builds
-
-Revision 1.43 2007/10/18 20:09:47 cheshire
-<rdar://problem/5545930> BTMM: Back to My Mac not working with D-Link DGL-4100 NAT gateway
-
-Revision 1.42 2007/10/16 17:37:18 cheshire
-<rdar://problem/3557903> Performance: Core code will not work on platforms with small stacks
-Cut SendSOAPMsgControlAction stack from 2144 to 96 bytes
-
-Revision 1.41 2007/10/15 23:02:00 cheshire
-Off-by-one error: Incorrect trailing zero byte on the end of the SSDP Discovery message
-
-Revision 1.40 2007/09/20 21:41:49 cheshire
-<rdar://problem/5495568> Legacy NAT Traversal - unmap request failed with error -65549
-
-Revision 1.39 2007/09/20 20:41:40 cheshire
-Reordered functions in file, in preparation for following fix
-
-Revision 1.38 2007/09/18 21:42:30 cheshire
-To reduce programming mistakes, renamed ExtPort to RequestedPort
-
-Revision 1.37 2007/09/14 21:26:09 cheshire
-<rdar://problem/5482627> BTMM: Need to manually avoid port conflicts when using UPnP gateways
-
-Revision 1.36 2007/09/14 01:15:50 cheshire
-Minor fixes for problems discovered in pre-submission testing
-
-Revision 1.35 2007/09/13 00:16:42 cheshire
-<rdar://problem/5468706> Miscellaneous NAT Traversal improvements
-
-Revision 1.34 2007/09/12 23:03:08 cheshire
-<rdar://problem/5476978> DNSServiceNATPortMappingCreate callback not giving correct interface index
-
-Revision 1.33 2007/09/12 19:22:20 cheshire
-Variable renaming in preparation for upcoming fixes e.g. priv/pub renamed to intport/extport
-Made NAT Traversal packet handlers take typed data instead of anonymous "mDNSu8 *" byte pointers
-
-Revision 1.32 2007/09/11 19:19:16 cheshire
-Correct capitalization of "uPNP" to "UPnP"
-
-Revision 1.31 2007/09/10 22:14:16 cheshire
-When constructing fake NATAddrReply or NATPortMapReply packet, need to calculate
-plausible upseconds value or core logic will think NAT engine has been rebooted
-
-Revision 1.30 2007/09/05 20:46:17 cheshire
-Tidied up alignment of code layout
-
-Revision 1.29 2007/08/03 20:18:01 vazquez
-<rdar://problem/5382177> LegacyNATTraversal: reading out of bounds can lead to DoS
-
-Revision 1.28 2007/07/31 02:28:36 vazquez
-<rdar://problem/3734269> NAT-PMP: Detect public IP address changes and base station reboot
-
-Revision 1.27 2007/07/30 23:17:03 vazquez
-Since lease times are meaningless in UPnP, return NATMAP_DEFAULT_LEASE in UPnP port mapping reply
-
-Revision 1.26 2007/07/27 22:50:08 vazquez
-Allocate memory for UPnP request and reply buffers instead of using arrays
-
-Revision 1.25 2007/07/27 20:33:44 vazquez
-Make sure we clean up previous port mapping requests before starting an unmap
-
-Revision 1.24 2007/07/27 00:57:48 vazquez
-If a tcp connection is already established for doing a port mapping, don't start it again
-
-Revision 1.23 2007/07/26 21:19:26 vazquez
-Retry port mapping with incremented port number (up to max) in order to handle
-port mapping conflicts on UPnP gateways
-
-Revision 1.22 2007/07/25 21:41:00 vazquez
-Make sure we clean up opened sockets when there are network transitions and when changing
-port mappings
-
-Revision 1.21 2007/07/25 03:05:03 vazquez
-Fixes for:
-<rdar://problem/5338913> LegacyNATTraversal: UPnP heap overflow
-<rdar://problem/5338933> LegacyNATTraversal: UPnP stack buffer overflow
-and a myriad of other security problems
-
-Revision 1.20 2007/07/16 20:15:10 vazquez
-<rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite
-
-Revision 1.19 2007/06/21 16:37:43 jgraessley
-Bug #: 5280520
-Reviewed by: Stuart Cheshire
-Additional changes to get this compiling on the embedded platform.
-
-Revision 1.18 2007/05/09 01:43:32 cheshire
-<rdar://problem/5187028> Change sprintf and strcpy to their safer snprintf and strlcpy equivalents
-
-Revision 1.17 2007/02/27 02:48:25 cheshire
-Parameter to LNT_GetPublicIP function is IPv4 address, not anonymous "mDNSOpaque32" object
-
-Revision 1.16 2006/08/14 23:24:39 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.15 2006/07/05 23:30:57 cheshire
-Rename LegacyNATInit() -> LNT_Init()
-
-Revision 1.14 2005/12/08 03:00:33 cheshire
-<rdar://problem/4349971> Byte order bugs in Legacy NAT traversal code
-
-Revision 1.13 2005/09/07 18:23:05 ksekar
-<rdar://problem/4151514> Off-by-one overflow in LegacyNATTraversal
-
-Revision 1.12 2005/07/22 21:36:16 ksekar
-Fix GCC 4.0/Intel compiler warnings
-
-Revision 1.11 2004/12/03 03:34:20 ksekar
-<rdar://problem/3882674> LegacyNATTraversal.c leaks threads
-
-Revision 1.10 2004/12/01 02:43:49 cheshire
-Update copyright message
-
-Revision 1.9 2004/10/27 02:25:05 cheshire
-<rdar://problem/3816029> Random memory smashing bug
-
-Revision 1.8 2004/10/27 02:17:21 cheshire
-Turn off "safe_close: ERROR" error messages -- there are too many of them
-
-Revision 1.7 2004/10/26 21:15:40 cheshire
-<rdar://problem/3854314> Legacy NAT traversal code closes file descriptor 0
-Additional fixes: Code should set fds to -1 after closing sockets.
-
-Revision 1.6 2004/10/26 20:59:20 cheshire
-<rdar://problem/3854314> Legacy NAT traversal code closes file descriptor 0
-
-Revision 1.5 2004/10/26 01:01:35 cheshire
-Use "#if 0" instead of commenting out code
-
-Revision 1.4 2004/10/10 06:51:36 cheshire
-Declared some strings "const" as appropriate
-
-Revision 1.3 2004/09/21 23:40:12 ksekar
-<rdar://problem/3810349> mDNSResponder to return errors on NAT traversal failure
-
-Revision 1.2 2004/09/17 01:08:52 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.1 2004/08/18 17:35:41 ksekar
-<rdar://problem/3651443>: Feature #9586: Need support for Legacy NAT gateways
-*/
+ */
#ifdef _LEGACY_NAT_TRAVERSAL_
int sslen = sizeof( ss );
ZeroMemory( &ss, sizeof( ss ) );
- ss.ss_family = family;
+ ss.ss_family = (ADDRESS_FAMILY)family;
- if ( WSAStringToAddressA( addr, family, NULL, ( struct sockaddr* ) &ss, &sslen ) == 0 )
+ if ( WSAStringToAddressA( (LPSTR)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; }
// In the event of a port conflict, handleLNTPortMappingResponse then increments tcpInfo->retries and calls back to SendPortMapRequest to try again
mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n);
-#define RequestedPortNum(n) (mDNSVal16(mDNSIPPortIsZero((n)->RequestedPort) ? (n)->IntPort : (n)->RequestedPort) + (n)->tcpInfo.retries)
+#define RequestedPortNum(n) (mDNSVal16(mDNSIPPortIsZero((n)->RequestedPort) ? (n)->IntPort : (n)->RequestedPort) + (mDNSu16)(n)->tcpInfo.retries)
// Note that this function assumes src is already NULL terminated
-mDNSlocal void AllocAndCopy(mDNSu8** dst, mDNSu8* src)
+mDNSlocal void AllocAndCopy(mDNSu8 **const dst, const mDNSu8 *const 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);
+ if ((*dst = mDNSPlatformMemAllocate((mDNSu32)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)
+mDNSlocal mStatus ParseHttpUrl(const mDNSu8 *ptr, const mDNSu8 *const end, mDNSu8 **const addressAndPort, mDNSIPPort *const port, mDNSu8 **const 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)
+ if (end - ptr >= 7 && strncasecmp((char*)ptr, "http://", 7) == 0)
{
- int i;
- char* stop = end;
- char* addrPtr = mDNSNULL;
+ int i;
+ const mDNSu8 *stop = end;
+ const mDNSu8 *addrPtr = mDNSNULL;
ptr += 7; //skip over "http://"
if (ptr >= end) { LogInfo("ParseHttpUrl: past end of buffer parsing host:port"); return mStatus_BadParamErr; }
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);
+ if ((*addressAndPort = mDNSPlatformMemAllocate(i+1)) == mDNSNULL)
+ { LogMsg("ParseHttpUrl: can't allocate address string"); return mStatus_NoMemoryErr; }
+ strncpy((char*)*addressAndPort, (char*)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--)
+ 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
+ *port = mDNSOpaque16fromIntVal((mDNSu16)strtol((char*)addrPtr, mDNSNULL, 10)); // store it properly converted
break;
}
}
// 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);
+ if ((*path = mDNSPlatformMemAllocate((mDNSu32)(end - ptr) + 1)) == mDNSNULL)
+ { LogMsg("ParseHttpUrl: can't mDNSPlatformMemAllocate path"); return mStatus_NoMemoryErr; }
+ strncpy((char*)*path, (char*)ptr, end - ptr);
(*path)[end - ptr] = '\0';
}
HTTPCode_500 = 500,
};
-mDNSlocal mDNSs16 ParseHTTPResponseCode(mDNSu8** data, mDNSu8* end)
+mDNSlocal mDNSs16 ParseHTTPResponseCode(const mDNSu8 **const data, const mDNSu8 *const end)
{
- mDNSu8* ptr = *data;
- char * code;
+ const mDNSu8 *ptr = *data;
+ const mDNSu8 *code;
if (end - ptr < 5) return HTTPCode_NeedMoreData;
if (strncasecmp((char*)ptr, "HTTP/", 5) != 0) return HTTPCode_Bad;
if (end - ptr < 3) return HTTPCode_NeedMoreData;
- code = (char*)ptr;
+ code = ptr;
ptr += 3;
while (ptr && ptr != end)
{
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;
+ if (memcmp((char*)code, "200", 3) == 0) return HTTPCode_200;
+ if (memcmp((char*)code, "404", 3) == 0) return HTTPCode_404;
+ if (memcmp((char*)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
+// 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)
{
mDNS *m = tcpInfo->m;
- char *ptr = (char *)tcpInfo->Reply;
- char *end = (char *)tcpInfo->Reply + tcpInfo->nread;
- char *stop = mDNSNULL;
+ const mDNSu8 *ptr = tcpInfo->Reply;
+ const mDNSu8 *end = tcpInfo->Reply + tcpInfo->nread;
+ const mDNSu8 *stop;
mDNSs16 http_result;
if (!mDNSIPPortIsZero(m->UPnPSOAPPort)) return; // already have the info we need
- http_result = ParseHTTPResponseCode((mDNSu8**)&ptr, (mDNSu8*)end); // Note: modifies ptr
+ http_result = ParseHTTPResponseCode(&ptr, end); // Note: modifies ptr
if (http_result == HTTPCode_404) LNT_ClearState(m);
if (http_result != HTTPCode_200)
{
// find either service we care about
while (ptr && ptr < end)
{
- if (*ptr == 'W' && (strncasecmp(ptr, "WANIPConnection:1", 17) == 0)) break;
+ if ((*ptr & 0xDF) == 'W' && (strncasecmp((char*)ptr, "WANIPConnection:1", 17) == 0)) break;
ptr++;
}
if (ptr == end)
{
- ptr = (char *)tcpInfo->Reply;
+ ptr = tcpInfo->Reply;
while (ptr && ptr < end)
{
- if (*ptr == 'W' && (strncasecmp(ptr, "WANPPPConnection:1", 18) == 0))
+ if ((*ptr & 0xDF) == 'W' && (strncasecmp((char*)ptr, "WANPPPConnection:1", 18) == 0))
{
m->UPnPWANPPPConnection = mDNStrue;
break;
// find "controlURL", starting from where we left off
while (ptr && ptr < end)
{
- if (*ptr == 'c' && (strncasecmp(ptr, "controlURL", 10) == 0)) break; // find the first 'c'; is this controlURL? if not, keep looking
+ if ((*ptr & 0xDF) == 'C' && (strncasecmp((char*)ptr, "controlURL", 10) == 0)) break; // find the first 'c'; is this controlURL? if not, keep looking
ptr++;
}
if (ptr == mDNSNULL || ptr == end) { LogInfo("handleLNTDeviceDescriptionResponse: didn't find controlURL string"); return; }
if (m->UPnPSOAPAddressString == mDNSNULL)
{
- ptr = (char *)tcpInfo->Reply;
+ ptr = tcpInfo->Reply;
while (ptr && ptr < end)
{
- if (*ptr == 'U' && (strncasecmp(ptr, "URLBase", 7) == 0)) break;
+ if ((*ptr & 0xDF) == 'U' && (strncasecmp((char*)ptr, "URLBase", 7) == 0)) break;
ptr++;
}
}
// if all else fails, use the router address string
- if (m->UPnPSOAPAddressString == mDNSNULL) AllocAndCopy(&m->UPnPSOAPAddressString, m->UPnPRouterAddressString);
+ 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);
mDNS *m = tcpInfo->m;
mDNSu16 err = NATErr_None;
mDNSv4Addr ExtAddr;
- 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
+ const mDNSu8 *ptr = tcpInfo->Reply;
+ const mDNSu8 *end = tcpInfo->Reply + tcpInfo->nread;
+ mDNSu8 *addrend;
+ static char tagname[20] = { 'N','e','w','E','x','t','e','r','n','a','l','I','P','A','d','d','r','e','s','s' };
+ // Array NOT including a terminating nul
// LogInfo("handleLNTGetExternalAddressResponse: %s", ptr);
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;
+ // (Might be better to copy this to a local string here -- this is overwriting tcpInfo->Reply in-place
+ addrend = (mDNSu8*)ptr;
while (addrend < end && (mDNSIsDigit(*addrend) || *addrend == '.')) addrend++;
if (addrend >= end) return;
*addrend = 0;
mDNSlocal void handleLNTPortMappingResponse(tcpLNTInfo *tcpInfo)
{
- mDNS *m = tcpInfo->m;
- mDNSIPPort extport = zeroIPPort;
- mDNSu8 *ptr = (mDNSu8*)tcpInfo->Reply;
- mDNSu8 *end = (mDNSu8*)tcpInfo->Reply + tcpInfo->nread;
+ mDNS *m = tcpInfo->m;
+ mDNSIPPort extport = zeroIPPort;
+ const mDNSu8 *ptr = tcpInfo->Reply;
+ const mDNSu8 *const end = tcpInfo->Reply + tcpInfo->nread;
NATTraversalInfo *natInfo;
mDNSs16 http_result;
{
while (ptr && ptr != end)
{
- 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))
+ if (((*ptr & 0xDF) == 'C' && end - ptr >= 8 && strncasecmp((char*)ptr, "Conflict", 8) == 0) ||
+ (*ptr == '>' && end - ptr >= 15 && strncasecmp((char*)ptr, ">718</errorCode", 15) == 0))
{
if (tcpInfo->retries < 100)
{
if (ConnectionEstablished) // connection is established - send the message
{
LogInfo("tcpConnectionCallback: connection established, sending message");
- nsent = mDNSPlatformWriteTCP(sock, (char *)tcpInfo->Request, tcpInfo->requestLen);
+ 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);
+ n = mDNSPlatformReadTCP(sock, (char*)tcpInfo->Reply + tcpInfo->nread, tcpInfo->replyLen - tcpInfo->nread, &closed);
LogInfo("tcpConnectionCallback: mDNSPlatformReadTCP read %d bytes", n);
if (n < 0) { LogInfo("tcpConnectionCallback - read returned %d", n); status = mStatus_ConnFailed; goto exit; }
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", "");
+ 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",
info->op = op;
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) { LogInfo("can't allocate reply buffer"); return (mStatus_NoMemoryErr); }
+ if (info->Reply != mDNSNULL) mDNSPlatformMemZero(info->Reply, LNT_MAXBUFSIZE); // reuse previously allocated buffer
+ else if ((info->Reply = mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL) { LogInfo("can't allocate reply buffer"); return (mStatus_NoMemoryErr); }
if (info->sock) { LogInfo("MakeTCPConnection: closing previous open connection"); mDNSPlatformTCPCloseConnection(info->sock); info->sock = mDNSNULL; }
info->sock = mDNSPlatformTCPSocket(m, kTCPSocketFlags_Zero, &srcport);
if (!info->sock) { LogMsg("LNT MakeTCPConnection: unable to create TCP socket"); mDNSPlatformMemFree(info->Reply); info->Reply = mDNSNULL; return(mStatus_NoMemoryErr); }
LogInfo("MakeTCPConnection: connecting to %#a:%d", &info->Address, mDNSVal16(info->Port));
- err = mDNSPlatformTCPConnect(info->sock, Addr, Port, 0, tcpConnectionCallback, info);
+ err = mDNSPlatformTCPConnect(info->sock, Addr, Port, mDNSNULL, 0, tcpConnectionCallback, info);
if (err == mStatus_ConnPending) err = mStatus_NoError;
else if (err == mStatus_ConnEstablished)
return(err);
}
-mDNSlocal unsigned int AddSOAPArguments(char *buf, unsigned int maxlen, int numArgs, Property *a)
+mDNSlocal unsigned int AddSOAPArguments(char *const buf, const unsigned int maxlen, const int numArgs, const Property *const a)
{
static const char f1[] = "<%s>%s</%s>";
static const char f2[] = "<%s xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"%s\">%s</%s>";
return(len);
}
-mDNSlocal mStatus SendSOAPMsgControlAction(mDNS *m, tcpLNTInfo *info, char *Action, int numArgs, Property *Arguments, LNTOp_t op)
+mDNSlocal mStatus SendSOAPMsgControlAction(mDNS *m, tcpLNTInfo *info, const char *const Action, const int numArgs, const Property *const Arguments, const LNTOp_t op)
{
// SOAP message header format -
// - control URL
"</SOAP-ENV:Envelope>\r\n";
mStatus err;
- char *body = (char *)&m->omsg; // Typically requires 1110-1122 bytes; m->omsg is 8952 bytes, which is plenty
+ char *body = (char*)&m->omsg; // Typically requires 1110-1122 bytes; m->omsg is 8952 bytes, which is plenty
int bodyLen;
if (mDNSIPPortIsZero(m->UPnPSOAPPort) || m->UPnPSOAPURL == mDNSNULL || m->UPnPSOAPAddressString == mDNSNULL) // if no SOAP URL or address exists get out here
// Create info->Request; the header needs to contain the bodyLen in the "Content-Length" field
if (!info->Request) info->Request = mDNSPlatformMemAllocate(LNT_MAXBUFSIZE);
if (!info->Request) { LogMsg("SendSOAPMsgControlAction: Can't allocate info->Request"); return mStatus_NoMemoryErr; }
- info->requestLen = mDNS_snprintf((char *)info->Request, LNT_MAXBUFSIZE, header, m->UPnPSOAPURL, m->UPnPWANPPPConnection ? "PPP" : "IP", Action, m->UPnPSOAPAddressString, bodyLen, body);
+ info->requestLen = mDNS_snprintf((char*)info->Request, LNT_MAXBUFSIZE, header, m->UPnPSOAPURL, m->UPnPWANPPPConnection ? "PPP" : "IP", Action, m->UPnPSOAPAddressString, bodyLen, body);
err = MakeTCPConnection(m, info, &m->Router, m->UPnPSOAPPort, op);
if (err) { mDNSPlatformMemFree(info->Request); info->Request = mDNSNULL; }
return SendSOAPMsgControlAction(m, &n->tcpInfo, "AddPortMapping", 8, propArgs, LNTPortMapOp);
}
-mDNSexport mStatus LNT_MapPort(mDNS *m, NATTraversalInfo *n)
+mDNSexport mStatus LNT_MapPort(mDNS *m, NATTraversalInfo *const n)
{
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
return SendPortMapRequest(m, n);
}
-mDNSexport mStatus LNT_UnmapPort(mDNS *m, NATTraversalInfo *n)
+mDNSexport mStatus LNT_UnmapPort(mDNS *m, NATTraversalInfo *const n)
{
char externalPort[10];
Property propArgs[3];
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); }
+ 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) { 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);
+ if (info->Request != mDNSNULL) mDNSPlatformMemZero(info->Request, LNT_MAXBUFSIZE); // reuse previously allocated buffer
+ else if ((info->Request = 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);
LogInfo("Describe Device: [%s]", info->Request);
return MakeTCPConnection(m, info, &m->Router, m->UPnPRouterPort, LNTDiscoveryOp);
}
// This function parses the response to our SSDP discovery message. Basically, we look to make sure this is a response
// referencing a service we care about (WANIPConnection or WANPPPConnection), then look for the "Location:" header and copy the addressing and
// URL info we need.
-mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 *data, mDNSu16 len)
+mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, const mDNSu8 *const data, const mDNSu16 len)
{
- char *ptr = (char *)data;
- char *end = (char *)data + len;
- char *stop = ptr;
+ const mDNSu8 *ptr = data;
+ const mDNSu8 *end = data + len;
+ const mDNSu8 *stop = ptr;
if (!mDNSIPPortIsZero(m->UPnPRouterPort)) return; // already have the info we need
// figure out if this is a message from a service we care about
while (ptr && ptr != end)
{
- if (*ptr == 'W' && (strncasecmp(ptr, "WANIPConnection:1", 17) == 0)) break;
+ if ((*ptr & 0xDF) == 'W' && (strncasecmp((char*)ptr, "WANIPConnection:1", 17) == 0)) break;
ptr++;
}
if (ptr == end)
{
- ptr = (char *)data;
+ ptr = data;
while (ptr && ptr != end)
{
- if (*ptr == 'W' && (strncasecmp(ptr, "WANPPPConnection:1", 18) == 0)) break;
+ if ((*ptr & 0xDF) == 'W' && (strncasecmp((char*)ptr, "WANPPPConnection:1", 18) == 0)) break;
ptr++;
}
}
if (ptr == mDNSNULL || ptr == end) return; // not a message we care about
// find "Location:", starting from the beginning
- ptr = (char *)data;
+ ptr = data;
while (ptr && ptr != end)
{
- if ((*ptr & 0xDF) == 'L' && (strncasecmp(ptr, "Location:", 9) == 0)) break; // find the first 'L'; is this Location? if not, keep looking
+ if ((*ptr & 0xDF) == 'L' && (strncasecmp((char*)ptr, "Location:", 9) == 0)) break; // find the first 'L'; is this Location? if not, keep looking
ptr++;
}
if (ptr == mDNSNULL || ptr == end)
"MX:3\r\n\r\n";
static const mDNSAddr multicastDest = { mDNSAddrType_IPv4, { { { 239, 255, 255, 250 } } } };
- mDNSu8* buf = (mDNSu8*)&m->omsg; //m->omsg is 8952 bytes, which is plenty
+ mDNSu8 *buf = (mDNSu8*)&m->omsg; //m->omsg is 8952 bytes, which is plenty
unsigned int bufLen;
if (!mDNSIPPortIsZero(m->UPnPRouterPort))
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: 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
-
-Revision 1.1 2005/02/05 02:28:22 cheshire
-Add Preference Pane to facilitate testing of DDNS & wide-area features
-
-*/
+ */
#include "ConfigurationAuthority.h"
#include "ConfigurationRights.h"
require_noerr( err, NewAuthFailed);
err = AuthorizationRightGet( UPDATE_SC_RIGHT, (CFDictionaryRef*) NULL);
- if( err == errAuthorizationDenied)
+ if (err == errAuthorizationDenied)
{
rightInfo = CFCopyLocalizedString(CFSTR("Authentication required to set Dynamic DNS preferences."),
CFSTR("Describes operation that requires user authorization"));
require_noerr( err, AuthSetFailed);
err = AuthorizationRightGet( EDIT_SYS_KEYCHAIN_RIGHT, (CFDictionaryRef*) NULL);
- if( err == errAuthorizationDenied)
+ if (err == errAuthorizationDenied)
{
rightInfo = CFCopyLocalizedString( CFSTR("Authentication required to edit System Keychain."),
CFSTR("Describes operation that requires user authorization"));
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: ConfigurationAuthority.h,v $
-Revision 1.1 2005/02/05 02:32:30 cheshire
-Add Preference Pane to facilitate testing of DDNS & wide-area features
-
-*/
+ */
#include <CoreServices/CoreServices.h>
#include <Security/Security.h>
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: ConfigurationRights.h,v $
-Revision 1.2 2006/08/14 23:15:47 cheshire
-Tidy up Change History comment
-
-Revision 1.1 2005/02/05 01:59:19 cheshire
-Add Preference Pane to facilitate testing of DDNS & wide-area features
-
-*/
+ */
#define UPDATE_SC_RIGHT "system.preferences"
#define EDIT_SYS_KEYCHAIN_RIGHT "system.preferences"
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: DNSServiceDiscoveryPref.h,v $
-Revision 1.6 2006/08/14 23:15:47 cheshire
-Tidy up Change History comment
-
-Revision 1.5 2005/02/26 00:44:24 cheshire
-Restore default reg domain if user deletes text and clicks "apply"
-
-Revision 1.4 2005/02/25 02:29:28 cheshire
-Show yellow dot for "update in progress"
-
-Revision 1.3 2005/02/10 22:35:19 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.2 2005/02/08 01:32:05 cheshire
-Add trimCharactersFromDomain routine to strip leading and trailing
-white space and punctuation from user-entered fields.
-
-Revision 1.1 2005/02/05 01:59:19 cheshire
-Add Preference Pane to facilitate testing of DDNS & wide-area features
-
-*/
+ */
#import <Cocoa/Cocoa.h>
#import <PreferencePanes/PreferencePanes.h>
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: 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
-
-Revision 1.10 2007/09/18 19:09:02 cheshire
-<rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
-
-Revision 1.9 2007/02/09 00:39:06 cheshire
-Fix compile warnings
-
-Revision 1.8 2006/08/14 23:15:47 cheshire
-Tidy up Change History comment
-
-Revision 1.7 2006/07/14 03:59:14 cheshire
-Fix compile warnings: 'sortUsingFunction:context:' comparison function needs to return int
-
-Revision 1.6 2005/02/26 00:44:24 cheshire
-Restore default reg domain if user deletes text and clicks "apply"
-
-Revision 1.5 2005/02/25 02:29:28 cheshire
-Show yellow dot for "update in progress"
-
-Revision 1.4 2005/02/16 00:18:33 cheshire
-Bunch o' fixes
-
-Revision 1.3 2005/02/10 22:35:20 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.2 2005/02/08 01:32:05 cheshire
-Add trimCharactersFromDomain routine to strip leading and trailing
-white space and punctuation from user-entered fields.
-
-Revision 1.1 2005/02/05 01:59:19 cheshire
-Add Preference Pane to facilitate testing of DDNS & wide-area features
-
-*/
+ */
#import "DNSServiceDiscoveryPref.h"
#import "ConfigurationAuthority.h"
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: 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
-
-Revision 1.7 2007/02/09 00:39:06 cheshire
-Fix compile warnings
-
-Revision 1.6 2006/08/14 23:15:47 cheshire
-Tidy up Change History comment
-
-Revision 1.5 2006/06/10 02:07:11 mkrochma
-Whoa. Make sure code compiles before checking it in.
-
-Revision 1.4 2006/05/27 02:32:38 mkrochma
-Wait for installer script to exit before returning result
-
-Revision 1.3 2005/06/04 04:50:00 cheshire
-<rdar://problem/4138070> ddnswriteconfig (Bonjour PreferencePane) vulnerability
-Use installtool instead of requiring ddnswriteconfig to self-install
-
-Revision 1.2 2005/02/10 22:35:20 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.1 2005/02/05 01:59:19 cheshire
-Add Preference Pane to facilitate testing of DDNS & wide-area features
-
-*/
+ */
#include "PrivilegedOperations.h"
#include "ConfigurationAuthority.h"
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: PrivilegedOperations.h,v $
-Revision 1.5 2006/08/14 23:15:47 cheshire
-Tidy up Change History comment
-
-Revision 1.4 2005/06/04 04:50:00 cheshire
-<rdar://problem/4138070> ddnswriteconfig (Bonjour PreferencePane) vulnerability
-Use installtool instead of requiring ddnswriteconfig to self-install
-
-Revision 1.3 2005/02/16 00:17:35 cheshire
-Don't create empty arrays -- CFArrayGetValueAtIndex(array,0) returns an essentially random (non-null)
-result for empty arrays, which can lead to code crashing if it's not sufficiently defensive.
-
-Revision 1.2 2005/02/10 22:35:20 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.1 2005/02/05 01:59:19 cheshire
-Add Preference Pane to facilitate testing of DDNS & wide-area features
-
-*/
+ */
#include <CoreServices/CoreServices.h>
#include <CoreFoundation/CoreFoundation.h>
-#define PRIV_OP_TOOL_VERS 3
+#define PRIV_OP_TOOL_VERS 4
#define kToolName "ddnswriteconfig"
#define kToolPath "/Library/Application Support/Bonjour/" kToolName
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: 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
-
-Revision 1.9 2007/09/18 19:09:02 cheshire
-<rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
-
-Revision 1.8 2007/07/20 23:41:03 mkrochma
-<rdar://problem/5348663> null deref in ddnswriteconfig
-
-Revision 1.7 2007/03/07 00:49:00 cheshire
-<rdar://problem/4618207> Security: ddnswriteconfig does not verify that authorization blob is of correct size
-
-Revision 1.6 2007/02/09 00:39:06 cheshire
-Fix compile warnings
-
-Revision 1.5 2006/08/14 23:15:47 cheshire
-Tidy up Change History comment
-
-Revision 1.4 2005/06/04 04:47:47 cheshire
-<rdar://problem/4138070> ddnswriteconfig (Bonjour PreferencePane) vulnerability
-Remove self-installing capability of ddnswriteconfig
-
-Revision 1.3 2005/02/16 00:17:35 cheshire
-Don't create empty arrays -- CFArrayGetValueAtIndex(array,0) returns an essentially random (non-null)
-result for empty arrays, which can lead to code crashing if it's not sufficiently defensive.
-
-Revision 1.2 2005/02/10 22:35:20 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.1 2005/02/05 01:59:19 cheshire
-Add Preference Pane to facilitate testing of DDNS & wide-area features
-
-*/
+ */
#import "PrivilegedOperations.h"
readTaggedBlock(int fd, u_int32_t *pTag, u_int32_t *pLen, char **ppBuff)
// Read tag, block len and block data from stream and return. Dealloc *ppBuff via free().
{
- ssize_t num, len;
- u_int32_t tag;
+ ssize_t num;
+ u_int32_t tag, len; // Don't use ssize_t because that's different on 32- vs. 64-bit
int result = 0;
num = read(fd, &tag, sizeof tag);
require_action(*ppBuff != NULL, AllocFailed, result = -1;);
num = read(fd, *ppBuff, len);
- if (num == len) {
+ if (num == (ssize_t)len) {
*pTag = tag;
*pLen = len;
} else {
# 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: installtool,v $
-# Revision 1.3 2006/09/05 20:00:13 cheshire
-# Moved Emacs settings to second line of file
-#
-# Revision 1.2 2006/08/14 23:15:14 cheshire
-# Added "tab-width" emacs header line
-#
-# Revision 1.1 2005/06/04 04:51:48 cheshire
-# <rdar://problem/4138070> ddnswriteconfig (Bonjour PreferencePane) vulnerability
-# Added separate "installtool" script instead of making ddnswriteconfig self-install
#
# Create the Bonjour subdirectory.
# Copy ARGV[0] to $dest and set owner and suid permissions.
* thinking that variables x and y are both of type "char*" -- and anyone who doesn't
* understand why variable y is not of type "char*" just proves the point that poor code
* layout leads people to unfortunate misunderstandings about how the C language really works.)
-
- 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
-
-Revision 1.53 2007/09/18 19:09:02 cheshire
-<rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
-
-Revision 1.52 2007/03/06 22:45:52 cheshire
-
-<rdar://problem/4138615> argv buffer overflow issues
-
-Revision 1.51 2007/02/13 18:56:45 cheshire
-<rdar://problem/4993485> Mach mDNS tool inconsistent with UDS-based dns-sd tool
-(missing domain should mean "system default(s)", not "local")
-
-Revision 1.50 2007/01/05 08:30:47 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.49 2007/01/04 21:54:49 cheshire
-Fix compile warnings related to the deprecated Mach-based API
-
-Revision 1.48 2006/08/14 23:24:39 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.47 2006/01/10 02:29:22 cheshire
-<rdar://problem/4403861> Cosmetic IPv6 address display problem in mDNS test tool
-
-*/
+ */
#include <libc.h>
#include <arpa/nameser.h>
* thinking that variables x and y are both of type "char*" -- and anyone who doesn't
* understand why variable y is not of type "char*" just proves the point that poor code
* layout leads people to unfortunate misunderstandings about how the C language really works.)
+ */
- 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
-
-Revision 1.359 2008/03/12 23:02:58 mcguire
-<rdar://problem/5769316> fix deprecated warnings/errors
-
-Revision 1.358 2008/03/06 21:26:11 cheshire
-Moved duplicated STRINGIFY macro from individual C files to DNSCommon.h
-
-Revision 1.357 2008/02/13 17:40:43 cheshire
-<rdar://problem/5740501> Investigate mysterious SIGABRTs in mDNSResponder
-
-Revision 1.356 2007/12/18 00:28:56 cheshire
-<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
-Error in ReadyForSleep() logic -- missing "not" in "!mDNSOpaque16IsZero(q->TargetQID)"
-
-Revision 1.355 2007/12/17 22:29:22 cheshire
-<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
-Log message indicating when we make IOAllowPowerChange call; make sure nextTimerEvent is set appropriately
-
-Revision 1.354 2007/12/15 01:12:28 cheshire
-<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
-
-Revision 1.353 2007/12/14 19:14:02 cheshire
-Added (commented out) code for testing sleep/wake
-
-Revision 1.352 2007/12/14 00:58:29 cheshire
-<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
-Additional fixes: When going to sleep, mDNSResponder needs to postpone sleep
-until TLS/TCP deregistrations have completed (up to five seconds maximum)
-
-Revision 1.351 2007/12/12 21:34:18 cheshire
-Now that <rdar://problem/5124399> "Not getting Keychain events" is apparently fixed,
-it makes sense to reduce our workaround retry count from 5 to 2 retries. Once we've
-confirmed that the bug is definitely fixed we'll remove the workaround altogether.
-
-Revision 1.350 2007/12/07 00:45:58 cheshire
-<rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
-
-Revision 1.349 2007/12/04 22:00:54 cheshire
-Fixed mistake in comment
-
-Revision 1.348 2007/12/01 00:27:43 cheshire
-Fixed compile warning: declaration of 'r' shadows a previous local
-
-Revision 1.347 2007/11/02 22:00:13 cheshire
-<rdar://problem/5575583> BTMM: Work around keychain notification bug <rdar://problem/5124399>
-Need to hold the lock while calling SetDomainSecrets
-
-Revision 1.346 2007/11/02 20:18:13 cheshire
-<rdar://problem/5575583> BTMM: Work around keychain notification bug <rdar://problem/5124399>
-
-Revision 1.345 2007/10/17 18:41:21 cheshire
-For debugging, make SIGUSR1 simulate a KeychainChanged event as well as a NetworkChanged
-
-Revision 1.344 2007/09/29 01:06:17 mcguire
-<rdar://problem/5507862> 9A564: mDNSResponder crash in mDNS_Execute
-
-Revision 1.343 2007/09/24 05:02:41 cheshire
-Debugging: In SIGINFO output, indicate explicitly when a given section is empty
-
-Revision 1.342 2007/09/18 19:09:02 cheshire
-<rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
-
-Revision 1.341 2007/09/12 01:22:13 cheshire
-Improve validatelists() checking to detect when 'next' pointer gets smashed to ~0
-
-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
-LogClientOperations check needs to be "#if LogClientOperations || MDNS_DEBUGMSGS"
-
-Revision 1.338 2007/09/05 23:34:27 mcguire
-Revert logging change
-
-Revision 1.337 2007/09/05 20:45:50 cheshire
-Added list of KQSocketEventSources in SIGINFO output
-
-Revision 1.336 2007/08/31 17:15:37 cheshire
-Reordered startup log messages so that "mDNSResponder ... starting" is the first message
-
-Revision 1.335 2007/08/31 02:00:16 cheshire
-Added comment explaining use of zero-width non-breaking space character to tag literal strings
-
-Revision 1.334 2007/08/24 23:40:24 cheshire
-Added comment about FreeServiceInstance
-
-Revision 1.333 2007/08/23 21:02:35 cheshire
-SecKeychainSetPreferenceDomain() call should be in platform-support layer, not daemon.c
-
-Revision 1.332 2007/08/22 23:54:54 mcguire
-<rdar://problem/5422558> BTMM: mDNSResponder should be able to run from the cmdline
-
-Revision 1.331 2007/08/18 01:02:03 mcguire
-<rdar://problem/5415593> No Bonjour services are getting registered at boot
-
-Revision 1.330 2007/08/10 22:25:57 mkrochma
-<rdar://problem/5396302> mDNSResponder continually complains about slow UDP packet reception -- about 400 msecs
-
-Revision 1.329 2007/08/08 22:34:58 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
-
-Revision 1.328 2007/07/27 22:43:37 cheshire
-Improved mallocL/freeL "suspiciously large" debugging messages
-
-Revision 1.327 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
-
-Revision 1.326 2007/07/24 17:23:33 cheshire
-<rdar://problem/5357133> Add list validation checks for debugging
-
-Revision 1.325 2007/07/11 23:43:43 cheshire
-Rename PurgeCacheResourceRecord to mDNS_PurgeCacheResourceRecord
-
-Revision 1.324 2007/07/11 22:44:40 cheshire
-<rdar://problem/5328801> SIGHUP should purge the cache
-
-Revision 1.323 2007/07/11 03:01:50 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-
-Revision 1.322 2007/07/06 18:58:16 cheshire
-Check m->NextScheduledNATOp in ShowTaskSchedulingError()
-
-Revision 1.321 2007/07/02 21:54:20 cheshire
-Fix compile error in MACOSX_MDNS_MALLOC_DEBUGGING checks
-
-Revision 1.320 2007/06/28 21:16:27 cheshire
-Rename "m->nextevent" as more informative "m->NextuDNSEvent"
-
-Revision 1.319 2007/06/22 20:47:08 cheshire
-<rdar://problem/5285417> DOS charset changes from CP932 to CP850 after Computer Name conflict
-Made a "SafeSCPreferencesSetComputerName" routine to set the Computer Name without changing the machine's default character set
-
-Revision 1.318 2007/06/20 01:45:40 cheshire
-When showing dormant interfaces, display last-seen IP address for that dormant interface
-
-Revision 1.317 2007/06/20 01:10:12 cheshire
-<rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
-
-Revision 1.316 2007/06/19 19:27:11 cheshire
-<rdar://problem/5141540> Sandbox mDNSResponder
-Weak-link sandbox_init, so mDNSResponder can be run on Tiger for regression testing
-
-Revision 1.315 2007/06/15 21:54:51 cheshire
-<rdar://problem/4883206> Add packet logging to help debugging private browsing over TLS
-
-Revision 1.314 2007/06/15 19:23:17 cheshire
-<rdar://problem/5254053> mDNSResponder renames my host without asking
-Improve log messages, to distinguish user-initiated renames from automatic (name conflict) renames
-
-Revision 1.313 2007/05/25 16:02:05 cheshire
-When MACOSX_MDNS_MALLOC_DEBUGGING is enabled, log suspiciously large memory allocations
-
-Revision 1.312 2007/05/22 19:07:21 cheshire
-Add comment explaining RR_CACHE_SIZE calculation
-
-Revision 1.311 2007/05/15 21:47:21 cheshire
-Get rid of "#pragma unused(m)"
-
-Revision 1.310 2007/05/08 00:56:17 cheshire
-<rdar://problem/4118503> Share single socket instead of creating separate socket for each active interface
-
-Revision 1.309 2007/04/30 21:33:38 cheshire
-Fix crash when a callback unregisters a service while the UpdateSRVRecords() loop
-is iterating through the m->ServiceRegistrations list
-
-Revision 1.308 2007/04/28 01:31:59 cheshire
-Improve debugging support for catching memory corruption problems
-
-Revision 1.307 2007/04/24 18:32:00 cheshire
-Grab a copy of KQtask string pointer in case KQcallback deletes the task
-
-Revision 1.306 2007/04/22 19:11:51 cheshire
-Some quirk of RemoveFromList (GenLinkedList.c) was corrupting the list and causing a crash
-if the element being removed was not the last in the list. Fixed by removing GenLinkedList.c
-from the project and just using simple vanilla C linked-list manipulation instead.
-
-Revision 1.305 2007/04/22 06:02:03 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.304 2007/04/21 21:47:47 cheshire
-<rdar://problem/4376383> Daemon: Add watchdog timer
-
-Revision 1.303 2007/04/18 00:50:47 cheshire
-<rdar://problem/5141540> Sandbox mDNSResponder
-
-Revision 1.302 2007/04/07 01:01:48 cheshire
-<rdar://problem/5095167> mDNSResponder periodically blocks in SSLRead
-
-Revision 1.301 2007/04/05 19:13:48 cheshire
-Use better name in SCPreferencesCreate
-
-Revision 1.300 2007/04/04 21:22:18 cheshire
-Suppress "Local Hostname changed" syslog message when name has not actually changed
-
-Revision 1.299 2007/04/03 19:19:33 cheshire
-Use mDNSIPPortIsZero() instead of peeking into 'NotAnInteger' field
-
-Revision 1.298 2007/03/30 21:51:45 cheshire
-Minor code tidying
-
-Revision 1.297 2007/03/27 22:47:19 cheshire
-On memory corruption, if ForceAlerts is set, force a crash to get a stack trace
-
-Revision 1.296 2007/03/24 01:23:29 cheshire
-Call validator for uDNS data structures
-
-Revision 1.295 2007/03/20 23:32:49 cheshire
-Minor textual tidying
-
-Revision 1.294 2007/03/07 02:50:50 cheshire
-<rdar://problem/4574528> Name conflict dialog doesn't appear if Bonjour is persistantly unable to find an available hostname
-
-Revision 1.293 2007/03/06 22:59:01 cheshire
-<rdar://problem/4157921> Security: Null dereference possible in daemon.c
-
-Revision 1.292 2007/02/28 21:55:10 cheshire
-<rdar://problem/3862944> UI: Name conflict notifications should be localized
-Additional fix: We were not getting our NotificationCallBackDismissed messages
-because we were scheduling our CFUserNotification RunLoopSource on the wrong runloop.
-(We were incorrectly assuming CFRunLoopGetCurrent() would be the right runloop.)
-
-Revision 1.291 2007/02/28 03:51:24 cheshire
-<rdar://problem/3862944> UI: Name conflict notifications should be localized
-Moved curly quotes out of the literal text and into the localized text, so they
-can be replaced with alternate characters as appropriate for other languages.
-
-Revision 1.290 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
-
-Revision 1.289 2007/02/07 19:32:00 cheshire
-<rdar://problem/4980353> All mDNSResponder components should contain version strings in SCCS-compatible format
-
-Revision 1.288 2007/02/07 01:01:24 cheshire
-<rdar://problem/3956518> Need to go native with launchd
-Additional refinements -- was unnecessarily calling launch_data_free()
-
-Revision 1.287 2007/02/06 19:06:48 cheshire
-<rdar://problem/3956518> Need to go native with launchd
-
-Revision 1.286 2007/01/06 01:00:33 cheshire
-Improved SIGINFO output
-
-Revision 1.285 2007/01/05 08:30:47 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.284 2007/01/05 05:44:35 cheshire
-Move automatic browse/registration management from uDNS.c to mDNSShared/uds_daemon.c,
-so that mDNSPosix embedded clients will compile again
-
-Revision 1.283 2007/01/04 23:11:14 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-When an automatic browsing domain is removed, generate appropriate "remove" events for legacy queries
-
-Revision 1.282 2006/12/21 00:09:45 cheshire
-Use mDNSPlatformMemZero instead of bzero
-
-Revision 1.281 2006/11/18 05:01:32 cheshire
-Preliminary support for unifying the uDNS and mDNS code,
-including caching of uDNS answers
-
-Revision 1.280 2006/11/10 00:54:16 cheshire
-<rdar://problem/4816598> Changing case of Computer Name doesn't work
-
-Revision 1.279 2006/11/02 17:44:01 cheshire
-No longer have a separate uDNS ActiveQueries list
-
-Revision 1.278 2006/10/05 04:04:24 herscher
-Remove embedded uDNS_info struct from DNSQuestion_struct
-
-Revision 1.277 2006/09/21 21:01:24 cheshire
-Change 'autorename' to more accurate name 'renameonmemfree'
-
-Revision 1.276 2006/09/17 19:12:02 cheshire
-Further changes for removal of uDNS_info substructure from mDNS_struct
-
-Revision 1.275 2006/09/15 21:20:16 cheshire
-Remove uDNS_info substructure from mDNS_struct
-
-Revision 1.274 2006/08/14 23:24:39 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.273 2006/07/30 05:43:19 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-Problems using KQueueFD with select() -- for now we'll stick to pure kevent()
-
-Revision 1.272 2006/07/27 03:24:35 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-Further refinement: Declare KQueueEntry parameter "const"
-
-Revision 1.271 2006/07/27 02:59:26 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-Further refinements: CFRunLoop thread needs to explicitly wake the kqueue thread
-after releasing BigMutex, in case actions it took have resulted in new work for the
-kqueue thread (e.g. NetworkChanged events may result in the kqueue thread having to
-add new active interfaces to its list, and consequently schedule queries to be sent).
-
-Revision 1.270 2006/07/25 17:16:36 mkrochma
-Quick fix to solve kqueue related crashes and hangs
-
-Revision 1.269 2006/07/22 06:11:37 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-
-Revision 1.268 2006/07/15 02:01:32 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Fix broken "empty string" browsing
-
-Revision 1.267 2006/07/07 01:09:10 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-Only use mallocL/freeL debugging routines when building mDNSResponder, not dnsextd
-
-Revision 1.266 2006/07/05 23:34:53 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-
-Revision 1.265 2006/06/29 07:32:08 cheshire
-Added missing LogOperation logging for DNSServiceBrowse results
-
-Revision 1.264 2006/06/29 05:33:30 cheshire
-<rdar://problem/4607043> mDNSResponder conditional compilation options
-
-Revision 1.263 2006/06/08 23:23:48 cheshire
-Fix errant indentation of curly brace at the end of provide_DNSServiceBrowserCreate_rpc()
-
-Revision 1.262 2006/03/18 21:49:11 cheshire
-Added comment in ShowTaskSchedulingError(mDNS *const m)
-
-Revision 1.261 2006/01/06 01:22:28 cheshire
-<rdar://problem/4108164> Reword "mach_absolute_time went backwards" dialog
-
-*/
+// We set VERSION_MIN_REQUIRED to 10.4 to avoid "bootstrap_register is deprecated" warnings from bootstrap.h
+#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_4
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <servers/bootstrap.h>
#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
#include <unistd.h>
#include <paths.h>
#include <fcntl.h>
static const char kmDNSBootstrapName[] = "com.apple.mDNSResponderRestart";
static mach_port_t m_port = MACH_PORT_NULL;
+
+#ifdef __LIB_DISPATCH__
+mDNSlocal void PrepareForIdle(void *m_param);
+#else __LIB_DISPATCH__
static mach_port_t client_death_port = MACH_PORT_NULL;
static mach_port_t signal_port = MACH_PORT_NULL;
+#endif __LIB_DISPATCH__
+
static mach_port_t server_priv_port = MACH_PORT_NULL;
static dnssd_sock_t *launchd_fds = mDNSNULL;
return(e || b || l || r);
}
+#ifndef __LIB_DISPATCH__
+
mDNSlocal void ClientDeathCallback(CFMachPortRef unusedport, void *voidmsg, CFIndex size, void *info)
{
KQueueLock(&mDNSStorage);
KQueueUnlock(&mDNSStorage, "Mach AbortClient");
}
+#endif __LIB_DISPATCH__
+
mDNSlocal void EnableDeathNotificationForClient(mach_port_t ClientMachPort, void *m)
{
+#ifdef __LIB_DISPATCH__
+ dispatch_source_t mach_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, ClientMachPort, 0, dispatch_get_main_queue());
+ if (mach_source == mDNSNULL)
+ {
+ AbortClientWithLogMessage(ClientMachPort, "died/deallocated before we could enable death notification", "", m);
+ return;
+ }
+ dispatch_source_set_event_handler(mach_source, ^{
+ mach_port_destroy(mach_task_self(), ClientMachPort);
+ });
+ dispatch_resume(mach_source);
+#else __LIB_DISPATCH__
mach_port_t prev;
kern_return_t r = mach_port_request_notification(mach_task_self(), ClientMachPort, MACH_NOTIFY_DEAD_NAME, 0,
client_death_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev);
// If the port already died while we were thinking about it, then abort the operation right away
if (r != KERN_SUCCESS)
AbortClientWithLogMessage(ClientMachPort, "died/deallocated before we could enable death notification", "", m);
+#endif __LIB_DISPATCH__
}
//*************************************************************************************************************
kern_return_t status;
DNSServiceResolver *x = (DNSServiceResolver *)query->ServiceInfoQueryContext;
NetworkInterfaceInfoOSX *ifx = IfindexToInterfaceInfoOSX(m, query->info->InterfaceID);
- if (query->info->InterfaceID == mDNSInterface_LocalOnly) ifx = mDNSNULL;
+ if (query->info->InterfaceID == mDNSInterface_LocalOnly || query->info->InterfaceID == mDNSInterface_P2P) ifx = mDNSNULL;
struct sockaddr_storage interface;
struct sockaddr_storage address;
char cstring[1024];
return(err);
}
+mDNSlocal void mDNSPreferencesSetNames(mDNS *const m, int key, domainlabel *old, domainlabel *new)
+ {
+ domainlabel *prevold, *prevnew;
+ switch (key)
+ {
+ case kmDNSComputerName:
+ case kmDNSLocalHostName:
+ if (key == kmDNSComputerName)
+ {
+ prevold = &m->p->prevoldnicelabel;
+ prevnew = &m->p->prevnewnicelabel;
+ }
+ else
+ {
+ prevold = &m->p->prevoldhostlabel;
+ prevnew = &m->p->prevnewhostlabel;
+ }
+ // There are a few cases where we need to invoke the helper.
+ //
+ // 1. If the "old" label and "new" label are not same, it means there is a conflict. We need
+ // to invoke the helper so that it pops up a dialogue to inform the user about the
+ // conflict
+ //
+ // 2. If the "old" label and "new" label are same, it means the user has set the host/nice label
+ // through the preferences pane. We may have to inform the helper as it may have popped up
+ // a dialogue previously (due to a conflict) and it needs to suppress it now. We can avoid invoking
+ // the helper in this case if the previous values (old and new) that we told helper last time
+ // are same. If the previous old and new values are same, helper does not care.
+ //
+ // Note: "new" can be NULL when we have repeated conflicts and we are asking helper to give up. "old"
+ // is not called with NULL today, but this makes it future proof.
+ if (!old || !new || !SameDomainLabelCS(old->c, new->c) ||
+ !SameDomainLabelCS(old->c, prevold->c) ||
+ !SameDomainLabelCS(new->c, prevnew->c))
+ {
+ if (old)
+ *prevold = *old;
+ else
+ prevold->c[0] = 0;
+ if (new)
+ *prevnew = *new;
+ else
+ prevnew->c[0] = 0;
+ mDNSPreferencesSetName(key, old, new);
+ }
+ else
+ {
+ LogInfo("mDNSPreferencesSetNames not invoking helper %s %#s, %s %#s, old %#s, new %#s",
+ (key == kmDNSComputerName ? "prevoldnicelabel" : "prevoldhostlabel"), prevold->c,
+ (key == kmDNSComputerName ? "prevnewnicelabel" : "prevnewhostlabel"), prevnew->c,
+ old->c, new->c);
+ }
+ break;
+ default:
+ LogMsg("mDNSPreferencesSetNames: unrecognized key: %d", key);
+ return;
+ }
+ }
+
mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
{
(void)m; // Unused
else if (m->timenow - m->p->HostNameConflict > 60 * mDNSPlatformOneSecond)
{
// Tell the helper we've given up
- mDNSPreferencesSetName(kmDNSLocalHostName, &m->p->userhostlabel, NULL);
+ mDNSPreferencesSetNames(m, kmDNSLocalHostName, &m->p->userhostlabel, NULL);
}
}
else if (result == mStatus_GrowCache)
else if (result == mStatus_ConfigChanged)
{
// Tell the helper we've seen a change in the labels. It will dismiss the name conflict alert if needed.
- mDNSPreferencesSetName(kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
- mDNSPreferencesSetName(kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
+ mDNSPreferencesSetNames(m, kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
+ mDNSPreferencesSetNames(m, kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
// First we check our list of old Mach-based registered services, to see if any need to be updated to a new name
DNSServiceRegistration *r;
{
debugf("NetworkChanged renaming %##s to %#s", si->srs.RR_SRV.resrec.name->c, m->nicelabel.c);
si->renameonmemfree = mDNStrue;
- if (mDNS_DeregisterService(m, &si->srs)) // If service deregistered already, we can re-register immediately
- RegCallback(m, &si->srs, mStatus_MemFree);
+ if (mDNS_DeregisterService_drt(m, &si->srs, mDNS_Dereg_rapid))
+ RegCallback(m, &si->srs, mStatus_MemFree); // If service deregistered already, we can re-register immediately
}
}
}
return mStatus_UnknownErr;
}
-mDNSlocal void UpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData)
+mDNSlocal void UpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData, mDNSu16 OldRDLen)
{
(void)m; // Unused
+ (void)OldRDLen; // Unused
if (OldRData != &rr->rdatastorage)
freeL("Old RData", OldRData);
}
mDNS_StartExit(&mDNSStorage);
}
+#ifndef __LIB_DISPATCH__
+
// Send a mach_msg to ourselves (since that is signal safe) telling us to cleanup and exit
mDNSlocal void HandleSIG(int sig)
{
while(1) *(long*)0 = 0;
}
+#endif __LIB_DISPATCH__
+
mDNSlocal void INFOCallback(void)
{
mDNSs32 utc = mDNSPlatformUTC();
NetworkInterfaceInfoOSX *i;
DNSServer *s;
- LogMsg("---- BEGIN STATE LOG ----");
+ LogMsg("---- BEGIN STATE LOG ---- %s", mDNSResponderVersionString);
udsserver_info(&mDNSStorage);
for (qptr = b->qlist; qptr; qptr = qptr->next)
LogMsgNoIdent("%5d: Mach ServiceBrowse %##s", b->ClientMachPort, qptr->q.qname.c);
}
+
for (l = DNSServiceResolverList; l; l=l->next)
LogMsgNoIdent("%5d: Mach ServiceResolve %##s", l->ClientMachPort, l->i.name.c);
{
KQSocketEventSource *k;
for (k = gEventSources; k; k=k->next)
+ {
LogMsgNoIdent("%3d %s", k->fd, k->kqs.KQtask);
+ usleep((mDNSStorage.KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
+ }
}
LogMsgNoIdent("------ Network Interfaces ------");
{
// Allow six characters for interface name, for names like "vmnet8"
if (!i->Exists)
- LogMsgNoIdent("%p %s %-6s(%lu) %.6a %.6a %#-14a dormant for %d seconds",
- i->ifinfo.InterfaceID,
+ LogMsgNoIdent("%p (%p), Registered %p, %s %-6s(%lu) %.6a %.6a %#-14a dormant for %d seconds",
+ i->ifinfo.InterfaceID, i, i->Registered,
i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, i->scope_id, &i->ifinfo.MAC, &i->BSSID,
&i->ifinfo.ip, utc - i->LastSeen);
else
{
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,
+ LogMsgNoIdent("%p (%p), Registered %p, %s %-6s(%lu) %.6a %.6a %s %s %-15.4a %s %s %s %s %#a",
+ i->ifinfo.InterfaceID, i, i->Registered,
i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, i->scope_id, &i->ifinfo.MAC, &i->BSSID,
i->ifinfo.InterfaceActive ? "Active" : " ",
i->ifinfo.IPv4Available ? "v4" : " ",
for (s = mDNSStorage.DNSServers; s; s = s->next)
{
NetworkInterfaceInfoOSX *ifx = IfindexToInterfaceInfoOSX(&mDNSStorage, s->interface);
- LogMsgNoIdent("DNS Server %##s %s%s%#a:%d %d %s",
+ LogMsgNoIdent("DNS Server %##s %s%s%#a:%d %d %s %s",
s->domain.c, ifx ? ifx->ifinfo.ifname : "", ifx ? " " : "", &s->addr, mDNSVal16(s->port),
- s->penaltyTime ? s->penaltyTime - mDNS_TimeNow(&mDNSStorage) : 0,
+ s->penaltyTime ? s->penaltyTime - mDNS_TimeNow(&mDNSStorage) : 0, s->scoped ? "Scoped" : "",
s->teststate == DNSServer_Untested ? "(Untested)" :
s->teststate == DNSServer_Passed ? "" :
s->teststate == DNSServer_Failed ? "(Failed)" :
mDNSs32 now = mDNS_TimeNow(&mDNSStorage);
LogMsgNoIdent("Timenow 0x%08lX (%d)", (mDNSu32)now, now);
- LogMsg("---- END STATE LOG ----");
+ LogMsg("---- END STATE LOG ---- %s", mDNSResponderVersionString);
}
+#ifndef __LIB_DISPATCH__
+
mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
{
(void)port; // Unused
// On 10.2 the MachServerName is DNSServiceDiscoveryServer
// On 10.3 and later, the MachServerName is com.apple.mDNSResponder
-
mDNSlocal kern_return_t mDNSDaemonInitialize(void)
{
mStatus err;
CFMachPortRef s_port;
+ CFRunLoopSourceRef s_rls;
+ CFRunLoopSourceRef d_rls;
// If launchd already created our Mach port for us, then use that, else we create a new one of our own
if (m_port != MACH_PORT_NULL)
if (status == 1103)
LogMsg("bootstrap_register() failed: A copy of the daemon is apparently already running");
else
- LogMsg("bootstrap_register() failed: %s %d", mach_error_string(status), status);
+ LogMsg("bootstrap_register() failed: %d %X %s", status, status, mach_error_string(status));
return(status);
}
}
CFMachPortRef d_port = CFMachPortCreate(NULL, ClientDeathCallback, NULL, NULL);
- CFMachPortRef i_port = CFMachPortCreate(NULL, SignalCallback, NULL, NULL);
- CFRunLoopSourceRef d_rls = CFMachPortCreateRunLoopSource(NULL, d_port, 0);
- CFRunLoopSourceRef s_rls = CFMachPortCreateRunLoopSource(NULL, s_port, 0);
- CFRunLoopSourceRef i_rls = CFMachPortCreateRunLoopSource(NULL, i_port, 0);
err = mDNS_Init(&mDNSStorage, &PlatformStorage,
rrcachestorage, RR_CACHE_SIZE,
if (err) { LogMsg("Daemon start: mDNS_Init failed %d", err); return(err); }
client_death_port = CFMachPortGetPort(d_port);
- signal_port = CFMachPortGetPort(i_port);
- CFRunLoopAddSource(PlatformStorage.CFRunLoop, d_rls, kCFRunLoopDefaultMode);
+ s_rls = CFMachPortCreateRunLoopSource(NULL, s_port, 0);
CFRunLoopAddSource(PlatformStorage.CFRunLoop, s_rls, kCFRunLoopDefaultMode);
- CFRunLoopAddSource(PlatformStorage.CFRunLoop, i_rls, kCFRunLoopDefaultMode);
- CFRelease(d_rls);
CFRelease(s_rls);
+
+ d_rls = CFMachPortCreateRunLoopSource(NULL, d_port, 0);
+ CFRunLoopAddSource(PlatformStorage.CFRunLoop, d_rls, kCFRunLoopDefaultMode);
+ CFRelease(d_rls);
+
+ CFMachPortRef i_port = CFMachPortCreate(NULL, SignalCallback, NULL, NULL);
+ CFRunLoopSourceRef i_rls = CFMachPortCreateRunLoopSource(NULL, i_port, 0);
+ signal_port = CFMachPortGetPort(i_port);
+ CFRunLoopAddSource(PlatformStorage.CFRunLoop, i_rls, kCFRunLoopDefaultMode);
CFRelease(i_rls);
+
+ if (mDNS_DebugMode) printf("Service registered with Mach Port %d\n", m_port);
+ return(err);
+ }
+
+#else __LIB_DISPATCH__
+
+// SignalDispatch is mostly just a copy/paste of entire code block from SignalCallback above.
+// The common code should be a subroutine, or we end up having to fix bugs in two places all the time.
+// The same applies to mDNSDaemonInitialize, much of which is just a copy/paste of chunks
+// of code from above. Alternatively we could remove the duplicated source code by having
+// single routines, with the few differing parts bracketed with "#ifndef __LIB_DISPATCH__"
+
+mDNSlocal void SignalDispatch(dispatch_source_t source)
+ {
+ int sig = (int)dispatch_source_get_handle(source);
+ mDNS *const m = &mDNSStorage;
+ KQueueLock(m);
+ switch(sig)
+ {
+ case SIGHUP: {
+ mDNSu32 slot;
+ 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(sig); break;
+ case SIGINFO: INFOCallback(); break;
+ 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;
+ default: LogMsg("SignalCallback: Unknown signal %d", sig); break;
+ }
+ KQueueUnlock(m, "Unix Signal");
+ }
+
+mDNSlocal void mDNSSetupSignal(dispatch_queue_t queue, int sig)
+ {
+ signal(sig, SIG_IGN);
+ dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, sig, 0, queue);
+
+ if (source)
+ {
+ dispatch_source_set_event_handler(source, ^{SignalDispatch(source);});
+ // Start processing signals
+ dispatch_resume(source);
+ }
+ else
+ {
+ LogMsg("mDNSSetupSignal: Cannot setup signal %d", sig);
+ }
+ }
+
+// On 10.2 the MachServerName is DNSServiceDiscoveryServer
+// On 10.3 and later, the MachServerName is com.apple.mDNSResponder
+mDNSlocal kern_return_t mDNSDaemonInitialize(void)
+ {
+ mStatus err;
+ CFMachPortRef s_port;
+ dispatch_source_t mach_source;
+ dispatch_queue_t queue = dispatch_get_main_queue();
+
+ // If launchd already created our Mach port for us, then use that, else we create a new one of our own
+ if (m_port != MACH_PORT_NULL)
+ s_port = CFMachPortCreateWithPort(NULL, m_port, DNSserverCallback, NULL, NULL);
+ else
+ {
+ s_port = CFMachPortCreate(NULL, DNSserverCallback, NULL, NULL);
+ m_port = CFMachPortGetPort(s_port);
+ char *MachServerName = OSXVers < OSXVers_10_3_Panther ? "DNSServiceDiscoveryServer" : "com.apple.mDNSResponder";
+ kern_return_t status = bootstrap_register(bootstrap_port, MachServerName, m_port);
+
+ if (status)
+ {
+ if (status == 1103)
+ LogMsg("bootstrap_register() failed: A copy of the daemon is apparently already running");
+ else
+ LogMsg("bootstrap_register() failed: %d %X %s", status, status, mach_error_string(status));
+ return(status);
+ }
+ }
+
+ err = mDNS_Init(&mDNSStorage, &PlatformStorage,
+ rrcachestorage, RR_CACHE_SIZE,
+ advertise,
+ mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
+
+ if (err) { LogMsg("Daemon start: mDNS_Init failed %d", err); return(err); }
+
+ mach_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, m_port, 0, queue);
+ if (mach_source == mDNSNULL){LogMsg("mDNSDaemonInitialize: Error creating source for m_port"); return -1;}
+ dispatch_source_set_event_handler(mach_source, ^{
+ dispatch_mig_server(mach_source, sizeof(union __RequestUnion__DNSServiceDiscoveryReply_subsystem),
+ DNSServiceDiscoveryRequest_server);
+ });
+ dispatch_resume(mach_source);
+
+ mDNSSetupSignal(queue, SIGHUP);
+ mDNSSetupSignal(queue, SIGINT);
+ mDNSSetupSignal(queue, SIGTERM);
+ mDNSSetupSignal(queue, SIGINFO);
+ mDNSSetupSignal(queue, SIGUSR1);
+ mDNSSetupSignal(queue, SIGUSR2);
+ mDNSSetupSignal(queue, SIGHUP);
+
+ // Create a custom handler for doing the housekeeping work. This is either triggered
+ // by the timer or an event source
+ PlatformStorage.custom = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
+ if (PlatformStorage.custom == mDNSNULL){LogMsg("mDNSDaemonInitialize: Error creating custom source"); return -1;}
+ dispatch_source_set_event_handler(PlatformStorage.custom, ^{PrepareForIdle(&mDNSStorage);});
+ dispatch_resume(PlatformStorage.custom);
+
+ // Create a timer source to trigger housekeeping work. The houskeeping work itself
+ // is done in the custom handler that we set below.
+
+ PlatformStorage.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
+ if (PlatformStorage.timer == mDNSNULL){LogMsg("mDNSDaemonInitialize: Error creating timer source"); return -1;}
+
+ // As the API does not support one shot timers, we pass zero for the interval. In the custom handler, we
+ // always reset the time to the new time computed. In effect, we ignore the interval
+ dispatch_source_set_timer(PlatformStorage.timer, DISPATCH_TIME_NOW, 1000ull * 1000000000, 0);
+ dispatch_source_set_event_handler(PlatformStorage.timer, ^{
+ dispatch_source_merge_data(PlatformStorage.custom, 1);
+ });
+ dispatch_resume(PlatformStorage.timer);
+
+ LogMsg("DaemonIntialize done successfully");
+
if (mDNS_DebugMode) printf("Service registered with Mach Port %d\n", m_port);
return(err);
}
+#endif __LIB_DISPATCH__
+
mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
{
mDNSs32 now = mDNS_TimeNow(m);
if (!SameDomainLabelCS(m->p->usernicelabel.c, m->nicelabel.c))
{
LogMsg("Name Conflict: Updated Computer Name from \"%#s\" to \"%#s\"", m->p->usernicelabel.c, m->nicelabel.c);
- mDNSPreferencesSetName(kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
+ mDNSPreferencesSetNames(m, kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
m->p->usernicelabel = m->nicelabel;
}
if (!SameDomainLabelCS(m->p->userhostlabel.c, m->hostlabel.c))
{
LogMsg("Name Conflict: Updated Local Hostname from \"%#s.local\" to \"%#s.local\"", m->p->userhostlabel.c, m->hostlabel.c);
- mDNSPreferencesSetName(kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
+ mDNSPreferencesSetNames(m, kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
m->p->HostNameConflict = 0; // Clear our indicator, now name change has been successful
m->p->userhostlabel = m->hostlabel;
}
}
LogSPS("AllowSleepNow: %s(%lX) %s at %ld (%d ticks remaining)",
-#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+#if !TARGET_OS_EMBEDDED && defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements)
(m->p->IOPMConnection) ? "IOPMConnectionAcknowledgeEventWithOptions" :
#endif
(result == kIOReturnSuccess) ? "IOAllowPowerChange" : "IOCancelPowerChange",
m->SleepLimit = 0; // Don't clear m->SleepLimit until after we've logged it above
-#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+#if !TARGET_OS_EMBEDDED && defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements)
if (m->p->IOPMConnection) IOPMConnectionAcknowledgeEventWithOptions(m->p->IOPMConnection, m->p->SleepCookie, opts);
else
#endif
return(mDNStrue);
}
+#ifdef __LIB_DISPATCH__
+
+mDNSexport void TriggerEventCompletion()
+ {
+ debugf("TriggerEventCompletion: Merge data");
+ dispatch_source_merge_data(PlatformStorage.custom, 1);
+ }
+
+mDNSlocal void PrepareForIdle(void *m_param)
+ {
+ mDNS *m = m_param;
+ int64_t time_offset;
+ dispatch_time_t dtime;
+
+ const int multiplier = 1000000000 / mDNSPlatformOneSecond;
+
+ // 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
+ // (2) Then we make sure we've delivered all waiting browse messages to our clients
+ // (3) Then we sleep for the time requested by mDNSCore, or until the next event, whichever is sooner
+
+ debugf("PrepareForIdle: called");
+ // Run mDNS_Execute to find out the time we next need to wake up
+ mDNSs32 start = mDNSPlatformRawTime();
+ mDNSs32 nextTimerEvent = udsserver_idle(mDNSDaemonIdle(m));
+ mDNSs32 end = mDNSPlatformRawTime();
+ if (end - start >= WatchDogReportingThreshold)
+ LogInfo("CustomSourceHandler: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 (mDNS_ExitNow(m, now))
+ {
+ if (!mDNSStorage.ResourceRecords)
+ safe_vproc_transaction_end();
+ LogInfo("IdleLoop: mDNS_FinalExit");
+ mDNS_FinalExit(&mDNSStorage);
+ usleep(1000); // Little 1ms pause before exiting, so we don't lose our final syslog messages
+ exit(0);
+ }
+ if (nextTimerEvent - m->ShutdownTime >= 0)
+ nextTimerEvent = m->ShutdownTime;
+ }
+
+ 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;
+ if (ticks < 1) ticks = 1;
+
+ static mDNSs32 RepeatedBusy = 0; // Debugging sanity check, to guard against CPU spins
+ if (ticks > 1)
+ RepeatedBusy = 0;
+ else
+ {
+ ticks = 1;
+ if (++RepeatedBusy >= mDNSPlatformOneSecond) { ShowTaskSchedulingError(&mDNSStorage); RepeatedBusy = 0; }
+ }
+
+ time_offset = ((mDNSu32)ticks / mDNSPlatformOneSecond) * 1000000000 + (ticks % mDNSPlatformOneSecond) * multiplier;
+ dtime = dispatch_time(DISPATCH_TIME_NOW, time_offset);
+ dispatch_source_set_timer(PlatformStorage.timer, dtime, 1000ull*1000000000, 0);
+ debugf("PrepareForIdle: scheduling timer with ticks %d", ticks);
+ return;
+ }
+
+#else __LIB_DISPATCH__
+
mDNSlocal void KQWokenFlushBytes(int fd, __unused short filter, __unused void *context)
{
// Read all of the bytes so we won't wake again.
{
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
+ AuthRecord *rr;
+ for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
+ {
+ LogInfo("Cannot exit yet; Resource Record still exists: %s", ARDisplayString(m, rr));
+ 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))
{
- if (!mDNSStorage.ResourceRecords && !mDNSStorage.ServiceRegistrations)
+ if (!mDNSStorage.ResourceRecords)
safe_vproc_transaction_end();
LogInfo("mDNS_FinalExit");
mDNS_FinalExit(&mDNSStorage);
return NULL;
}
+#endif __LIB_DISPATCH__
+
mDNSlocal void LaunchdCheckin(void)
{
launch_data_t msg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
{
int i;
kern_return_t status;
- pthread_t KQueueThread;
LogMsg("%s starting", mDNSResponderVersionString);
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], "-DisableSleepProxyClient" )) DisableSleepProxyClient = mDNStrue;
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;
- if (!strcasecmp(argv[i], "-StrictUnicastOrdering" )) StrictUnicastOrdering = mDNStrue;
+ if (!strcasecmp(argv[i], "-StrictUnicastOrdering" )) StrictUnicastOrdering = mDNStrue;
+ if (!strcasecmp(argv[i], "-DisableInboundRelay" )) DisableInboundRelayConnection = mDNStrue;
}
// Note that mDNSPlatformInit will set DivertMulticastAdvertisements in the mDNS structure
OSXVers = mDNSMacOSXSystemBuildNumber(NULL);
+#ifndef __LIB_DISPATCH__
+
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
// 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
signal(SIGUSR1, HandleSIG); // (Debugging) Enable Logging
signal(SIGUSR2, HandleSIG); // (Debugging) Enable Packet Logging
+#endif __LIB_DISPATCH__
+
mDNSStorage.p = &PlatformStorage; // Make sure mDNSStorage.p is set up, because validatelists uses it
LaunchdCheckin();
}
}
+#ifndef __LIB_DISPATCH__
+
// Create the kqueue, mutex and thread to support KQSockets
KQueueFD = kqueue();
if (KQueueFD == -1) { LogMsg("kqueue() failed errno %d (%s)", errno, strerror(errno)); status = errno; goto exit; }
// We will use the first socket to send the second socket. The second socket
// will be added to the kqueue so it will wake when data is sent.
static const KQueueEntry wakeKQEntry = { KQWokenFlushBytes, NULL, "kqueue wakeup after CFRunLoop event" };
+
PlatformStorage.WakeKQueueLoopFD = fdpair[0];
KQueueSet(fdpair[1], EV_ADD, EVFILT_READ, &wakeKQEntry);
+
+#endif __LIB_DISPATCH__
// Invoke sandbox profile /usr/share/sandbox/mDNSResponder.sb
#if MDNS_NO_SANDBOX
LogMsg("Note: Compiled without Apple Sandbox support");
-#else
+#else MDNS_NO_SANDBOX
if (!sandbox_init)
LogMsg("Note: Running without Apple Sandbox support (not available on this OS)");
else
{
char *sandbox_msg;
- int sandbox_err = sandbox_init("mDNSResponder", SANDBOX_NAMED, &sandbox_msg);
+ struct stat s;
+ uint64_t sandbox_flags = SANDBOX_NAMED;
+
+ if (stat("/usr/share/sandbox/mDNSResponder.sb", &s) == 0)
+ {
+ sandbox_flags = SANDBOX_NAMED_EXTERNAL;
+ LogInfo("Will load Sandbox profile from filesystem");
+ }
+
+ int sandbox_err = sandbox_init("mDNSResponder", sandbox_flags, &sandbox_msg);
if (sandbox_err) { LogMsg("WARNING: sandbox_init error %s", sandbox_msg); sandbox_free_error(sandbox_msg); }
else LogInfo("Now running under Apple Sandbox restrictions");
}
-#endif
+#endif MDNS_NO_SANDBOX
status = mDNSDaemonInitialize();
if (status) { LogMsg("Daemon start: mDNSDaemonInitialize failed"); goto exit; }
mDNSMacOSXNetworkChanged(&mDNSStorage);
+#ifdef __LIB_DISPATCH__
+ LogInfo("Daemon Start: Using LibDispatch");
+ // CFRunLoopRun runs both CFRunLoop sources and dispatch sources
+ CFRunLoopRun();
+#else __LIB_DISPATCH__
// Start the kqueue thread
+ pthread_t KQueueThread;
i = pthread_create(&KQueueThread, NULL, KQueueLoop, &mDNSStorage);
if (i == -1) { LogMsg("pthread_create() failed errno %d (%s)", errno, strerror(errno)); status = errno; goto exit; }
-
if (status == 0)
{
CFRunLoopRun();
LogMsg("ERROR: CFRunLoopRun Exiting.");
mDNS_Close(&mDNSStorage);
}
+#endif __LIB_DISPATCH__
LogMsg("%s exiting", mDNSResponderVersionString);
// uds_daemon.c support routines /////////////////////////////////////////////
// Arrange things so that when data appears on fd, callback is called with context
-mDNSexport mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context)
+mDNSexport mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context, void **platform_data)
{
KQSocketEventSource **p = &gEventSources;
+ (void) platform_data;
while (*p && (*p)->fd != fd) p = &(*p)->next;
if (*p) { LogMsg("udsSupportAddFDToEventLoop: ERROR fd %d already has EventLoop source entry", fd); return mStatus_AlreadyRegistered; }
newSource->kqs.KQcallback = callback;
newSource->kqs.KQcontext = context;
newSource->kqs.KQtask = "UDS client";
+#ifdef __LIB_DISPATCH__
+ newSource->kqs.readSource = mDNSNULL;
+ newSource->kqs.writeSource = mDNSNULL;
+ newSource->kqs.fdClosed = mDNSfalse;
+#endif __LIB_DISPATCH__
if (KQueueSet(fd, EV_ADD, EVFILT_READ, &newSource->kqs) == 0)
{
return mStatus_BadParamErr;
}
-mDNSexport mStatus udsSupportRemoveFDFromEventLoop(int fd) // Note: This also CLOSES the file descriptor
+int udsSupportReadFD(dnssd_sock_t fd, char *buf, int len, int flags, void *platform_data)
+ {
+ (void) platform_data;
+ return recv(fd, buf, len, flags);
+ }
+
+mDNSexport mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data) // Note: This also CLOSES the file descriptor
{
KQSocketEventSource **p = &gEventSources;
+ (void) platform_data;
while (*p && (*p)->fd != fd) p = &(*p)->next;
if (*p)
{
*p = (*p)->next;
// We don't have to explicitly do a kqueue EV_DELETE here because closing the fd
// causes the kernel to automatically remove any associated kevents
- close(s->fd);
+ mDNSPlatformCloseFD(&s->kqs, s->fd);
freeL("KQSocketEventSource", s);
return mStatus_NoError;
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.SystemConfiguration.SCDynamicStore-write-access</key>
+ <true/>
+ <key>com.apple.SystemConfiguration.SCPreferences-write-access</key>
+ <array>
+ <string>com.apple.AutoWake.xml</string>
+ </array>
+</dict>
+</plist>
* 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: helper-error.h,v $
-Revision 1.8 2007/11/07 00:22:30 jgraessley
-Bug #: <rdar://problem/5573573> mDNSResponder doesn't build without IPSec
-Reviewed by: Stuart Cheshire
-
-Revision 1.7 2007/09/12 00:42:47 mcguire
-<rdar://problem/5468236> BTMM: Need to clean up security associations
-
-Revision 1.6 2007/09/04 22:32:58 mcguire
-<rdar://problem/5453633> BTMM: BTMM overwrites /etc/racoon/remote/anonymous.conf
-
-Revision 1.5 2007/08/29 21:42:12 mcguire
-<rdar://problem/5431192> BTMM: Duplicate Private DNS names are being added to DynamicStore
-
-Revision 1.4 2007/08/23 21:15:49 cheshire
-Added $Log header
-
-Revision 1.3 2007/08/23 21:04:44 cheshire
-Tidied up alignment of error message list
-
-Revision 1.2 2007/08/18 01:02:03 mcguire
-<rdar://problem/5415593> No Bonjour services are getting registered at boot
-
-Revision 1.1 2007/08/08 22:34:58 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
-
*/
ERROR(kmDNSHelperCommunicationFailed, "Mach communication failed")
* 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: 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
-
-Revision 1.14 2008/03/12 23:02:59 mcguire
-<rdar://problem/5769316> fix deprecated warnings/errors
-
-Revision 1.13 2007/09/21 16:13:14 cheshire
-Additional Tiger compatibility fix: After bootstrap_check_in, we need to give
-ourselves a Mach "send" right to the port, otherwise our ten-second idle timeout
-mechanism is not able to send the "mDNSIdleExit" message to itself
-
-Revision 1.12 2007/09/20 22:26:20 cheshire
-Add necessary bootstrap_check_in() in Tiger compatibility code (not used on Leopard)
-
-Revision 1.11 2007/09/18 19:09:02 cheshire
-<rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
-
-Revision 1.10 2007/09/09 02:21:17 mcguire
-<rdar://problem/5469345> Leopard Server9A547(Insatll):mDNSResponderHelper crashing
-
-Revision 1.9 2007/09/07 22:44:03 mcguire
-<rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
-
-Revision 1.8 2007/09/07 22:24:36 vazquez
-<rdar://problem/5466301> Need to stop spewing mDNSResponderHelper logs
-
-Revision 1.7 2007/08/31 18:09:32 cheshire
-<rdar://problem/5434050> Restore ability to run mDNSResponder on Tiger
-
-Revision 1.6 2007/08/31 17:45:13 cheshire
-Allow maxidle time of zero, meaning "run indefinitely"
-
-Revision 1.5 2007/08/31 00:09:54 cheshire
-Deleted extraneous whitespace (shortened code from 260 lines to 160)
-
-Revision 1.4 2007/08/28 00:33:04 jgraessley
-<rdar://problem/5423932> Selective compilation options
-
-Revision 1.3 2007/08/23 23:21:24 cheshire
-Tiger compatibility: Use old bootstrap_register() instead of Leopard-only bootstrap_register2()
-
-Revision 1.2 2007/08/23 21:36:17 cheshire
-Made code layout style consistent with existing project style; added $Log header
-
-Revision 1.1 2007/08/08 22:34:58 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
*/
#define _FORTIFY_SOURCE 2
+
+// We set VERSION_MIN_REQUIRED to 10.4 to avoid "bootstrap_register is deprecated" warnings from bootstrap.h
+#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_4
+
#include <CoreFoundation/CoreFoundation.h>
#include <sys/cdefs.h>
#include <sys/time.h>
if (MACH_PORT_NULL == (port = launch_data_get_machport(datum)))
{ helplog(ASL_LEVEL_ERR, "Launchd gave me a null Mach port."); goto fin; }
if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND)))
- { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); goto fin; }
+ { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %d %X %s", kr, kr, mach_error_string(kr)); goto fin; }
fin:
if (NULL != msg) launch_data_free(msg);
if (KERN_SUCCESS == (kr = bootstrap_check_in(bootstrap_port, (char *)service_name, &port)))
{
if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND)))
- helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr));
+ helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %d %X %s", kr, kr, mach_error_string(kr));
else
return port;
}
if (KERN_SUCCESS != (kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port)))
- { helplog(ASL_LEVEL_ERR, "mach_port_allocate: %s", mach_error_string(kr)); goto error; }
+ { helplog(ASL_LEVEL_ERR, "mach_port_allocate: %d %X %s", kr, kr, mach_error_string(kr)); goto error; }
if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND)))
- { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); goto error; }
+ { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %d %X %s", kr, kr, mach_error_string(kr)); goto error; }
// XXX bootstrap_register does not modify its second argument, but the prototype does not include const.
if (KERN_SUCCESS != (kr = bootstrap_register(bootstrap_port, (char *)service_name, port)))
- { helplog(ASL_LEVEL_ERR, "bootstrap_register failed: %s", mach_error_string(kr)); goto error; }
+ { helplog(ASL_LEVEL_ERR, "bootstrap_register failed: %s %d %X %s", service_name, kr, kr, mach_error_string(kr)); goto error; }
return port;
error:
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));
+ if (MACH_RCV_TOO_LARGE != kr)
+ helplog(ASL_LEVEL_ERR, "main MACH_RCV_MSG error: %d %X %s", kr, 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); }
+ { helplog(ASL_LEVEL_ERR, "mach_msg_server: %d %X %s", kr, kr, mach_error_string(kr)); exit(EXIT_FAILURE); }
safe_vproc_transaction_end();
}
* 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: 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
-
-Revision 1.2 2007/08/23 21:39:01 cheshire
-Made code layout style consistent with existing project style; added $Log header
-
-Revision 1.1 2007/08/08 22:34:58 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
*/
#ifndef H_HELPER_SERVER_H
* 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: 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)
-
-Revision 1.5 2007/09/07 22:44:03 mcguire
-<rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
-
-Revision 1.4 2007/09/04 22:32:58 mcguire
-<rdar://problem/5453633> BTMM: BTMM overwrites /etc/racoon/remote/anonymous.conf
-
-Revision 1.3 2007/08/23 21:44:55 cheshire
-Made code layout style consistent with existing project style; added $Log header
-
-Revision 1.2 2007/08/18 01:02:03 mcguire
-<rdar://problem/5415593> No Bonjour services are getting registered at boot
-
-Revision 1.1 2007/08/08 22:34:58 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
*/
#include <mach/mach.h>
else \
{ \
(err) = kmDNSHelperCommunicationFailed; \
- LogMsg("%s: Mach communication failed: %s", __func__, mach_error_string(kr)); \
+ LogMsg("%s: Mach communication failed: %d %X %s", __func__, kr, kr, mach_error_string(kr)); \
goto fin; \
} \
} \
return err;
}
-int mDNSSetARP(int ifindex, const v4addr_t ip, const ethaddr_t eth)
+int mDNSSetLocalAddressCacheEntry(int ifindex, int family, const v6addr_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);
+ kr = proxy_mDNSSetLocalAddressCacheEntry(getHelperPort(retry), ifindex, family, (uint8_t*)ip, (uint8_t*)eth, &err);
MACHRETRYLOOP_END(kr, retry, err, fin);
fin:
return err;
CFDataRef bytes = NULL;
kern_return_t kr = KERN_FAILURE;
unsigned int numsecrets = 0;
- void *secrets = NULL;
+ vm_offset_t secrets = 0;
mach_msg_type_number_t secretsCnt = 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, &secrets, &secretsCnt, &err);
MACHRETRYLOOP_END(kr, retry, err, fin);
- if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, secrets, secretsCnt, kCFAllocatorNull)))
+ if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (void*)secrets, secretsCnt, kCFAllocatorNull)))
{
err = kmDNSHelperCreationFailed;
LogMsg("%s: CFDataCreateWithBytesNoCopy failed", __func__);
*result = (CFArrayRef)plist;
fin:
- if (NULL != bytes) CFRelease(bytes);
- if (NULL != secrets) vm_deallocate(mach_task_self(), (vm_offset_t)secrets, secretsCnt);
+ if (bytes) CFRelease(bytes);
+ if (secrets) vm_deallocate(mach_task_self(), secrets, secretsCnt);
return err;
}
}
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)
+ v6addr_t local_outer, short local_port, v6addr_t remote_inner,
+ v6addr_t remote_outer, short remote_port, const domainname *const fqdn)
{
kern_return_t kr = KERN_SUCCESS;
int retry = 0, err = 0;
* 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: 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
-
-Revision 1.23 2007/11/30 23:21:51 cheshire
-Rename variables to eliminate "declaration of 'sin_loc' shadows a previous local" warning
-
-Revision 1.22 2007/11/27 00:08:49 jgraessley
-<rdar://problem/5613538> Interface specific resolvers not setup correctly
-
-Revision 1.21 2007/11/07 00:22:30 jgraessley
-Bug #: <rdar://problem/5573573> mDNSResponder doesn't build without IPSec
-Reviewed by: Stuart Cheshire
-
-Revision 1.20 2007/09/12 18:07:44 cheshire
-Fix compile errors ("passing argument from incompatible pointer type")
-
-Revision 1.19 2007/09/12 00:42:47 mcguire
-<rdar://problem/5468236> BTMM: Need to clean up security associations
-
-Revision 1.18 2007/09/12 00:40:16 mcguire
-<rdar://problem/5469660> 9A547: Computer Name had incorrectly encoded unicode
-
-Revision 1.17 2007/09/09 02:21:17 mcguire
-<rdar://problem/5469345> Leopard Server9A547(Insatll):mDNSResponderHelper crashing
-
-Revision 1.16 2007/09/07 22:44:03 mcguire
-<rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
-
-Revision 1.15 2007/09/07 22:24:36 vazquez
-<rdar://problem/5466301> Need to stop spewing mDNSResponderHelper logs
-
-Revision 1.14 2007/09/06 20:39:05 cheshire
-Added comment explaining why we allow both "ddns" and "sndd" as valid item types
-The Keychain APIs on Intel appear to store the four-character item type backwards (at least some of the time)
-
-Revision 1.13 2007/09/04 22:32:58 mcguire
-<rdar://problem/5453633> BTMM: BTMM overwrites /etc/racoon/remote/anonymous.conf
-
-Revision 1.12 2007/08/29 21:42:12 mcguire
-<rdar://problem/5431192> BTMM: Duplicate Private DNS names are being added to DynamicStore
-
-Revision 1.11 2007/08/28 00:33:04 jgraessley
-<rdar://problem/5423932> Selective compilation options
-
-Revision 1.10 2007/08/27 22:16:38 mcguire
-<rdar://problem/5437362> BTMM: MTU should be set to 1280
-
-Revision 1.9 2007/08/27 22:13:59 mcguire
-<rdar://problem/5437373> BTMM: IPSec security associations should have a shorter timeout
-
-Revision 1.8 2007/08/23 21:49:51 cheshire
-Made code layout style consistent with existing project style; added $Log header
-
-Revision 1.7 2007/08/23 00:29:05 mcguire
-<rdar://problem/5425800> BTMM: IPSec policy not installed in some situations - connections fail
-
-Revision 1.6 2007/08/18 01:02:03 mcguire
-<rdar://problem/5415593> No Bonjour services are getting registered at boot
-
-Revision 1.5 2007/08/18 00:59:55 mcguire
-<rdar://problem/5392568> Blocked: BTMM: Start racoon with '-e' parameter
-
-Revision 1.4 2007/08/16 01:00:06 mcguire
-<rdar://problem/5392548> BTMM: Install generate IPsec policies to block non-BTMM traffic
-
-Revision 1.3 2007/08/15 23:20:28 mcguire
-<rdar://problem/5408105> BTMM: racoon files can get corrupted if autotunnel is listening on port > 32767
-
-Revision 1.2 2007/08/10 22:30:39 mcguire
-<rdar://problem/5400259> BTMM: racoon config files are not always the correct mode
-
-Revision 1.1 2007/08/08 22:34:58 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
*/
#include <sys/cdefs.h>
#include <netinet6/nd6.h>
#include <netinet6/ipsec.h>
#include <sys/ioctl.h>
+#include <sys/param.h>
#include <sys/socket.h>
#include <asl.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
#endif
#if TARGET_OS_EMBEDDED
+#ifndef MDNS_NO_IPSEC
+#define MDNS_NO_IPSEC 1
+#endif
#define NO_CFUSERNOTIFICATION 1
#define NO_SECURITYFRAMEWORK 1
#endif
return KERN_SUCCESS;
}
-kern_return_t do_mDNSSetARP(__unused mach_port_t port, int ifindex, v4addr_t v4, ethaddr_t eth, int *err, audit_token_t token)
+kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int ifindex, int family, v6addr_t ip, ethaddr_t eth, int *err, audit_token_t token)
{
- //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]);
+ #define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X"
+ #define IPv6FMTARGS ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]
+ #if 0
+ if (family == 4)
+ helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d %d.%d.%d.%d %02X:%02X:%02X:%02X:%02X:%02X",
+ ifindex, family, ip[0], ip[1], ip[2], ip[3], eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+ else
+ helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d " IPv6FMTSTRING " %02X:%02X:%02X:%02X:%02X:%02X",
+ ifindex, family, IPv6FMTARGS, eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+ #endif
*err = -1;
if (!authorized(&token)) { *err = kmDNSHelperNotAuthorized; goto fin; }
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) helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: socket(PF_ROUTE, SOCK_RAW, 0) failed %d (%s)", errno, strerror(errno));
}
if (s >= 0)
{
struct timeval tv;
gettimeofday(&tv, 0);
+ if (family == 4)
+ {
+ struct { struct rt_msghdr hdr; struct sockaddr_inarp dst; struct sockaddr_dl sdl; } rtmsg;
+ memset(&rtmsg, 0, sizeof(rtmsg));
+
+ rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
+ rtmsg.hdr.rtm_version = RTM_VERSION;
+ rtmsg.hdr.rtm_type = RTM_ADD;
+ rtmsg.hdr.rtm_index = ifindex;
+ rtmsg.hdr.rtm_flags = RTF_HOST | RTF_STATIC | RTF_IFSCOPE;
+ rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
+ rtmsg.hdr.rtm_pid = 0;
+ rtmsg.hdr.rtm_seq = seq++;
+ rtmsg.hdr.rtm_errno = 0;
+ rtmsg.hdr.rtm_use = 0;
+ rtmsg.hdr.rtm_inits = RTV_EXPIRE;
+ rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30;
+
+ rtmsg.dst.sin_len = sizeof(rtmsg.dst);
+ rtmsg.dst.sin_family = AF_INET;
+ rtmsg.dst.sin_port = 0;
+ rtmsg.dst.sin_addr.s_addr = *(in_addr_t*)ip;
+ rtmsg.dst.sin_srcaddr.s_addr = 0;
+ rtmsg.dst.sin_tos = 0;
+ rtmsg.dst.sin_other = 0;
+
+ rtmsg.sdl.sdl_len = sizeof(rtmsg.sdl);
+ rtmsg.sdl.sdl_family = AF_LINK;
+ rtmsg.sdl.sdl_index = ifindex;
+ rtmsg.sdl.sdl_type = IFT_ETHER;
+ rtmsg.sdl.sdl_nlen = 0;
+ rtmsg.sdl.sdl_alen = ETHER_ADDR_LEN;
+ rtmsg.sdl.sdl_slen = 0;
+
+ // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
+ memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
+
+ int len = write(s, (char *)&rtmsg, sizeof(rtmsg));
+ if (len < 0)
+ helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s)",
+ sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
+ len = read(s, (char *)&rtmsg, sizeof(rtmsg));
+ if (len < 0 || rtmsg.hdr.rtm_errno)
+ helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s) %d",
+ sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
+
+ *err = 0;
+ }
+ else
+ {
+ struct { struct rt_msghdr hdr; struct sockaddr_in6 dst; struct sockaddr_dl sdl; } rtmsg;
+ memset(&rtmsg, 0, sizeof(rtmsg));
+
+ rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
+ rtmsg.hdr.rtm_version = RTM_VERSION;
+ rtmsg.hdr.rtm_type = RTM_ADD;
+ rtmsg.hdr.rtm_index = ifindex;
+ rtmsg.hdr.rtm_flags = RTF_HOST | RTF_STATIC | RTF_IFSCOPE;
+ rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
+ rtmsg.hdr.rtm_pid = 0;
+ rtmsg.hdr.rtm_seq = seq++;
+ rtmsg.hdr.rtm_errno = 0;
+ rtmsg.hdr.rtm_use = 0;
+ rtmsg.hdr.rtm_inits = RTV_EXPIRE;
+ rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30;
+
+ rtmsg.dst.sin6_len = sizeof(rtmsg.dst);
+ rtmsg.dst.sin6_family = AF_INET6;
+ rtmsg.dst.sin6_port = 0;
+ rtmsg.dst.sin6_flowinfo = 0;
+ rtmsg.dst.sin6_addr = *(struct in6_addr*)ip;
+ rtmsg.dst.sin6_scope_id = ifindex;
+
+ rtmsg.sdl.sdl_len = sizeof(rtmsg.sdl);
+ rtmsg.sdl.sdl_family = AF_LINK;
+ rtmsg.sdl.sdl_index = ifindex;
+ rtmsg.sdl.sdl_type = IFT_ETHER;
+ rtmsg.sdl.sdl_nlen = 0;
+ rtmsg.sdl.sdl_alen = ETHER_ADDR_LEN;
+ rtmsg.sdl.sdl_slen = 0;
+
+ // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
+ memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
+
+ int len = write(s, (char *)&rtmsg, sizeof(rtmsg));
+ if (len < 0)
+ helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s)",
+ sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
+ len = read(s, (char *)&rtmsg, sizeof(rtmsg));
+ if (len < 0 || rtmsg.hdr.rtm_errno)
+ helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s) %d",
+ sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
+
+ *err = 0;
+ }
- 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:
if (err) helplog(ASL_LEVEL_ERR, "CFUserNotificationDisplayNotice returned %d", err);
CFRelease(alertHeader);
CFRelease(alertMessage);
+#else
+ (void)title;
+ (void)msg;
#endif /* NO_CFUSERNOTIFICATION */
update_idle_timer();
if (0 == strncmp(old, new, MAX_DOMAIN_LABEL+1))
{
- // if we've changed the name, but now someone else has set it to something different, we no longer need the notification
+ // old and new are same means the config changed i.e, the user has set something in the preferences pane.
+ // This means the conflict has been resolved. We need to dismiss the dialogue.
if (last[0] && 0 != strncmp(last, new, MAX_DOMAIN_LABEL+1))
{
last[0] = 0;
}
else
{
+ // old and new are not same, this means there is a conflict. For the first conflict, we show
+ // the old value and the new value. For all subsequent conflicts, while the dialogue is still
+ // up, we do a real time update of the "new" value in the dialogue. That's why we update just
+ // "last" here and not "user".
if (strncmp(last, new, MAX_DOMAIN_LABEL+1))
{
strncpy(last, new, MAX_DOMAIN_LABEL);
}
}
+ // If we are not showing the dialogue, we need to remember the first "old" value so that
+ // we maintain the same through the lifetime of the dialogue. Subsequence conflicts don't
+ // update the "old" value.
if (!user[0])
{
strncpy(user, old, MAX_DOMAIN_LABEL);
kmDNSTunnelPolicyGenerate
} mDNSTunnelPolicyWhich;
+// For kmDNSTunnelPolicySetup, you can setup IPv6-in-IPv6 tunnel or IPv6-in-IPv4 tunnel
+// kmDNSNoTunnel is used for other Policy types
+typedef enum _mDNSTunnelType
+ {
+ kmDNSNoTunnel,
+ kmDNSIPv6IPv4Tunnel,
+ kmDNSIPv6IPv6Tunnel
+ } mDNSTunnelType;
+
static const uint8_t kWholeV6Mask = 128;
static const uint8_t kZeroV6Mask = 0;
static int
-doTunnelPolicy(mDNSTunnelPolicyWhich which,
+doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
v6addr_t loc_inner, uint8_t loc_bits,
v4addr_t loc_outer, uint16_t loc_port,
v6addr_t rmt_inner, uint8_t rmt_bits,
- v4addr_t rmt_outer, uint16_t rmt_port);
+ v4addr_t rmt_outer, uint16_t rmt_port,
+ v6addr_t loc_outer6, v6addr_t rmt_outer6);
static int
aliasTunnelAddress(v6addr_t address)
}
v6addr_t zero = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
- err = doTunnelPolicy(kmDNSTunnelPolicyGenerate,
+ err = doTunnelPolicy(kmDNSTunnelPolicyGenerate, kmDNSNoTunnel,
address, kWholeV6Mask, NULL, 0,
- zero, kZeroV6Mask, NULL, 0);
+ zero, kZeroV6Mask, NULL, 0, NULL, NULL);
fin:
if (0 <= s)
}
v6addr_t zero = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- err = doTunnelPolicy(kmDNSTunnelPolicyTeardown,
+ err = doTunnelPolicy(kmDNSTunnelPolicyTeardown, kmDNSNoTunnel,
address, kWholeV6Mask, NULL, 0,
- zero, kZeroV6Mask, NULL, 0);
+ zero, kZeroV6Mask, NULL, 0, NULL, NULL);
fin:
if (0 <= s)
fin:
#else
(void)port; (void)updown; (void)address; (void)token;
- *err = kmDNSHelperIPsecDisabled;
#endif
update_idle_timer();
return KERN_SUCCESS;
return(major);
}
-static int g_oldRacoon = -1;
-static int g_racoonSignal = SIGUSR1;
-
-static void DetermineRacoonVersion()
+static int UseOldRacoon()
{
+ static int g_oldRacoon = -1;
+
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);
+ debug("%s", g_oldRacoon?"old":"new");
}
- }
-static int UseOldRacoon()
- {
- DetermineRacoonVersion();
return g_oldRacoon;
}
static int RacoonSignal()
{
- DetermineRacoonVersion();
- return g_racoonSignal;
+ return UseOldRacoon() ? SIGHUP : SIGUSR1;
}
static const char* GetRacoonConfigDir()
bytes = 0;
h.cookie = 0;
- while (counter < 100)
+ for (counter = 0; counter < 100; counter++)
{
FD_ZERO(&fds);
FD_SET(fd, &fds);
fin:
#else
(void)port; (void)updown; (void)fqdn; (void)token;
- *err = kmDNSHelperIPsecDisabled;
#endif
update_idle_timer();
return KERN_SUCCESS;
/* Caller owns object returned in `policy' */
static int
-generateTunnelPolicy(mDNSTunnelPolicyWhich which, int in,
+generateTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, int in,
v4addr_t src, uint16_t src_port,
v4addr_t dst, uint16_t dst_port,
+ v6addr_t src6, v6addr_t dst6,
ipsec_policy_t *policy, size_t *len)
{
char srcs[INET_ADDRSTRLEN], dsts[INET_ADDRSTRLEN];
- char buf[128];
+ char srcs6[INET6_ADDRSTRLEN], dsts6[INET6_ADDRSTRLEN];
+ char buf[512];
char *inOut = in ? "in" : "out";
ssize_t n = 0;
int err = 0;
switch (which)
{
case kmDNSTunnelPolicySetup:
- if (0 != (err = v4addr_to_string(src, srcs, sizeof(srcs))))
- goto fin;
- if (0 != (err = v4addr_to_string(dst, dsts, sizeof(dsts))))
- goto fin;
- n = snprintf(buf, sizeof(buf),
- "%s ipsec esp/tunnel/%s[%u]-%s[%u]/require",
- inOut, srcs, src_port, dsts, dst_port);
+ if (type == kmDNSIPv6IPv4Tunnel)
+ {
+ if (0 != (err = v4addr_to_string(src, srcs, sizeof(srcs))))
+ goto fin;
+ if (0 != (err = v4addr_to_string(dst, dsts, sizeof(dsts))))
+ goto fin;
+ n = snprintf(buf, sizeof(buf),
+ "%s ipsec esp/tunnel/%s[%u]-%s[%u]/require",
+ inOut, srcs, src_port, dsts, dst_port);
+ }
+ else if (type == kmDNSIPv6IPv6Tunnel)
+ {
+ if (0 != (err = v6addr_to_string(src6, srcs6, sizeof(srcs6))))
+ goto fin;
+ if (0 != (err = v6addr_to_string(dst6, dsts6, sizeof(dsts6))))
+ goto fin;
+ n = snprintf(buf, sizeof(buf),
+ "%s ipsec esp/tunnel/%s-%s/require",
+ inOut, srcs6, dsts6);
+ }
break;
case kmDNSTunnelPolicyTeardown:
n = strlcpy(buf, inOut, sizeof(buf));
}
static int
-doTunnelPolicy(mDNSTunnelPolicyWhich which,
+doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
v6addr_t loc_inner, uint8_t loc_bits,
v4addr_t loc_outer, uint16_t loc_port,
v6addr_t rmt_inner, uint8_t rmt_bits,
- v4addr_t rmt_outer, uint16_t rmt_port)
+ v4addr_t rmt_outer, uint16_t rmt_port,
+ v6addr_t loc_outer6, v6addr_t rmt_outer6)
{
struct sockaddr_in6 sin6_loc;
struct sockaddr_in6 sin6_rmt;
int setup = which != kmDNSTunnelPolicyTeardown;
- if (0 != (err = generateTunnelPolicy(which, 1,
+ if (0 != (err = generateTunnelPolicy(which, type, 1,
rmt_outer, rmt_port,
loc_outer, loc_port,
+ rmt_outer6, loc_outer6,
&policy, &len)))
goto fin;
if (0 != (err = sendPolicy(s, setup,
free(policy);
policy = NULL;
}
- if (0 != (err = generateTunnelPolicy(which, 0,
+ if (0 != (err = generateTunnelPolicy(which, type, 0,
loc_outer, loc_port,
rmt_outer, rmt_port,
+ loc_outer6, rmt_outer6,
&policy, &len)))
goto fin;
if (0 != (err = sendPolicy(s, setup,
policy, len)))
goto fin;
- if (which == kmDNSTunnelPolicyTeardown && loc_outer && rmt_outer)
+ if (which == kmDNSTunnelPolicyTeardown)
{
- struct sockaddr_in sin_loc;
- struct sockaddr_in sin_rmt;
+ if (rmt_port) // Outer tunnel is IPv4
+ {
+ if (loc_outer && rmt_outer)
+ {
+ struct sockaddr_in sin_loc;
+ struct sockaddr_in sin_rmt;
+ memset(&sin_loc, 0, sizeof(sin_loc));
+ sin_loc.sin_len = sizeof(sin_loc);
+ sin_loc.sin_family = AF_INET;
+ memcpy(&sin_loc.sin_addr, loc_outer, sizeof(sin_loc.sin_addr));
- memset(&sin_loc, 0, sizeof(sin_loc));
- sin_loc.sin_len = sizeof(sin_loc);
- sin_loc.sin_family = AF_INET;
- sin_loc.sin_port = htons(0);
- memcpy(&sin_loc.sin_addr, loc_outer, sizeof(sin_loc.sin_addr));
-
- memset(&sin_rmt, 0, sizeof(sin_rmt));
- sin_rmt.sin_len = sizeof(sin_rmt);
- sin_rmt.sin_family = AF_INET;
- sin_rmt.sin_port = htons(0);
- memcpy(&sin_rmt.sin_addr, rmt_outer, sizeof(sin_rmt.sin_addr));
-
- if (0 != (err = removeSA(s, (struct sockaddr *)&sin_loc, (struct sockaddr *)&sin_rmt)))
- goto fin;
+ memset(&sin_rmt, 0, sizeof(sin_rmt));
+ sin_rmt.sin_len = sizeof(sin_rmt);
+ sin_rmt.sin_family = AF_INET;
+ memcpy(&sin_rmt.sin_addr, rmt_outer, sizeof(sin_rmt.sin_addr));
+ if (0 != (err = removeSA(s, (struct sockaddr *)&sin_loc, (struct sockaddr *)&sin_rmt)))
+ goto fin;
+ }
+ }
+ else
+ {
+ if (loc_outer6 && rmt_outer6)
+ {
+ struct sockaddr_in6 sin6_lo;
+ struct sockaddr_in6 sin6_rm;
+
+ memset(&sin6_lo, 0, sizeof(sin6_lo));
+ sin6_lo.sin6_len = sizeof(sin6_lo);
+ sin6_lo.sin6_family = AF_INET6;
+ memcpy(&sin6_lo.sin6_addr, loc_outer6, sizeof(sin6_lo.sin6_addr));
+
+ memset(&sin6_rm, 0, sizeof(sin6_rm));
+ sin6_rm.sin6_len = sizeof(sin6_rm);
+ sin6_rm.sin6_family = AF_INET6;
+ memcpy(&sin6_rm.sin6_addr, rmt_outer6, sizeof(sin6_rm.sin6_addr));
+ if (0 != (err = removeSA(s, (struct sockaddr *)&sin6_lo, (struct sockaddr *)&sin6_rm)))
+ goto fin;
+ }
+ }
}
+
debug("succeeded");
fin:
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,
+ v6addr_t loc_inner, v6addr_t loc_outer6, uint16_t loc_port,
+ v6addr_t rmt_inner, v6addr_t rmt_outer6, uint16_t rmt_port,
const char *fqdn, int *err, audit_token_t token)
{
#ifndef MDNS_NO_IPSEC
" compression_algorithm deflate;\n"
"}\n";
char path[PATH_MAX] = "";
- char li[INET6_ADDRSTRLEN], lo[INET_ADDRSTRLEN],
- ri[INET6_ADDRSTRLEN], ro[INET_ADDRSTRLEN];
+ char li[INET6_ADDRSTRLEN], lo[INET_ADDRSTRLEN], lo6[INET6_ADDRSTRLEN],
+ ri[INET6_ADDRSTRLEN], ro[INET_ADDRSTRLEN], ro6[INET6_ADDRSTRLEN];
FILE *fp = NULL;
int fd = -1;
char tmp_path[PATH_MAX] = "";
+ v4addr_t loc_outer, rmt_outer;
debug("entry");
*err = 0;
*err = kmDNSHelperInvalidTunnelSetKeysOperation;
goto fin;
}
+
if (0 != (*err = v6addr_to_string(loc_inner, li, sizeof(li))))
goto fin;
if (0 != (*err = v6addr_to_string(rmt_inner, ri, sizeof(ri))))
goto fin;
- if (0 != (*err = v4addr_to_string(loc_outer, lo, sizeof(lo))))
- goto fin;
- if (0 != (*err = v4addr_to_string(rmt_outer, ro, sizeof(ro))))
- goto fin;
+
debug("loc_inner=%s rmt_inner=%s", li, ri);
- debug("loc_outer=%s loc_port=%u rmt_outer=%s rmt_port=%u",
- lo, loc_port, ro, rmt_port);
+ if (!rmt_port)
+ {
+ loc_outer[0] = loc_outer[1] = loc_outer[2] = loc_outer[3] = 0;
+ rmt_outer[0] = rmt_outer[1] = rmt_outer[2] = rmt_outer[3] = 0;
- if ((int)sizeof(path) <= snprintf(path, sizeof(path),
- "%s%s.%u.conf", GetRacoonConfigDir(), ro,
- rmt_port))
+ if (0 != (*err = v6addr_to_string(loc_outer6, lo6, sizeof(lo6))))
+ goto fin;
+ if (0 != (*err = v6addr_to_string(rmt_outer6, ro6, sizeof(ro6))))
+ goto fin;
+ debug("IPv6 outer tunnel: loc_outer6=%s rmt_outer6=%s", lo6, ro6);
+ if ((int)sizeof(path) <= snprintf(path, sizeof(path),
+ "%s%s.conf", GetRacoonConfigDir(), ro6))
+ {
+ *err = kmDNSHelperResultTooLarge;
+ goto fin;
+ }
+ }
+ else
{
- *err = kmDNSHelperResultTooLarge;
- goto fin;
+ loc_outer[0] = loc_outer6[0];
+ loc_outer[1] = loc_outer6[1];
+ loc_outer[2] = loc_outer6[2];
+ loc_outer[3] = loc_outer6[3];
+
+ rmt_outer[0] = rmt_outer6[0];
+ rmt_outer[1] = rmt_outer6[1];
+ rmt_outer[2] = rmt_outer6[2];
+ rmt_outer[3] = rmt_outer6[3];
+
+ if (0 != (*err = v4addr_to_string(loc_outer, lo, sizeof(lo))))
+ goto fin;
+ if (0 != (*err = v4addr_to_string(rmt_outer, ro, sizeof(ro))))
+ goto fin;
+ debug("IPv4 outer tunnel: loc_outer=%s loc_port=%u rmt_outer=%s rmt_port=%u",
+ lo, loc_port, ro, rmt_port);
+
+ if ((int)sizeof(path) <= snprintf(path, sizeof(path),
+ "%s%s.%u.conf", GetRacoonConfigDir(), ro,
+ rmt_port))
+ {
+ *err = kmDNSHelperResultTooLarge;
+ goto fin;
+ }
}
+
+
+
if (kmDNSAutoTunnelSetKeysReplace == replacedelete)
{
if (0 > ensureExistenceOfRacoonConfigDir(GetRacoonConfigDir()))
goto fin;
}
fd = -1;
- fprintf(fp, config, configHeader, ro, rmt_port, fqdn, fqdn, ri, li, li, ri);
+ fprintf(fp, config, configHeader, (!rmt_port ? ro6 : ro), rmt_port, fqdn, fqdn, ri, li, li, ri);
fclose(fp);
fp = NULL;
if (0 > rename(tmp_path, path))
*err = kmDNSHelperRacoonConfigCreationFailed;
goto fin;
}
- if (0 != (*err = kickRacoon()))
- goto fin;
}
else
{
strerror(errno));
}
- if (0 != (*err = doTunnelPolicy(kmDNSTunnelPolicyTeardown,
+ if (0 != (*err = doTunnelPolicy(kmDNSTunnelPolicyTeardown, kmDNSNoTunnel,
loc_inner, kWholeV6Mask, loc_outer, loc_port,
- rmt_inner, kWholeV6Mask, rmt_outer, rmt_port)))
+ rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6)))
goto fin;
if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
- 0 != (*err = doTunnelPolicy(kmDNSTunnelPolicySetup,
+ 0 != (*err = doTunnelPolicy(kmDNSTunnelPolicySetup, (!rmt_port ? kmDNSIPv6IPv6Tunnel : kmDNSIPv6IPv4Tunnel),
loc_inner, kWholeV6Mask, loc_outer, loc_port,
- rmt_inner, kWholeV6Mask, rmt_outer, rmt_port)))
+ rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6)))
goto fin;
if (0 != (*err = teardownTunnelRoute(rmt_inner)))
0 != (*err = setupTunnelRoute(loc_inner, rmt_inner)))
goto fin;
+ if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
+ 0 != (*err = kickRacoon()))
+ goto fin;
+
debug("succeeded");
fin:
close(fd);
unlink(tmp_path);
#else
- (void)replacedelete; (void)loc_inner; (void)loc_outer; (void)loc_port; (void)rmt_inner;
- (void)rmt_outer; (void)rmt_port; (void)keydata; (void)token;
+ (void)replacedelete; (void)loc_inner; (void)loc_outer6; (void)loc_port; (void)rmt_inner;
+ (void)rmt_outer6; (void)rmt_port; (void)fqdn; (void)token;
*err = kmDNSHelperIPsecDisabled;
#endif /* MDNS_NO_IPSEC */
* 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: 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
-
-Revision 1.5 2007/09/07 22:44:03 mcguire
-<rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
-
-Revision 1.4 2007/09/04 22:32:58 mcguire
-<rdar://problem/5453633> BTMM: BTMM overwrites /etc/racoon/remote/anonymous.conf
-
-Revision 1.3 2007/08/23 21:51:44 cheshire
-Made code layout style consistent with existing project style; added $Log header
-
-Revision 1.1 2007/08/08 22:34:58 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
*/
#ifndef H_HELPER_H
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 int mDNSSetLocalAddressCacheEntry(int ifindex, int family, const v6addr_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 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);
+ v6addr_t local_outer, short local_port, v6addr_t remote_inner,
+ v6addr_t remote_outer, short remote_port, const domainname *const fqdn);
#endif /* H_HELPER_H */
* 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: 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
-
-Revision 1.1 2007/08/08 22:34:58 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
*/
#ifndef H_HELPERMSG_TYPES_H
* 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: 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
-
-Revision 1.5 2007/09/04 22:32:58 mcguire
-<rdar://problem/5453633> BTMM: BTMM overwrites /etc/racoon/remote/anonymous.conf
-
-Revision 1.4 2007/08/23 21:53:13 cheshire
-Added $Log header
-
-Revision 1.3 2007/08/18 01:02:03 mcguire
-<rdar://problem/5415593> No Bonjour services are getting registered at boot
-
-Revision 1.2 2007/08/15 23:20:28 mcguire
-<rdar://problem/5408105> BTMM: racoon files can get corrupted if autotunnel is listening on port > 32767
-
-Revision 1.1 2007/08/08 22:34:58 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
*/
#include <mach/std_types.defs>
out err : int;
ServerAuditToken token : audit_token_t);
-routine mDNSSetARP( port : mach_port_t;
+routine mDNSSetLocalAddressCacheEntry(
+ port : mach_port_t;
ifindex : int;
- ip : v4addr_t;
+ family : int;
+ ip : v6addr_t;
eth : ethaddr_t;
out err : int;
ServerAuditToken token : audit_token_t);
value : pointer_t;
ServerAuditToken token : audit_token_t);
-simpleroutine mDNSPreferencesSetName( port : mach_port_t;
+simpleroutine mDNSPreferencesSetName(
+ port : mach_port_t;
key : int;
old : string_t;
new : string_t;
address : v6addr_t;
ServerAuditToken token : audit_token_t);
-simpleroutine mDNSConfigureServer( port : mach_port_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;
+ local_outer : v6addr_t;
+ local_port : uint16_t; /* Port expressed as a numeric integer value */
remote_inner : v6addr_t;
- remote_outer : v4addr_t;
- remote_port : uint16_t;
+ remote_outer : v6addr_t;
+ remote_port : uint16_t; /* Port expressed as a numeric integer value */
fqdn : string_t;
out err : int;
ServerAuditToken token : audit_token_t);
* 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: mDNSMacOSX.c,v $
-Revision 1.691 2009/07/30 20:28:15 mkrochma
-<rdar://problem/7100784> Sleep Proxy: Structure changes to data passed to userclient
-
-Revision 1.690 2009/07/15 22:34:25 cheshire
-<rdar://problem/6613674> Sleep Proxy: Add support for using sleep proxy in local network interface hardware
-Fixes to make the code still compile with old headers and libraries (pre 10.5) that don't include IOConnectCallStructMethod
-
-Revision 1.689 2009/07/15 22:09:19 cheshire
-<rdar://problem/6613674> Sleep Proxy: Add support for using sleep proxy in local network interface hardware
-Removed unnecessary sleep(1) and syslog message
-
-Revision 1.688 2009/07/11 01:58:17 cheshire
-<rdar://problem/6613674> Sleep Proxy: Add support for using sleep proxy in local network interface hardware
-Added ActivateLocalProxy routine for transferring mDNS records to local proxy
-
-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.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
+// ***************************************************************************
+// mDNSMacOSX.c:
+// Supporting routines to run mDNS on a CFRunLoop platform
+// ***************************************************************************
-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.
+// For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
+// including ones that mDNSResponder chooses not to use.
+#define LIST_ALL_INTERFACES 0
-Revision 1.679 2009/05/01 23:48:46 jessic2
-<rdar://problem/6830541> regservice_callback: instance->request is NULL 0
+// For enabling AAAA records over IPv4. Setting this to 0 sends only
+// A records over IPv4 and AAAA over IPv6. Setting this to 1 sends both
+// AAAA and A records over both IPv4 and IPv6.
+#define AAAA_OVER_V4 1
-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
+// In Mac OS X 10.4 and earlier, to reduce traffic, we would send and receive using IPv6 only on interfaces that had no routable
+// IPv4 address. Having a routable IPv4 address assigned is a reasonable indicator of being on a large configured network,
+// which means there's a good chance that most or all the other devices on that network should also have IPv4.
+// By doing this we lost the ability to talk to true IPv6-only devices on that link, but we cut the packet rate in half.
+// At that time, reducing the packet rate was more important than v6-only devices on a large configured network,
+// so were willing to make that sacrifice.
+// In Mac OS X 10.5, in 2007, two things have changed:
+// 1. IPv6-only devices are starting to become more common, so we can't ignore them.
+// 2. Other efficiency improvements in the code mean that crude hacks like this should no longer be necessary.
-Revision 1.677 2009/04/24 20:50:16 mcguire
-<rdar://problem/6791775> 4 second delay in DNS response
+#define USE_V6_ONLY_WHEN_NO_ROUTABLE_V4 0
-Revision 1.676 2009/04/24 02:17:58 mcguire
-<rdar://problem/5264124> uDNS: Not always respecting preference order of DNS servers
+#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
+#include "DNSCommon.h"
+#include "uDNS.h"
+#include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
+#include "dns_sd.h" // For mDNSInterface_LocalOnly etc.
+#include "PlatformCommon.h"
+#include "uds_daemon.h"
+#include <CoreServices/CoreServices.h>
-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)
+#include <stdio.h>
+#include <stdarg.h> // For va_list support
+#include <stdlib.h> // For arc4random
+#include <net/if.h>
+#include <net/if_types.h> // For IFT_ETHER
+#include <net/if_dl.h>
+#include <net/bpf.h> // For BIOCSETIF etc.
+#include <sys/uio.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/event.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <time.h> // platform support for UTC time
+#include <arpa/inet.h> // for inet_aton
+#include <pthread.h>
-Revision 1.674 2009/04/23 00:58:01 jessic2
-<rdar://problem/6802117> uDNS: DNS stops working after configd crashes
+#include <netinet/in.h> // For IP_RECVTTL
+#ifndef IP_RECVTTL
+#define IP_RECVTTL 24 // bool; receive reception TTL w/dgram
+#endif
-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
+#include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below
+#include <netinet/ip.h> // For IPTOS_LOWDELAY etc.
+#include <netinet6/in6_var.h> // For IN6_IFF_NOTREADY etc.
+#include <netinet6/nd6.h> // For ND6_INFINITE_LIFETIME etc.
-Revision 1.672 2009/04/21 16:34:47 mcguire
-<rdar://problem/6810663> null deref in mDNSPlatformSetDNSConfig
+#if TARGET_OS_EMBEDDED
+#define NO_SECURITYFRAMEWORK 1
+#define NO_CFUSERNOTIFICATION 1
+#endif
-Revision 1.671 2009/04/15 01:14:07 mcguire
-<rdar://problem/6791775> 4 second delay in DNS response
+#ifndef NO_SECURITYFRAMEWORK
+#include <Security/SecureTransport.h>
+#include <Security/Security.h>
+#endif /* NO_SECURITYFRAMEWORK */
-Revision 1.670 2009/04/15 01:10:39 jessic2
-<rdar://problem/6466541> BTMM: Add support for setting kDNSServiceErr_NoSuchRecord in DynamicStore
+#include <DebugServices.h>
+#include "dnsinfo.h"
-Revision 1.669 2009/04/11 02:02:34 mcguire
-<rdar://problem/6780046> crash in doSSLHandshake
+// Code contributed by Dave Heller:
+// Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will
+// work on Mac OS X 10.1, which does not have the getifaddrs call.
+#define RUN_ON_PUMA_WITHOUT_IFADDRS 0
+#if RUN_ON_PUMA_WITHOUT_IFADDRS
+#include "mDNSMacOSXPuma.c"
+#else
+#include <ifaddrs.h>
+#endif
-Revision 1.668 2009/04/11 00:20:08 jessic2
-<rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOMessage.h>
-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
+#ifdef __LIB_DISPATCH__
+// This is currently defined in IOKit/PrivateHeaders/IOKitLibPrivate.h. Till it becomes an Public
+// API, we will have our own declaration
+void IONotificationPortSetDispatchQueue(IONotificationPortRef notify, dispatch_queue_t queue);
+#endif
-Revision 1.666 2009/04/07 21:57:53 cheshire
-<rdar://problem/6767122> IOPMCopyActivePMPreferences not available on Apple TV
-Put previous code back
+#if USE_IOPMCOPYACTIVEPMPREFERENCES
+#include <IOKit/ps/IOPowerSources.h>
+#include <IOKit/ps/IOPowerSourcesPrivate.h>
+#endif
-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)
+#include <mach/mach_error.h>
+#include <mach/mach_port.h>
+#include <mach/mach_time.h>
+#include "helper.h"
-Revision 1.663 2009/04/02 22:21:16 mcguire
-<rdar://problem/6577409> Adopt IOPM APIs
+#include <asl.h>
-Revision 1.662 2009/04/02 01:08:15 mcguire
-<rdar://problem/6735635> Don't be a sleep proxy when set to sleep never
+#if APPLE_OSX_mDNSResponder
+#include <DeviceToDeviceManager/DeviceToDeviceManager.h>
+#include <AWACS.h>
-Revision 1.661 2009/04/01 17:50:14 mcguire
-cleanup mDNSRandom
+#if ! NO_D2D
+D2DStatus D2DInitialize(CFRunLoopRef runLoop, D2DServiceCallback serviceCallback, void* userData) __attribute__((weak_import));
+D2DStatus D2DTerminate() __attribute__((weak_import));
+D2DStatus D2DStartAdvertisingPair(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize) __attribute__((weak_import));
+D2DStatus D2DStopAdvertisingPair(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize) __attribute__((weak_import));
+D2DStatus D2DStartBrowsingForKey(const Byte *key, const size_t keySize) __attribute__((weak_import));
+D2DStatus D2DStopBrowsingForKey(const Byte *key, const size_t keySize) __attribute__((weak_import));
+void D2DStartResolvingPair(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize) __attribute__((weak_import));
+void D2DStopResolvingPair(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize) __attribute__((weak_import));
+D2DStatus D2DRetain(D2DServiceInstance instanceHandle, D2DTransportType transportType) __attribute__((weak_import));
+D2DStatus D2DRelease(D2DServiceInstance instanceHandle, D2DTransportType transportType) __attribute__((weak_import));
-Revision 1.660 2009/04/01 01:13:10 mcguire
-<rdar://problem/6744276> Sleep Proxy: Detect lid closed
+#define CHECK_D2D_FUNCTION(X) if (X)
-Revision 1.659 2009/03/30 21:11:07 jessic2
-<rdar://problem/6728725> Need to do some polish work on MessageTracer logging
+#endif // ! NO_D2D
-Revision 1.658 2009/03/30 20:07:28 mcguire
-<rdar://problem/6736133> BTMM: SSLHandshake threads are leaking Mach ports
+#else
+#define NO_D2D 1
+#define NO_AWACS 1
+#endif // APPLE_OSX_mDNSResponder
-Revision 1.657 2009/03/27 17:27:13 cheshire
-<rdar://problem/6724859> Need to support querying IPv6 DNS servers
+#define kInterfaceSpecificOption "interface="
-Revision 1.656 2009/03/26 05:02:48 mcguire
-fix build error in dnsextd
+// ***************************************************************************
+// Globals
-Revision 1.655 2009/03/26 03:59:00 jessic2
-Changes for <rdar://problem/6492552&6492593&6492609&6492613&6492628&6492640&6492699>
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark - Globals
+#endif
-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
+// By default we don't offer sleep proxy service
+// If OfferSleepProxyService is set non-zero (typically via command-line switch),
+// then we'll offer sleep proxy service on desktop Macs that are set to never sleep.
+// We currently do not offer sleep proxy service on laptops, or on machines that are set to go to sleep.
+mDNSexport int OfferSleepProxyService = 0;
+mDNSexport int DisableSleepProxyClient = 0;
-Revision 1.653 2009/03/20 20:52:22 cheshire
-<rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
+// We disable inbound relay connection if this value is set to true (typically via command-line switch).
+mDNSBool DisableInboundRelayConnection = mDNSfalse;
+mDNSexport int OSXVers;
+mDNSexport int KQueueFD;
-Revision 1.652 2009/03/19 23:44:47 mcguire
-<rdar://problem/6699216> Properly handle EADDRINUSE
+#ifndef NO_SECURITYFRAMEWORK
+static CFArrayRef ServerCerts;
+OSStatus SSLSetAllowAnonymousCiphers(SSLContextRef context, Boolean enable);
+#endif /* NO_SECURITYFRAMEWORK */
-Revision 1.651 2009/03/17 19:15:24 mcguire
-<rdar://problem/6655415> SSLHandshake deadlock issues
+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 CFStringRef NetworkChangedKey_BTMMConnectivity = CFSTR("State:/Network/Connectivity");
+static CFStringRef NetworkChangedKey_PowerSettings = CFSTR("State:/IOKit/PowerManagement/CurrentSettings");
-Revision 1.650 2009/03/17 01:24:22 cheshire
-Updated to new Sleep Proxy metric ranges: 100000-999999; 1000000 means "do not use"
+static char HINFO_HWstring_buffer[32];
+static char *HINFO_HWstring = "Device";
+static int HINFO_HWstring_prefixlen = 6;
-Revision 1.649 2009/03/15 01:30:29 mcguire
-fix log message
+mDNSexport int WatchDogReportingThreshold = 250;
-Revision 1.648 2009/03/15 01:16:08 mcguire
-<rdar://problem/6655415> SSLHandshake deadlock issues
+#ifdef __LIB_DISPATCH__
+dispatch_queue_t SSLqueue;
+#endif
-Revision 1.647 2009/03/14 01:42:56 mcguire
-<rdar://problem/5457116> BTMM: Fix issues with multiple .Mac accounts on the same machine
+#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
-Revision 1.646 2009/03/13 01:36:24 mcguire
-<rdar://problem/6657640> Reachability fixes on DNS config change
+// ***************************************************************************
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - D2D Support
+#endif
-Revision 1.645 2009/03/10 23:48:33 cheshire
-<rdar://problem/6665739> Task scheduling failure when Sleep Proxy Server is active
+#if ! NO_D2D
-Revision 1.644 2009/03/10 04:17:09 cheshire
-Check for NULL answer in UpdateSPSStatus()
+// Name compression items for fake packet version number 1
+static const mDNSu8 compression_packet_v1 = 0x01;
-Revision 1.643 2009/03/10 01:15:55 cheshire
-Sleep Proxies with invalid names (score 10000) need to be ignored
+static DNSMessage compression_base_msg = { { {{0}}, {{0}}, 2, 0, 0, 0 }, "\x04_tcp\x05local\x00\x00\x0C\x00\x01\x04_udp\xC0\x11\x00\x0C\x00\x01" };
+static mDNSu8 *const compression_limit = (mDNSu8 *) &compression_base_msg + sizeof(DNSMessage);
+static mDNSu8 *const compression_lhs = (mDNSu8 *const) compression_base_msg.data + 27;
-Revision 1.642 2009/03/08 04:46:51 mkrochma
-Change Keychain LogMsg to LogInfo
+mDNSlocal void FreeD2DARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
+mDNSlocal void PrintHex(mDNSu8 *data, mDNSu16 len);
-Revision 1.641 2009/03/05 23:53:34 cheshire
-Removed spurious "SnowLeopardPowerChanged: wake ERROR" syslog message
+static ARListElem *D2DRecords = NULL; // List of locally-generated PTR records to records found via D2D
-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
+typedef struct D2DBrowseListElem
+ {
+ struct D2DBrowseListElem *next;
+ domainname name;
+ mDNSu16 type;
+ unsigned int refCount;
+ } D2DBrowseListElem;
-Revision 1.639 2009/03/04 01:45:01 cheshire
-HW_MODEL information should be LogSPS, not LogMsg
+D2DBrowseListElem* D2DBrowseList = NULL;
-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
+mDNSlocal mDNSu8 *putVal16(mDNSu8 *ptr, mDNSu16 val)
+ {
+ ptr[0] = (mDNSu8)((val >> 8 ) & 0xFF);
+ ptr[1] = (mDNSu8)((val ) & 0xFF);
+ return ptr + sizeof(mDNSu16);
+ }
-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.
+mDNSlocal mDNSu8 *putVal32(mDNSu8 *ptr, mDNSu32 val)
+ {
+ ptr[0] = (mDNSu8)((val >> 24) & 0xFF);
+ ptr[1] = (mDNSu8)((val >> 16) & 0xFF);
+ ptr[2] = (mDNSu8)((val >> 8) & 0xFF);
+ ptr[3] = (mDNSu8)((val ) & 0xFF);
+ return ptr + sizeof(mDNSu32);
+ }
-Revision 1.636 2009/02/21 01:38:39 cheshire
-Added comment: mDNSCoreMachineSleep(m, false); // Will set m->SleepState = SleepState_Awake;
+mDNSlocal void DomainnameToLower(const domainname * const in, domainname * const out)
+ {
+ const mDNSu8 * const start = (const mDNSu8 * const)in;
+ mDNSu8 *ptr = (mDNSu8*)start;
+ while(*ptr)
+ {
+ mDNSu8 c = *ptr;
+ out->c[ptr-start] = *ptr;
+ ptr++;
+ for (;c;c--,ptr++) out->c[ptr-start] = mDNSIsUpperCase(*ptr) ? (*ptr - 'A' + 'a') : *ptr;
+ }
+ out->c[ptr-start] = *ptr;
+ }
-Revision 1.635 2009/02/17 23:29:03 cheshire
-Throttle logging to a slower rate when running on SnowLeopard
+mDNSlocal mStatus DNSNameCompressionParseBytes(mDNS *const m, const mDNSu8 *const lhs, const mDNSu16 lhs_len, const mDNSu8 *const rhs, const mDNSu16 rhs_len, AuthRecord *rr)
+ {
+ if (mDNS_LoggingEnabled)
+ {
+ LogInfo("%s", __func__);
+ LogInfo(" Static Bytes: ");
+ PrintHex((mDNSu8*)&compression_base_msg, compression_lhs - (mDNSu8*)&compression_base_msg);
+ }
+
+ mDNSu8 *ptr = compression_lhs; // pointer to the end of our fake packet
-Revision 1.634 2009/02/14 00:29:17 mcguire
-fixed typo
+ // Check to make sure we're not going to go past the end of the DNSMessage data
+ // 7 = 2 for CLASS (-1 for our version) + 4 for TTL + 2 for RDLENGTH
+ if (ptr + lhs_len - 7 + rhs_len >= compression_limit) return mStatus_NoMemoryErr;
+
+ // Copy the LHS onto our fake wire packet
+ mDNSPlatformMemCopy(ptr, lhs, lhs_len);
+ ptr += lhs_len - 1;
+
+ // Check the 'fake packet' version number, to ensure that we know how to decompress this data
+ if (*ptr != compression_packet_v1) return mStatus_Incompatible;
+
+ // two bytes of CLASS
+ ptr = putVal16(ptr, kDNSClass_IN | kDNSClass_UniqueRRSet);
+
+ // four bytes of TTL
+ ptr = putVal32(ptr, 120);
+
+ // Copy the RHS length into the RDLENGTH of our fake wire packet
+ ptr = putVal16(ptr, rhs_len);
+
+ // Copy the RHS onto our fake wire packet
+ mDNSPlatformMemCopy(ptr, rhs, rhs_len);
+ ptr += rhs_len;
+
+ if (mDNS_LoggingEnabled)
+ {
+ LogInfo(" Our Bytes %d: ", __LINE__);
+ PrintHex(compression_lhs, ptr - compression_lhs);
+ }
-Revision 1.633 2009/02/14 00:07:11 cheshire
-Need to set up m->SystemWakeOnLANEnabled before calling UpdateInterfaceList(m, utc);
+ ptr = (mDNSu8 *) GetLargeResourceRecord(m, &compression_base_msg, compression_lhs, ptr, mDNSInterface_Any, kDNSRecordTypePacketAns, &m->rec);
+ if (!ptr || m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative)
+ { LogMsg("DNSNameCompressionParseBytes: failed to get large RR"); m->rec.r.resrec.RecordType = 0; return mStatus_UnknownErr; }
+ else LogInfo("DNSNameCompressionParseBytes: got rr: %s", CRDisplayString(m, &m->rec.r));
-Revision 1.632 2009/02/13 19:40:07 cheshire
-Improved alignment of LogSPS messages
+ mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_P2P, m->rec.r.resrec.rrtype, 7200, kDNSRecordTypeShared, FreeD2DARElemCallback, NULL);
+ AssignDomainName(&rr->namestorage, &m->rec.namestorage);
+ rr->resrec.rdlength = m->rec.r.resrec.rdlength;
+ rr->resrec.rdata->MaxRDLength = m->rec.r.resrec.rdlength;
+ mDNSPlatformMemCopy(rr->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, m->rec.r.resrec.rdlength);
+ rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
+ SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us
+
+ m->rec.r.resrec.RecordType = 0; // Mark m->rec as no longer in use
-Revision 1.631 2009/02/13 18:16:05 cheshire
-Fixed some compile warnings
+ return mStatus_NoError;
+ }
-Revision 1.630 2009/02/13 06:32:43 cheshire
-Converted LogOperation messages to LogInfo or LogSPS
+mDNSlocal mDNSu8 * DNSNameCompressionBuildLHS(const domainname const *typeDomain, DNS_TypeValues qtype)
+ {
+ mDNSu8 *ptr = putDomainNameAsLabels(&compression_base_msg, compression_lhs, compression_limit, typeDomain);
+ if (!ptr) return ptr;
+ *ptr = (qtype >> 8) & 0xff;
+ ptr += 1;
+ *ptr = qtype & 0xff;
+ ptr += 1;
+ *ptr = compression_packet_v1;
+ return ptr + 1;
+ }
-Revision 1.629 2009/02/12 20:57:26 cheshire
-Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
+mDNSlocal mDNSu8 * DNSNameCompressionBuildRHS(mDNSu8 *start, const ResourceRecord *const resourceRecord)
+ {
+ return putRData(&compression_base_msg, start, compression_limit, resourceRecord);
+ }
-Revision 1.628 2009/02/11 02:34:45 cheshire
-m->p->SystemWakeForNetworkAccessEnabled renamed to m->SystemWakeOnLANEnabled
+mDNSlocal void PrintHex(mDNSu8 *data, mDNSu16 len)
+ {
+ mDNSu8 *end = data + len;
+ char buffer[49] = {0};
+ char *bufend = buffer + sizeof(buffer);
+ while(data<end)
+ {
+ char *ptr = buffer;
+ for(; data < end && ptr < bufend-1; ptr+=3,data++)
+ mDNS_snprintf(ptr, bufend - ptr, "%02X ", *data);
+ LogInfo(" %s", buffer);
+ }
+ }
-Revision 1.627 2009/02/10 00:19:17 cheshire
-<rdar://problem/6107426> Sleep Proxy: Adopt SIOCGIFWAKEFLAGS ioctl to determine interface WOMP-ability
+mDNSlocal void PrintHelper(const char *const tag, mDNSu8 *lhs, mDNSu16 lhs_len, mDNSu8 *rhs, mDNSu16 rhs_len)
+ {
+ if (!mDNS_LoggingEnabled) return;
+
+ LogInfo("%s:", tag);
+ LogInfo(" LHS: ");
+ PrintHex(lhs, lhs_len);
+
+ if (!rhs) return;
+
+ LogInfo(" RHS: ");
+ PrintHex(rhs, rhs_len);
+ }
-Revision 1.626 2009/02/10 00:15:38 cheshire
-<rdar://problem/6551529> Sleep Proxy: "Unknown DNS packet type 8849" logs
+mDNSlocal void FreeD2DARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
+ {
+ (void)m; // unused
+ if (result == mStatus_MemFree)
+ {
+ ARListElem **ptr = &D2DRecords;
+ ARListElem *tmp;
+ while (*ptr && &(*ptr)->ar != rr) ptr = &(*ptr)->next;
+ if (!*ptr) { LogMsg("FreeD2DARElemCallback: Could not find in D2DRecords: %s", ARDisplayString(m, rr)); return; }
+ LogInfo("FreeD2DARElemCallback: Found in D2DRecords: %s", ARDisplayString(m, rr));
+ tmp = *ptr;
+ *ptr = (*ptr)->next;
+ // Just because we stoppped browsing, doesn't mean we should tear down the PAN connection.
+ mDNSPlatformMemFree(tmp);
+ }
+ }
-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)
+mDNSlocal void xD2DClearCache(mDNS *const m, const domainname *regType)
+ {
+ ARListElem *ptr = D2DRecords;
+ for ( ; ptr ; ptr = ptr->next)
+ {
+ if (SameDomainName(&ptr->ar.namestorage, regType))
+ {
+ char buffer[MAX_ESCAPED_DOMAIN_NAME];
+ mDNS_Deregister(m, &ptr->ar);
+ ConvertDomainNameToCString(regType, buffer);
+ LogInfo("xD2DClearCache: Clearing cache record and deregistering %s", buffer);
+ }
+ }
+ }
-Revision 1.624 2009/02/09 21:11:43 cheshire
-Need to acknowledge kIOPMSystemPowerStateCapabilityCPU message
+mDNSlocal D2DBrowseListElem ** D2DFindInBrowseList(const domainname *const name, mDNSu16 type)
+ {
+ D2DBrowseListElem **ptr = &D2DBrowseList;
-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
+ for ( ; *ptr; ptr = &(*ptr)->next)
+ if ((*ptr)->type == type && SameDomainName(&(*ptr)->name, name))
+ break;
+
+ return ptr;
+ }
-Revision 1.622 2009/02/07 02:57:32 cheshire
-<rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
+mDNSlocal unsigned int D2DBrowseListRefCount(const domainname *const name, mDNSu16 type)
+ {
+ D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
+ return *ptr ? (*ptr)->refCount : 0;
+ }
-Revision 1.621 2009/02/06 03:18:12 mcguire
-<rdar://problem/6534643> BTMM: State not cleaned up on SIGTERM w/o reboot
+mDNSlocal void D2DBrowseListRetain(const domainname *const name, mDNSu16 type)
+ {
+ D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
+
+ if (!*ptr)
+ {
+ *ptr = mDNSPlatformMemAllocate(sizeof(**ptr));
+ mDNSPlatformMemZero(*ptr, sizeof(**ptr));
+ (*ptr)->type = type;
+ AssignDomainName(&(*ptr)->name, name);
+ }
+ (*ptr)->refCount += 1;
+
+ LogInfo("D2DBrowseListRetain: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount);
+ }
-Revision 1.620 2009/02/02 22:14:11 cheshire
-Instead of repeatedly checking the Dynamic Store, use m->p->SystemWakeForNetworkAccessEnabled variable
+mDNSlocal void D2DBrowseListRelease(const domainname *const name, mDNSu16 type)
+ {
+ D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
+
+ if (!*ptr) { LogMsg("D2DBrowseListRelease: Didn't find %##s %s in list", name->c, DNSTypeName(type)); return; }
+
+ (*ptr)->refCount -= 1;
+
+ LogInfo("D2DBrowseListRelease: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount);
+
+ if (!(*ptr)->refCount)
+ {
+ D2DBrowseListElem *tmp = *ptr;
+ *ptr = (*ptr)->next;
+ mDNSPlatformMemFree(tmp);
+ }
+ }
-Revision 1.619 2009/01/24 02:11:58 cheshire
-Handle case where config->resolver[0]->nameserver[0] is NULL
+mDNSlocal mStatus xD2DParse(mDNS *const m, const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, AuthRecord *rr)
+ {
+ if (*(lhs + (lhs_len - 1)) == compression_packet_v1)
+ return DNSNameCompressionParseBytes(m, lhs, lhs_len, rhs, rhs_len, rr);
+ else
+ return mStatus_Incompatible;
+ }
-Revision 1.618 2009/01/24 01:55:51 cheshire
-Handle case where config->resolver[0]->domain is NULL
+mDNSlocal void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+ {
+ (void)transportType; // We don't care about this, yet.
+ (void)instanceHandle; // We don't care about this, yet.
+
+ if (result == kD2DSuccess)
+ {
+ if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DAddToCache: NULL Byte * passed in or length == 0"); return; }
+
+ mStatus err;
+ ARListElem *ptr = mDNSPlatformMemAllocate(sizeof(ARListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData)));
-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
+ if (ptr == NULL) { LogMsg("xD2DAddToCache: memory allocation failure"); return; }
-Revision 1.616 2009/01/24 00:28:43 cheshire
-Updated comments
+ err = xD2DParse(m, (const mDNSu8 * const)key, (const mDNSu16)keySize, (const mDNSu8 * const)value, (const mDNSu16)valueSize, &ptr->ar);
+ if (err)
+ {
+ LogMsg("xD2DAddToCache: xD2DParse returned error: %d", err);
+ PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize);
+ mDNSPlatformMemFree(ptr);
+ return;
+ }
+
+ err = mDNS_Register(m, &ptr->ar);
+ if (err)
+ {
+ LogMsg("xD2DAddToCache: mDNS_Register returned error %d for %s", err, ARDisplayString(m, &ptr->ar));
+ mDNSPlatformMemFree(ptr);
+ return;
+ }
-Revision 1.615 2009/01/22 02:14:26 cheshire
-<rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
+ LogInfo("xD2DAddToCache: mDNS_Register succeeded for %s", ARDisplayString(m, &ptr->ar));
+ ptr->next = D2DRecords;
+ D2DRecords = ptr;
+ }
+ else
+ LogMsg("xD2DAddToCache: Unexpected result %d", result);
+ }
-Revision 1.614 2009/01/21 03:43:57 mcguire
-<rdar://problem/6511765> BTMM: Add support for setting kDNSServiceErr_NATPortMappingDisabled in DynamicStore
+mDNSlocal ARListElem * xD2DFindInList(mDNS *const m, const Byte *const key, const size_t keySize, const Byte *const value, const size_t valueSize)
+ {
+ ARListElem *ptr = D2DRecords;
+ ARListElem *arptr;
+
+ if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DFindInList: NULL Byte * passed in or length == 0"); return NULL; }
-Revision 1.613 2009/01/20 02:38:41 mcguire
-fix previous checkin comment
+ arptr = mDNSPlatformMemAllocate(sizeof(ARListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData)));
+ if (arptr == NULL) { LogMsg("xD2DFindInList: memory allocation failure"); return NULL; }
-Revision 1.612 2009/01/20 02:35:15 mcguire
-<rdar://problem/6508974> don't update BTMM & SleepProxyServers status at shutdown time
+ if (xD2DParse(m, (const mDNSu8 *const)key, (const mDNSu16)keySize, (const mDNSu8 *const)value, (const mDNSu16)valueSize, &arptr->ar) != mStatus_NoError)
+ {
+ LogMsg("xD2DFindInList: xD2DParse failed for key: %p (%u) value: %p (%u)", key, keySize, value, valueSize);
+ mDNSPlatformMemFree(arptr);
+ return NULL;
+ }
+
+ while (ptr)
+ {
+ if (IdenticalResourceRecord(&arptr->ar.resrec, &ptr->ar.resrec)) break;
+ ptr = ptr->next;
+ }
+
+ if (!ptr) LogMsg("xD2DFindInList: Could not find in D2DRecords: %s", ARDisplayString(m, &arptr->ar));
+ mDNSPlatformMemFree(arptr);
+ return ptr;
+ }
-Revision 1.611 2009/01/17 04:15:40 cheshire
-Updated "did sleep(5)" debugging message
+mDNSlocal void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+ {
+ (void)transportType; // We don't care about this, yet.
+ (void)instanceHandle; // We don't care about this, yet.
+
+ if (result == kD2DSuccess)
+ {
+ ARListElem *ptr = xD2DFindInList(m, key, keySize, value, valueSize);
+ if (ptr)
+ {
+ LogInfo("xD2DRemoveFromCache: Remove from cache: %s", ARDisplayString(m, &ptr->ar));
+ mDNS_Deregister(m, &ptr->ar);
+ }
+ }
+ else
+ LogMsg("xD2DRemoveFromCache: Unexpected result %d", result);
+ }
-Revision 1.610 2009/01/16 20:37:30 cheshire
-Fixed incorrect value of EOPNOTSUPP
+mDNSlocal void xD2DServiceResolved(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+ {
+ (void)m;
+ (void)key;
+ (void)keySize;
+ (void)value;
+ (void)valueSize;
+
+ if (result == kD2DSuccess)
+ {
+ LogInfo("xD2DServiceResolved: Starting up PAN connection for %p", instanceHandle);
+ CHECK_D2D_FUNCTION(D2DRetain) D2DRetain(instanceHandle, transportType);
+ }
+ else LogMsg("xD2DServiceResolved: Unexpected result %d", result);
+ }
-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)
+mDNSlocal void xD2DRetainHappened(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+ {
+ (void)m;
+ (void)instanceHandle;
+ (void)transportType;
+ (void)key;
+ (void)keySize;
+ (void)value;
+ (void)valueSize;
+
+ if (result == kD2DSuccess) LogInfo("xD2DRetainHappened: Opening up PAN connection for %p", instanceHandle);
+ else LogMsg("xD2DRetainHappened: Unexpected result %d", result);
+ }
-Revision 1.608 2009/01/16 01:27:03 cheshire
-Initial work to adopt SIOCGIFWAKEFLAGS ioctl to determine whether an interface is WakeOnLAN-capable
+mDNSlocal void xD2DReleaseHappened(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+ {
+ (void)m;
+ (void)instanceHandle;
+ (void)transportType;
+ (void)key;
+ (void)keySize;
+ (void)value;
+ (void)valueSize;
+
+ if (result == kD2DSuccess) LogInfo("xD2DReleaseHappened: Closing PAN connection for %p", instanceHandle);
+ else LogMsg("xD2DReleaseHappened: Unexpected result %d", result);
+ }
-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
+mDNSlocal void xD2DServiceCallback(D2DServiceEvent event, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize, void *userData)
+ {
+ mDNS *m = (mDNS *) userData;
+ const char *eventString = "unknown";
+
+ KQueueLock(m);
+
+ if (keySize > 0xFFFF) LogMsg("xD2DServiceCallback: keySize too large: %u", keySize);
+ if (valueSize > 0xFFFF) LogMsg("xD2DServiceCallback: valueSize too large: %u", valueSize);
+
+ switch (event)
+ {
+ case D2DServiceFound:
+ eventString = "D2DServiceFound";
+ break;
+ case D2DServiceLost:
+ eventString = "D2DServiceLost";
+ break;
+ case D2DServiceResolved:
+ eventString = "D2DServiceResolved";
+ break;
+ case D2DServiceRetained:
+ eventString = "D2DServiceRetained";
+ break;
+ case D2DServiceReleased:
+ eventString = "D2DServiceReleased";
+ break;
+ default:
+ break;
+ }
+
+ LogInfo("xD2DServiceCallback: event=%s result=%d instanceHandle=%p transportType=%d LHS=%p (%u) RHS=%p (%u) userData=%p", eventString, result, instanceHandle, transportType, key, keySize, value, valueSize, userData);
+ PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize);
+
+ switch (event)
+ {
+ case D2DServiceFound:
+ xD2DAddToCache(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
+ break;
+ case D2DServiceLost:
+ xD2DRemoveFromCache(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
+ break;
+ case D2DServiceResolved:
+ xD2DServiceResolved(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
+ break;
+ case D2DServiceRetained:
+ xD2DRetainHappened(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
+ break;
+ case D2DServiceReleased:
+ xD2DReleaseHappened(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
+ break;
+ default:
+ break;
+ }
+
+ // Need to tickle the main kqueue loop to potentially handle records we removed or added.
+ KQueueUnlock(m, "xD2DServiceCallback");
+ }
-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
+mDNSexport void external_start_browsing_for_service(mDNS *const m, const domainname *const typeDomain, DNS_TypeValues qtype)
+ {
+ (void)m;
+ domainname lower;
+
+ if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA)
+ {
+ LogInfo("external_start_browsing_for_service: ignoring address record");
+ return;
+ }
+
+ DomainnameToLower(typeDomain, &lower);
+
+ if (!D2DBrowseListRefCount(&lower, qtype))
+ {
+ LogInfo("external_start_browsing_for_service: Starting browse for: %##s %s", lower.c, DNSTypeName(qtype));
+ mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype);
+ PrintHelper(__func__, compression_lhs, end - compression_lhs, mDNSNULL, 0);
+ CHECK_D2D_FUNCTION(D2DStartBrowsingForKey) D2DStartBrowsingForKey(compression_lhs, end - compression_lhs);
+ }
+ D2DBrowseListRetain(&lower, qtype);
+ }
-Revision 1.597 2008/12/10 20:37:05 cheshire
-Don't mark interfaces like PPP as being WakeonLAN-capable
+mDNSexport void external_stop_browsing_for_service(mDNS *const m, const domainname *const typeDomain, DNS_TypeValues qtype)
+ {
+ domainname lower;
+
+ if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA)
+ {
+ LogInfo("external_stop_browsing_for_service: ignoring address record");
+ return;
+ }
+
+ DomainnameToLower(typeDomain, &lower);
+
+ D2DBrowseListRelease(&lower, qtype);
+ if (!D2DBrowseListRefCount(&lower, qtype))
+ {
+ LogInfo("external_stop_browsing_for_service: Stopping browse for: %##s %s", lower.c, DNSTypeName(qtype));
+ mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype);
+ PrintHelper(__func__, compression_lhs, end - compression_lhs, mDNSNULL, 0);
+ CHECK_D2D_FUNCTION(D2DStopBrowsingForKey) D2DStopBrowsingForKey(compression_lhs, end - compression_lhs);
+ xD2DClearCache(m, &lower);
+ }
+ }
-Revision 1.596 2008/12/10 19:34:30 cheshire
-Use symbolic OS version names instead of literal integers
+mDNSexport void external_start_advertising_service(const ResourceRecord *const resourceRecord)
+ {
+ domainname lower;
+ mDNSu8 *rhs = NULL;
+ mDNSu8 *end = NULL;
+ DomainnameToLower(resourceRecord->name, &lower);
+
+ LogInfo("external_start_advertising_service: %s", RRDisplayString(&mDNSStorage, resourceRecord));
+ if (resourceRecord->rrtype == kDNSServiceType_A || resourceRecord->rrtype == kDNSServiceType_AAAA)
+ {
+ LogInfo("external_start_advertising_service: ignoring address record");
+ return;
+ }
+ rhs = DNSNameCompressionBuildLHS(&lower, resourceRecord->rrtype);
+ end = DNSNameCompressionBuildRHS(rhs, resourceRecord);
+ PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
+ CHECK_D2D_FUNCTION(D2DStartAdvertisingPair) D2DStartAdvertisingPair(compression_lhs, rhs - compression_lhs, rhs, end - rhs);
+ }
-Revision 1.595 2008/12/10 02:25:31 cheshire
-Minor fixes to use of LogClientOperations symbol
+mDNSexport void external_stop_advertising_service(const ResourceRecord *const resourceRecord)
+ {
+ domainname lower;
+ mDNSu8 *rhs = NULL;
+ mDNSu8 *end = NULL;
+ DomainnameToLower(resourceRecord->name, &lower);
+
+ LogInfo("external_stop_advertising_service: %s", RRDisplayString(&mDNSStorage, resourceRecord));
+ if (resourceRecord->rrtype == kDNSServiceType_A || resourceRecord->rrtype == kDNSServiceType_AAAA)
+ {
+ LogInfo("external_stop_advertising_service: ignoring address record");
+ return;
+ }
+ rhs = DNSNameCompressionBuildLHS(&lower, resourceRecord->rrtype);
+ end = DNSNameCompressionBuildRHS(rhs, resourceRecord);
+ PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
+ CHECK_D2D_FUNCTION(D2DStopAdvertisingPair) D2DStopAdvertisingPair(compression_lhs, rhs - compression_lhs, rhs, end - rhs);
+ }
-Revision 1.594 2008/12/10 02:11:45 cheshire
-ARMv5 compiler doesn't like uncommented stuff after #endif
+mDNSexport void external_start_resolving_service(const domainname *const fqdn)
+ {
+ domainname lower;
+ mDNSu8 *rhs = NULL;
+ mDNSu8 *end = NULL;
+ DomainnameToLower(SkipLeadingLabels(fqdn, 1), &lower);
+
+ LogInfo("external_start_resolving_service: %##s", fqdn->c);
+ rhs = DNSNameCompressionBuildLHS(&lower, kDNSType_PTR);
+ end = putDomainNameAsLabels(&compression_base_msg, rhs, compression_limit, fqdn);
+ PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
+ CHECK_D2D_FUNCTION(D2DStartResolvingPair) D2DStartResolvingPair(compression_lhs, rhs - compression_lhs, rhs, end - rhs);
+ }
-Revision 1.593 2008/12/09 23:08:55 mcguire
-<rdar://problem/6430877> should use IP_BOUND_IF
-additional cleanup
+mDNSexport void external_stop_resolving_service(const domainname *const fqdn)
+ {
+ domainname lower;
+ mDNSu8 *rhs = NULL;
+ mDNSu8 *end = NULL;
+ DomainnameToLower(SkipLeadingLabels(fqdn, 1), &lower);
+
+ LogInfo("external_stop_resolving_service: %##s", fqdn->c);
+ rhs = DNSNameCompressionBuildLHS(&lower, kDNSType_PTR);
+ end = putDomainNameAsLabels(&compression_base_msg, rhs, compression_limit, fqdn);
+ PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
+ CHECK_D2D_FUNCTION(D2DStopResolvingPair) D2DStopResolvingPair(compression_lhs, rhs - compression_lhs, rhs, end - rhs);
+ }
-Revision 1.592 2008/12/09 19:58:44 mcguire
-<rdar://problem/6430877> should use IP_BOUND_IF
+#elif APPLE_OSX_mDNSResponder
-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
+mDNSexport void external_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype) { (void)m; (void)type; (void)qtype; }
+mDNSexport void external_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype) { (void)m; (void)type; (void)qtype; }
+mDNSexport void external_start_advertising_service(const ResourceRecord *const resourceRecord) { (void)resourceRecord; }
+mDNSexport void external_stop_advertising_service(const ResourceRecord *const resourceRecord) { (void)resourceRecord; }
+mDNSexport void external_start_resolving_service(const domainname *const fqdn) { (void)fqdn; }
+mDNSexport void external_stop_resolving_service(const domainname *const fqdn) { (void)fqdn; }
-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.
+#endif // ! NO_D2D
-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
+// ***************************************************************************
+// Functions
-Revision 1.588 2008/12/04 21:08:52 mcguire
-<rdar://problem/6116863> mDNS: Provide mechanism to disable Multicast advertisements
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Utility Functions
+#endif
-Revision 1.587 2008/12/04 02:17:47 cheshire
-Additional sleep/wake debugging messages
+// We only attempt to send and receive multicast packets on interfaces that are
+// (a) flagged as multicast-capable
+// (b) *not* flagged as point-to-point (e.g. modem)
+// Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want
+// to run up the user's bill sending multicast traffic over a link where there's only a single device at the
+// other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
+#define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
-Revision 1.586 2008/11/26 20:34:55 cheshire
-Changed some "LogOperation" debugging messages to "debugf"
+mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both strings are UTF-8 text
+ {
+ static int notifyCount = 0;
+ if (notifyCount) return;
-Revision 1.585 2008/11/25 20:53:35 cheshire
-Updated portability metrics; added Xserve and PowerBook to list
+ // If we display our alert early in the boot process, then it vanishes once the desktop appears.
+ // To avoid this, we don't try to display alerts in the first three minutes after boot.
+ if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return;
-Revision 1.584 2008/11/25 05:07:16 cheshire
-<rdar://problem/6374328> Advertise Sleep Proxy metrics in service name
+ // Unless ForceAlerts is defined, we only show these bug report alerts on machines that have a 17.x.x.x address
+ #if !ForceAlerts
+ {
+ // Determine if we're at Apple (17.*.*.*)
+ extern mDNS mDNSStorage;
+ NetworkInterfaceInfoOSX *i;
+ for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
+ if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && i->ifinfo.ip.ip.v4.b[0] == 17)
+ break;
+ if (!i) return; // If not at Apple, don't show the alert
+ }
+ #endif
-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.
+ LogMsg("%s", title);
+ LogMsg("%s", msg);
+ // Display a notification to the user
+ notifyCount++;
-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
+#ifndef NO_CFUSERNOTIFICATION
+ mDNSNotify(title, msg);
+#endif /* NO_CFUSERNOTIFICATION */
+ }
-Revision 1.581 2008/11/14 21:01:26 cheshire
-Log a warning if we fail to get a MAC address for an interface
+mDNSlocal struct ifaddrs *myGetIfAddrs(int refresh)
+ {
+ static struct ifaddrs *ifa = NULL;
-Revision 1.580 2008/11/14 02:16:15 cheshire
-Clean up NetworkChanged handling
+ if (refresh && ifa)
+ {
+ freeifaddrs(ifa);
+ ifa = NULL;
+ }
-Revision 1.579 2008/11/12 23:15:37 cheshire
-Updated log messages
+ if (ifa == NULL) getifaddrs(&ifa);
-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
+ return ifa;
+ }
-Revision 1.577 2008/11/06 01:15:47 mcguire
-Fix compile error that occurs when LogOperation is disabled
+// To match *either* a v4 or v6 instance of this interface name, pass AF_UNSPEC for type
+mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const char *ifname, int type)
+ {
+ NetworkInterfaceInfoOSX *i;
+ for (i = m->p->InterfaceList; i; i = i->next)
+ if (i->Exists && !strcmp(i->ifinfo.ifname, ifname) &&
+ ((type == AF_UNSPEC ) ||
+ (type == AF_INET && i->ifinfo.ip.type == mDNSAddrType_IPv4) ||
+ (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6))) return(i);
+ return(NULL);
+ }
-Revision 1.576 2008/11/05 21:55:21 cheshire
-Fixed mistake in BPF filter generation
+mDNSlocal int myIfIndexToName(u_short ifindex, char *name)
+ {
+ struct ifaddrs *ifa;
+ for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
+ if (ifa->ifa_addr->sa_family == AF_LINK)
+ if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == ifindex)
+ { strlcpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; }
+ return -1;
+ }
-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.
+mDNSexport NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(const mDNS *const m, mDNSInterfaceID ifindex)
+{
+ mDNSu32 scope_id = (mDNSu32)(uintptr_t)ifindex;
+ NetworkInterfaceInfoOSX *i;
-Revision 1.574 2008/11/04 00:27:58 cheshire
-Corrected some timing anomalies in sleep/wake causing spurious name self-conflicts
+ // Don't get tricked by inactive interfaces
+ for (i = m->p->InterfaceList; i; i = i->next)
+ if (i->Registered && i->scope_id == scope_id) return(i);
-Revision 1.573 2008/11/03 01:12:42 mkrochma
-Fix compile error that occurs when LogOperation is disabled
+ return mDNSNULL;
+}
-Revision 1.572 2008/10/31 23:36:13 cheshire
-One wakeup clear any previous power requests
+mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex)
+ {
+ if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
+ if (ifindex == kDNSServiceInterfaceIndexP2P ) return(mDNSInterface_P2P);
+ if (ifindex == kDNSServiceInterfaceIndexAny ) return(mDNSNULL);
-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
+ NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
+ if (!ifi)
+ {
+ // Not found. Make sure our interface list is up to date, then try again.
+ LogInfo("mDNSPlatformInterfaceIDfromInterfaceIndex: InterfaceID for interface index %d not found; Updating interface list", ifindex);
+ mDNSMacOSXNetworkChanged(m);
+ ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
+ }
-Revision 1.570 2008/10/30 01:08:19 cheshire
-After waking for network maintenance operations go back to sleep again
+ if (!ifi) return(mDNSNULL);
+
+ return(ifi->ifinfo.InterfaceID);
+ }
-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
+mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id)
+ {
+ NetworkInterfaceInfoOSX *i;
+ if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
+ if (id == mDNSInterface_P2P ) return(kDNSServiceInterfaceIndexP2P);
+ if (id == mDNSInterface_Any ) return(0);
-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
+ mDNSu32 scope_id = (mDNSu32)(uintptr_t)id;
-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
+ // Don't use i->Registered here, because we DO want to find inactive interfaces, which have no Registered set
+ for (i = m->p->InterfaceList; i; i = i->next)
+ if (i->scope_id == scope_id) return(i->scope_id);
-Revision 1.565 2008/10/22 23:23:55 cheshire
-Moved definition of OSXVers from daemon.c into mDNSMacOSX.c
+ // Not found. Make sure our interface list is up to date, then try again.
+ LogInfo("Interface index for InterfaceID %p not found; Updating interface list", id);
+ mDNSMacOSXNetworkChanged(m);
+ for (i = m->p->InterfaceList; i; i = i->next)
+ if (i->scope_id == scope_id) return(i->scope_id);
-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
+ return(0);
+ }
-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
+#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;
-Revision 1.562 2008/10/22 19:48:29 cheshire
-Improved syslog messages
+ static char buffer[512];
+ aslmsg asl_msg = asl_new(ASL_TYPE_MSG);
-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
+ if (!asl_msg) { LogMsg("mDNSASLLog: asl_new failed"); return; }
+ if (uuid)
+ {
+ char uuidStr[37];
+ uuid_unparse(*uuid, uuidStr);
+ asl_set (asl_msg, "com.apple.message.uuid", uuidStr);
+ }
-Revision 1.560 2008/10/22 01:09:36 cheshire
-Fixed build warning when not using LogClientOperations
+ static char domainBase[] = "com.apple.mDNSResponder.%s";
+ mDNS_snprintf (buffer, sizeof(buffer), domainBase, subdomain);
+ asl_set (asl_msg, "com.apple.message.domain", buffer);
-Revision 1.559 2008/10/21 01:05:30 cheshire
-Added code to receive raw packets using Berkeley Packet Filter (BPF)
+ if (result) asl_set(asl_msg, "com.apple.message.result", result);
+ if (signature) asl_set(asl_msg, "com.apple.message.signature", signature);
-Revision 1.558 2008/10/16 22:42:06 cheshire
-Removed debugging messages
+ va_list ptr;
+ va_start(ptr,fmt);
+ mDNS_vsnprintf(buffer, sizeof(buffer), fmt, ptr);
+ va_end(ptr);
-Revision 1.557 2008/10/09 22:33:14 cheshire
-Fill in ifinfo.MAC field when fetching interface list
+ 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 // APPLE_OSX_mDNSResponder
-Revision 1.556 2008/10/09 21:15:23 cheshire
-In mDNSPlatformUDPSocket(), need to create an IPv6 socket as well as IPv4
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - UDP & TCP send & receive
+#endif
-Revision 1.555 2008/10/09 19:05:57 cheshire
-No longer want to inhibit all networking when going to sleep
+mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr)
+ {
+ mDNSBool result = mDNSfalse;
+ SCNetworkConnectionFlags flags;
+ SCNetworkReachabilityRef ReachRef = NULL;
-Revision 1.554 2008/10/08 18:36:51 mkrochma
-<rdar://problem/4371323> Supress Couldn't read user-specified Computer Name logs
+ ReachRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, addr);
+ if (!ReachRef) { LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithAddress"); goto end; }
+ if (!SCNetworkReachabilityGetFlags(ReachRef, &flags)) { LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); goto end; }
+ result = flags & kSCNetworkFlagsConnectionRequired;
-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)
+ end:
+ if (ReachRef) CFRelease(ReachRef);
+ return result;
+ }
-Revision 1.552 2008/10/03 23:32:15 cheshire
-Added definition of mDNSPlatformSendRawPacket
+// Note: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
+// Note: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
+// OR send via our primary v4 unicast socket
+// UPDATE: The UDPSocket *src parameter now allows the caller to specify the source socket
+mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
+ mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstPort)
+ {
+ NetworkInterfaceInfoOSX *info = mDNSNULL;
+ struct sockaddr_storage to;
+ int s = -1, err;
+ mStatus result = mStatus_NoError;
-Revision 1.551 2008/10/03 18:25:16 cheshire
-Instead of calling "m->MainCallback" function pointer directly, call mDNSCore routine "mDNS_ConfigChanged(m);"
+ if (InterfaceID)
+ {
+ info = IfindexToInterfaceInfoOSX(m, InterfaceID);
+ if (info == NULL)
+ {
+ LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
+ return mStatus_BadParamErr;
+ }
+ }
-Revision 1.550 2008/10/03 00:51:58 cheshire
-Removed spurious "else" case that got left in by mistake
+ char *ifa_name = InterfaceID ? info->ifinfo.ifname : "unicast";
-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
+ if (dst->type == mDNSAddrType_IPv4)
+ {
+ struct sockaddr_in *sin_to = (struct sockaddr_in*)&to;
+ sin_to->sin_len = sizeof(*sin_to);
+ sin_to->sin_family = AF_INET;
+ sin_to->sin_port = dstPort.NotAnInteger;
+ sin_to->sin_addr.s_addr = dst->ip.v4.NotAnInteger;
+ s = (src ? src->ss : m->p->permanentsockets).sktv4;
-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
+ if (info) // Specify outgoing interface
+ {
+ if (!mDNSAddrIsDNSMulticast(dst))
+ {
+ #ifdef IP_BOUND_IF
+ if (info->scope_id == 0)
+ LogInfo("IP_BOUND_IF socket option not set -- info %p (%s) scope_id is zero", info, ifa_name);
+ else
+ setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
+ #else
+ {
+ static int displayed = 0;
+ if (displayed < 1000)
+ {
+ displayed++;
+ LogInfo("IP_BOUND_IF socket option not defined -- cannot specify interface for unicast packets");
+ }
+ }
+ #endif
+ }
+ else
+ #ifdef IP_MULTICAST_IFINDEX
+ {
+ err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IFINDEX, &info->scope_id, sizeof(info->scope_id));
+ // We get an error when we compile on a machine that supports this option and run the binary on
+ // a different machine that does not support it
+ if (err < 0)
+ {
+ if (errno != ENOPROTOOPT) LogInfo("mDNSPlatformSendUDP: setsockopt: IP_MUTLTICAST_IFINDEX returned %d", errno);
+ err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
+ if (err < 0 && !m->p->NetworkChanged)
+ LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
+ }
+ }
+ #else
+ {
+ err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
+ if (err < 0 && !m->p->NetworkChanged)
+ LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
-Revision 1.538 2008/06/02 05:39:39 mkrochma
-<rdar://problem/5932760> Don't set TOS bits anymore
+ }
+ #endif
+ }
+ }
+#ifndef NO_IPV6
+ else if (dst->type == mDNSAddrType_IPv6)
+ {
+ struct sockaddr_in6 *sin6_to = (struct sockaddr_in6*)&to;
+ sin6_to->sin6_len = sizeof(*sin6_to);
+ sin6_to->sin6_family = AF_INET6;
+ sin6_to->sin6_port = dstPort.NotAnInteger;
+ sin6_to->sin6_flowinfo = 0;
+ sin6_to->sin6_addr = *(struct in6_addr*)&dst->ip.v6;
+ sin6_to->sin6_scope_id = info ? info->scope_id : 0;
+ s = (src ? src->ss : m->p->permanentsockets).sktv6;
+ if (info && mDNSAddrIsDNSMulticast(dst)) // Specify outgoing interface
+ {
+ err = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &info->scope_id, sizeof(info->scope_id));
+ if (err < 0) LogMsg("setsockopt - IPV6_MULTICAST_IF error %d errno %d (%s)", err, errno, strerror(errno));
+ }
+ }
+#endif
+ else
+ {
+ LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
+#if ForceAlerts
+ *(long*)0 = 0;
+#endif
+ return mStatus_BadParamErr;
+ }
-Revision 1.537 2008/05/01 18:30:54 mkrochma
-<rdar://problem/5895642> Make mDNSResponder and mDNSResponderHelper shutdown at regular time
+ if (s >= 0)
+ verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
+ InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s);
+ else
+ verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
+ InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort));
-Revision 1.536 2008/03/25 01:27:30 mcguire
-<rdar://problem/5810718> Status sometimes wrong when link goes down
+ // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
+ // If we don't have the corresponding type of socket available, then return mStatus_Invalid
+ if (s < 0) return(mStatus_Invalid);
-Revision 1.535 2008/03/14 22:52:51 mcguire
-<rdar://problem/5321824> write status to the DS
-Ignore duplicate queries, which don't get established (since they're duplicates)
+ err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len);
+ if (err < 0)
+ {
+ static int MessageCount = 0;
+ // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
+ if (!mDNSAddressIsAllDNSLinkGroup(dst))
+ if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
+ // Don't report EHOSTUNREACH in the first three minutes after boot
+ // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
+ // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
+ if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr);
+ // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
+ if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(mStatus_TransientErr);
+ if (MessageCount < 1000)
+ {
+ MessageCount++;
+ 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;
+ }
-Revision 1.534 2008/03/12 22:58:15 mcguire
-<rdar://problem/5321824> write status to the DS
-Fixes for NO_SECURITYFRAMEWORK
+#ifdef IP_BOUND_IF
+ if (dst->type == mDNSAddrType_IPv4 && info && !mDNSAddrIsDNSMulticast(dst))
+ {
+ static const mDNSu32 ifindex = 0;
+ setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
+ }
+#endif
-Revision 1.533 2008/03/07 00:48:54 mcguire
-<rdar://problem/5321824> write status to the DS
-cleanup strings
+ return(result);
+ }
-Revision 1.532 2008/03/06 23:44:39 mcguire
-<rdar://problem/5321824> write status to the DS
-cleanup function names & log messages
-add external port numbers to dictionary
-add defensive code in case CF*Create fails
-don't output NAT statuses if zero
+mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
+ struct sockaddr *const from, size_t *const fromlen, mDNSAddr *dstaddr, char ifname[IF_NAMESIZE], mDNSu8 *ttl)
+ {
+ static unsigned int numLogMessages = 0;
+ struct iovec databuffers = { (char *)buffer, max };
+ struct msghdr msg;
+ ssize_t n;
+ struct cmsghdr *cmPtr;
+ char ancillary[1024];
-Revision 1.531 2008/03/06 21:27:47 cheshire
-<rdar://problem/5500969> BTMM: Need ability to identify version of mDNSResponder client
-To save network bandwidth, removed unnecessary redundant information from HINFO record
+ *ttl = 255; // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
-Revision 1.530 2008/03/06 03:15:48 mcguire
-<rdar://problem/5321824> write status to the DS
-use mStatus_* instead of kDNSServiceErr_*
+ // Set up the message
+ msg.msg_name = (caddr_t)from;
+ msg.msg_namelen = *fromlen;
+ msg.msg_iov = &databuffers;
+ msg.msg_iovlen = 1;
+ msg.msg_control = (caddr_t)&ancillary;
+ msg.msg_controllen = sizeof(ancillary);
+ msg.msg_flags = 0;
-Revision 1.529 2008/03/06 02:48:35 mcguire
-<rdar://problem/5321824> write status to the DS
+ // Receive the data
+ n = recvmsg(s, &msg, 0);
+ if (n<0)
+ {
+ if (errno != EWOULDBLOCK && numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s, n, errno);
+ return(-1);
+ }
+ if (msg.msg_controllen < (int)sizeof(struct cmsghdr))
+ {
+ if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned %d msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
+ s, n, msg.msg_controllen, sizeof(struct cmsghdr));
+ return(-1);
+ }
+ if (msg.msg_flags & MSG_CTRUNC)
+ {
+ if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s);
+ return(-1);
+ }
-Revision 1.528 2008/02/29 01:33:57 mcguire
-<rdar://problem/5611801> BTMM: Services stay registered after previously successful NAT Port mapping fails
+ *fromlen = msg.msg_namelen;
-Revision 1.527 2008/02/28 03:25:26 mcguire
-<rdar://problem/5535772> config cleanup on shutdown/reboot
+ // Parse each option out of the ancillary data.
+ for (cmPtr = CMSG_FIRSTHDR(&msg); cmPtr; cmPtr = CMSG_NXTHDR(&msg, cmPtr))
+ {
+ // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
+ if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVDSTADDR)
+ {
+ dstaddr->type = mDNSAddrType_IPv4;
+ dstaddr->ip.v4 = *(mDNSv4Addr*)CMSG_DATA(cmPtr);
+ //LogMsg("mDNSMacOSX.c: recvmsg IP_RECVDSTADDR %.4a", &dstaddr->ip.v4);
+ }
+ if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
+ {
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)CMSG_DATA(cmPtr);
+ if (sdl->sdl_nlen < IF_NAMESIZE)
+ {
+ mDNSPlatformMemCopy(ifname, sdl->sdl_data, sdl->sdl_nlen);
+ ifname[sdl->sdl_nlen] = 0;
+ // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
+ }
+ }
+ if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVTTL)
+ *ttl = *(u_char*)CMSG_DATA(cmPtr);
+ if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_PKTINFO)
+ {
+ struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmPtr);
+ dstaddr->type = mDNSAddrType_IPv6;
+ dstaddr->ip.v6 = *(mDNSv6Addr*)&ip6_info->ipi6_addr;
+ myIfIndexToName(ip6_info->ipi6_ifindex, ifname);
+ }
+ if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_HOPLIMIT)
+ *ttl = *(int*)CMSG_DATA(cmPtr);
+ }
-Revision 1.526 2008/02/26 21:43:54 cheshire
-Renamed 'clockdivisor' to 'mDNSPlatformClockDivisor' (LogTimeStamps code needs to be able to access it)
+ return(n);
+ }
-Revision 1.525 2008/02/20 00:53:20 cheshire
-<rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
-Removed overly alarming syslog message
+mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
+ {
+ KQSocketSet *const ss = (KQSocketSet *)context;
+ mDNS *const m = ss->m;
+ int err = 0, count = 0, closed = 0;
-Revision 1.524 2008/01/31 22:25:10 jgraessley
-<rdar://problem/5715434> using default Macintosh-0016CBF62EFD.local
-Use sysctlbyname to get hardware type for the default name.
+ if (filter != EVFILT_READ)
+ LogMsg("myKQSocketCallBack: Why is filter %d not EVFILT_READ (%d)?", filter, EVFILT_READ);
-Revision 1.523 2008/01/15 01:32:56 jgraessley
-Bug #: 5595309
-Reviewed by: Stuart Cheshire
-Additional change to print warning message up to 1000 times to make it more visible
+ if (s1 != ss->sktv4
+#ifndef NO_IPV6
+ && s1 != ss->sktv6
+#endif
+ )
+ {
+ LogMsg("myKQSocketCallBack: native socket %d", s1);
+ LogMsg("myKQSocketCallBack: sktv4 %d", ss->sktv4);
+#ifndef NO_IPV6
+ LogMsg("myKQSocketCallBack: sktv6 %d", ss->sktv6);
+#endif
+ }
-Revision 1.522 2008/01/15 01:14:02 mcguire
-<rdar://problem/5674390> mDNSPlatformSendUDP should allow unicast queries on specific interfaces
-removed check and log message, as they are no longer relevant
+ while (!closed)
+ {
+ mDNSAddr senderAddr, destAddr;
+ mDNSIPPort senderPort;
+ struct sockaddr_storage from;
+ size_t fromlen = sizeof(from);
+ char packetifname[IF_NAMESIZE] = "";
+ mDNSu8 ttl;
+ err = myrecvfrom(s1, &m->imsg, sizeof(m->imsg), (struct sockaddr *)&from, &fromlen, &destAddr, packetifname, &ttl);
+ if (err < 0) break;
-Revision 1.521 2007/12/14 00:58:28 cheshire
-<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
-Additional fixes: When going to sleep, mDNSResponder needs to postpone sleep
-until TLS/TCP deregistrations have completed (up to five seconds maximum)
+ count++;
+ if (from.ss_family == AF_INET)
+ {
+ struct sockaddr_in *s = (struct sockaddr_in*)&from;
+ senderAddr.type = mDNSAddrType_IPv4;
+ senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
+ senderPort.NotAnInteger = s->sin_port;
+ //LogInfo("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
+ }
+ else if (from.ss_family == AF_INET6)
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
+ senderAddr.type = mDNSAddrType_IPv6;
+ senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
+ senderPort.NotAnInteger = sin6->sin6_port;
+ //LogInfo("myKQSocketCallBack received IPv6 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
+ }
+ else
+ {
+ LogMsg("myKQSocketCallBack from is unknown address family %d", from.ss_family);
+ return;
+ }
-Revision 1.520 2007/12/10 23:01:01 cheshire
-Remove some unnecessary log messages
+ // 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;
-Revision 1.519 2007/12/06 00:22:27 mcguire
-<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
+ NetworkInterfaceInfoOSX *intf = m->p->InterfaceList;
+ while (intf && strcmp(intf->ifinfo.ifname, packetifname)) intf = intf->next;
-Revision 1.518 2007/12/05 01:52:30 cheshire
-<rdar://problem/5624763> BTMM: getaddrinfo_async_start returns EAI_NONAME when resolving BTMM hostname
-Delay returning IPv4 address ("A") results for autotunnel names until after we've set up the tunnel (or tried to)
+ // When going to sleep we deregister all our interfaces, but if the machine
+ // takes a few seconds to sleep we may continue to receive multicasts
+ // during that time, which would confuse mDNSCoreReceive, because as far
+ // as it's concerned, we should have no active interfaces any more.
+ // Hence we ignore multicasts for which we can find no matching InterfaceID.
+ if (intf) InterfaceID = intf->ifinfo.InterfaceID;
+ else if (mDNSAddrIsDNSMulticast(&destAddr)) continue;
-Revision 1.517 2007/12/03 18:37:26 cheshire
-Moved mDNSPlatformWriteLogMsg & mDNSPlatformWriteDebugMsg
-from mDNSMacOSX.c to PlatformCommon.c, so that Posix build can use them
+// LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s",
+// &senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifinfo.ifname);
-Revision 1.516 2007/12/01 01:21:27 jgraessley
-<rdar://problem/5623140> mDNSResponder unicast DNS improvements
+ // mDNSCoreReceive may close the socket we're reading from. We must break out of our
+ // loop when that happens, or we may try to read from an invalid FD. We do this by
+ // setting the closeFlag pointer in the socketset, so CloseSocketSet can inform us
+ // if it closes the socketset.
+ ss->closeFlag = &closed;
-Revision 1.515 2007/12/01 00:40:00 cheshire
-Add mDNSPlatformWriteLogMsg & mDNSPlatformWriteDebugMsg abstractions, to facilitate EFI conversion
+ mDNSCoreReceive(m, &m->imsg, (unsigned char*)&m->imsg + err, &senderAddr, senderPort, &destAddr, ss->port, InterfaceID);
-Revision 1.514 2007/12/01 00:38:32 cheshire
-Fixed compile warning: declaration of 'index' shadows a global declaration
+ // if we didn't close, we can safely dereference the socketset, and should to
+ // reset the closeFlag, since it points to something on the stack
+ if (!closed) ss->closeFlag = mDNSNULL;
+ }
-Revision 1.513 2007/11/27 00:08:49 jgraessley
-<rdar://problem/5613538> Interface-specific resolvers not setup correctly
-
-Revision 1.512 2007/11/16 22:09:26 cheshire
-Added missing type information in mDNSPlatformTCPCloseConnection debugging log message
-
-Revision 1.511 2007/11/14 23:06:13 cheshire
-<rdar://problem/5585972> IP_ADD_MEMBERSHIP fails for previously-connected removable interfaces
-
-Revision 1.510 2007/11/14 22:29:19 cheshire
-Updated comments and debugging log messages
-
-Revision 1.509 2007/11/14 01:07:53 cheshire
-Updated comments
-
-Revision 1.508 2007/11/02 21:59:37 cheshire
-Added comment about locking
-
-Revision 1.507 2007/11/02 20:18:13 cheshire
-<rdar://problem/5575583> BTMM: Work around keychain notification bug <rdar://problem/5124399>
-
-Revision 1.506 2007/10/30 20:46:45 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-
-Revision 1.505 2007/10/29 23:55:10 cheshire
-<rdar://problem/5526791> BTMM: Changing Local Hostname doesn't update Back to My Mac registered records
-Don't need to manually fake another AutoTunnelNATCallback if it has not yet received its first callback
-(and indeed should not, since the result fields will not yet be set up correctly in this case)
-
-Revision 1.504 2007/10/26 00:50:37 cheshire
-<rdar://problem/5526791> BTMM: Changing Local Hostname doesn't update Back to My Mac registered records
-
-Revision 1.503 2007/10/25 23:11:42 cheshire
-Ignore IPv6 ULA addresses configured on lo0 loopback interface
-
-Revision 1.502 2007/10/22 20:07:07 cheshire
-Moved mDNSPlatformSourceAddrForDest from mDNSMacOSX.c to PlatformCommon.c so
-Posix build can share the code (better than just pasting it into mDNSPosix.c)
+ if (err < 0 && (errno != EWOULDBLOCK || count == 0))
+ {
+ // Something is busted here.
+ // kqueue says there is a packet, but myrecvfrom says there is not.
+ // Try calling select() to get another opinion.
+ // Find out about other socket parameter that can help understand why select() says the socket is ready for read
+ // All of this is racy, as data may have arrived after the call to select()
+ static unsigned int numLogMessages = 0;
+ int save_errno = errno;
+ int so_error = -1;
+ int so_nread = -1;
+ int fionread = -1;
+ socklen_t solen = sizeof(int);
+ fd_set readfds;
+ struct timeval timeout;
+ int selectresult;
+ FD_ZERO(&readfds);
+ FD_SET(s1, &readfds);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ selectresult = select(s1+1, &readfds, NULL, NULL, &timeout);
+ if (getsockopt(s1, SOL_SOCKET, SO_ERROR, &so_error, &solen) == -1)
+ LogMsg("myKQSocketCallBack getsockopt(SO_ERROR) error %d", errno);
+ if (getsockopt(s1, SOL_SOCKET, SO_NREAD, &so_nread, &solen) == -1)
+ LogMsg("myKQSocketCallBack getsockopt(SO_NREAD) error %d", errno);
+ if (ioctl(s1, FIONREAD, &fionread) == -1)
+ LogMsg("myKQSocketCallBack ioctl(FIONREAD) error %d", errno);
+ if (numLogMessages++ < 100)
+ LogMsg("myKQSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
+ s1, err, save_errno, strerror(save_errno), selectresult, FD_ISSET(s1, &readfds) ? "" : "*NO* ", so_error, so_nread, fionread, count);
+ if (numLogMessages > 5)
+ NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)",
+ "Congratulations, you've reproduced an elusive bug.\r"
+ "Please contact the current assignee of <rdar://problem/3375328>.\r"
+ "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
+ "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
-Revision 1.501 2007/10/22 19:40:30 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
-Made subroutine mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst)
+ sleep(1); // After logging this error, rate limit so we don't flood syslog
+ }
+ }
-Revision 1.500 2007/10/17 22:49:55 cheshire
-<rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
+// TCP socket support
-Revision 1.499 2007/10/17 19:47:54 cheshire
-Improved debugging messages
+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
+ TCPConnectionCallback callback;
+ int fd;
+ KQueueEntry *kqEntry;
+ KQSocketSet ss;
+#ifndef NO_SECURITYFRAMEWORK
+ SSLContextRef tlsContext;
+ pthread_t handshake_thread;
+#endif /* NO_SECURITYFRAMEWORK */
+ domainname hostname;
+ void *context;
+ mDNSBool setup;
+ mDNSBool connected;
+ handshakeStatus handshake;
+ mDNS *m; // So we can call KQueueLock from the SSLHandshake thread
+ mStatus err;
+ };
-Revision 1.498 2007/10/17 18:42:06 cheshire
-Export SetDomainSecrets so its callable from other files
+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!
+ }
-Revision 1.497 2007/10/16 17:03:07 cheshire
-<rdar://problem/3557903> Performance: Core code will not work on platforms with small stacks
-Cut SetDomainSecrets stack from 3792 to 1760 bytes
+#ifndef NO_SECURITYFRAMEWORK
-Revision 1.496 2007/10/04 20:33:05 mcguire
-<rdar://problem/5518845> BTMM: Racoon configuration removed when network changes
+mDNSlocal OSStatus tlsWriteSock(SSLConnectionRef connection, const void *data, size_t *dataLength)
+ {
+ int ret = send(((TCPSocket *)connection)->fd, data, *dataLength, 0);
+ if (ret >= 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
+ if (ret >= 0) { *dataLength = ret; return(noErr); }
+ *dataLength = 0;
+ if (errno == EAGAIN ) return(errSSLWouldBlock);
+ if (errno == ENOENT ) return(errSSLClosedGraceful);
+ if (errno == EPIPE || errno == ECONNRESET) return(errSSLClosedAbort);
+ LogMsg("ERROR: tlsWriteSock: %d error %d (%s)\n", ((TCPSocket *)connection)->fd, errno, strerror(errno));
+ return(errSSLClosedAbort);
+ }
-Revision 1.495 2007/10/02 05:03:38 cheshire
-Fix bogus indentation in mDNSPlatformDynDNSHostNameStatusChanged
+mDNSlocal OSStatus tlsReadSock(SSLConnectionRef connection, void *data, size_t *dataLength)
+ {
+ int ret = recv(((TCPSocket *)connection)->fd, data, *dataLength, 0);
+ if (ret > 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
+ if (ret > 0) { *dataLength = ret; return(noErr); }
+ *dataLength = 0;
+ if (ret == 0 || errno == ENOENT ) return(errSSLClosedGraceful);
+ if ( errno == EAGAIN ) return(errSSLWouldBlock);
+ if ( errno == ECONNRESET) return(errSSLClosedAbort);
+ LogMsg("ERROR: tlsSockRead: error %d (%s)\n", errno, strerror(errno));
+ return(errSSLClosedAbort);
+ }
-Revision 1.494 2007/09/29 20:40:19 cheshire
-<rdar://problem/5513378> Crash in ReissueBlockedQuestions
+mDNSlocal OSStatus tlsSetupSock(TCPSocket *sock, mDNSBool server)
+ {
+ char domname_cstr[MAX_ESCAPED_DOMAIN_NAME];
-Revision 1.493 2007/09/29 03:16:45 cheshire
-<rdar://problem/5513168> BTMM: mDNSResponder memory corruption in GetAuthInfoForName_internal
-When AutoTunnel information changes, wait for record deregistrations to complete before registering new data
+ mStatus err = SSLNewContext(server, &sock->tlsContext);
+ if (err) { LogMsg("ERROR: tlsSetupSock: SSLNewContext failed with error code: %d", err); return(err); }
-Revision 1.492 2007/09/28 23:58:35 mcguire
-<rdar://problem/5505280> BTMM: v6 address and security policies being setup too soon
-Fix locking issue.
+ err = SSLSetIOFuncs(sock->tlsContext, tlsReadSock, tlsWriteSock);
+ if (err) { LogMsg("ERROR: tlsSetupSock: SSLSetIOFuncs failed with error code: %d", err); return(err); }
-Revision 1.491 2007/09/27 23:28:53 mcguire
-<rdar://problem/5508042> BTMM: Anonymous racoon configuration not always cleaned up correctly
+ err = SSLSetConnection(sock->tlsContext, (SSLConnectionRef) sock);
+ if (err) { LogMsg("ERROR: tlsSetupSock: SSLSetConnection failed with error code: %d", err); return(err); }
-Revision 1.490 2007/09/26 23:01:21 mcguire
-<rdar://problem/5505280> BTMM: v6 address and security policies being setup too soon
+ // Instead of listing all the acceptable ciphers, we just disable the bad ciphers. It does not disable
+ // all the bad ciphers like RC4_MD5, but it assumes that the servers don't offer them.
+ err = SSLSetAllowAnonymousCiphers(sock->tlsContext, 0);
+ if (err) { LogMsg("ERROR: tlsSetupSock: SSLSetAllowAnonymousCiphers failed with error code: %d", err); return(err); }
-Revision 1.489 2007/09/26 22:58:16 mcguire
-<rdar://problem/5505092> BTMM: Client tunnels being created to ::0 via 0.0.0.0
+ // We already checked for NULL in hostname and this should never happen. Hence, returning -1
+ // (error not in OSStatus space) is okay.
+ if (!sock->hostname.c[0]) {LogMsg("ERROR: tlsSetupSock: hostname NULL"); return -1; }
-Revision 1.488 2007/09/26 00:32:45 cheshire
-Rearrange struct TCPSocket_struct so "TCPSocketFlags flags" comes first (needed for debug logging)
+ ConvertDomainNameToCString(&sock->hostname, domname_cstr);
+ err = SSLSetPeerDomainName(sock->tlsContext, domname_cstr, strlen(domname_cstr));
+ if (err) { LogMsg("ERROR: tlsSetupSock: SSLSetPeerDomainname: %s failed with error code: %d", domname_cstr, err); return(err); }
-Revision 1.487 2007/09/21 17:07:41 mcguire
-<rdar://problem/5487354> BTMM: Need to modify IPSec tunnel setup files when shared secret changes (server-role)
+ return(err);
+ }
-Revision 1.486 2007/09/19 23:17:38 cheshire
-<rdar://problem/5482131> BTMM: Crash when switching .Mac accounts
+#ifdef __LIB_DISPATCH__
+mDNSlocal void doSSLHandshake(void *ctx)
+ {
+ TCPSocket *sock = (TCPSocket*)ctx;
+ mStatus err = SSLHandshake(sock->tlsContext);
+
+ //Can't have multiple threads in mDNS core. When __LIB_DISPATCH__ is
+ //defined, KQueueLock is a noop. Hence we need to serialize here
+ //
+ //NOTE: We just can't serialize doTcpSocketCallback alone on the main queue.
+ //We need the rest of the logic also. Otherwise, we can enable the READ
+ //events below, dispatch a doTcpSocketCallback on the main queue. Assume it is
+ //ConnFailed which means we are going to free the tcpInfo. While it
+ //is waiting to be dispatched, another read event can come into tcpKQSocketCallback
+ //and potentially call doTCPCallback with error which can close the fd and free the
+ //tcpInfo. Later when the thread gets dispatched it will crash because the tcpInfo
+ //is already freed.
-Revision 1.485 2007/09/19 21:44:29 cheshire
-Improved "mDNSKeychainGetSecrets failed" error message
+ dispatch_async(dispatch_get_main_queue(), ^{
-Revision 1.484 2007/09/18 21:44:55 cheshire
-<rdar://problem/5469006> Crash in GetAuthInfoForName_internal
-Code was using n->ExtPort (now n->RequestedPort) when it should have been using n->ExternalPort
+ LogInfo("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
-Revision 1.483 2007/09/17 22:19:39 mcguire
-<rdar://problem/5482519> BTMM: Tunnel is getting configured too much which causes long delays
-No need to configure a tunnel again if all the parameters are the same -- just remove the older duplicate tunnel from the list.
+ if (sock->handshake == handshake_to_be_closed)
+ {
+ LogInfo("SSLHandshake completed after close");
+ mDNSPlatformTCPCloseConnection(sock);
+ }
+ else
+ {
+ if (sock->fd != -1) KQueueSet(sock->fd, EV_ADD, EVFILT_READ, sock->kqEntry);
+ else LogMsg("doSSLHandshake: sock->fd is -1");
+
+ if (err == errSSLWouldBlock)
+ sock->handshake = handshake_required;
+ else
+ {
+ if (err)
+ {
+ LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
+ SSLDisposeContext(sock->tlsContext);
+ sock->tlsContext = NULL;
+ }
+
+ sock->err = err ? mStatus_ConnFailed : 0;
+ sock->handshake = handshake_completed;
+
+ LogInfo("doSSLHandshake: %p calling doTcpSocketCallback fd %d", sock, sock->fd);
+ doTcpSocketCallback(sock);
+ }
+ }
+
+ LogInfo("SSLHandshake %p: dropping lock for fd %d", sock, sock->fd);
+ return;
+ });
+ }
+#else
+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);
+ debugf("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
-Revision 1.482 2007/09/14 21:16:03 cheshire
-<rdar://problem/5413170> mDNSResponder using 100% CPU spinning in tlsReadSock
+ 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");
-Revision 1.481 2007/09/14 21:14:56 mcguire
-<rdar://problem/5481318> BTMM: Need to modify IPSec tunnel setup files when shared secret changes
+ if (err == errSSLWouldBlock)
+ sock->handshake = handshake_required;
+ else
+ {
+ if (err)
+ {
+ LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
+ SSLDisposeContext(sock->tlsContext);
+ sock->tlsContext = NULL;
+ }
+
+ sock->err = err ? mStatus_ConnFailed : 0;
+ sock->handshake = handshake_completed;
+
+ debugf("doSSLHandshake: %p calling doTcpSocketCallback fd %d", sock, sock->fd);
+ doTcpSocketCallback(sock);
+ }
+ }
+
+ debugf("SSLHandshake %p: dropping lock for fd %d", sock, sock->fd);
+ KQueueUnlock(m, "doSSLHandshake");
+ return NULL;
+ }
+#endif
-Revision 1.480 2007/09/13 00:16:42 cheshire
-<rdar://problem/5468706> Miscellaneous NAT Traversal improvements
+mDNSlocal mStatus spawnSSLHandshake(TCPSocket* sock)
+ {
+ debugf("spawnSSLHandshake %p: entry", sock);
+ mStatus err;
-Revision 1.479 2007/09/12 19:22:20 cheshire
-Variable renaming in preparation for upcoming fixes e.g. priv/pub renamed to intport/extport
-Made NAT Traversal packet handlers take typed data instead of anonymous "mDNSu8 *" byte pointers
+ 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);
+#ifdef __LIB_DISPATCH__
-Revision 1.478 2007/09/07 22:21:45 vazquez
-<rdar://problem/5460830> BTMM: Connection stops working after connecting VPN
+ // Dispatch it on a separate serial queue to avoid deadlocks with threads running on main queue
+ dispatch_async(SSLqueue, ^{doSSLHandshake(sock);});
+ err = 0;
+#else
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ 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);
+ }
+#endif
+ debugf("spawnSSLHandshake %p: done for %d", sock, sock->fd);
+ return err;
+ }
-Revision 1.477 2007/09/07 21:22:30 cheshire
-<rdar://problem/5460210> BTMM: SetupSocket 5351 failed; Can't allocate UDP multicast socket spew on wake from sleep with internet sharing on
-Don't log failures binding to port 5351
+mDNSlocal mDNSBool IsTunnelModeDomain(const domainname *d)
+ {
+ static const domainname *mmc = (const domainname*) "\x7" "members" "\x3" "mac" "\x3" "com";
+ const domainname *d1 = mDNSNULL; // TLD
+ const domainname *d2 = mDNSNULL; // SLD
+ const domainname *d3 = mDNSNULL;
+ while (d->c[0]) { d3 = d2; d2 = d1; d1 = d; d = (const domainname*)(d->c + 1 + d->c[0]); }
+ return(d3 && SameDomainName(d3, mmc));
+ }
-Revision 1.476 2007/09/06 20:38:08 cheshire
-<rdar://problem/5439021> Only call SetDomainSecrets() for Keychain changes that are relevant to mDNSResponder
+#endif /* NO_SECURITYFRAMEWORK */
-Revision 1.475 2007/09/05 02:24:28 cheshire
-<rdar://problem/5457287> mDNSResponder taking up 100% CPU in ReissueBlockedQuestions
-In ReissueBlockedQuestions, only restart questions marked NoAnswer_Suspended, not those marked NoAnswer_Fail
+mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context)
+ {
+ TCPSocket *sock = context;
+ sock->err = mStatus_NoError;
-Revision 1.474 2007/09/04 22:32:58 mcguire
-<rdar://problem/5453633> BTMM: BTMM overwrites /etc/racoon/remote/anonymous.conf
+ //if (filter == EVFILT_READ ) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_READ", filter);
+ //if (filter == EVFILT_WRITE) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_WRITE", filter);
+ // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it here with EV_DELETE
+ if (filter == EVFILT_WRITE) KQueueSet(sock->fd, EV_DELETE, EVFILT_WRITE, sock->kqEntry);
-Revision 1.473 2007/08/31 19:53:15 cheshire
-<rdar://problem/5431151> BTMM: IPv6 address lookup should not succeed if autotunnel cannot be setup
-If AutoTunnel setup fails, the code now generates a fake NXDomain error saying that the requested AAAA record does not exist
+ if (sock->flags & kTCPSocketFlags_UseTLS)
+ {
+#ifndef NO_SECURITYFRAMEWORK
+ if (!sock->setup) { sock->setup = mDNStrue; tlsSetupSock(sock, mDNSfalse); }
+
+ 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)
+ {
+ if (!sock->err) sock->err = mStatus_UnknownErr;
+ LogMsg("tcpKQSocketCallback called with unexpected SSLHandshake status: %d", sock->handshake);
+ }
+#else
+ sock->err = mStatus_UnsupportedErr;
+#endif /* NO_SECURITYFRAMEWORK */
+ }
+
+ doTcpSocketCallback(sock);
+ }
-Revision 1.472 2007/08/31 18:49:49 vazquez
-<rdar://problem/5393719> BTMM: Need to properly deregister when stopping BTMM
+#ifdef __LIB_DISPATCH__
+mDNSexport int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef)
+ {
+ dispatch_queue_t queue = dispatch_get_main_queue();
+ dispatch_source_t source;
+ if (flags == EV_DELETE)
+ {
+ if (filter == EVFILT_READ)
+ {
+ dispatch_source_cancel(entryRef->readSource);
+ dispatch_release(entryRef->readSource);
+ entryRef->readSource = mDNSNULL;
+ debugf("KQueueSet: source cancel for read %p, %p", entryRef->readSource, entryRef->writeSource);
+ }
+ else if (filter == EVFILT_WRITE)
+ {
+ dispatch_source_cancel(entryRef->writeSource);
+ dispatch_release(entryRef->writeSource);
+ entryRef->writeSource = mDNSNULL;
+ debugf("KQueueSet: source cancel for write %p, %p", entryRef->readSource, entryRef->writeSource);
+ }
+ else
+ LogMsg("KQueueSet: ERROR: Wrong filter value %d for EV_DELETE", filter);
+ return 0;
+ }
+ if (flags != EV_ADD) LogMsg("KQueueSet: Invalid flags %d", flags);
-Revision 1.471 2007/08/31 02:05:46 cheshire
-Need to hold mDNS_Lock when calling mDNS_AddDynDNSHostName
+ if (filter == EVFILT_READ)
+ {
+ source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, queue);
+ }
+ else if (filter == EVFILT_WRITE)
+ {
+ source = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, queue);
+ }
+ else
+ {
+ LogMsg("KQueueSet: ERROR: Wrong filter value %d for EV_ADD", filter);
+ return -1;
+ }
+ if (!source) return -1;
+ dispatch_source_set_event_handler(source, ^{
-Revision 1.470 2007/08/30 22:50:04 mcguire
-<rdar://problem/5430628> BTMM: Tunneled services are registered when autotunnel can't be setup
+ mDNSs32 stime = mDNSPlatformRawTime();
+ entryRef->KQcallback(fd, filter, entryRef->KQcontext);
+ mDNSs32 etime = mDNSPlatformRawTime();
+ if (etime - stime >= WatchDogReportingThreshold)
+ LogInfo("KQEntryCallback Block: WARNING: took %dms to complete", etime - stime);
-Revision 1.469 2007/08/30 19:40:51 cheshire
-Added syslog messages to report various initialization failures
+ // Trigger the event delivery to the application. Even though we trigger the
+ // event completion after handling every event source, these all will hopefully
+ // get merged
+ TriggerEventCompletion();
-Revision 1.468 2007/08/30 00:12:20 cheshire
-Check error codes and log failures during AutoTunnel setup
+ });
+ dispatch_source_set_cancel_handler(source, ^{
+ if (entryRef->fdClosed)
+ {
+ //LogMsg("CancelHandler: closing fd %d", fd);
+ close(fd);
+ }
+ });
+ dispatch_resume(source);
+ if (filter == EVFILT_READ)
+ entryRef->readSource = source;
+ else
+ entryRef->writeSource = source;
+
+ return 0;
+ }
-Revision 1.467 2007/08/28 00:33:04 jgraessley
-<rdar://problem/5423932> Selective compilation options
-
-Revision 1.466 2007/08/24 23:25:55 cheshire
-Debugging messages to help track down duplicate items being read from system keychain
-
-Revision 1.465 2007/08/24 00:39:12 cheshire
-Added comment explaining why we set info->AutoTunnelService.resrec.RecordType to kDNSRecordTypeUnregistered
+mDNSexport void KQueueLock(mDNS *const m)
+ {
+ (void)m; //unused
+ }
+mDNSexport void KQueueUnlock(mDNS *const m, const char const *task)
+ {
+ (void)m; //unused
+ (void)task; //unused
+ }
+#else
+mDNSexport int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *const entryRef)
+ {
+ struct kevent new_event;
+ EV_SET(&new_event, fd, filter, flags, 0, 0, (void*)entryRef);
+ return (kevent(KQueueFD, &new_event, 1, NULL, 0, NULL) < 0) ? errno : 0;
+ }
-Revision 1.464 2007/08/24 00:15:21 cheshire
-Renamed GetAuthInfoForName() to GetAuthInfoForName_internal() to make it clear that it may only be called with the lock held
+mDNSexport void KQueueLock(mDNS *const m)
+ {
+ pthread_mutex_lock(&m->p->BigMutex);
+ m->p->BigMutexStartTime = mDNSPlatformRawTime();
+ }
-Revision 1.463 2007/08/23 21:02:35 cheshire
-SecKeychainSetPreferenceDomain() call should be in platform-support layer, not daemon.c
+mDNSexport void KQueueUnlock(mDNS *const m, const char const *task)
+ {
+ mDNSs32 end = mDNSPlatformRawTime();
+ (void)task;
+ if (end - m->p->BigMutexStartTime >= WatchDogReportingThreshold)
+ LogInfo("WARNING: %s took %dms to complete", task, end - m->p->BigMutexStartTime);
-Revision 1.462 2007/08/18 01:02:03 mcguire
-<rdar://problem/5415593> No Bonjour services are getting registered at boot
+ pthread_mutex_unlock(&m->p->BigMutex);
-Revision 1.461 2007/08/10 22:25:57 mkrochma
-<rdar://problem/5396302> mDNSResponder continually complains about slow UDP packet reception -- about 400 msecs
+ char wake = 1;
+ if (send(m->p->WakeKQueueLoopFD, &wake, sizeof(wake), 0) == -1)
+ LogMsg("ERROR: KQueueWake: send failed with error code: %d (%s)", errno, strerror(errno));
+ }
+#endif
-Revision 1.460 2007/08/08 22:34:59 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
+mDNSexport void mDNSPlatformCloseFD(KQueueEntry *kq, int fd)
+ {
+#ifdef __LIB_DISPATCH__
+ (void)fd; //unused
+ if (kq->readSource)
+ {
+ dispatch_source_cancel(kq->readSource);
+ kq->readSource = mDNSNULL;
+ }
+ if (kq->writeSource)
+ {
+ dispatch_source_cancel(kq->writeSource);
+ kq->writeSource = mDNSNULL;
+ }
+ // Close happens in the cancellation handler
+ debugf("mDNSPlatformCloseFD: resetting sources for %d", fd);
+ kq->fdClosed = mDNStrue;
+#else
+ (void)kq; //unused
+ close(fd);
+#endif
+ }
-Revision 1.459 2007/08/08 21:07:48 vazquez
-<rdar://problem/5244687> BTMM: Need to advertise model information via wide-area bonjour
+mDNSlocal mStatus SetupTCPSocket(TCPSocket *sock, u_short sa_family, mDNSIPPort *port)
+ {
+ KQSocketSet *cp = &sock->ss;
+#ifndef NO_IPV6
+ int *s = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
+ KQueueEntry *k = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
+#else
+ int *s = &cp->sktv4;
+ KQueueEntry *k = &cp->kqsv4;
+#endif
+ const int on = 1; // "on" for setsockopt
+ mStatus err;
-Revision 1.458 2007/08/03 02:18:41 mcguire
-<rdar://problem/5381687> BTMM: Use port numbers in IPsec policies & configuration files
+ int skt = socket(sa_family, SOCK_STREAM, IPPROTO_TCP);
+ if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupTCPSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); }
+ if (sa_family == AF_INET)
+ {
+ // Bind it
+ struct sockaddr_in addr;
+ mDNSPlatformMemZero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = port->NotAnInteger;
+ err = bind(skt, (struct sockaddr*) &addr, sizeof(addr));
+ if (err < 0) { LogMsg("ERROR: bind %s", strerror(errno)); return err; }
+
+ // Receive interface identifiers
+ err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
+ if (err < 0) { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); return err; }
+
+ mDNSPlatformMemZero(&addr, sizeof(addr));
+ socklen_t len = sizeof(addr);
+ err = getsockname(skt, (struct sockaddr*) &addr, &len);
+ if (err < 0) { LogMsg("getsockname - %s", strerror(errno)); return err; }
+
+ port->NotAnInteger = addr.sin_port;
+ }
+ else
+ {
+ // Bind it
+ struct sockaddr_in6 addr6;
+ mDNSPlatformMemZero(&addr6, sizeof(addr6));
+ addr6.sin6_family = AF_INET6;
+ addr6.sin6_port = port->NotAnInteger;
+ err = bind(skt, (struct sockaddr*) &addr6, sizeof(addr6));
+ if (err < 0) { LogMsg("ERROR: bind6 %s", strerror(errno)); return err; }
-Revision 1.457 2007/08/02 16:48:45 mcguire
-<rdar://problem/5329526> BTMM: Don't try to create tunnel back to same machine
+ // We want to receive destination addresses and receive interface identifiers
+ err = setsockopt(skt, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on));
+ if (err < 0) { LogMsg("ERROR: setsockopt IPV6_PKTINFO %s", strerror(errno)); return err; }
-Revision 1.456 2007/08/02 03:28:30 vazquez
-Make ExternalAddress and err unused to fix build warnings
+ mDNSPlatformMemZero(&addr6, sizeof(addr6));
+ socklen_t len = sizeof(addr6);
+ err = getsockname(skt, (struct sockaddr *) &addr6, &len);
+ if (err < 0) { LogMsg("getsockname6 - %s", strerror(errno)); return err; }
+
+ port->NotAnInteger = addr6.sin6_port;
-Revision 1.455 2007/08/01 03:09:22 cheshire
-<rdar://problem/5344587> BTMM: Create NAT port mapping for autotunnel port
+ }
+ *s = skt;
+ k->KQcallback = tcpKQSocketCallback;
+ k->KQcontext = sock;
+ k->KQtask = "mDNSPlatformTCPSocket";
+#ifdef __LIB_DISPATCH__
+ k->readSource = mDNSNULL;
+ k->writeSource = mDNSNULL;
+ k->fdClosed = mDNSfalse;
+#endif
+ return mStatus_NoError;
+ }
-Revision 1.454 2007/07/31 23:08:34 mcguire
-<rdar://problem/5329542> BTMM: Make AutoTunnel mode work with multihoming
+mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port)
+ {
+ mStatus err;
+ (void) m;
-Revision 1.453 2007/07/31 19:13:58 mkrochma
-No longer need to include "btmm" in hostname to avoid name conflicts
+ TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPSocket", sizeof(TCPSocket));
+ if (!sock) { LogMsg("mDNSPlatformTCPSocket: memory allocation failure"); return(mDNSNULL); }
-Revision 1.452 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
+ mDNSPlatformMemZero(sock, sizeof(TCPSocket));
-Revision 1.451 2007/07/25 22:25:45 cheshire
-<rdar://problem/5360853> BTMM: Code not cleaning up old racoon files
+ sock->ss.m = m;
+ sock->ss.sktv4 = -1;
+#ifndef NO_IPV6
+ sock->ss.sktv6 = -1;
+#endif
+ err = SetupTCPSocket(sock, AF_INET, port);
+#ifndef NO_IPV6
+ if (!err)
+ {
+ err = SetupTCPSocket(sock, AF_INET6, port);
+ if (err) { mDNSPlatformCloseFD(&sock->ss.kqsv4, sock->ss.sktv4); sock->ss.sktv4 = -1; }
+ }
+#endif
+ if (err)
+ {
+ LogMsg("mDNSPlatformTCPSocket: socket error %d errno %d (%s)", sock->fd, errno, strerror(errno));
+ freeL("TCPSocket/mDNSPlatformTCPSocket", sock);
+ return(mDNSNULL);
+ }
-Revision 1.450 2007/07/25 21:19:10 cheshire
-<rdar://problem/5359507> Fails to build with NO_SECURITYFRAMEWORK: 'IsTunnelModeDomain' defined but not used
+ sock->callback = mDNSNULL;
+ sock->flags = flags;
+ sock->context = mDNSNULL;
+ sock->setup = mDNSfalse;
+ sock->connected = mDNSfalse;
+ sock->handshake = handshake_required;
+ sock->m = m;
+ sock->err = mStatus_NoError;
+
+ return sock;
+ }
-Revision 1.449 2007/07/25 01:36:09 mcguire
-<rdar://problem/5345290> BTMM: Replace popen() `setkey` calls to setup/teardown ipsec policies
+mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname, mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context)
+ {
+ KQSocketSet *cp = &sock->ss;
+#ifndef NO_IPV6
+ int *s = (dst->type == mDNSAddrType_IPv4) ? &cp->sktv4 : &cp->sktv6;
+ KQueueEntry *k = (dst->type == mDNSAddrType_IPv4) ? &cp->kqsv4 : &cp->kqsv6;
+#else
+ int *s = &cp->sktv4;
+ KQueueEntry *k = &cp->kqsv4;
+#endif
+ mStatus err = mStatus_NoError;
+ struct sockaddr_storage ss;
-Revision 1.448 2007/07/24 21:30:09 cheshire
-Added "AutoTunnel server listening for connections..." diagnostic message
+ sock->callback = callback;
+ sock->context = context;
+ sock->setup = mDNSfalse;
+ sock->connected = mDNSfalse;
+ sock->handshake = handshake_required;
+ sock->err = mStatus_NoError;
-Revision 1.447 2007/07/24 20:24:18 cheshire
-Only remove AutoTunnel address if we have created it.
-Otherwise, we get "errno 49 (Can't assign requested address)" errors on exit.
+ if (hostname) { debugf("mDNSPlatformTCPConnect: hostname %##s", hostname->c); AssignDomainName(&sock->hostname, hostname); }
-Revision 1.446 2007/07/24 03:00:09 cheshire
-SetDomainSecrets() should call SetupLocalAutoTunnelInterface_internal(), not SetupLocalAutoTunnelInterface()
+ if (dst->type == mDNSAddrType_IPv4)
+ {
+ struct sockaddr_in *saddr = (struct sockaddr_in *)&ss;
+ mDNSPlatformMemZero(saddr, sizeof(*saddr));
+ saddr->sin_family = AF_INET;
+ saddr->sin_port = dstport.NotAnInteger;
+ saddr->sin_len = sizeof(*saddr);
+ saddr->sin_addr.s_addr = dst->ip.v4.NotAnInteger;
+ }
+ else
+ {
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&ss;
+ mDNSPlatformMemZero(saddr6, sizeof(*saddr6));
+ saddr6->sin6_family = AF_INET6;
+ saddr6->sin6_port = dstport.NotAnInteger;
+ saddr6->sin6_len = sizeof(*saddr6);
+ saddr6->sin6_addr = *(struct in6_addr *)&dst->ip.v6;
+ }
-Revision 1.445 2007/07/23 20:26:26 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
-Move code that reads "Setup:/Network/BackToMyMac" preferences outside the check
-for existence of "Setup:/Network/DynamicDNS" settings
+ // Watch for connect complete (write is ready)
+ // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it in tcpKQSocketCallback using EV_DELETE
+ if (KQueueSet(*s, EV_ADD /* | EV_ONESHOT */, EVFILT_WRITE, k))
+ {
+ LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
+ return errno;
+ }
-Revision 1.444 2007/07/21 00:54:49 cheshire
-<rdar://problem/5344576> Delay IPv6 address callback until AutoTunnel route and policy is configured
+ // Watch for incoming data
+ if (KQueueSet(*s, EV_ADD, EVFILT_READ, k))
+ {
+ LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
+ return errno;
+ }
-Revision 1.443 2007/07/20 23:23:11 cheshire
-Rename out-of-date name "atq" (was AutoTunnelQuery) to simpler "tun"
+ if (fcntl(*s, F_SETFL, fcntl(*s, F_GETFL, 0) | O_NONBLOCK) < 0) // set non-blocking
+ {
+ LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno));
+ return mStatus_UnknownErr;
+ }
-Revision 1.442 2007/07/20 20:23:24 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
-Fixed errors reading the Setup:/Network/BackToMyMac preferences
+ // We bind to the interface and all subsequent packets including the SYN will be sent out
+ // on this interface
+ //
+ // Note: If we are in Active Directory domain, we may try TCP (if the response can't fit in
+ // UDP). mDNSInterface_Unicast indicates this case and not a valid interface.
+ if (InterfaceID && InterfaceID != mDNSInterface_Unicast)
+ {
+ extern mDNS mDNSStorage;
+ NetworkInterfaceInfoOSX *info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
+ if (dst->type == mDNSAddrType_IPv4)
+ {
+ #ifdef IP_BOUND_IF
+ if (info) setsockopt(*s, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
+ else { LogMsg("mDNSPlatformTCPConnect: Invalid interface index %p", InterfaceID); return mStatus_BadParamErr; }
+ #else
+ (void)InterfaceID; // Unused
+ (void)info; // Unused
+ #endif
+ }
+ else
+ {
+ #ifdef IPV6_BOUND_IF
+ if (info) setsockopt(*s, IPPROTO_IPV6, IPV6_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
+ else { LogMsg("mDNSPlatformTCPConnect: Invalid interface index %p", InterfaceID); return mStatus_BadParamErr; }
+ #else
+ (void)InterfaceID; // Unused
+ (void)info; // Unused
+ #endif
+ }
+ }
-Revision 1.441 2007/07/20 16:46:45 mcguire
-<rdar://problem/5345233> BTMM: Replace system() `route` calls to setup/teardown routes
+ // mDNSPlatformReadTCP/WriteTCP (unlike the UDP counterpart) does not provide the destination address
+ // from which we can infer the destination address family. Hence we need to remember that here.
+ // Instead of remembering the address family, we remember the right fd.
+ sock->fd = *s;
+ sock->kqEntry = k;
+ // initiate connection wth peer
+ if (connect(*s, (struct sockaddr *)&ss, ss.ss_len) < 0)
+ {
+ if (errno == EINPROGRESS) return mStatus_ConnPending;
+ if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
+ LogInfo("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock->fd, errno, strerror(errno));
+ else
+ LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s) length %d", sock->fd, errno, strerror(errno), ss.ss_len);
+ return mStatus_ConnFailed;
+ }
-Revision 1.440 2007/07/20 16:22:07 mcguire
-<rdar://problem/5344584> BTMM: Replace system() `ifconfig` calls to setup/teardown IPv6 address
+ LogMsg("NOTE: mDNSPlatformTCPConnect completed synchronously");
+ // kQueue should notify us, but this LogMsg is to help track down if it doesn't
+ return err;
+ }
-Revision 1.439 2007/07/20 01:14:56 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
-Cleaned up log messages
+// Why doesn't mDNSPlatformTCPAccept actually call accept() ?
+mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int fd)
+ {
+ mStatus err = mStatus_NoError;
-Revision 1.438 2007/07/20 00:54:21 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
+ TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPAccept", sizeof(TCPSocket));
+ if (!sock) return(mDNSNULL);
-Revision 1.437 2007/07/19 22:01:27 cheshire
-Added "#pragma mark" sections headings to divide code into related function groups
+ mDNSPlatformMemZero(sock, sizeof(*sock));
+ sock->fd = fd;
+ sock->flags = flags;
-Revision 1.436 2007/07/18 03:25:25 cheshire
-<rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
-Bring up server-side tunnel on demand, when necessary
+ if (flags & kTCPSocketFlags_UseTLS)
+ {
+#ifndef NO_SECURITYFRAMEWORK
+ if (!ServerCerts) { LogMsg("ERROR: mDNSPlatformTCPAccept: unable to find TLS certificates"); err = mStatus_UnknownErr; goto exit; }
-Revision 1.435 2007/07/18 01:05:08 cheshire
-<rdar://problem/5303834> Automatically configure IPSec policy when resolving services
-Add list of client tunnels so we can automatically reconfigure when local address changes
+ err = tlsSetupSock(sock, mDNStrue);
+ if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: tlsSetupSock failed with error code: %d", err); goto exit; }
-Revision 1.434 2007/07/16 20:16:00 vazquez
-<rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite
-Remove unnecessary LNT init code
+ err = SSLSetCertificate(sock->tlsContext, ServerCerts);
+ if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: SSLSetCertificate failed with error code: %d", err); goto exit; }
+#else
+ err = mStatus_UnsupportedErr;
+#endif /* NO_SECURITYFRAMEWORK */
+ }
+#ifndef NO_SECURITYFRAMEWORK
+exit:
+#endif
-Revision 1.433 2007/07/14 00:36:07 cheshire
-Remove temporary IPv4LL tunneling mode now that IPv6-over-IPv4 is working
+ if (err) { freeL("TCPSocket/mDNSPlatformTCPAccept", sock); return(mDNSNULL); }
+ return(sock);
+ }
-Revision 1.432 2007/07/12 23:55:11 cheshire
-<rdar://problem/5303834> Automatically configure IPSec policy when resolving services
-Don't need two separate DNSQuestion structures when looking up tunnel endpoint
+mDNSlocal void CloseSocketSet(KQSocketSet *ss)
+ {
+ if (ss->sktv4 != -1)
+ {
+ mDNSPlatformCloseFD(&ss->kqsv4, ss->sktv4);
+ ss->sktv4 = -1;
+ }
+#ifndef NO_IPV6
+ if (ss->sktv6 != -1)
+ {
+ mDNSPlatformCloseFD(&ss->kqsv6, ss->sktv6);
+ ss->sktv6 = -1;
+ }
+#endif
+ if (ss->closeFlag) *ss->closeFlag = 1;
+ }
-Revision 1.431 2007/07/12 23:34:48 cheshire
-Removed 'LogOperation' message to reduce verbosity in syslog
+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;
-Revision 1.430 2007/07/12 22:16:46 cheshire
-Improved "could not convert shared secret from base64" log message so it doesn't reveal key data in syslog
+ SSLClose(sock->tlsContext);
+ SSLDisposeContext(sock->tlsContext);
+ sock->tlsContext = NULL;
+ }
+#endif /* NO_SECURITYFRAMEWORK */
+ if (sock->ss.sktv4 != -1) shutdown(sock->ss.sktv4, 2);
+#ifndef NO_IPV6
+ if (sock->ss.sktv6 != -1) shutdown(sock->ss.sktv6, 2);
+#endif
+ CloseSocketSet(&sock->ss);
+ sock->fd = -1;
-Revision 1.429 2007/07/12 02:51:28 cheshire
-<rdar://problem/5303834> Automatically configure IPSec policy when resolving services
+ freeL("TCPSocket/mDNSPlatformTCPCloseConnection", sock);
+ }
+ }
-Revision 1.428 2007/07/11 23:17:31 cheshire
-<rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
-Improve log message to indicate if we're starting or restarting racoon
+mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
+ {
+ size_t nread = 0;
+ *closed = mDNSfalse;
-Revision 1.427 2007/07/11 22:50:30 cheshire
-<rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
-Write /etc/racoon/remote/anonymous.conf configuration file and start up /usr/sbin/racoon
+ if (sock->flags & kTCPSocketFlags_UseTLS)
+ {
+#ifndef NO_SECURITYFRAMEWORK
+ if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformReadTCP called while handshake required"); return 0; }
+ else if (sock->handshake == handshake_in_progress) return 0;
+ else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformReadTCP called with unexpected SSLHandshake status: %d", sock->handshake);
-Revision 1.426 2007/07/11 20:40:49 cheshire
-<rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
-In mDNSPlatformGetPrimaryInterface(), prefer routable IPv4 address to IPv4LL
+ //LogMsg("Starting SSLRead %d %X", sock->fd, fcntl(sock->fd, F_GETFL, 0));
+ mStatus err = SSLRead(sock->tlsContext, buf, buflen, &nread);
+ //LogMsg("SSLRead returned %d (%d) nread %d buflen %d", err, errSSLWouldBlock, nread, buflen);
+ if (err == errSSLClosedGraceful) { nread = 0; *closed = mDNStrue; }
+ else if (err && err != errSSLWouldBlock)
+ { LogMsg("ERROR: mDNSPlatformReadTCP - SSLRead: %d", err); nread = -1; *closed = mDNStrue; }
+#else
+ nread = -1;
+ *closed = mDNStrue;
+#endif /* NO_SECURITYFRAMEWORK */
+ }
+ else
+ {
+ static int CLOSEDcount = 0;
+ static int EAGAINcount = 0;
+ nread = recv(sock->fd, buf, buflen, 0);
-Revision 1.425 2007/07/11 19:24:19 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for services
-Configure internal AutoTunnel address
-(For temporary testing we're faking up an IPv4LL address instead of IPv6 ULA, and we're
-assigning it with "system(commandstring);" which probably isn't the most efficient way to do it)
+ if (nread > 0) { CLOSEDcount = 0; EAGAINcount = 0; } // On success, clear our error counters
+ else if (nread == 0)
+ {
+ *closed = mDNStrue;
+ if ((++CLOSEDcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got CLOSED %d times", sock->fd, CLOSEDcount); sleep(1); }
+ }
+ // else nread is negative -- see what kind of error we got
+ else if (errno == ECONNRESET) { nread = 0; *closed = mDNStrue; }
+ else if (errno != EAGAIN) { LogMsg("ERROR: mDNSPlatformReadTCP - recv: %d (%s)", errno, strerror(errno)); nread = -1; }
+ else // errno is EAGAIN (EWOULDBLOCK) -- no data available
+ {
+ nread = 0;
+ if ((++EAGAINcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got EAGAIN %d times", sock->fd, EAGAINcount); sleep(1); }
+ }
+ }
-Revision 1.424 2007/07/11 19:00:27 cheshire
-Only need to set up m->AutoTunnelHostAddr first time through UpdateInterfaceList()
+ return nread;
+ }
-Revision 1.423 2007/07/11 03:00:59 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-Add AutoTunnel parameter to mDNS_SetSecretForDomain; Generate IPv6 ULA address for tunnel endpoint
+mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
+ {
+ int nsent;
-Revision 1.422 2007/07/10 01:21:20 cheshire
-Added (commented out) line for displaying key data for debugging
-
-Revision 1.421 2007/06/25 20:58:11 cheshire
-<rdar://problem/5234463> Write the Multicast DNS domains to the DynamicStore
-Additional refinement: Add mDNS domain list new new DynamicStore entity "State:/Network/MulticastDNS"
-
-Revision 1.420 2007/06/22 21:52:14 cheshire
-<rdar://problem/5234463> Write the Multicast DNS domains to the DynamicStore
-
-Revision 1.419 2007/06/22 21:32:00 cheshire
-<rdar://problem/5239020> Use SecKeychainCopyDefault instead of SecKeychainOpen
-
-Revision 1.418 2007/06/21 16:37:43 jgraessley
-Bug #: 5280520
-Reviewed by: Stuart Cheshire
-Additional changes to get this compiling on the embedded platform.
-
-Revision 1.417 2007/06/20 01:44:00 cheshire
-More information in "Network Configuration Change" message
-
-Revision 1.416 2007/06/20 01:10:12 cheshire
-<rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
-
-Revision 1.415 2007/06/15 19:23:38 cheshire
-<rdar://problem/5254053> mDNSResponder renames my host without asking
-Improve log messages, to distinguish user-initiated renames from automatic (name conflict) renames
-
-Revision 1.414 2007/05/17 22:00:59 cheshire
-<rdar://problem/5210966> Lower network change delay from two seconds to one second
-
-Revision 1.413 2007/05/16 16:43:27 cheshire
-Only log "bind" failures for our shared mDNS port and for binding to zero
--- other attempts to bind to a particular port may legitimately fail
-
-Revision 1.412 2007/05/15 21:49:21 cheshire
-Get rid of "#pragma unused"
-
-Revision 1.411 2007/05/14 23:54:55 cheshire
-Instead of sprintf, use safer length-limited mDNS_snprintf
-
-Revision 1.410 2007/05/12 01:05:00 cheshire
-Updated debugging messages
-
-Revision 1.409 2007/05/10 22:39:48 cheshire
-<rdar://problem/4118503> Share single socket instead of creating separate socket for each active interface
-Only define CountMaskBits for builds with debugging messages
-
-Revision 1.408 2007/05/10 22:19:00 cheshire
-<rdar://problem/4118503> Share single socket instead of creating separate socket for each active interface
-Don't deliver multicast packets for which we can't find an associated InterfaceID
-
-Revision 1.407 2007/05/10 21:40:28 cheshire
-Don't log unnecessary "Address already in use" errors when joining multicast groups
-
-Revision 1.406 2007/05/08 00:56:17 cheshire
-<rdar://problem/4118503> Share single socket instead of creating separate socket for each active interface
-
-Revision 1.405 2007/05/04 20:21:39 cheshire
-Improve "connect failed" error message
-
-Revision 1.404 2007/05/02 19:41:53 cheshire
-No need to alarm people with "Connection reset by peer" syslog message
-
-Revision 1.403 2007/04/28 01:31:59 cheshire
-Improve debugging support for catching memory corruption problems
-
-Revision 1.402 2007/04/26 22:54:57 cheshire
-Debugging messages to help track down <rdar://problem/5164206> mDNSResponder takes 50%+ CPU
-
-Revision 1.401 2007/04/26 00:35:16 cheshire
-<rdar://problem/5140339> uDNS: Domain discovery not working over VPN
-Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server
-inside the firewall may give answers where a public one gives none, and vice versa.)
-
-Revision 1.400 2007/04/24 21:50:27 cheshire
-Debugging: Show list of changedKeys in NetworkChanged callback
-
-Revision 1.399 2007/04/23 22:28:47 cheshire
-Allan Nathanson informs us we should only be looking at the search list for resolver[0], not all of them
-
-Revision 1.398 2007/04/23 04:57:00 cheshire
-Log messages for debugging <rdar://problem/4570952> IPv6 multicast not working properly
-
-Revision 1.397 2007/04/22 06:02:03 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.396 2007/04/21 21:47:47 cheshire
-<rdar://problem/4376383> Daemon: Add watchdog timer
-
-Revision 1.395 2007/04/18 20:58:34 cheshire
-<rdar://problem/5140339> Domain discovery not working over VPN
-Needed different code to handle the case where there's only a single search domain
-
-Revision 1.394 2007/04/17 23:05:50 cheshire
-<rdar://problem/3957358> Shouldn't send domain queries when we have 169.254 or loopback address
-
-Revision 1.393 2007/04/17 19:21:29 cheshire
-<rdar://problem/5140339> Domain discovery not working over VPN
-
-Revision 1.392 2007/04/17 17:15:09 cheshire
-Change NO_CFUSERNOTIFICATION code so it still logs to syslog
-
-Revision 1.391 2007/04/07 01:01:48 cheshire
-<rdar://problem/5095167> mDNSResponder periodically blocks in SSLRead
-
-Revision 1.390 2007/04/06 18:45:02 cheshire
-Fix SetupActiveInterfaces() -- accidentally changed SetupSocket parameter
-
-Revision 1.389 2007/04/05 21:39:49 cheshire
-Debugging messages to help diagnose <rdar://problem/5095167> mDNSResponder periodically blocks in SSLRead
-
-Revision 1.388 2007/04/05 21:09:52 cheshire
-Condense sprawling code
-
-Revision 1.387 2007/04/05 20:40:37 cheshire
-Remove unused mDNSPlatformTCPGetFlags()
-
-Revision 1.386 2007/04/05 19:50:56 cheshire
-Fixed memory leak: GetCertChain() was not releasing cert returned by SecIdentityCopyCertificate()
-
-Revision 1.385 2007/04/03 19:39:19 cheshire
-Fixed intel byte order bug in mDNSPlatformSetDNSServers()
-
-Revision 1.384 2007/03/31 01:10:53 cheshire
-Add debugging
-
-Revision 1.383 2007/03/31 00:13:48 cheshire
-Remove LogMsg
-
-Revision 1.382 2007/03/28 21:01:29 cheshire
-<rdar://problem/4743285> Remove inappropriate use of IsPrivateV4Addr()
-
-Revision 1.381 2007/03/28 15:56:37 cheshire
-<rdar://problem/5085774> Add listing of NAT port mapping and GetAddrInfo requests in SIGINFO output
-
-Revision 1.380 2007/03/26 22:54:46 cheshire
-Fix compile error
-
-Revision 1.379 2007/03/22 18:31:48 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.378 2007/03/22 00:49:20 cheshire
-<rdar://problem/4848295> Advertise model information via Bonjour
-
-Revision 1.377 2007/03/21 00:30:05 cheshire
-<rdar://problem/4789455> Multiple errors in DNameList-related code
-
-Revision 1.376 2007/03/20 17:07:15 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.375 2007/03/20 00:50:57 cheshire
-<rdar://problem/4530644> Remove logic to disable IPv6 discovery on interfaces which have a routable IPv4 address
-
-Revision 1.374 2007/03/06 23:29:50 cheshire
-<rdar://problem/4331696> Need to call IONotificationPortDestroy on shutdown
-
-Revision 1.373 2007/02/28 01:51:20 cheshire
-Added comment about reverse-order IP address
-
-Revision 1.372 2007/02/28 01:06:48 cheshire
-Use %#a format code instead of %d.%d.%d.%d
-
-Revision 1.371 2007/02/08 21:12:28 cheshire
-<rdar://problem/4386497> Stop reading /etc/mDNSResponder.conf on every sleep/wake
-
-Revision 1.370 2007/01/16 22:59:58 cheshire
-Error code ioErr is from wrong conceptual namespace; use errSSLClosedAbort instead
-
-Revision 1.369 2007/01/10 02:09:32 cheshire
-Better LogOperation record of keys read from System Keychain
-
-Revision 1.368 2007/01/10 01:25:31 cheshire
-Use symbol kDNSServiceCompPrivateDNS instead of fixed string "State:/Network/PrivateDNS"
-
-Revision 1.367 2007/01/10 01:22:01 cheshire
-Make sure c1, c2, c3 are initialized
-
-Revision 1.366 2007/01/09 22:37:20 cheshire
-Provide ten-second grace period for deleted keys, to give mDNSResponder
-time to delete host name before it gives up access to the required key.
-
-Revision 1.365 2007/01/09 21:09:20 cheshire
-Need locking in KeychainChanged()
-
-Revision 1.364 2007/01/09 20:17:04 cheshire
-mDNSPlatformGetDNSConfig() needs to initialize fields even when no "Setup:/Network/DynamicDNS" entity exists
-
-Revision 1.363 2007/01/09 02:41:18 cheshire
-uDNS_SetupDNSConfig() shouldn't be called from mDNSMacOSX.c (platform support layer);
-moved it to mDNS_Init() in mDNS.c (core code)
-
-Revision 1.362 2007/01/08 23:54:01 cheshire
-Made mDNSPlatformGetDNSConfig() more selective -- only reads prefs for non-null parameters
-
-Revision 1.361 2007/01/05 08:30:48 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.360 2007/01/04 00:12:24 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.359 2006/12/22 21:14:37 cheshire
-Added comment explaining why we allow both "ddns" and "sndd" as valid item types
-The Keychain APIs on Intel appear to store the four-character item type backwards (at least some of the time)
-
-Revision 1.358 2006/12/22 20:59:50 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.357 2006/12/21 00:09:45 cheshire
-Use mDNSPlatformMemZero instead of bzero
-
-Revision 1.356 2006/12/20 23:15:53 mkrochma
-Fix the private domain list code so that it actually works
-
-Revision 1.355 2006/12/20 23:04:36 mkrochma
-Fix crash when adding private domain list to Dynamic Store
-
-Revision 1.354 2006/12/19 22:43:55 cheshire
-Fix compiler warnings
-
-Revision 1.353 2006/12/14 22:08:29 cheshire
-Fixed memory leak: need to call SecKeychainItemFreeAttributesAndData()
-to release data allocated by SecKeychainItemCopyAttributesAndData()
-
-Revision 1.352 2006/12/14 02:33:26 cheshire
-<rdar://problem/4841422> uDNS: Wide-area registrations sometimes fail
-
-Revision 1.351 2006/11/28 21:37:51 mkrochma
-Tweak where the private DNS data is written
-
-Revision 1.350 2006/11/28 07:55:02 herscher
-<rdar://problem/4742743> dnsextd has a slow memory leak
-
-Revision 1.349 2006/11/28 07:45:58 herscher
-<rdar://problem/4787010> Daemon: Need to write list of private domain names to the DynamicStore
-
-Revision 1.348 2006/11/16 21:47:20 mkrochma
-<rdar://problem/4841422> uDNS: Wide-area registrations sometimes fail
-
-Revision 1.347 2006/11/10 00:54:16 cheshire
-<rdar://problem/4816598> Changing case of Computer Name doesn't work
-
-Revision 1.346 2006/10/31 02:34:58 cheshire
-<rdar://problem/4692130> Stop creating HINFO records
-
-Revision 1.345 2006/09/21 20:04:38 mkrochma
-Accidently changed function name while checking in previous fix
-
-Revision 1.344 2006/09/21 19:04:13 mkrochma
-<rdar://problem/4733803> uDNS: Update keychain format of DNS key to include prefix
-
-Revision 1.343 2006/09/15 21:20:16 cheshire
-Remove uDNS_info substructure from mDNS_struct
-
-Revision 1.342 2006/08/16 00:31:50 mkrochma
-<rdar://problem/4386944> Get rid of NotAnInteger references
-
-Revision 1.341 2006/08/14 23:24:40 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.340 2006/07/29 19:11:13 mkrochma
-Change GetUserSpecifiedDDNSConfig LogMsg to debugf
-
-Revision 1.339 2006/07/27 03:24:35 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-Further refinement: Declare KQueueEntry parameter "const"
-
-Revision 1.338 2006/07/27 02:59:25 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-Further refinements: CFRunLoop thread needs to explicitly wake the kqueue thread
-after releasing BigMutex, in case actions it took have resulted in new work for the
-kqueue thread (e.g. NetworkChanged events may result in the kqueue thread having to
-add new active interfaces to its list, and consequently schedule queries to be sent).
-
-Revision 1.337 2006/07/22 06:11:37 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-
-Revision 1.336 2006/07/15 02:01:32 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Fix broken "empty string" browsing
-
-Revision 1.335 2006/07/14 05:25:11 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Fixed crash in mDNSPlatformGetDNSConfig() reading BrowseDomains array
+ if (sock->flags & kTCPSocketFlags_UseTLS)
+ {
+#ifndef NO_SECURITYFRAMEWORK
+ size_t processed;
+ if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformWriteTCP called while handshake required"); return 0; }
+ if (sock->handshake == handshake_in_progress) return 0;
+ else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformWriteTCP called with unexpected SSLHandshake status: %d", sock->handshake);
+
+ mStatus err = SSLWrite(sock->tlsContext, msg, len, &processed);
-Revision 1.334 2006/07/05 23:42:00 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
+ if (!err) nsent = (int) processed;
+ else if (err == errSSLWouldBlock) nsent = 0;
+ else { LogMsg("ERROR: mDNSPlatformWriteTCP - SSLWrite returned %d", err); nsent = -1; }
+#else
+ nsent = -1;
+#endif /* NO_SECURITYFRAMEWORK */
+ }
+ else
+ {
+ nsent = send(sock->fd, msg, len, 0);
+ if (nsent < 0)
+ {
+ if (errno == EAGAIN) nsent = 0;
+ else { LogMsg("ERROR: mDNSPlatformWriteTCP - send %s", strerror(errno)); nsent = -1; }
+ }
+ }
-Revision 1.333 2006/06/29 05:33:30 cheshire
-<rdar://problem/4607043> mDNSResponder conditional compilation options
+ return nsent;
+ }
-Revision 1.332 2006/06/28 09:10:36 cheshire
-Extra debugging messages
+mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
+ {
+ return sock->fd;
+ }
-Revision 1.331 2006/06/21 22:29:42 cheshire
-Make _CFCopySystemVersionDictionary() call more defensive on systems that have no build information set
+// If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
+// If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
+mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa_family, mDNSIPPort *const outport)
+ {
+#ifndef NO_IPV6
+ int *s = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
+ KQueueEntry *k = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
+#else
+ int *s = &cp->sktv4;
+ KQueueEntry *k = &cp->kqsv4;
+#endif
+ const int on = 1;
+ const int twofivefive = 255;
+ mStatus err = mStatus_NoError;
+ char *errstr = mDNSNULL;
-Revision 1.330 2006/06/20 23:06:00 cheshire
-Fix some keychain API type mismatches (was mDNSu32 instead of UInt32)
+#ifdef NO_IPV6
+ if (sa_family != AF_INET) return -1;
+#endif
+
+ cp->closeFlag = mDNSNULL;
-Revision 1.329 2006/06/08 23:22:33 cheshire
-Comment changes
+ int skt = socket(sa_family, SOCK_DGRAM, IPPROTO_UDP);
+ if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); }
-Revision 1.328 2006/03/19 03:27:49 cheshire
-<rdar://problem/4118624> Suppress "interface flapping" logic for loopback
+ // ... with a shared UDP port, if it's for multicast receiving
+ if (mDNSSameIPPort(port, MulticastDNSPort) || mDNSSameIPPort(port, NATPMPAnnouncementPort)) err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
+ if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; }
-Revision 1.327 2006/03/19 02:00:09 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
+ if (sa_family == AF_INET)
+ {
+ // We want to receive destination addresses
+ err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
+ if (err < 0) { errstr = "setsockopt - IP_RECVDSTADDR"; goto fail; }
-Revision 1.326 2006/03/08 22:42:23 cheshire
-Fix spelling mistake: LocalReverseMapomain -> LocalReverseMapDomain
+ // We want to receive interface identifiers
+ err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
+ if (err < 0) { errstr = "setsockopt - IP_RECVIF"; goto fail; }
-Revision 1.325 2006/01/10 00:39:17 cheshire
-Add comments explaining how IPv6 link-local addresses sometimes have an embedded scope_id
+ // We want to receive packet TTL value so we can check it
+ err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
+ // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
-Revision 1.324 2006/01/09 19:28:59 cheshire
-<rdar://problem/4403128> Cap number of "sendto failed" messages we allow mDNSResponder to log
+ // Send unicast packets with TTL 255
+ err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive));
+ if (err < 0) { errstr = "setsockopt - IP_TTL"; goto fail; }
-Revision 1.323 2006/01/05 21:45:27 cheshire
-<rdar://problem/4400118> Fix uninitialized structure member in IPv6 code
+ // And multicast packets with TTL 255 too
+ err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
+ if (err < 0) { errstr = "setsockopt - IP_MULTICAST_TTL"; goto fail; }
-Revision 1.322 2006/01/05 21:41:50 cheshire
-<rdar://problem/4108164> Reword "mach_absolute_time went backwards" dialog
+ // And start listening for packets
+ struct sockaddr_in listening_sockaddr;
+ listening_sockaddr.sin_family = AF_INET;
+ listening_sockaddr.sin_port = port.NotAnInteger; // Pass in opaque ID without any byte swapping
+ listening_sockaddr.sin_addr.s_addr = mDNSSameIPPort(port, NATPMPAnnouncementPort) ? AllHosts_v4.NotAnInteger : 0;
+ err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
+ if (err) { errstr = "bind"; goto fail; }
+ if (outport) outport->NotAnInteger = listening_sockaddr.sin_port;
+ }
+#ifndef NO_IPV6
+ 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; }
-Revision 1.321 2006/01/05 21:35:06 cheshire
-Add (commented out) trigger value for testing "mach_absolute_time went backwards" notice
+ // We want to receive packet hop count value so we can check it
+ err = setsockopt(skt, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
+ if (err < 0) { errstr = "setsockopt - IPV6_HOPLIMIT"; goto fail; }
-*/
+ // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
+ // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
+ err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
+ if (err < 0) { errstr = "setsockopt - IPV6_V6ONLY"; goto fail; }
-// ***************************************************************************
-// mDNSMacOSX.c:
-// Supporting routines to run mDNS on a CFRunLoop platform
-// ***************************************************************************
+ // Send unicast packets with TTL 255
+ err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive));
+ if (err < 0) { errstr = "setsockopt - IPV6_UNICAST_HOPS"; goto fail; }
-// For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
-// including ones that mDNSResponder chooses not to use.
-#define LIST_ALL_INTERFACES 0
+ // And multicast packets with TTL 255 too
+ err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
+ if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_HOPS"; goto fail; }
-// For enabling AAAA records over IPv4. Setting this to 0 sends only
-// A records over IPv4 and AAAA over IPv6. Setting this to 1 sends both
-// AAAA and A records over both IPv4 and IPv6.
-#define AAAA_OVER_V4 1
+ // 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; }
-// In Mac OS X 10.4 and earlier, to reduce traffic, we would send and receive using IPv6 only on interfaces that had no routable
-// IPv4 address. Having a routable IPv4 address assigned is a reasonable indicator of being on a large configured network,
-// which means there's a good chance that most or all the other devices on that network should also have IPv4.
-// By doing this we lost the ability to talk to true IPv6-only devices on that link, but we cut the packet rate in half.
-// At that time, reducing the packet rate was more important than v6-only devices on a large configured network,
-// so were willing to make that sacrifice.
-// In Mac OS X 10.5, in 2007, two things have changed:
-// 1. IPv6-only devices are starting to become more common, so we can't ignore them.
-// 2. Other efficiency improvements in the code mean that crude hacks like this should no longer be necessary.
+ // And start listening for packets
+ struct sockaddr_in6 listening_sockaddr6;
+ mDNSPlatformMemZero(&listening_sockaddr6, sizeof(listening_sockaddr6));
+ listening_sockaddr6.sin6_len = sizeof(listening_sockaddr6);
+ listening_sockaddr6.sin6_family = AF_INET6;
+ listening_sockaddr6.sin6_port = port.NotAnInteger; // Pass in opaque ID without any byte swapping
+ listening_sockaddr6.sin6_flowinfo = 0;
+ listening_sockaddr6.sin6_addr = in6addr_any; // Want to receive multicasts AND unicasts on this socket
+ listening_sockaddr6.sin6_scope_id = 0;
+ err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
+ if (err) { errstr = "bind"; goto fail; }
+ if (outport) outport->NotAnInteger = listening_sockaddr6.sin6_port;
+ }
+#endif
-#define USE_V6_ONLY_WHEN_NO_ROUTABLE_V4 0
+ fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
+ fcntl(skt, F_SETFD, 1); // set close-on-exec
+ *s = skt;
+ k->KQcallback = myKQSocketCallBack;
+ k->KQcontext = cp;
+ k->KQtask = "UDP packet reception";
+#ifdef __LIB_DISPATCH__
+ k->readSource = mDNSNULL;
+ k->writeSource = mDNSNULL;
+ k->fdClosed = mDNSfalse;
+#endif
+ KQueueSet(*s, EV_ADD, EVFILT_READ, k);
-#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
-#include "DNSCommon.h"
-#include "uDNS.h"
-#include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
-#include "dns_sd.h" // For mDNSInterface_LocalOnly etc.
-#include "PlatformCommon.h"
+ return(err);
-#include <stdio.h>
-#include <stdarg.h> // For va_list support
-#include <stdlib.h> // For arc4random
-#include <net/if.h>
-#include <net/if_types.h> // For IFT_ETHER
-#include <net/if_dl.h>
-#include <net/bpf.h> // For BIOCSETIF etc.
-#include <sys/uio.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/event.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <time.h> // platform support for UTC time
-#include <arpa/inet.h> // for inet_aton
-#include <pthread.h>
-
-#include <netinet/in.h> // For IP_RECVTTL
-#ifndef IP_RECVTTL
-#define IP_RECVTTL 24 // bool; receive reception TTL w/dgram
-#endif
-
-#include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below
-#include <netinet/ip.h> // For IPTOS_LOWDELAY etc.
-#include <netinet6/in6_var.h> // For IN6_IFF_NOTREADY etc.
-#include <netinet6/nd6.h> // For ND6_INFINITE_LIFETIME etc.
-
-#if TARGET_OS_EMBEDDED
-#define NO_SECURITYFRAMEWORK 1
-#define NO_CFUSERNOTIFICATION 1
-#endif
-
-#ifndef NO_SECURITYFRAMEWORK
-#include <Security/SecureTransport.h>
-#include <Security/Security.h>
-#endif /* NO_SECURITYFRAMEWORK */
-
-#include <DebugServices.h>
-#include "dnsinfo.h"
-
-// Code contributed by Dave Heller:
-// Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will
-// work on Mac OS X 10.1, which does not have the getifaddrs call.
-#define RUN_ON_PUMA_WITHOUT_IFADDRS 0
-#if RUN_ON_PUMA_WITHOUT_IFADDRS
-#include "mDNSMacOSXPuma.c"
-#else
-#include <ifaddrs.h>
-#endif
-
-#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="
-
-// ***************************************************************************
-// Globals
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark - Globals
-#endif
-
-// By default we don't offer sleep proxy service
-// If OfferSleepProxyService is set non-zero (typically via command-line switch),
-// then we'll offer sleep proxy service on desktop Macs that are set to never sleep.
-// We currently do not offer sleep proxy service on laptops, or on machines that are set to go to sleep.
-mDNSexport int OfferSleepProxyService = 0;
-
-mDNSexport int OSXVers;
-mDNSexport int KQueueFD;
-
-#ifndef NO_SECURITYFRAMEWORK
-static CFArrayRef ServerCerts;
-#endif /* NO_SECURITYFRAMEWORK */
-
-static CFStringRef NetworkChangedKey_IPv4;
-static CFStringRef NetworkChangedKey_IPv6;
-static CFStringRef NetworkChangedKey_Hostnames;
-static CFStringRef NetworkChangedKey_Computername;
-static CFStringRef NetworkChangedKey_DNS;
-static CFStringRef NetworkChangedKey_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;
-
-#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
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Utility Functions
-#endif
-
-// We only attempt to send and receive multicast packets on interfaces that are
-// (a) flagged as multicast-capable
-// (b) *not* flagged as point-to-point (e.g. modem)
-// Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want
-// to run up the user's bill sending multicast traffic over a link where there's only a single device at the
-// other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
-#define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
-
-mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both strings are UTF-8 text
- {
- static int notifyCount = 0;
- if (notifyCount) return;
-
- // If we display our alert early in the boot process, then it vanishes once the desktop appears.
- // To avoid this, we don't try to display alerts in the first three minutes after boot.
- if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return;
-
- // Unless ForceAlerts is defined, we only show these bug report alerts on machines that have a 17.x.x.x address
- #if !ForceAlerts
- {
- // Determine if we're at Apple (17.*.*.*)
- extern mDNS mDNSStorage;
- NetworkInterfaceInfoOSX *i;
- for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
- if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && i->ifinfo.ip.ip.v4.b[0] == 17)
- break;
- if (!i) return; // If not at Apple, don't show the alert
- }
- #endif
-
- LogMsg("%s", title);
- LogMsg("%s", msg);
- // Display a notification to the user
- notifyCount++;
-
-#ifndef NO_CFUSERNOTIFICATION
- mDNSNotify(title, msg);
-#endif /* NO_CFUSERNOTIFICATION */
- }
-
-mDNSlocal struct ifaddrs *myGetIfAddrs(int refresh)
- {
- static struct ifaddrs *ifa = NULL;
-
- if (refresh && ifa)
- {
- freeifaddrs(ifa);
- ifa = NULL;
- }
-
- if (ifa == NULL) getifaddrs(&ifa);
-
- return ifa;
- }
-
-// To match *either* a v4 or v6 instance of this interface name, pass AF_UNSPEC for type
-mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const char *ifname, int type)
- {
- NetworkInterfaceInfoOSX *i;
- for (i = m->p->InterfaceList; i; i = i->next)
- if (i->Exists && !strcmp(i->ifinfo.ifname, ifname) &&
- ((type == AF_UNSPEC ) ||
- (type == AF_INET && i->ifinfo.ip.type == mDNSAddrType_IPv4) ||
- (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6))) return(i);
- return(NULL);
- }
-
-mDNSlocal int myIfIndexToName(u_short ifindex, char *name)
- {
- struct ifaddrs *ifa;
- for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
- if (ifa->ifa_addr->sa_family == AF_LINK)
- if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == ifindex)
- { strlcpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; }
- return -1;
- }
-
-mDNSexport NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(const mDNS *const m, mDNSInterfaceID ifindex)
-{
- mDNSu32 scope_id = (mDNSu32)(uintptr_t)ifindex;
- NetworkInterfaceInfoOSX *i;
-
- // Don't get tricked by inactive interfaces
- for (i = m->p->InterfaceList; i; i = i->next)
- if (i->Registered && i->scope_id == scope_id) return(i);
-
- return mDNSNULL;
-}
-
-mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex)
- {
- if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
- if (ifindex == kDNSServiceInterfaceIndexAny ) return(mDNSNULL);
-
- NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
- if (!ifi)
- {
- // Not found. Make sure our interface list is up to date, then try again.
- LogInfo("mDNSPlatformInterfaceIDfromInterfaceIndex: InterfaceID for interface index %d not found; Updating interface list", ifindex);
- mDNSMacOSXNetworkChanged(m);
- ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
- }
-
- if (!ifi) return(mDNSNULL);
-
- return(ifi->ifinfo.InterfaceID);
- }
-
-
-mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id)
- {
- NetworkInterfaceInfoOSX *i;
- if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
- if (id == mDNSInterface_Any ) return(0);
-
- mDNSu32 scope_id = (mDNSu32)(uintptr_t)id;
-
- // Don't use i->Registered here, because we DO want to find inactive interfaces, which have no Registered set
- for (i = m->p->InterfaceList; i; i = i->next)
- if (i->scope_id == scope_id) return(i->scope_id);
-
- // Not found. Make sure our interface list is up to date, then try again.
- LogInfo("Interface index for InterfaceID %p not found; Updating interface list", id);
- mDNSMacOSXNetworkChanged(m);
- for (i = m->p->InterfaceList; i; i = i->next)
- if (i->scope_id == scope_id) return(i->scope_id);
-
- return(0);
- }
-
-#if APPLE_OSX_mDNSResponder
-mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *result, const char *signature, const char *fmt, ...)
- {
- if (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[37];
- uuid_unparse(*uuid, uuidStr);
- asl_set (asl_msg, "com.apple.message.uuid", uuidStr);
- }
-
- static char domainBase[] = "com.apple.mDNSResponder.%s";
- mDNS_snprintf (buffer, sizeof(buffer), domainBase, subdomain);
- asl_set (asl_msg, "com.apple.message.domain", buffer);
-
- if (result) asl_set(asl_msg, "com.apple.message.result", result);
- if (signature) asl_set(asl_msg, "com.apple.message.signature", signature);
-
- va_list ptr;
- va_start(ptr,fmt);
- mDNS_vsnprintf(buffer, sizeof(buffer), fmt, ptr);
- va_end(ptr);
-
- int old_filter = asl_set_filter(NULL,ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
- asl_log(NULL, asl_msg, ASL_LEVEL_DEBUG, "%s", buffer);
- asl_set_filter(NULL, old_filter);
- asl_free(asl_msg);
- }
-#endif // APPLE_OSX_mDNSResponder
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - UDP & TCP send & receive
-#endif
-
-mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr)
- {
- mDNSBool result = mDNSfalse;
- SCNetworkConnectionFlags flags;
- SCNetworkReachabilityRef ReachRef = NULL;
-
- ReachRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, addr);
- if (!ReachRef) { LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithAddress"); goto end; }
- if (!SCNetworkReachabilityGetFlags(ReachRef, &flags)) { LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); goto end; }
- result = flags & kSCNetworkFlagsConnectionRequired;
-
- end:
- if (ReachRef) CFRelease(ReachRef);
- 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"
-// OR send via our primary v4 unicast socket
-// UPDATE: The UDPSocket *src parameter now allows the caller to specify the source socket
-mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
- mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstPort)
- {
- NetworkInterfaceInfoOSX *info = mDNSNULL;
- struct sockaddr_storage to;
- int s = -1, err;
- mStatus result = mStatus_NoError;
-
- if (InterfaceID)
- {
- info = IfindexToInterfaceInfoOSX(m, InterfaceID);
- if (info == NULL)
- {
- LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
- return mStatus_BadParamErr;
- }
- }
-
- char *ifa_name = InterfaceID ? info->ifinfo.ifname : "unicast";
-
- if (dst->type == mDNSAddrType_IPv4)
- {
- struct sockaddr_in *sin_to = (struct sockaddr_in*)&to;
- sin_to->sin_len = sizeof(*sin_to);
- sin_to->sin_family = AF_INET;
- sin_to->sin_port = dstPort.NotAnInteger;
- sin_to->sin_addr.s_addr = dst->ip.v4.NotAnInteger;
- s = (src ? src->ss : m->p->permanentsockets).sktv4;
-
- if (info) // Specify outgoing interface
- {
- if (!mDNSAddrIsDNSMulticast(dst))
- {
- #ifdef IP_BOUND_IF
- if (info->scope_id == 0)
- LogInfo("IP_BOUND_IF socket option not set -- info %p (%s) scope_id is zero", info, ifa_name);
- else
- setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
- #else
- {
- static int displayed = 0;
- if (displayed < 1000)
- {
- displayed++;
- LogInfo("IP_BOUND_IF socket option not defined -- cannot specify interface for unicast packets");
- }
- }
- #endif
- }
- else
- {
- err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
- if (err < 0 && !m->p->NetworkChanged)
- LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
- }
- }
- }
- else if (dst->type == mDNSAddrType_IPv6)
- {
- struct sockaddr_in6 *sin6_to = (struct sockaddr_in6*)&to;
- sin6_to->sin6_len = sizeof(*sin6_to);
- sin6_to->sin6_family = AF_INET6;
- sin6_to->sin6_port = dstPort.NotAnInteger;
- sin6_to->sin6_flowinfo = 0;
- sin6_to->sin6_addr = *(struct in6_addr*)&dst->ip.v6;
- sin6_to->sin6_scope_id = info ? info->scope_id : 0;
- s = (src ? src->ss : m->p->permanentsockets).sktv6;
- if (info && mDNSAddrIsDNSMulticast(dst)) // Specify outgoing interface
- {
- err = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &info->scope_id, sizeof(info->scope_id));
- if (err < 0) LogMsg("setsockopt - IPV6_MULTICAST_IF error %d errno %d (%s)", err, errno, strerror(errno));
- }
- }
- else
- {
- LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
-#if ForceAlerts
- *(long*)0 = 0;
-#endif
- return mStatus_BadParamErr;
- }
-
- if (s >= 0)
- verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
- InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s);
- else
- verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
- InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort));
-
- // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
- // If we don't have the corresponding type of socket available, then return mStatus_Invalid
- if (s < 0) return(mStatus_Invalid);
-
- err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len);
- if (err < 0)
- {
- static int MessageCount = 0;
- // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
- if (!mDNSAddressIsAllDNSLinkGroup(dst))
- if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
- // Don't report EHOSTUNREACH in the first three minutes after boot
- // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
- // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
- if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr);
- // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
- if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(mStatus_TransientErr);
- if (MessageCount < 1000)
- {
- MessageCount++;
- 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_BOUND_IF
- if (dst->type == mDNSAddrType_IPv4 && info && !mDNSAddrIsDNSMulticast(dst))
- {
- static const mDNSu32 ifindex = 0;
- setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
- }
-#endif
-
- return(result);
- }
-
-mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
- struct sockaddr *const from, size_t *const fromlen, mDNSAddr *dstaddr, char ifname[IF_NAMESIZE], mDNSu8 *ttl)
- {
- static unsigned int numLogMessages = 0;
- struct iovec databuffers = { (char *)buffer, max };
- struct msghdr msg;
- ssize_t n;
- struct cmsghdr *cmPtr;
- char ancillary[1024];
-
- *ttl = 255; // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
-
- // Set up the message
- msg.msg_name = (caddr_t)from;
- msg.msg_namelen = *fromlen;
- msg.msg_iov = &databuffers;
- msg.msg_iovlen = 1;
- msg.msg_control = (caddr_t)&ancillary;
- msg.msg_controllen = sizeof(ancillary);
- msg.msg_flags = 0;
-
- // Receive the data
- n = recvmsg(s, &msg, 0);
- if (n<0)
- {
- if (errno != EWOULDBLOCK && numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s, n, errno);
- return(-1);
- }
- if (msg.msg_controllen < (int)sizeof(struct cmsghdr))
- {
- if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned %d msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
- s, n, msg.msg_controllen, sizeof(struct cmsghdr));
- return(-1);
- }
- if (msg.msg_flags & MSG_CTRUNC)
- {
- if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s);
- return(-1);
- }
-
- *fromlen = msg.msg_namelen;
-
- // Parse each option out of the ancillary data.
- for (cmPtr = CMSG_FIRSTHDR(&msg); cmPtr; cmPtr = CMSG_NXTHDR(&msg, cmPtr))
- {
- // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
- if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVDSTADDR)
- {
- dstaddr->type = mDNSAddrType_IPv4;
- dstaddr->ip.v4 = *(mDNSv4Addr*)CMSG_DATA(cmPtr);
- //LogMsg("mDNSMacOSX.c: recvmsg IP_RECVDSTADDR %.4a", &dstaddr->ip.v4);
- }
- if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
- {
- struct sockaddr_dl *sdl = (struct sockaddr_dl *)CMSG_DATA(cmPtr);
- if (sdl->sdl_nlen < IF_NAMESIZE)
- {
- mDNSPlatformMemCopy(ifname, sdl->sdl_data, sdl->sdl_nlen);
- ifname[sdl->sdl_nlen] = 0;
- // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
- }
- }
- if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVTTL)
- *ttl = *(u_char*)CMSG_DATA(cmPtr);
- if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_PKTINFO)
- {
- struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmPtr);
- dstaddr->type = mDNSAddrType_IPv6;
- dstaddr->ip.v6 = *(mDNSv6Addr*)&ip6_info->ipi6_addr;
- myIfIndexToName(ip6_info->ipi6_ifindex, ifname);
- }
- if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_HOPLIMIT)
- *ttl = *(int*)CMSG_DATA(cmPtr);
- }
-
- return(n);
- }
-
-mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
- {
- KQSocketSet *const ss = (KQSocketSet *)context;
- mDNS *const m = ss->m;
- int err = 0, count = 0, closed = 0;
-
- if (filter != EVFILT_READ)
- LogMsg("myKQSocketCallBack: Why is filter %d not EVFILT_READ (%d)?", filter, EVFILT_READ);
-
- if (s1 != ss->sktv4 && s1 != ss->sktv6)
- {
- LogMsg("myKQSocketCallBack: native socket %d", s1);
- LogMsg("myKQSocketCallBack: sktv4 %d", ss->sktv4);
- LogMsg("myKQSocketCallBack: sktv6 %d", ss->sktv6);
- }
-
- while (!closed)
- {
- mDNSAddr senderAddr, destAddr;
- mDNSIPPort senderPort;
- struct sockaddr_storage from;
- size_t fromlen = sizeof(from);
- char packetifname[IF_NAMESIZE] = "";
- mDNSu8 ttl;
- err = myrecvfrom(s1, &m->imsg, sizeof(m->imsg), (struct sockaddr *)&from, &fromlen, &destAddr, packetifname, &ttl);
- if (err < 0) break;
-
- count++;
- if (from.ss_family == AF_INET)
- {
- struct sockaddr_in *s = (struct sockaddr_in*)&from;
- senderAddr.type = mDNSAddrType_IPv4;
- senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
- senderPort.NotAnInteger = s->sin_port;
- //LogInfo("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
- }
- else if (from.ss_family == AF_INET6)
- {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
- senderAddr.type = mDNSAddrType_IPv6;
- senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
- senderPort.NotAnInteger = sin6->sin6_port;
- //LogInfo("myKQSocketCallBack received IPv6 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
- }
- else
- {
- LogMsg("myKQSocketCallBack from is unknown address family %d", from.ss_family);
- return;
- }
-
- // Note: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
- mDNSInterfaceID InterfaceID = mDNSNULL;
- //NetworkInterfaceInfo *intf = m->HostInterfaces;
- //while (intf && strcmp(intf->ifname, packetifname)) intf = intf->next;
-
- NetworkInterfaceInfoOSX *intf = m->p->InterfaceList;
- while (intf && strcmp(intf->ifinfo.ifname, packetifname)) intf = intf->next;
-
- // When going to sleep we deregister all our interfaces, but if the machine
- // takes a few seconds to sleep we may continue to receive multicasts
- // during that time, which would confuse mDNSCoreReceive, because as far
- // as it's concerned, we should have no active interfaces any more.
- // Hence we ignore multicasts for which we can find no matching InterfaceID.
- if (intf) InterfaceID = intf->ifinfo.InterfaceID;
- else if (mDNSAddrIsDNSMulticast(&destAddr)) continue;
-
-// LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s",
-// &senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifinfo.ifname);
-
- // mDNSCoreReceive may close the socket we're reading from. We must break out of our
- // loop when that happens, or we may try to read from an invalid FD. We do this by
- // setting the closeFlag pointer in the socketset, so CloseSocketSet can inform us
- // if it closes the socketset.
- ss->closeFlag = &closed;
-
- mDNSCoreReceive(m, &m->imsg, (unsigned char*)&m->imsg + err, &senderAddr, senderPort, &destAddr, ss->port, InterfaceID);
-
- // if we didn't close, we can safely dereference the socketset, and should to
- // reset the closeFlag, since it points to something on the stack
- if (!closed) ss->closeFlag = mDNSNULL;
- }
-
- if (err < 0 && (errno != EWOULDBLOCK || count == 0))
- {
- // Something is busted here.
- // kqueue says there is a packet, but myrecvfrom says there is not.
- // Try calling select() to get another opinion.
- // Find out about other socket parameter that can help understand why select() says the socket is ready for read
- // All of this is racy, as data may have arrived after the call to select()
- static unsigned int numLogMessages = 0;
- int save_errno = errno;
- int so_error = -1;
- int so_nread = -1;
- int fionread = -1;
- socklen_t solen = sizeof(int);
- fd_set readfds;
- struct timeval timeout;
- int selectresult;
- FD_ZERO(&readfds);
- FD_SET(s1, &readfds);
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- selectresult = select(s1+1, &readfds, NULL, NULL, &timeout);
- if (getsockopt(s1, SOL_SOCKET, SO_ERROR, &so_error, &solen) == -1)
- LogMsg("myKQSocketCallBack getsockopt(SO_ERROR) error %d", errno);
- if (getsockopt(s1, SOL_SOCKET, SO_NREAD, &so_nread, &solen) == -1)
- LogMsg("myKQSocketCallBack getsockopt(SO_NREAD) error %d", errno);
- if (ioctl(s1, FIONREAD, &fionread) == -1)
- LogMsg("myKQSocketCallBack ioctl(FIONREAD) error %d", errno);
- if (numLogMessages++ < 100)
- LogMsg("myKQSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
- s1, err, save_errno, strerror(save_errno), selectresult, FD_ISSET(s1, &readfds) ? "" : "*NO* ", so_error, so_nread, fionread, count);
- if (numLogMessages > 5)
- NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)",
- "Congratulations, you've reproduced an elusive bug.\r"
- "Please contact the current assignee of <rdar://problem/3375328>.\r"
- "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
- "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
-
- sleep(1); // After logging this error, rate limit so we don't flood syslog
- }
- }
-
-// 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
- TCPConnectionCallback callback;
- int fd;
- KQueueEntry kqEntry;
-#ifndef NO_SECURITYFRAMEWORK
- SSLContextRef tlsContext;
- pthread_t handshake_thread;
-#endif /* NO_SECURITYFRAMEWORK */
- void *context;
- mDNSBool setup;
- 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)
- {
- int ret = send(((TCPSocket *)connection)->fd, data, *dataLength, 0);
- if (ret >= 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
- if (ret >= 0) { *dataLength = ret; return(noErr); }
- *dataLength = 0;
- if (errno == EAGAIN ) return(errSSLWouldBlock);
- if (errno == ENOENT ) return(errSSLClosedGraceful);
- if (errno == EPIPE || errno == ECONNRESET) return(errSSLClosedAbort);
- LogMsg("ERROR: tlsWriteSock: %d error %d (%s)\n", ((TCPSocket *)connection)->fd, errno, strerror(errno));
- return(errSSLClosedAbort);
- }
-
-mDNSlocal OSStatus tlsReadSock(SSLConnectionRef connection, void *data, size_t *dataLength)
- {
- int ret = recv(((TCPSocket *)connection)->fd, data, *dataLength, 0);
- if (ret > 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
- if (ret > 0) { *dataLength = ret; return(noErr); }
- *dataLength = 0;
- if (ret == 0 || errno == ENOENT ) return(errSSLClosedGraceful);
- if ( errno == EAGAIN ) return(errSSLWouldBlock);
- if ( errno == ECONNRESET) return(errSSLClosedAbort);
- LogMsg("ERROR: tlsSockRead: error %d (%s)\n", errno, strerror(errno));
- return(errSSLClosedAbort);
- }
-
-mDNSlocal OSStatus tlsSetupSock(TCPSocket *sock, mDNSBool server)
- {
- mStatus err = SSLNewContext(server, &sock->tlsContext);
- if (err) { LogMsg("ERROR: tlsSetupSock: SSLNewContext failed with error code: %d", err); return(err); }
-
- err = SSLSetIOFuncs(sock->tlsContext, tlsReadSock, tlsWriteSock);
- if (err) { LogMsg("ERROR: tlsSetupSock: SSLSetIOFuncs failed with error code: %d", err); return(err); }
+ fail:
+ // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero
+ if (strcmp(errstr, "bind") || mDNSSameIPPort(port, MulticastDNSPort) || mDNSIPPortIsZero(port))
+ LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr, skt, mDNSVal16(port), err, errno, strerror(errno));
- err = SSLSetConnection(sock->tlsContext, (SSLConnectionRef) sock);
- if (err) { LogMsg("ERROR: tlsSetupSock: SSLSetConnection failed with error code: %d", err); return(err); }
+ // 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.");
+ }
+ mDNSPlatformCloseFD(k, skt);
return(err);
}
-mDNSlocal void *doSSLHandshake(void *ctx)
+mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
{
- // 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);
- debugf("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
+ mStatus err;
+ mDNSIPPort port = requestedport;
+ mDNSBool randomizePort = mDNSIPPortIsZero(requestedport);
+ int i = 10000; // Try at most 10000 times to get a unique random port
+ UDPSocket *p = mallocL("UDPSocket", sizeof(UDPSocket));
+ if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); }
+ mDNSPlatformMemZero(p, sizeof(UDPSocket));
+ p->ss.port = zeroIPPort;
+ p->ss.m = m;
+ p->ss.sktv4 = -1;
+#ifndef NO_IPV6
+ p->ss.sktv6 = -1;
+#endif
- if (sock->handshake == handshake_to_be_closed)
- {
- LogInfo("SSLHandshake completed after close");
- mDNSPlatformTCPCloseConnection(sock);
- }
- else
+ do
{
- 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
+ // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here
+ if (randomizePort) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
+ err = SetupSocket(&p->ss, port, AF_INET, &p->ss.port);
+#ifndef NO_IPV6
+ if (!err)
{
- if (err)
- {
- LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
- SSLDisposeContext(sock->tlsContext);
- sock->tlsContext = NULL;
- }
-
- sock->err = err ? mStatus_ConnFailed : 0;
- sock->handshake = handshake_completed;
-
- debugf("doSSLHandshake: %p calling doTcpSocketCallback", sock);
- doTcpSocketCallback(sock);
+ err = SetupSocket(&p->ss, port, AF_INET6, &p->ss.port);
+ if (err) { mDNSPlatformCloseFD(&p->ss.kqsv4, p->ss.sktv4); p->ss.sktv4 = -1; }
}
- }
-
- debugf("SSLHandshake %p: dropping lock", sock);
- KQueueUnlock(m, "doSSLHandshake");
- return NULL;
- }
+#endif
+ i--;
+ } while (err == EADDRINUSE && randomizePort && i);
-mDNSlocal mStatus spawnSSLHandshake(TCPSocket* sock)
- {
- debugf("spawnSSLHandshake %p: entry", sock);
- if (sock->handshake != handshake_required) LogMsg("spawnSSLHandshake: handshake status not required: %d", sock->handshake);
- sock->handshake = handshake_in_progress;
- KQueueSet(sock->fd, EV_DELETE, EVFILT_READ, &sock->kqEntry);
- 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);
+ // In customer builds we don't want to log failures with port 5351, because this is a known issue
+ // of failing to bind to this port when Internet Sharing has already bound to it
+ // We also don't want to log about port 5350, due to a known bug when some other
+ // process is bound to it.
+ if (mDNSSameIPPort(requestedport, NATPMPPort) || mDNSSameIPPort(requestedport, NATPMPAnnouncementPort))
+ LogInfo("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
+ else LogMsg("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
+ freeL("UDPSocket", p);
+ return(mDNSNULL);
}
- debugf("spawnSSLHandshake %p: done", sock);
- return err;
+ return(p);
}
-mDNSlocal mDNSBool IsTunnelModeDomain(const domainname *d)
+mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
{
- static const domainname *mmc = (const domainname*) "\x7" "members" "\x3" "mac" "\x3" "com";
- const domainname *d1 = mDNSNULL; // TLD
- const domainname *d2 = mDNSNULL; // SLD
- const domainname *d3 = mDNSNULL;
- while (d->c[0]) { d3 = d2; d2 = d1; d1 = d; d = (const domainname*)(d->c + 1 + d->c[0]); }
- return(d3 && SameDomainName(d3, mmc));
+ CloseSocketSet(&sock->ss);
+ freeL("UDPSocket", sock);
}
-#endif /* NO_SECURITYFRAMEWORK */
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - BPF Raw packet sending/receiving
+#endif
-mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context)
- {
- TCPSocket *sock = context;
- sock->err = mStatus_NoError;
+#if APPLE_OSX_mDNSResponder
- //if (filter == EVFILT_READ ) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_READ", filter);
- //if (filter == EVFILT_WRITE) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_WRITE", filter);
- // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it here with EV_DELETE
- if (filter == EVFILT_WRITE) KQueueSet(sock->fd, EV_DELETE, EVFILT_WRITE, &sock->kqEntry);
+mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
+ {
+ if (!InterfaceID) { LogMsg("mDNSPlatformSendRawPacket: No InterfaceID specified"); return; }
+ NetworkInterfaceInfoOSX *info;
- if (sock->flags & kTCPSocketFlags_UseTLS)
+ extern mDNS mDNSStorage;
+ info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
+ if (info == NULL)
{
-#ifndef NO_SECURITYFRAMEWORK
- if (!sock->setup) { sock->setup = mDNStrue; tlsSetupSock(sock, mDNSfalse); }
-
- 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)
- {
- if (!sock->err) sock->err = mStatus_UnknownErr;
- LogMsg("tcpKQSocketCallback called with unexpected SSLHandshake status: %d", sock->handshake);
- }
-#else
- sock->err = mStatus_UnsupportedErr;
-#endif /* NO_SECURITYFRAMEWORK */
+ LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
+ return;
+ }
+ if (info->BPF_fd < 0)
+ LogMsg("mDNSPlatformSendRawPacket: %s BPF_fd %d not ready", info->ifinfo.ifname, info->BPF_fd);
+ else
+ {
+ //LogMsg("mDNSPlatformSendRawPacket %d bytes on %s", end - (mDNSu8 *)msg, info->ifinfo.ifname);
+ if (write(info->BPF_fd, msg, end - (mDNSu8 *)msg) < 0)
+ LogMsg("mDNSPlatformSendRawPacket: BPF write(%d) failed %d (%s)", info->BPF_fd, errno, strerror(errno));
}
-
- doTcpSocketCallback(sock);
}
-mDNSexport int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *const entryRef)
+mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
{
- struct kevent new_event;
- EV_SET(&new_event, fd, filter, flags, 0, 0, (void*)entryRef);
- return (kevent(KQueueFD, &new_event, 1, NULL, 0, NULL) < 0) ? errno : 0;
+ if (!InterfaceID) { LogMsg("mDNSPlatformSetLocalAddressCacheEntry: No InterfaceID specified"); return; }
+ NetworkInterfaceInfoOSX *info;
+ info = IfindexToInterfaceInfoOSX(m, InterfaceID);
+ if (info == NULL) { LogMsg("mDNSPlatformSetLocalAddressCacheEntry: Invalid interface index %p", InterfaceID); return; }
+ // Manually inject an entry into our local ARP cache.
+ // (We can't do this by sending an ARP broadcast, because the kernel only pays attention to incoming ARP packets, not outgoing.)
+ if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, tpa))
+ LogSPS("Don't need address cache entry for %s %#a %.6a", info->ifinfo.ifname, tpa, tha);
+ else
+ {
+ int result = mDNSSetLocalAddressCacheEntry(info->scope_id, tpa->type, tpa->ip.v6.b, tha->b);
+ if (result) LogMsg("Set local address cache entry for %s %#a %.6a failed: %d", info->ifinfo.ifname, tpa, tha, result);
+ else LogSPS("Set local address cache entry for %s %#a %.6a", info->ifinfo.ifname, tpa, tha);
+ }
}
-mDNSexport void KQueueLock(mDNS *const m)
+mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i)
{
- pthread_mutex_lock(&m->p->BigMutex);
- m->p->BigMutexStartTime = mDNSPlatformRawTime();
+ LogSPS("%s closing BPF fd %d", i->ifinfo.ifname, i->BPF_fd);
+#ifdef __LIB_DISPATCH__
+ // close will happen in the cancel handler
+ dispatch_source_cancel(i->BPF_source);
+#else
+
+ // Note: MUST NOT close() the underlying native BSD sockets.
+ // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately, because
+ // it first has to unhook the sockets from its select() call on its other thread, before it can safely close them.
+ CFRunLoopRemoveSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
+ CFRelease(i->BPF_rls);
+ CFSocketInvalidate(i->BPF_cfs);
+ CFRelease(i->BPF_cfs);
+#endif
+ i->BPF_fd = -1;
+ if (i->BPF_mcfd >= 0) { close(i->BPF_mcfd); i->BPF_mcfd = -1; }
}
-mDNSexport void KQueueUnlock(mDNS *const m, const char const *task)
+mDNSlocal void bpf_callback_common(NetworkInterfaceInfoOSX *info)
{
- mDNSs32 end = mDNSPlatformRawTime();
- (void)task;
- if (end - m->p->BigMutexStartTime >= WatchDogReportingThreshold)
- LogInfo("WARNING: %s took %dms to complete", task, end - m->p->BigMutexStartTime);
-
- pthread_mutex_unlock(&m->p->BigMutex);
+ KQueueLock(info->m);
- 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));
- }
+ // 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;
-mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port)
- {
- (void) m;
+ 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);
- TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPSocket", sizeof(TCPSocket));
- if (!sock) { LogMsg("mDNSPlatformTCPSocket: memory allocation failure"); return(mDNSNULL); }
+ 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;
+ }
- mDNSPlatformMemZero(sock, sizeof(TCPSocket));
- sock->callback = mDNSNULL;
- sock->fd = socket(AF_INET, SOCK_STREAM, 0);
- sock->kqEntry.KQcallback= tcpKQSocketCallback;
- sock->kqEntry.KQcontext = sock;
- sock->kqEntry.KQtask = "mDNSPlatformTCPSocket";
- sock->flags = flags;
- sock->context = mDNSNULL;
- sock->setup = mDNSfalse;
- sock->connected = mDNSfalse;
- sock->handshake = handshake_required;
- sock->m = m;
- sock->err = mStatus_NoError;
-
- if (sock->fd == -1)
+ while (ptr < end)
{
- LogMsg("mDNSPlatformTCPSocket: socket error %d errno %d (%s)", sock->fd, errno, strerror(errno));
- freeL("TCPSocket/mDNSPlatformTCPSocket", sock);
- return(mDNSNULL);
+ const struct bpf_hdr *const bh = (const struct bpf_hdr *)ptr;
+ debugf("%3d: bpf_callback ptr %p bh_hdrlen %d data %p bh_caplen %4d bh_datalen %4d next %p remaining %4d",
+ info->BPF_fd, ptr, bh->bh_hdrlen, ptr + bh->bh_hdrlen, bh->bh_caplen, bh->bh_datalen,
+ ptr + BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen), end - (ptr + BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen)));
+ // Note that BPF guarantees that the NETWORK LAYER header will be word aligned, not the link-layer header.
+ // Given that An Ethernet header is 14 bytes, this means that if the network layer header (e.g. IP header,
+ // ARP message, etc.) is 4-byte aligned, then necessarily the Ethernet header will be NOT be 4-byte aligned.
+ mDNSCoreReceiveRawPacket(info->m, ptr + bh->bh_hdrlen, ptr + bh->bh_hdrlen + bh->bh_caplen, info->ifinfo.InterfaceID);
+ ptr += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen);
}
+exit:
+ KQueueUnlock(info->m, "bpf_callback");
+ }
+#ifdef __LIB_DISPATCH__
+mDNSlocal void bpf_callback_dispatch(NetworkInterfaceInfoOSX *const info)
+ {
+ bpf_callback_common(info);
+ }
+#else
+mDNSlocal void bpf_callback(const CFSocketRef cfs, const CFSocketCallBackType CallBackType, const CFDataRef address, const void *const data, void *const context)
+ {
+ (void)cfs;
+ (void)CallBackType;
+ (void)address;
+ (void)data;
+ bpf_callback_common((NetworkInterfaceInfoOSX *)context);
+ }
+#endif
- // Bind it
- struct sockaddr_in addr;
- mDNSPlatformMemZero(&addr, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = port->NotAnInteger;
- if (bind(sock->fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
- { LogMsg("ERROR: bind %s", strerror(errno)); goto error; }
+#define BPF_SetOffset(from, cond, to) (from)->cond = (to) - 1 - (from)
- // Receive interface identifiers
- const int on = 1; // "on" for setsockopt
- if (setsockopt(sock->fd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0)
- { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); goto error; }
+mDNSlocal int CountProxyTargets(mDNS *const m, NetworkInterfaceInfoOSX *x, int *p4, int *p6)
+ {
+ int numv4 = 0, numv6 = 0;
+ AuthRecord *rr;
- 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; }
+ for (rr = m->ResourceRecords; rr; rr=rr->next)
+ if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
+ {
+ if (p4) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.4a", x->BPF_fd, x->ifinfo.ifname, numv4, &rr->AddressProxy.ip.v4);
+ numv4++;
+ }
- port->NotAnInteger = addr.sin_port;
- return sock;
+ for (rr = m->ResourceRecords; rr; rr=rr->next)
+ if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
+ {
+ if (p6) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.16a", x->BPF_fd, x->ifinfo.ifname, numv6, &rr->AddressProxy.ip.v6);
+ numv6++;
+ }
-error:
- close(sock->fd);
- freeL("TCPSocket/mDNSPlatformTCPSocket", sock);
- return(mDNSNULL);
+ if (p4) *p4 = numv4;
+ if (p6) *p6 = numv6;
+ return(numv4 + numv6);
}
-mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID,
- TCPConnectionCallback callback, void *context)
+mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
{
- struct sockaddr_in saddr;
- mStatus err = mStatus_NoError;
+ NetworkInterfaceInfoOSX *x;
- sock->callback = callback;
- sock->context = context;
- sock->setup = mDNSfalse;
- sock->connected = mDNSfalse;
- sock->handshake = handshake_required;
- sock->err = mStatus_NoError;
+ // Note: We can't use IfIndexToInterfaceInfoOSX because that looks for Registered also.
+ for (x = m->p->InterfaceList; x; x = x->next) if (x->ifinfo.InterfaceID == InterfaceID) break;
- (void) InterfaceID; //!!!KRS use this if non-zero!!!
+ if (!x) { LogMsg("mDNSPlatformUpdateProxyList: ERROR InterfaceID %p not found", InterfaceID); return; }
+
+ #define MAX_BPF_ADDRS 250
+ int numv4 = 0, numv6 = 0;
- if (dst->type != mDNSAddrType_IPv4)
+ if (CountProxyTargets(m, x, &numv4, &numv6) > MAX_BPF_ADDRS)
{
- LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: opperation not supported");
- return mStatus_UnknownErr;
+ 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;
}
- mDNSPlatformMemZero(&saddr, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_port = dstport.NotAnInteger;
- saddr.sin_len = sizeof(saddr);
- saddr.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
-
- sock->kqEntry.KQcallback = tcpKQSocketCallback;
- sock->kqEntry.KQcontext = sock;
- sock->kqEntry.KQtask = "Outgoing TCP";
+ LogSPS("mDNSPlatformUpdateProxyList: fd %d %-7s MAC %.6a %d v4 %d v6", x->BPF_fd, x->ifinfo.ifname, &x->ifinfo.MAC, numv4, numv6);
- // Watch for connect complete (write is ready)
- // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it in tcpKQSocketCallback using EV_DELETE
- if (KQueueSet(sock->fd, EV_ADD /* | EV_ONESHOT */, EVFILT_WRITE, &sock->kqEntry))
+ // 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] =
{
- LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
- close(sock->fd);
- return errno;
- }
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), // 0 Read Ethertype (bytes 12,13)
- // Watch for incoming data
- if (KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry))
- {
- LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
- close(sock->fd); // Closing the descriptor removes all filters from the kqueue
- return errno;
- }
+ 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
- if (fcntl(sock->fd, F_SETFL, fcntl(sock->fd, F_GETFL, 0) | O_NONBLOCK) < 0) // set non-blocking
- {
- LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno));
- return mStatus_UnknownErr;
- }
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0800, 4, 0), // 3 If Ethertype == IPv4 goto 8 (IPv4 address list check) else next
- // initiate connection wth peer
- if (connect(sock->fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
- {
- if (errno == EINPROGRESS) return mStatus_ConnPending;
- if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
- LogInfo("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock->fd, errno, strerror(errno));
- else
- LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock->fd, errno, strerror(errno));
- close(sock->fd);
- return mStatus_ConnFailed;
- }
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x86DD, 0, 9), // 4 If Ethertype == IPv6 goto next, else exit
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), // 5 Read Protocol and Hop Limit (bytes 20,21)
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x3AFF, 0, 9), // 6 If (Prot,TTL) == (3A,FF) goto next, else IPv6 address list check
+ BPF_STMT(BPF_RET + BPF_K, 86), // 7 Return 86-byte ND
- LogMsg("NOTE: mDNSPlatformTCPConnect completed synchronously");
- // kQueue should notify us, but this LogMsg is to help track down if it doesn't
- return err;
- }
+ // 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)
+ };
-// Why doesn't mDNSPlatformTCPAccept actually call accept() ?
-mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int fd)
- {
- mStatus err = mStatus_NoError;
+ 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;
- TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPAccept", sizeof(TCPSocket));
- if (!sock) return(mDNSNULL);
+ static const struct bpf_insn rf = BPF_STMT(BPF_RET + BPF_K, 0); // No match: Return nothing
- mDNSPlatformMemZero(sock, sizeof(*sock));
- sock->fd = fd;
- sock->flags = flags;
+ static const struct bpf_insn g6 = BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 50); // Read IPv6 Dst LSW (bytes 50,51,52,53)
- if (flags & kTCPSocketFlags_UseTLS)
- {
-#ifndef NO_SECURITYFRAMEWORK
- if (!ServerCerts) { LogMsg("ERROR: mDNSPlatformTCPAccept: unable to find TLS certificates"); err = mStatus_UnknownErr; goto exit; }
+ static const struct bpf_insn r4a = BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14); // Get IP Header length (normally 20)
+ static const struct bpf_insn r4b = BPF_STMT(BPF_LD + BPF_IMM, 54); // A = 54 (14-byte Ethernet plus 20-byte TCP + 20 bytes spare)
+ static const struct bpf_insn r4c = BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0); // A += IP Header length
+ static const struct bpf_insn r4d = BPF_STMT(BPF_RET + BPF_A, 0); // Success: Return Ethernet + IP + TCP + 20 bytes spare (normally 74)
- err = tlsSetupSock(sock, mDNStrue);
- if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: tlsSetupSock failed with error code: %d", err); goto exit; }
+ static const struct bpf_insn r6a = BPF_STMT(BPF_RET + BPF_K, 94); // Success: Return Eth + IPv6 + TCP + 20 bytes spare
- err = SSLSetCertificate(sock->tlsContext, ServerCerts);
- if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: SSLSetCertificate failed with error code: %d", err); goto exit; }
-#else
- err = mStatus_UnsupportedErr;
-#endif /* NO_SECURITYFRAMEWORK */
- }
-#ifndef NO_SECURITYFRAMEWORK
-exit:
-#endif
+ 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
- if (err) { freeL("TCPSocket/mDNSPlatformTCPAccept", sock); return(mDNSNULL); }
- return(sock);
- }
+ // 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.
-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;
+ // IPSEC capture size notes:
+ // 8 bytes UDP header
+ // 4 bytes Non-ESP Marker
+ // 28 bytes IKE Header
+ // --
+ // 40 Total. Capturing TCP Header + 20 gets us enough bytes to receive the IKE Header in a UDP-encapsulated IKE packet.
- SSLClose(sock->tlsContext);
- SSLDisposeContext(sock->tlsContext);
- sock->tlsContext = NULL;
+ 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++;
}
-#endif /* NO_SECURITYFRAMEWORK */
- if (sock->fd != -1)
+ *pc++ = rf;
+
+ if (pc != chk6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != chk6 %p", pc, chk6);
+ *pc++ = g6; // chk6 points here
+
+ // First cancel any previous ND group memberships we had, then create a fresh socket
+ if (x->BPF_mcfd >= 0) close(x->BPF_mcfd);
+ x->BPF_mcfd = socket(AF_INET6, SOCK_DGRAM, 0);
+
+ for (rr = m->ResourceRecords; rr; rr=rr->next)
+ if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
{
- shutdown(sock->fd, 2);
- close(sock->fd);
- sock->fd = -1;
+ const mDNSv6Addr *const a = &rr->AddressProxy.ip.v6;
+ pc->code = BPF_JMP + BPF_JEQ + BPF_K;
+ BPF_SetOffset(pc, jt, ret6);
+ pc->jf = 0;
+ pc->k = (bpf_u_int32)a->b[0x0C] << 24 | (bpf_u_int32)a->b[0x0D] << 16 | (bpf_u_int32)a->b[0x0E] << 8 | (bpf_u_int32)a->b[0x0F];
+ pc++;
+
+ struct ipv6_mreq i6mr;
+ i6mr.ipv6mr_interface = x->scope_id;
+ i6mr.ipv6mr_multiaddr = *(const struct in6_addr*)&NDP_prefix;
+ i6mr.ipv6mr_multiaddr.s6_addr[0xD] = a->b[0xD];
+ i6mr.ipv6mr_multiaddr.s6_addr[0xE] = a->b[0xE];
+ i6mr.ipv6mr_multiaddr.s6_addr[0xF] = a->b[0xF];
+
+ // Do precautionary IPV6_LEAVE_GROUP first, necessary to clear stale kernel state
+ mStatus err = setsockopt(x->BPF_mcfd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &i6mr, sizeof(i6mr));
+ if (err < 0 && (errno != EADDRNOTAVAIL))
+ LogMsg("mDNSPlatformUpdateProxyList: IPV6_LEAVE_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+
+ err = setsockopt(x->BPF_mcfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
+ if (err < 0 && (errno != EADDRINUSE)) // Joining same group twice can give "Address already in use" error -- no need to report that
+ LogMsg("mDNSPlatformUpdateProxyList: IPV6_JOIN_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+
+ LogSPS("Joined IPv6 ND multicast group %.16a for %.16a", &i6mr.ipv6mr_multiaddr, a);
}
- freeL("TCPSocket/mDNSPlatformTCPCloseConnection", sock);
- }
- }
+ if (pc != fail) LogMsg("mDNSPlatformUpdateProxyList: pc %p != fail %p", pc, fail);
+ *pc++ = rf; // fail points here
-mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
- {
- long nread = 0;
- *closed = mDNSfalse;
+ if (pc != ret4) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret4 %p", pc, ret4);
+ *pc++ = r4a; // ret4 points here
+ *pc++ = r4b;
+ *pc++ = r4c;
+ *pc++ = r4d;
- if (sock->flags & kTCPSocketFlags_UseTLS)
- {
-#ifndef NO_SECURITYFRAMEWORK
- if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformReadTCP called while handshake required"); return 0; }
- else if (sock->handshake == handshake_in_progress) return 0;
- else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformReadTCP called with unexpected SSLHandshake status: %d", sock->handshake);
+ if (pc != ret6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret6 %p", pc, ret6);
+ *pc++ = r6a; // ret6 points here
- //LogMsg("Starting SSLRead %d %X", sock->fd, fcntl(sock->fd, F_GETFL, 0));
- mStatus err = SSLRead(sock->tlsContext, buf, buflen, (size_t*)&nread);
- //LogMsg("SSLRead returned %d (%d) nread %d buflen %d", err, errSSLWouldBlock, nread, buflen);
- if (err == errSSLClosedGraceful) { nread = 0; *closed = mDNStrue; }
- else if (err && err != errSSLWouldBlock)
- { LogMsg("ERROR: mDNSPlatformReadTCP - SSLRead: %d", err); nread = -1; *closed = mDNStrue; }
-#else
- nread = -1;
- *closed = mDNStrue;
-#endif /* NO_SECURITYFRAMEWORK */
+ struct bpf_program prog = { pc - filter, filter };
+
+#if 0
+ // For debugging BPF filter program
+ unsigned int q;
+ for (q=0; q<prog.bf_len; q++)
+ LogSPS("mDNSPlatformUpdateProxyList: %2d { 0x%02x, %d, %d, 0x%08x },", q, prog.bf_insns[q].code, prog.bf_insns[q].jt, prog.bf_insns[q].jf, prog.bf_insns[q].k);
+#endif
+
+ if (!numv4 && !numv6)
+ {
+ LogSPS("mDNSPlatformUpdateProxyList: No need for filter");
+ if (m->timenow == 0) LogMsg("mDNSPlatformUpdateProxyList: m->timenow == 0");
+ // Schedule check to see if we can close this BPF_fd now
+ if (!m->p->NetworkChanged) m->p->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
+ // prog.bf_len = 0; This seems to panic the kernel
+ if (x->BPF_fd < 0) return; // If we've already closed our BPF_fd, no need to generate an error message below
}
+
+ if (ioctl(x->BPF_fd, 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
{
- static int CLOSEDcount = 0;
- static int EAGAINcount = 0;
- nread = recv(sock->fd, buf, buflen, 0);
-
- if (nread > 0) { CLOSEDcount = 0; EAGAINcount = 0; } // On success, clear our error counters
- else if (nread == 0)
+ 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))
{
- *closed = mDNStrue;
- if ((++CLOSEDcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got CLOSED %d times", sock->fd, CLOSEDcount); sleep(1); }
+ 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);
}
- // else nread is negative -- see what kind of error we got
- else if (errno == ECONNRESET) { nread = 0; *closed = mDNStrue; }
- else if (errno != EAGAIN) { LogMsg("ERROR: mDNSPlatformReadTCP - recv: %d (%s)", errno, strerror(errno)); nread = -1; }
- else // errno is EAGAIN (EWOULDBLOCK) -- no data available
+
+ static const u_int opt_one = 1;
+ if (ioctl(fd, BIOCIMMEDIATE, &opt_one) < 0)
+ LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCIMMEDIATE failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+
+ //if (ioctl(fd, BIOCPROMISC, &opt_one) < 0)
+ // LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCPROMISC failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+
+ //if (ioctl(fd, BIOCSHDRCMPLT, &opt_one) < 0)
+ // LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSHDRCMPLT failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+
+ 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
{
- nread = 0;
- if ((++EAGAINcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got EAGAIN %d times", sock->fd, EAGAINcount); sleep(1); }
+#ifdef __LIB_DISPATCH__
+ i->BPF_fd = fd;
+ i->BPF_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatch_get_main_queue());
+ if (!i->BPF_source) {LogMsg("mDNSPlatformReceiveBPF_fd: dispatch source create failed");return;}
+ dispatch_source_set_event_handler(i->BPF_source, ^{bpf_callback_dispatch(i);});
+ dispatch_source_set_cancel_handler(i->BPF_source, ^{close(fd);});
+ dispatch_resume(i->BPF_source);
+#else
+ CFSocketContext myCFSocketContext = { 0, i, NULL, NULL, NULL };
+ i->BPF_fd = fd;
+ i->BPF_cfs = CFSocketCreateWithNative(kCFAllocatorDefault, fd, kCFSocketReadCallBack, bpf_callback, &myCFSocketContext);
+ i->BPF_rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, i->BPF_cfs, 0);
+ CFRunLoopAddSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
+#endif
+ mDNSPlatformUpdateProxyList(m, i->ifinfo.InterfaceID);
}
}
- return nread;
+ mDNS_Unlock(m);
}
-mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
- {
- int nsent;
+#endif // APPLE_OSX_mDNSResponder
- if (sock->flags & kTCPSocketFlags_UseTLS)
- {
-#ifndef NO_SECURITYFRAMEWORK
- size_t processed;
- if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformWriteTCP called while handshake required"); return 0; }
- if (sock->handshake == handshake_in_progress) return 0;
- else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformWriteTCP called with unexpected SSLHandshake status: %d", sock->handshake);
-
- mStatus err = SSLWrite(sock->tlsContext, msg, len, &processed);
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Key Management
+#endif
- if (!err) nsent = (int) processed;
- else if (err == errSSLWouldBlock) nsent = 0;
- else { LogMsg("ERROR: mDNSPlatformWriteTCP - SSLWrite returned %d", err); nsent = -1; }
-#else
- nsent = -1;
-#endif /* NO_SECURITYFRAMEWORK */
- }
+#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
{
- nsent = send(sock->fd, msg, len, 0);
- if (nsent < 0)
+ 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
{
- if (errno == EAGAIN) nsent = 0;
- else { LogMsg("ERROR: mDNSPlatformWriteTCP - send %s", strerror(errno)); nsent = -1; }
+ SecPolicyRef policy;
+ err = SecPolicySearchCopyNext(searchRef, &policy);
+ if (err || !policy) LogMsg("getCertChain: SecPolicySearchCopyNext() returned %d", (int) err);
+ else
+ {
+ CFArrayRef wrappedCert = CFArrayCreate(NULL, (const void**) &cert, 1, &kCFTypeArrayCallBacks);
+ if (!wrappedCert) LogMsg("getCertChain: wrappedCert is NULL");
+ else
+ {
+ SecTrustRef trust;
+ err = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
+ if (err || !trust) LogMsg("getCertChain: SecTrustCreateWithCertificates() returned %d", (int) err);
+ else
+ {
+ err = SecTrustEvaluate(trust, NULL);
+ if (err) LogMsg("getCertChain: SecTrustEvaluate() returned %d", (int) err);
+ else
+ {
+ CFArrayRef rawCertChain;
+ CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
+ err = SecTrustGetResult(trust, NULL, &rawCertChain, &statusChain);
+ if (err || !rawCertChain || !statusChain) LogMsg("getCertChain: SecTrustGetResult() returned %d", (int) err);
+ else
+ {
+ certChain = CFArrayCreateMutableCopy(NULL, 0, rawCertChain);
+ if (!certChain) LogMsg("getCertChain: certChain is NULL");
+ else
+ {
+ // Replace the SecCertificateRef at certChain[0] with a SecIdentityRef per documentation for SSLSetCertificate:
+ // <http://devworld.apple.com/documentation/Security/Reference/secureTransportRef/index.html>
+ CFArraySetValueAtIndex(certChain, 0, identity);
+ // Remove root from cert chain, but keep any and all intermediate certificates that have been signed by the root certificate
+ if (CFArrayGetCount(certChain) > 1) CFArrayRemoveValueAtIndex(certChain, CFArrayGetCount(certChain) - 1);
+ }
+ CFRelease(rawCertChain);
+ // Do not free statusChain:
+ // <http://developer.apple.com/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html> says:
+ // certChain: Call the CFRelease function to release this object when you are finished with it.
+ // statusChain: Do not attempt to free this pointer; it remains valid until the trust management object is released...
+ }
+ }
+ CFRelease(trust);
+ }
+ CFRelease(wrappedCert);
+ }
+ CFRelease(policy);
+ }
+ CFRelease(searchRef);
}
+ CFRelease(cert);
}
-
- return nsent;
- }
-
-mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
- {
- return sock->fd;
+ return certChain;
}
+#endif /* NO_SECURITYFRAMEWORK */
-// If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
-// If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
-mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa_family, mDNSIPPort *const outport)
+mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
{
- int *s = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
- KQueueEntry *k = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
- const int on = 1;
- const int twofivefive = 255;
- mStatus err = mStatus_NoError;
- char *errstr = mDNSNULL;
-
- cp->closeFlag = mDNSNULL;
-
- int skt = socket(sa_family, SOCK_DGRAM, IPPROTO_UDP);
- if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); }
+#ifdef NO_SECURITYFRAMEWORK
+ return mStatus_UnsupportedErr;
+#else
+ SecIdentityRef identity = nil;
+ SecIdentitySearchRef srchRef = nil;
+ OSStatus err;
- // ... with a shared UDP port, if it's for multicast receiving
- if (mDNSSameIPPort(port, MulticastDNSPort) || mDNSSameIPPort(port, NATPMPAnnouncementPort)) err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
- if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; }
+ // search for "any" identity matching specified key use
+ // In this app, we expect there to be exactly one
+ err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_DECRYPT, &srchRef);
+ if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCreate returned %d", (int) err); return err; }
- if (sa_family == AF_INET)
- {
- // We want to receive destination addresses
- err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
- if (err < 0) { errstr = "setsockopt - IP_RECVDSTADDR"; goto fail; }
+ err = SecIdentitySearchCopyNext(srchRef, &identity);
+ if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext returned %d", (int) err); return err; }
- // We want to receive interface identifiers
- err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
- if (err < 0) { errstr = "setsockopt - IP_RECVIF"; goto fail; }
+ if (CFGetTypeID(identity) != SecIdentityGetTypeID())
+ { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext CFTypeID failure"); return mStatus_UnknownErr; }
- // We want to receive packet TTL value so we can check it
- err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
- // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
+ // Found one. Call getCertChain to create the correct certificate chain.
+ ServerCerts = GetCertChain(identity);
+ if (ServerCerts == nil) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: getCertChain error"); return mStatus_UnknownErr; }
- // Send unicast packets with TTL 255
- err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive));
- if (err < 0) { errstr = "setsockopt - IP_TTL"; goto fail; }
+ return mStatus_NoError;
+#endif /* NO_SECURITYFRAMEWORK */
+ }
- // And multicast packets with TTL 255 too
- err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
- if (err < 0) { errstr = "setsockopt - IP_MULTICAST_TTL"; goto fail; }
+mDNSexport void mDNSPlatformTLSTearDownCerts(void)
+ {
+#ifndef NO_SECURITYFRAMEWORK
+ if (ServerCerts) { CFRelease(ServerCerts); ServerCerts = NULL; }
+#endif /* NO_SECURITYFRAMEWORK */
+ }
- // And start listening for packets
- struct sockaddr_in listening_sockaddr;
- listening_sockaddr.sin_family = AF_INET;
- listening_sockaddr.sin_port = port.NotAnInteger; // Pass in opaque ID without any byte swapping
- listening_sockaddr.sin_addr.s_addr = mDNSSameIPPort(port, NATPMPAnnouncementPort) ? 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)
+// This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
+mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
+ {
+ CFStringEncoding encoding = kCFStringEncodingUTF8;
+ CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding);
+ if (cfs)
{
- // 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; }
-
- // We want to receive packet hop count value so we can check it
- err = setsockopt(skt, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
- if (err < 0) { errstr = "setsockopt - IPV6_HOPLIMIT"; goto fail; }
-
- // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
- // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
- err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
- if (err < 0) { errstr = "setsockopt - IPV6_V6ONLY"; goto fail; }
-
- // Send unicast packets with TTL 255
- err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive));
- if (err < 0) { errstr = "setsockopt - IPV6_UNICAST_HOPS"; goto fail; }
-
- // And multicast packets with TTL 255 too
- err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
- if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_HOPS"; goto fail; }
-
- // Want to receive our own packets
- err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on));
- if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_LOOP"; goto fail; }
-
- // And start listening for packets
- struct sockaddr_in6 listening_sockaddr6;
- mDNSPlatformMemZero(&listening_sockaddr6, sizeof(listening_sockaddr6));
- listening_sockaddr6.sin6_len = sizeof(listening_sockaddr6);
- listening_sockaddr6.sin6_family = AF_INET6;
- listening_sockaddr6.sin6_port = port.NotAnInteger; // Pass in opaque ID without any byte swapping
- listening_sockaddr6.sin6_flowinfo = 0;
- listening_sockaddr6.sin6_addr = in6addr_any; // Want to receive multicasts AND unicasts on this socket
- listening_sockaddr6.sin6_scope_id = 0;
- err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
- if (err) { errstr = "bind"; goto fail; }
- if (outport) outport->NotAnInteger = listening_sockaddr6.sin6_port;
+ CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
+ CFRelease(cfs);
}
+ }
- fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
- fcntl(skt, F_SETFD, 1); // set close-on-exec
- *s = skt;
- k->KQcallback = myKQSocketCallBack;
- k->KQcontext = cp;
- k->KQtask = "UDP packet reception";
- KQueueSet(*s, EV_ADD, EVFILT_READ, k);
-
- return(err);
-
- fail:
- // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero
- if (strcmp(errstr, "bind") || mDNSSameIPPort(port, MulticastDNSPort) || mDNSIPPortIsZero(port))
- LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr, skt, mDNSVal16(port), err, errno, strerror(errno));
-
- // If we got a "bind" failure of EADDRINUSE, inform the caller as it might need to try another random port
- if (!strcmp(errstr, "bind") && errno == EADDRINUSE)
+// This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
+mDNSlocal void GetUserSpecifiedLocalHostName(domainlabel *const namelabel)
+ {
+ CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL);
+ if (cfs)
{
- 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.");
+ CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
+ CFRelease(cfs);
}
+ }
- close(skt);
- return(err);
+mDNSexport mDNSBool DictionaryIsEnabled(CFDictionaryRef dict)
+ {
+ mDNSs32 val;
+ CFNumberRef state = (CFNumberRef)CFDictionaryGetValue(dict, CFSTR("Enabled"));
+ if (!state) return mDNSfalse;
+ if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val))
+ { LogMsg("ERROR: DictionaryIsEnabled - CFNumberGetValue"); return mDNSfalse; }
+ return val ? mDNStrue : mDNSfalse;
}
-mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
+mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
{
- mStatus err;
- mDNSIPPort port = requestedport;
- mDNSBool randomizePort = mDNSIPPortIsZero(requestedport);
- int i = 10000; // Try at most 10000 times to get a unique random port
- UDPSocket *p = mallocL("UDPSocket", sizeof(UDPSocket));
- if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); }
- mDNSPlatformMemZero(p, sizeof(UDPSocket));
- p->ss.port = zeroIPPort;
- p->ss.m = m;
- p->ss.sktv4 = -1;
- p->ss.sktv6 = -1;
+ if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
- do
+ if (sa->sa_family == AF_INET)
{
- // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here
- if (randomizePort) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
- err = SetupSocket(&p->ss, port, AF_INET, &p->ss.port);
- if (!err)
- {
- err = SetupSocket(&p->ss, port, AF_INET6, &p->ss.port);
- if (err) { close(p->ss.sktv4); p->ss.sktv4 = -1; }
- }
- i--;
- } while (err == EADDRINUSE && randomizePort && i);
+ 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 (err)
+ if (sa->sa_family == AF_INET6)
{
- // In customer builds we don't want to log failures with port 5351, because this is a known issue
- // of failing to bind to this port when Internet Sharing has already bound to it
- // We also don't want to log about port 5350, due to a known bug when some other
- // process is bound to it.
- if (mDNSSameIPPort(requestedport, NATPMPPort) || mDNSSameIPPort(requestedport, NATPMPAnnouncementPort))
- LogInfo("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
- else LogMsg("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
- freeL("UDPSocket", p);
- return(mDNSNULL);
+ struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
+ // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id
+ // value into the second word of the IPv6 link-local address, so they can just
+ // pass around IPv6 address structures instead of full sockaddr_in6 structures.
+ // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do.
+ // To work around this we always whack the second word of any IPv6 link-local address back to zero.
+ if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
+ ip->type = mDNSAddrType_IPv6;
+ ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
+ return(mStatus_NoError);
}
- return(p);
+
+ LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
+ return(mStatus_Invalid);
}
-mDNSlocal void CloseSocketSet(KQSocketSet *ss)
+mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
{
- if (ss->sktv4 != -1)
- {
- close(ss->sktv4);
- ss->sktv4 = -1;
- }
- if (ss->sktv6 != -1)
+ mDNSEthAddr eth = zeroEthAddr;
+ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetBSSID"), NULL, NULL);
+ if (!store)
+ LogMsg("GetBSSID: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+ else
{
- close(ss->sktv6);
- ss->sktv6 = -1;
+ CFStringRef entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name);
+ if (entityname)
+ {
+ CFDictionaryRef dict = SCDynamicStoreCopyValue(store, entityname);
+ if (dict)
+ {
+ CFRange range = { 0, 6 }; // Offset, length
+ CFDataRef data = CFDictionaryGetValue(dict, CFSTR("BSSID"));
+ if (data && CFDataGetLength(data) == 6) CFDataGetBytes(data, range, eth.b);
+ CFRelease(dict);
+ }
+ CFRelease(entityname);
+ }
+ CFRelease(store);
}
- if (ss->closeFlag) *ss->closeFlag = 1;
+ return(eth);
}
-mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
+mDNSlocal int GetMAC(mDNSEthAddr *eth, u_short ifindex)
{
- CloseSocketSet(&sock->ss);
- freeL("UDPSocket", sock);
+ 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;
}
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - BPF Raw packet sending/receiving
+#ifndef SIOCGIFWAKEFLAGS
+#define SIOCGIFWAKEFLAGS _IOWR('i', 136, struct ifreq) /* get interface wake property flags */
#endif
-#if APPLE_OSX_mDNSResponder
+#ifndef IF_WAKE_ON_MAGIC_PACKET
+#define IF_WAKE_ON_MAGIC_PACKET 0x01
+#endif
-mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
+#ifndef ifr_wake_flags
+#define ifr_wake_flags ifr_ifru.ifru_intval
+#endif
+
+mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i)
{
- if (!InterfaceID) { LogMsg("mDNSPlatformSendRawPacket: No InterfaceID specified"); return; }
- NetworkInterfaceInfoOSX *info;
+ 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
- extern mDNS mDNSStorage;
- info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
- if (info == NULL)
- {
- LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
- return;
- }
- if (info->BPF_fd < 0)
- LogMsg("mDNSPlatformSendRawPacket: %s BPF_fd %d not ready", info->ifinfo.ifname, info->BPF_fd);
- else
+ int s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) { LogMsg("NetWakeInterface socket failed %s error %d errno %d (%s)", i->ifinfo.ifname, s, errno, strerror(errno)); return(mDNSfalse); }
+
+ struct ifreq ifr;
+ strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCGIFWAKEFLAGS, &ifr) < 0)
{
- //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));
+ // For some strange reason, in /usr/include/sys/errno.h, EOPNOTSUPP is defined to be
+ // 102 when compiling kernel code, and 45 when compiling user-level code. Since this
+ // error code is being returned from the kernel, we need to use the kernel version.
+ #define KERNEL_EOPNOTSUPP 102
+ if (errno != KERNEL_EOPNOTSUPP) // "Operation not supported on socket", the expected result on Leopard and earlier
+ LogMsg("NetWakeInterface SIOCGIFWAKEFLAGS %s errno %d (%s)", i->ifinfo.ifname, errno, strerror(errno));
+ // If on Leopard or earlier, we get EOPNOTSUPP, so in that case
+ // we enable WOL if this interface is not AirPort and "Wake for Network access" is turned on.
+ ifr.ifr_wake_flags = (errno == KERNEL_EOPNOTSUPP && !(i)->BSSID.l[0] && i->m->SystemWakeOnLANEnabled) ? IF_WAKE_ON_MAGIC_PACKET : 0;
}
+
+ close(s);
+
+ // ifr.ifr_wake_flags = IF_WAKE_ON_MAGIC_PACKET; // For testing with MacBook Air, using a USB dongle that doesn't actually support Wake-On-LAN
+
+ LogSPS("%-6s %#-14a %s WOMP", i->ifinfo.ifname, &i->ifinfo.ip, (ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) ? "supports" : "no");
+
+ return((ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) != 0);
}
-mDNSexport void mDNSPlatformSetLocalARP(const mDNSv4Addr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
+// Returns pointer to newly created NetworkInterfaceInfoOSX object, or
+// pointer to already-existing NetworkInterfaceInfoOSX object found in list, or
+// may return NULL if out of memory (unlikely) or parameters are invalid for some reason
+// (e.g. sa_family not AF_INET or AF_INET6)
+mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa, mDNSs32 utc)
{
- if (!InterfaceID) { LogMsg("mDNSPlatformSetLocalARP: No InterfaceID specified"); return; }
- NetworkInterfaceInfoOSX *info;
- extern mDNS mDNSStorage;
- info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
- if (info == NULL)
- {
- LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
- return;
- }
- // Manually inject an entry into our local ARP cache.
- // (We can't do this by sending an ARP broadcast, because the kernel only pays attention to incoming ARP packets, not outgoing.)
- 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);
- }
- }
+ mDNSu32 scope_id = if_nametoindex(ifa->ifa_name);
+ mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
+
+ mDNSAddr ip, mask;
+ if (SetupAddr(&ip, ifa->ifa_addr ) != mStatus_NoError) return(NULL);
+ if (SetupAddr(&mask, ifa->ifa_netmask) != mStatus_NoError) return(NULL);
+
+ NetworkInterfaceInfoOSX **p;
+ for (p = &m->p->InterfaceList; *p; p = &(*p)->next)
+ if (scope_id == (*p)->scope_id &&
+ mDNSSameAddress(&ip, &(*p)->ifinfo.ip) &&
+ mDNSSameEthAddress(&bssid, &(*p)->BSSID))
+ {
+ debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", 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)->Registered)
+ {
+ mDNS_Lock(m);
+ if (NetWake) mDNS_ActivateNetWake_internal (m, &(*p)->ifinfo);
+ else mDNS_DeactivateNetWake_internal(m, &(*p)->ifinfo);
+ mDNS_Unlock(m);
+ }
+ }
+
+ return(*p);
+ }
+
+ NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *)mallocL("NetworkInterfaceInfoOSX", sizeof(*i));
+ debugf("AddInterfaceToList: Making new interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, i);
+ if (!i) return(mDNSNULL);
+ mDNSPlatformMemZero(i, sizeof(NetworkInterfaceInfoOSX));
+ i->ifinfo.InterfaceID = (mDNSInterfaceID)(uintptr_t)scope_id;
+ i->ifinfo.ip = ip;
+ i->ifinfo.mask = mask;
+ strlcpy(i->ifinfo.ifname, ifa->ifa_name, sizeof(i->ifinfo.ifname));
+ i->ifinfo.ifname[sizeof(i->ifinfo.ifname)-1] = 0;
+ // We can be configured to disable multicast advertisement, but we want to to support
+ // local-only services, which need a loopback address record.
+ i->ifinfo.Advertise = m->DivertMulticastAdvertisements ? ((ifa->ifa_flags & IFF_LOOPBACK) ? mDNStrue : mDNSfalse) : m->AdvertiseLocalAddresses;
+ i->ifinfo.McastTxRx = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList
+
+ i->next = mDNSNULL;
+ i->m = m;
+ i->Exists = mDNStrue;
+ 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->BPF_fd = -1;
+ i->BPF_mcfd = -1;
+ i->BPF_len = 0;
+ i->Registered = mDNSNULL;
-mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i)
- {
- LogSPS("%s closing BPF fd %d", i->ifinfo.ifname, i->BPF_fd);
+ // 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);
- // 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;
+ *p = i;
+ return(i);
}
-mDNSlocal void bpf_callback(const CFSocketRef cfs, const CFSocketCallBackType CallBackType, const CFDataRef address, const void *const data, void *const context)
+#if USE_V6_ONLY_WHEN_NO_ROUTABLE_V4
+mDNSlocal NetworkInterfaceInfoOSX *FindRoutableIPv4(mDNS *const m, mDNSu32 scope_id)
{
- (void)cfs;
- (void)CallBackType;
- (void)address;
- (void)data;
+ NetworkInterfaceInfoOSX *i;
+ for (i = m->p->InterfaceList; i; i = i->next)
+ if (i->Exists && i->scope_id == scope_id && i->ifinfo.ip.type == mDNSAddrType_IPv4)
+ if (!mDNSv4AddressIsLinkLocal(&i->ifinfo.ip.ip.v4))
+ return(i);
+ return(mDNSNULL);
+ }
+#endif
- NetworkInterfaceInfoOSX *const info = (NetworkInterfaceInfoOSX *)context;
- KQueueLock(info->m);
+#if APPLE_OSX_mDNSResponder
- // 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;
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - AutoTunnel
+#endif
- 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);
+#define kRacoonPort 4500
- 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;
- }
+static DomainAuthInfo* AnonymousRacoonConfig = mDNSNULL;
- while (ptr < end)
+// We arbitrarily limit the message size to 128 bytes (which seems sufficient now) so that
+// freeing ELogContext is simpler which is treated as opaque quantity in many places
+typedef struct
+ {
+ char subdomain[32];
+ char message[128];
+ uuid_t uuid;
+ int result;
+ } ELogContext;
+
+typedef enum { HTTPGet = 1, HTTPPost } HTTPOperation;
+typedef enum { ConfigInvalid = 0, ConfigFetching, ConfigValid } ConfigState;
+typedef void (*HTTPClientCallback)(CFMutableDataRef responseData, ELogContext *context);
+#define kReadStreamBufferSize 4096
+#define kMaximumResponseSize 32768
+#define kHTTPResponseCodeOK 200
+#define kHTTPResponseCodeAuthFailure 401
+#define kHTTPResponseCodeForbidden 403
+#define kHTTPResponseCodeNotFound 404
+
+// eReporter configuration needs to be fetched whenever it becomes stale. We fetch it lazily
+// when we send the report.
+struct eReporterConfiguration {
+ CFDictionaryRef eRDict;
+ ConfigState eRState;
+} eReporterConfig;
+
+typedef struct
+ {
+ mDNSBool authChecked;
+ CFHTTPAuthenticationRef authentication;
+ CFMutableDataRef responseData;
+ HTTPClientCallback callback;
+ ELogContext cbcontext;
+ HTTPOperation op;
+ CFStringRef headerFieldName;
+ CFStringRef headerFieldValue;
+ CFDataRef bodyData;
+ CFStringRef url;
+ } HTTPDataStreamContext;
+
+
+// Forward declarations
+mDNSlocal void HTTPDataStream(CFStringRef url, HTTPOperation op, CFDataRef bodyData, CFStringRef headerFieldName,
+ CFStringRef headerFieldValue, CFHTTPAuthenticationRef auth, CFMutableDictionaryRef credentials,
+ HTTPClientCallback callback, ELogContext *context);
+mDNSlocal void mDNSReporterLogValidConfig(ELogContext *elog);
+
+mDNSlocal void CancelReadStream(CFReadStreamRef readStream)
+ {
+ if (readStream)
{
- 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);
+ CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL);
+ CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetMain(), kCFRunLoopCommonModes);
+ CFReadStreamClose(readStream);
+ CFRelease(readStream);
}
-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)
+mDNSlocal void CancelHTTPDataStream(CFReadStreamRef stream, HTTPDataStreamContext *context)
{
- int numv4 = 0, numv6 = 0;
- AuthRecord *rr;
-
- for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
- {
- if (p4) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.4a", x->BPF_fd, x->ifinfo.ifname, numv4, &rr->AddressProxy.ip.v4);
- numv4++;
- }
-
- for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
- {
- if (p6) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.16a", x->BPF_fd, x->ifinfo.ifname, numv6, &rr->AddressProxy.ip.v6);
- numv6++;
- }
-
- if (p4) *p4 = numv4;
- if (p6) *p6 = numv6;
- return(numv4 + numv6);
+ LogInfo("CancelHTTPDataStream: called");
+ if (context)
+ {
+ if (context->authentication) CFRelease(context->authentication);
+ if (context->responseData) CFRelease(context->responseData);
+ if (context->headerFieldName) CFRelease(context->headerFieldName);
+ if (context->headerFieldValue) CFRelease(context->headerFieldValue);
+ if (context->bodyData) CFRelease(context->bodyData);
+ if (context->url) CFRelease(context->url);
+ freeL("HTTPDataStreamContext", context);
+ }
+ CancelReadStream(stream);
}
-mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
+mDNSlocal CFIndex HTTPResponseCode(CFReadStreamRef stream)
{
- NetworkInterfaceInfoOSX *x;
-
- //NOTE: We can't use IfIndexToInterfaceInfoOSX because that looks for Registered also.
- for (x = m->p->InterfaceList; x; x = x->next) if (x->ifinfo.InterfaceID == InterfaceID) break;
-
- if (!x) { LogMsg("mDNSPlatformUpdateProxyList: ERROR InterfaceID %p not found", InterfaceID); return; }
-
- #define MAX_BPF_ADDRS 250
- int numv4 = 0, numv6 = 0;
-
- if (CountProxyTargets(m, x, &numv4, &numv6) > MAX_BPF_ADDRS)
+ CFIndex errorCode = 0;
+ CFHTTPMessageRef responseHeaders = (CFHTTPMessageRef)CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
+ if (responseHeaders)
{
- 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;
+ errorCode = CFHTTPMessageGetResponseStatusCode(responseHeaders);
+ CFRelease(responseHeaders);
}
+ return errorCode;
+ }
- LogSPS("mDNSPlatformUpdateProxyList: fd %d %-7s MAC %.6a %d v4 %d v6", x->BPF_fd, x->ifinfo.ifname, &x->ifinfo.MAC, numv4, numv6);
+mDNSlocal void RetryWithHTTPAuth(HTTPDataStreamContext *context, CFReadStreamRef stream)
+ {
+ CFStreamError err;
+ DomainAuthInfo *FoundInList;
+ CFMutableDictionaryRef credentials = NULL;
- // 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] =
+ // Need to use the same authentication object till it goes invalid
+ if (!context->authentication)
{
- 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, 54); // A = 54 (14-byte Ethernet plus 20-byte TCP + 20 bytes spare)
- static const struct bpf_insn r4c = BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0); // A += IP Header length
- static const struct bpf_insn r4d = BPF_STMT(BPF_RET + BPF_A, 0); // Success: Return Ethernet + IP + TCP + 20 bytes spare (normally 74)
-
- static const struct bpf_insn r6a = BPF_STMT(BPF_RET + BPF_K, 94); // Success: Return Eth + IPv6 + TCP + 20 bytes spare
-
- BPF_SetOffset(&filter[4], jf, fail); // If Ethertype not ARP, IPv4, or IPv6, fail
- BPF_SetOffset(&filter[6], jf, chk6); // If IPv6 but not ICMPv6, go to IPv6 address list check
-
- // BPF Byte-Order Note
- // The BPF API designers apparently thought that programmers would not be smart enough to use htons
- // and htonl correctly to convert numeric values to network byte order on little-endian machines,
- // so instead they chose to make the API implicitly byte-swap *ALL* values, even literal byte strings
- // that shouldn't be byte-swapped, like ASCII text, Ethernet addresses, IP addresses, etc.
- // As a result, if we put Ethernet addresses and IP addresses in the right byte order, the BPF API
- // will byte-swap and make them backwards, and then our filter won't work. So, we have to arrange
- // that on little-endian machines we deliberately put addresses in memory with the bytes backwards,
- // so that when the BPF API goes through and swaps them all, they end up back as they should be.
- // In summary, if we byte-swap all the non-numeric fields that shouldn't be swapped, and we *don't*
- // swap any of the numeric values that *should* be byte-swapped, then the filter will work correctly.
-
- // IPSEC capture size notes:
- // 8 bytes UDP header
- // 4 bytes Non-ESP Marker
- // 28 bytes IKE Header
- // --
- // 40 Total. Capturing TCP Header + 20 gets us enough bytes to receive the IKE Header in a UDP-encapsulated IKE packet.
-
- AuthRecord *rr;
- for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
- {
- mDNSv4Addr a = rr->AddressProxy.ip.v4;
- pc->code = BPF_JMP + BPF_JEQ + BPF_K;
- BPF_SetOffset(pc, jt, ret4);
- pc->jf = 0;
- pc->k = (bpf_u_int32)a.b[0] << 24 | (bpf_u_int32)a.b[1] << 16 | (bpf_u_int32)a.b[2] << 8 | (bpf_u_int32)a.b[3];
- pc++;
- }
- *pc++ = rf;
-
- if (pc != chk6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != chk6 %p", pc, chk6);
- *pc++ = g6; // chk6 points here
+ CFHTTPMessageRef responseHeader = (CFHTTPMessageRef)CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
+ // Get the authentication information from the response.
+ context->authentication = CFHTTPAuthenticationCreateFromResponse(NULL, responseHeader);
+ CFRelease(responseHeader);
+ }
- for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
+ // Check to see if the authentication is valid for use. Anything could have gone wrong
+ // from bad credentials to wrong type of authentication etc.
+ if (!context->authentication || !CFHTTPAuthenticationIsValid(context->authentication, &err))
+ {
+ LogMsg("RetryWithHTTPAuth: ERROR!! Authentication failed");
+ if (context->authentication)
{
- 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++;
+ // Check for bad credentials and treat these separately
+ if (err.domain == kCFStreamErrorDomainHTTP && (err.error == kCFStreamErrorHTTPAuthenticationBadUserName ||
+ err.error == kCFStreamErrorHTTPAuthenticationBadPassword))
+ {
+ LogMsg("RetryWithHTTPAuth: ERROR!! Bad credentials %d", err.error);
+ }
}
+ CancelHTTPDataStream(stream, context);
+ return;
+ }
- 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 };
+ // Do we need username & password? Not all authentication types require them.
+ if (CFHTTPAuthenticationRequiresUserNameAndPassword(context->authentication))
+ {
+ char username[MAX_DOMAIN_LABEL + 1];
-#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
- }
+ // Use the first BTMM username and password
+ for (FoundInList = (&mDNSStorage)->AuthInfoList; FoundInList; FoundInList = FoundInList->next)
+ if (!FoundInList->deltime && FoundInList->AutoTunnel) break;
- 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);
- }
+ if (!FoundInList)
+ {
+ LogInfo("RetryHTTPWithAuth: No BTMM credentials");
+ CancelHTTPDataStream(stream, context);
+ return;
+ }
-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))
+ ConvertDomainLabelToCString_unescaped((domainlabel *)FoundInList->domain.c, username);
+ CFStringRef user = CFStringCreateWithBytes(NULL, (const mDNSu8 *)username, strlen(username), kCFStringEncodingASCII, false);
+ if (!user)
{
- 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);
+ LogMsg("RetryHTTPWithAuth: ERROR!! CFStringCreateWithBytes error");
+ CancelHTTPDataStream(stream, context);
+ return;
}
-
- 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
+ CFStringRef pass = CFStringCreateWithBytes(NULL, (const mDNSu8 *)FoundInList->b64keydata, strlen(FoundInList->b64keydata),
+ kCFStringEncodingASCII, false);
+ if (!pass)
{
- 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, i->ifinfo.InterfaceID);
+ LogMsg("RetryHTTPWithAuth: ERROR!! CFStringCreateWithBytes error");
+ CFRelease(user);
+ CancelHTTPDataStream(stream, context);
+ return;
}
+ // Build the credentials dictionary
+ credentials = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (!credentials)
+ {
+ LogMsg("RetryHTTPWithAuth: ERROR!! cannot allocate credentials");
+ CFRelease(user);
+ CFRelease(pass);
+ CancelHTTPDataStream(stream, context);
+ return;
+ }
+ CFDictionarySetValue(credentials, kCFHTTPAuthenticationUsername, user);
+ CFDictionarySetValue(credentials, kCFHTTPAuthenticationPassword, pass);
+ CFRelease(user);
+ CFRelease(pass);
+ }
+ else
+ {
+ LogMsg("RetryHTTPWithAuth: ERROR!! Unknown authentication method");
+ CancelHTTPDataStream(stream, context);
+ return;
}
- mDNS_Unlock(m);
- }
+ HTTPDataStream(context->url, context->op, context->bodyData, context->headerFieldName, context->headerFieldValue,
+ context->authentication, credentials, context->callback, &context->cbcontext);
-#endif // APPLE_OSX_mDNSResponder
+ if (credentials) CFRelease(credentials);
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Key Management
-#endif
+ // Cancel the old one
+ CancelHTTPDataStream(stream, context);
+ }
-#ifndef NO_SECURITYFRAMEWORK
-mDNSlocal CFArrayRef GetCertChain(SecIdentityRef identity)
+mDNSlocal void HTTPDataStreamCallback(CFReadStreamRef stream, CFStreamEventType type, void *info)
{
- 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
+ HTTPDataStreamContext *context = (HTTPDataStreamContext *)info;
+ CFIndex status;
+
+ status = HTTPResponseCode(stream);
+
+ // if we are forbidden to access, we need to refetch the configuration file.
+ // For keeping it simple, we don't retry immediately. When the next message
+ // is logged, we will try getting the config file. If we want to modify this
+ // in the future to retry now, then we need to know to stop retrying after a
+ // few times.
+ if ((status == kHTTPResponseCodeNotFound) || (status == kHTTPResponseCodeForbidden))
+ {
+ if (status == kHTTPResponseCodeNotFound)
+ LogMsg("HTTPDataStreamCallback: ERROR!! Config plist cannot be found");
+ else if (status == kHTTPResponseCodeForbidden)
+ LogInfo("HTTPDataStreamCallback: Config plist Forbidden by server");
+ if (context->callback) context->callback(context->responseData, &context->cbcontext);
+ CancelHTTPDataStream(stream, context);
+ return;
+ }
+
+ switch (type)
{
- 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
+ case kCFStreamEventHasBytesAvailable:
{
- SecPolicyRef policy;
- err = SecPolicySearchCopyNext(searchRef, &policy);
- if (err || !policy) LogMsg("getCertChain: SecPolicySearchCopyNext() returned %d", (int) err);
- else
+ mDNSu8 buffer[kReadStreamBufferSize];
+ CFIndex bytesRead;
+
+ if (!context->authChecked)
{
- CFArrayRef wrappedCert = CFArrayCreate(NULL, (const void**) &cert, 1, &kCFTypeArrayCallBacks);
- if (!wrappedCert) LogMsg("getCertChain: wrappedCert is NULL");
- else
+ context->authChecked = mDNStrue;
+ if (status == kHTTPResponseCodeAuthFailure)
{
- SecTrustRef trust;
- err = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
- if (err || !trust) LogMsg("getCertChain: SecTrustCreateWithCertificates() returned %d", (int) err);
- else
- {
- err = SecTrustEvaluate(trust, NULL);
- if (err) LogMsg("getCertChain: SecTrustEvaluate() returned %d", (int) err);
- else
- {
- CFArrayRef rawCertChain;
- CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
- err = SecTrustGetResult(trust, NULL, &rawCertChain, &statusChain);
- if (err || !rawCertChain || !statusChain) LogMsg("getCertChain: SecTrustGetResult() returned %d", (int) err);
- else
- {
- certChain = CFArrayCreateMutableCopy(NULL, 0, rawCertChain);
- if (!certChain) LogMsg("getCertChain: certChain is NULL");
- else
- {
- // Replace the SecCertificateRef at certChain[0] with a SecIdentityRef per documentation for SSLSetCertificate:
- // <http://devworld.apple.com/documentation/Security/Reference/secureTransportRef/index.html>
- CFArraySetValueAtIndex(certChain, 0, identity);
- // Remove root from cert chain, but keep any and all intermediate certificates that have been signed by the root certificate
- if (CFArrayGetCount(certChain) > 1) CFArrayRemoveValueAtIndex(certChain, CFArrayGetCount(certChain) - 1);
- }
- CFRelease(rawCertChain);
- // Do not free statusChain:
- // <http://developer.apple.com/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html> says:
- // certChain: Call the CFRelease function to release this object when you are finished with it.
- // statusChain: Do not attempt to free this pointer; it remains valid until the trust management object is released...
- }
- }
- CFRelease(trust);
- }
- CFRelease(wrappedCert);
+ RetryWithHTTPAuth(context, stream);
+ return;
}
- CFRelease(policy);
}
- CFRelease(searchRef);
+
+ bytesRead = CFReadStreamRead(stream, buffer, sizeof(buffer));
+ if (bytesRead > 0)
+ {
+ CFDataAppendBytes(context->responseData, buffer, bytesRead);
+ if (CFDataGetLength(context->responseData) > kMaximumResponseSize)
+ {
+ LogMsg("HTTPDataStreamCallback: ERROR!! Appended max data %d", kMaximumResponseSize);
+ }
+ else { LogInfo("HTTPDataStreamCallback: successfully appended data of size %ld", bytesRead); return; }
+ }
+ else if (bytesRead < 0)
+ {
+ LogMsg("HTTPDataStreamCallback: ERROR!! CFReadStreamRead returned %ld", bytesRead);
+ }
}
- CFRelease(cert);
+ break;
+ case kCFStreamEventEndEncountered:
+ {
+ if (!context->authChecked)
+ {
+ context->authChecked = mDNStrue;
+ if (status == kHTTPResponseCodeAuthFailure)
+ {
+ RetryWithHTTPAuth(context, stream);
+ return;
+ }
+ }
+ if (status != kHTTPResponseCodeOK)
+ LogMsg("HTTPDataStreamCallback: ERROR!! EndEncountered, statusCode %d, Operation %d", status, context->op);
+ else
+ LogInfo("HTTPDataStreamCallback: HTTP Ok for Operation %d", context->op);
+ if (context->callback) context->callback(context->responseData, &context->cbcontext);
+ }
+ break;
+ case kCFStreamEventErrorOccurred:
+ LogInfo("HTTPDataStreamCallback: ERROR!! kCFStreamEventErrorOccurred for Operation %d", context->op);
+ if (context->callback) context->callback(context->responseData, &context->cbcontext);
+ break;
+ default:
+ LogMsg("HTTPDataStreamCallback: ERROR!! default case");
+ if (context->callback) context->callback(context->responseData, &context->cbcontext);
+ break;
}
- return certChain;
- }
-#endif /* NO_SECURITYFRAMEWORK */
+ CancelHTTPDataStream(stream, context);
+}
-mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
+// Everything needs to be copied or retained locally if need to be accessed beyond function scope
+mDNSlocal void HTTPDataStream(CFStringRef url, HTTPOperation op, CFDataRef bodyData, CFStringRef headerFieldName,
+ CFStringRef headerFieldValue, CFHTTPAuthenticationRef authentication, CFMutableDictionaryRef credentials,
+ HTTPClientCallback callback, ELogContext *cbcontext)
{
-#ifdef NO_SECURITYFRAMEWORK
- return mStatus_UnsupportedErr;
-#else
- SecIdentityRef identity = nil;
- SecIdentitySearchRef srchRef = nil;
- OSStatus err;
-
- // search for "any" identity matching specified key use
- // In this app, we expect there to be exactly one
- err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_DECRYPT, &srchRef);
- if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCreate returned %d", (int) err); return err; }
+ CFURLRef myURL = NULL;
+ CFHTTPMessageRef myRequest = NULL;
+ CFReadStreamRef readStream = NULL;
+ HTTPDataStreamContext *contextInfo = NULL;
+ CFDictionaryRef proxyDict = NULL;
+
+ contextInfo = mallocL("HTTPDataStreamContext", sizeof(HTTPDataStreamContext));
+ if (!contextInfo) { LogMsg("HTTPDataStream: mallocL failure"); return; }
+
+ mDNSPlatformMemZero(contextInfo, sizeof(*contextInfo));
+ // Need to remember the state, so that if we need to retry with authentication, we can
+ // reissue the request
+ contextInfo->url = CFRetain(url);
+ contextInfo->callback = callback;
+ if(cbcontext) memcpy(&contextInfo->cbcontext, cbcontext, sizeof(ELogContext));
+ contextInfo->authChecked = mDNSfalse;
+ contextInfo->op = op;
+ if (authentication) contextInfo->authentication = (CFHTTPAuthenticationRef) CFRetain(authentication);
+ if (headerFieldName) contextInfo->headerFieldName = CFRetain(headerFieldName);
+ if (headerFieldValue) contextInfo->headerFieldValue = CFRetain(headerFieldValue);
+ if (bodyData) contextInfo->bodyData = CFRetain(bodyData);
+
+ myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);
+ if (!myURL) { LogMsg("HTTPDataStream: CFURLCreateWithString error"); goto cleanup; }
+
+ CFStringRef requestMethod = op == HTTPGet ? CFSTR("GET") : CFSTR("POST");
+ myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
+ if (!myRequest) { LogMsg("HTTPDataStream: CFHTTPMessageCreateRequest error"); goto cleanup; }
+
+ if (bodyData) CFHTTPMessageSetBody(myRequest, bodyData);
+ if (headerFieldName) CFHTTPMessageSetHeaderFieldValue(myRequest, headerFieldName, headerFieldValue);
+
+ if (credentials)
+ {
+ if (!CFHTTPMessageApplyCredentialDictionary(myRequest, contextInfo->authentication, credentials, NULL))
+ {
+ LogMsg("HTTPDataStream: ERROR!! CFHTTPMessageApplyCredentialDictionary error");
+ goto cleanup;
+ }
+ }
- err = SecIdentitySearchCopyNext(srchRef, &identity);
- if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext returned %d", (int) err); return err; }
+ readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, myRequest);
+ if (!readStream) { LogMsg("HTTPDataStream: CFStringCreateWithBytes error"); goto cleanup; }
- if (CFGetTypeID(identity) != SecIdentityGetTypeID())
- { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext CFTypeID failure"); return mStatus_UnknownErr; }
+ proxyDict = SCDynamicStoreCopyProxies(NULL);
+ if (proxyDict)
+ {
+ mDNSBool ret = CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPProxy, proxyDict);
+ CFRelease(proxyDict);
+ if (!ret)
+ {
+ LogMsg("HTTPDataStream: CFReadStreamSetProperty HTTP proxy failed");
+ goto cleanup;
+ }
+ }
- // Found one. Call getCertChain to create the correct certificate chain.
- ServerCerts = GetCertChain(identity);
- if (ServerCerts == nil) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: getCertChain error"); return mStatus_UnknownErr; }
+ CFOptionFlags events = kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
- return mStatus_NoError;
-#endif /* NO_SECURITYFRAMEWORK */
+ CFStreamClientContext readContext = {0, contextInfo, NULL, NULL, NULL};
+ CFReadStreamSetClient(readStream, events, HTTPDataStreamCallback, &readContext);
+ CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetMain(), kCFRunLoopCommonModes);
+ if (CFReadStreamOpen(readStream))
+ {
+ contextInfo->responseData = CFDataCreateMutable(NULL, 0);
+ if (contextInfo->responseData)
+ {
+ // Release the things that we don't need
+ CFRelease(myURL);
+ CFRelease(myRequest);
+ return;
+ }
+ LogMsg("HTTPDataStream: ERROR!! responseData allocation failed");
+ }
+ else LogMsg("HTTPDataStream: ERROR!! CFReadStreamOpen failed");
+cleanup:
+ if (readStream) CancelReadStream(readStream);
+ if (myRequest) CFRelease(myRequest);
+ if (myURL) CFRelease(myURL);
+ if (contextInfo)
+ {
+ if (contextInfo->authentication) CFRelease(contextInfo->authentication);
+ if (contextInfo->headerFieldName) CFRelease(contextInfo->headerFieldName);
+ if (contextInfo->headerFieldValue) CFRelease(contextInfo->headerFieldValue);
+ if (contextInfo->bodyData) CFRelease(contextInfo->bodyData);
+ if (contextInfo->url) CFRelease(contextInfo->url);
+ freeL("HTTPDataStreamContext", contextInfo);
+ }
}
-mDNSexport void mDNSPlatformTLSTearDownCerts(void)
+mDNSlocal CFStringRef eReporterGetValueForKey(CFDictionaryRef dict, char *keyCString)
{
-#ifndef NO_SECURITYFRAMEWORK
- if (ServerCerts) { CFRelease(ServerCerts); ServerCerts = NULL; }
-#endif /* NO_SECURITYFRAMEWORK */
- }
+ CFStringRef value;
+ CFStringRef key;
-// This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
-mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
- {
- CFStringEncoding encoding = kCFStringEncodingUTF8;
- CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding);
- if (cfs)
+ key = CFStringCreateWithCString(NULL, keyCString, kCFStringEncodingUTF8);
+ if (!CFDictionaryContainsKey(dict, key))
{
- CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
- CFRelease(cfs);
+ LogMsg("eReporterGetValueForKey: ERROR!! key %s not found", keyCString);
+ return NULL;
}
- }
-
-// This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
-mDNSlocal void GetUserSpecifiedLocalHostName(domainlabel *const namelabel)
- {
- CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL);
- if (cfs)
+ value = (CFStringRef)CFDictionaryGetValue(dict, key);
+ CFRelease(key);
+ if (!value)
{
- CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
- CFRelease(cfs);
+ LogMsg("eReporterGetValueForKey: ERROR!! value not found for %s", keyCString);
+ return NULL;
}
+ return value;
}
-
-mDNSexport mDNSBool DictionaryIsEnabled(CFDictionaryRef dict)
- {
- mDNSs32 val;
- CFNumberRef state = CFDictionaryGetValue(dict, CFSTR("Enabled"));
- if (!state) return mDNSfalse;
- if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val))
- { LogMsg("ERROR: DictionaryIsEnabled - CFNumberGetValue"); return mDNSfalse; }
- return val ? mDNStrue : mDNSfalse;
- }
-
-mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
+
+mDNSlocal void eReporterConfigCallback(CFMutableDataRef responseData, ELogContext *context)
{
- if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
+ CFDictionaryRef dict = NULL;
+ char *plistKeys[] = {"URL", "Publish", "LoadText", "URI", NULL};
+ int i;
+ CFErrorRef error;
- if (sa->sa_family == AF_INET)
+ if (!CFDataGetLength(responseData))
{
- 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);
+ LogInfo("eReporterConfigCallback: Zero length data");
+ eReporterConfig.eRState = ConfigInvalid;
+ return;
}
-
- if (sa->sa_family == AF_INET6)
+ CFPropertyListFormat format = kCFPropertyListXMLFormat_v1_0;
+ dict = CFPropertyListCreateWithData(0, responseData, kCFPropertyListImmutable, &format, &error);
+ if ( dict == NULL )
{
- struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
- // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id
- // value into the second word of the IPv6 link-local address, so they can just
- // pass around IPv6 address structures instead of full sockaddr_in6 structures.
- // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do.
- // To work around this we always whack the second word of any IPv6 link-local address back to zero.
- if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
- ip->type = mDNSAddrType_IPv6;
- ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
- return(mStatus_NoError);
+ LogMsg("eReporterConfigCallback: Parsing property list failed");
+ eReporterConfig.eRState = ConfigInvalid;
+ CFRelease(error);
+ return;
}
-
- LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
- return(mStatus_Invalid);
- }
-
-mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
- {
- mDNSEthAddr eth = zeroEthAddr;
- SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetBSSID"), NULL, NULL);
- if (!store)
- LogMsg("GetBSSID: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
- else
+ i = 0;
+ while (plistKeys[i] != NULL)
{
- CFStringRef entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name);
- if (entityname)
+ if (eReporterGetValueForKey(dict, plistKeys[i]) == NULL)
{
- CFDictionaryRef dict = SCDynamicStoreCopyValue(store, entityname);
- if (dict)
- {
- CFRange range = { 0, 6 }; // Offset, length
- CFDataRef data = CFDictionaryGetValue(dict, CFSTR("BSSID"));
- if (data && CFDataGetLength(data) == 6) CFDataGetBytes(data, range, eth.b);
- CFRelease(dict);
- }
- CFRelease(entityname);
+ LogMsg("eReporterConfigCallback: ERROR!! problem accessing key %s", plistKeys[i]);
+ CFRelease(dict);
+ eReporterConfig.eRState = ConfigInvalid;
+ return;
}
- CFRelease(store);
+ i++;
}
- return(eth);
+ if (eReporterConfig.eRDict) CFRelease(eReporterConfig.eRDict);
+ eReporterConfig.eRDict = dict;
+ eReporterConfig.eRState = ConfigValid;
+ mDNSReporterLogValidConfig(context);
}
-mDNSlocal int GetMAC(mDNSEthAddr *eth, u_short ifindex)
+mDNSlocal mDNSBool FetchEReporterConfiguration(ELogContext *context)
{
- 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;
- }
+ const char *urlString = "https://configuration.apple.com./configurations/internetservices/e3/mDNSResponder/Configurations1.0.plist";
+ //const char *urlString = "http://isdev02:9702/configuration/configurations/internetservices/e3/btmm/Configurations1.0.plist"; //dev server
-#ifndef SIOCGIFWAKEFLAGS
-#define SIOCGIFWAKEFLAGS _IOWR('i', 136, struct ifreq) /* get interface wake property flags */
-#endif
+ CFStringRef url = CFStringCreateWithBytes(NULL, (const mDNSu8 *)urlString, strlen(urlString), kCFStringEncodingASCII, false);
+ if (!url) { LogMsg("FetchEReporterConfiguration: CFStringCreateWithBytes error"); return mDNSfalse; }
-#ifndef IF_WAKE_ON_MAGIC_PACKET
-#define IF_WAKE_ON_MAGIC_PACKET 0x01
-#endif
+ if (eReporterConfig.eRState == ConfigValid || eReporterConfig.eRState == ConfigFetching)
+ {
+ CFRelease(url);
+ return mDNSfalse;
+ }
-#ifndef ifr_wake_flags
-#define ifr_wake_flags ifr_ifru.ifru_intval
-#endif
+ eReporterConfig.eRState = ConfigFetching;
+ HTTPDataStream(url, HTTPGet, NULL, NULL, NULL, NULL, NULL, eReporterConfigCallback, context);
+ CFRelease(url);
+ return mDNStrue;
+ }
-mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i)
+// Builds an element of type : <key name="nameAttr"> value </key> and attaches it to
+// xmlTree
+mDNSlocal mDNSBool AddElementToTree(CFXMLTreeRef xmlTree, char *nameAttr, char *value)
{
- 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
+ /* <key name="BTMM domain"> domain </key> */
+
+ CFStringRef textval = CFStringCreateWithCString(NULL, value, kCFStringEncodingUTF8);
+ if (!textval) { LogMsg("AddElementToTree: cannot create CString for value %s", value); return mDNSfalse; }
- 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); }
+ CFStringRef keys[1] = { CFSTR("name") };
+ CFStringRef values[1] = { CFStringCreateWithCString(NULL, nameAttr, kCFStringEncodingUTF8) };
- struct ifreq ifr;
- strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCGIFWAKEFLAGS, &ifr) < 0)
+ CFDictionaryRef dict = CFDictionaryCreate(NULL, (void*)keys, (void*)values, 1, &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (!dict)
{
- // 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;
+ LogMsg("AddElementToTree: ERROR!! CFDictionaryCreate failed for %s", nameAttr);
+ CFRelease(textval);
+ CFRelease(values[0]);
+ return mDNSfalse;
}
-#if ASSUME_SNOWLEOPARD_INCORRECTLY_REPORTS_AIRPORT_INCAPABLE_OF_WAKE_ON_LAN
- else
+
+ CFMutableArrayRef attr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (!attr)
{
- // 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;
+ LogMsg("AddElementToTree: ERROR!! CFArrayCreateMutable failed for %s", nameAttr);
+ CFRelease(textval);
+ CFRelease(dict);
+ CFRelease(values[0]);
+ return mDNSfalse;
}
-#endif
- close(s);
+ CFArrayAppendValue(attr, keys[0]);
- // 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
+ /* Build <key name="nameAttr"> */
- LogSPS("%-6s %#-14a %s WOMP", i->ifinfo.ifname, &i->ifinfo.ip, (ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) ? "supports" : "no");
+ CFXMLElementInfo nameInfo;
+ nameInfo.attributes = (CFDictionaryRef)dict;
+ nameInfo.attributeOrder = (CFArrayRef) attr;
+ nameInfo.isEmpty = mDNSfalse;
+ CFXMLNodeRef nameNode = CFXMLNodeCreate(kCFAllocatorDefault, kCFXMLNodeTypeElement, CFSTR("key"), &nameInfo,
+ kCFXMLNodeCurrentVersion);
+ CFXMLTreeRef nameTree = CFXMLTreeCreateWithNode(kCFAllocatorDefault, nameNode);
+ CFTreeAppendChild(xmlTree, nameTree);
+ CFRelease(nameNode);
+ CFRelease(attr);
+ CFRelease(dict);
+ CFRelease(values[0]);
- return((ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) != 0);
+ /* Build the rest: value </key> */
+
+ CFXMLNodeRef nameTextNode = CFXMLNodeCreate(kCFAllocatorDefault, kCFXMLNodeTypeText, textval, NULL,
+ kCFXMLNodeCurrentVersion);
+ CFXMLTreeRef nameTextTree = CFXMLTreeCreateWithNode(kCFAllocatorDefault, nameTextNode);
+ CFTreeAppendChild(nameTree, nameTextTree);
+ CFRelease(nameTextTree);
+ CFRelease(nameTextNode);
+ CFRelease(textval);
+
+ // Now that we are done with nameTree, we can release it
+ CFRelease(nameTree);
+
+ return mDNStrue;
}
-// Returns pointer to newly created NetworkInterfaceInfoOSX object, or
-// pointer to already-existing NetworkInterfaceInfoOSX object found in list, or
-// may return NULL if out of memory (unlikely) or parameters are invalid for some reason
-// (e.g. sa_family not AF_INET or AF_INET6)
-mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa, mDNSs32 utc)
+mDNSlocal void LogPOSTArgs(CFStringRef finalURL, CFStringRef LoadTextName, CFStringRef LoadTextValue, CFDataRef bodyData)
{
- mDNSu32 scope_id = if_nametoindex(ifa->ifa_name);
- mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
+ char buf1[128], buf2[64], buf3[64], buf4[1024];
- mDNSAddr ip, mask;
- if (SetupAddr(&ip, ifa->ifa_addr ) != mStatus_NoError) return(NULL);
- if (SetupAddr(&mask, ifa->ifa_netmask) != mStatus_NoError) return(NULL);
+ if (!CFStringGetCString(finalURL, buf1, sizeof(buf1), kCFStringEncodingUTF8) ||
+ !CFStringGetCString(LoadTextName, buf2, sizeof(buf2), kCFStringEncodingUTF8) ||
+ !CFStringGetCString(LoadTextValue, buf3, sizeof(buf3), kCFStringEncodingUTF8))
+ {
+ LogMsg("mDNSEReportPOSTArgs: Error in parsing arguments");
+ return;
+ }
+ CFStringRef bstr = CFStringCreateFromExternalRepresentation(NULL, bodyData, kCFStringEncodingUTF8);
+ buf4[0] = 0;
+ if (!CFStringGetCString(bstr, buf4, sizeof(buf4), kCFStringEncodingUTF8))
+ {
+ LogMsg("mDNSEReportPOSTArgs: buf4 cstring conversion problem");
+ }
+ if (bstr) CFRelease(bstr);
+ LogInfo("LogPOSTArgs: URL : %s, LoadTextName: %s, LoadTextValue: %s, bodyData %s", buf1, buf2, buf3, buf4);
+ }
- NetworkInterfaceInfoOSX **p;
- for (p = &m->p->InterfaceList; *p; p = &(*p)->next)
- if (scope_id == (*p)->scope_id &&
- mDNSSameAddress(&ip, &(*p)->ifinfo.ip) &&
- mDNSSameEthAddress(&bssid, &(*p)->BSSID))
- {
- debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", 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;
+// This function is called when there is a valid configuration for eReporter service
+// We add the following:
+//
+// <key name="uuid"> uuid </key>
+// <key name="Subdomain"> subdomain </key>
+// <key name="Message"> message </key>
+// <key name="Time"> YYYY-MM-DD HH24:MI:SS </key>
+// <key name="SPS"> True/False </key>
+// <key name="Result"> Success/Fail </key>
+//
+// if result is -1, result won't be added. 1 means "Failed" and 0 means "Success"
+//
+mDNSlocal void mDNSReporterLogValidConfig(ELogContext *elog)
+ {
+ CFMutableStringRef finalURL = NULL;
+ CFStringRef LoadTextName = NULL;
+ CFDataRef bodyData = NULL;
+ CFBooleanRef pub;
+ CFXMLTreeRef appTree = NULL;
- // 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)
+ pub = (CFBooleanRef)eReporterGetValueForKey(eReporterConfig.eRDict, "Publish");
+ if (pub == NULL)
+ {
+ LogMsg("mDNSReporterLogValidConfig: Publish key does not exist");
+ return;
+ }
+
+ Boolean pubVal = CFBooleanGetValue(pub);
+ if (!pubVal)
+ {
+ // Set the config state to invalid so that we will refetch the configuration next time
+ // in case Publish value changes between now and then
+ eReporterConfig.eRState = ConfigInvalid;
+ LogInfo("mDNSReporterLogValidConfig: Value for Publish is %d", pubVal);
+ return;
+ }
+
+ CFXMLDocumentInfo documentInfo;
+ documentInfo.sourceURL = NULL;
+ documentInfo.encoding = kCFStringEncodingUTF8;
+ CFXMLNodeRef docNode = CFXMLNodeCreate( kCFAllocatorDefault, kCFXMLNodeTypeDocument, CFSTR(""), &documentInfo,
+ kCFXMLNodeCurrentVersion);
+ CFXMLTreeRef xmlDocument = CFXMLTreeCreateWithNode(kCFAllocatorDefault, docNode);
+ CFRelease(docNode);
+
+ /* <?xml version="1.0" encoding="utf-8"?> */
+ CFXMLProcessingInstructionInfo instructionInfo;
+ instructionInfo.dataString = CFSTR("version=\"1.0\" encoding=\"utf-8\"");
+ CFXMLNodeRef instructionNode = CFXMLNodeCreate(NULL, kCFXMLNodeTypeProcessingInstruction, CFSTR("xml"),
+ &instructionInfo, kCFXMLNodeCurrentVersion);
+ CFXMLTreeRef instructionTree = CFXMLTreeCreateWithNode(kCFAllocatorDefault, instructionNode);
+ CFTreeAppendChild(xmlDocument, instructionTree);
+ CFRelease(instructionTree);
+ CFRelease(instructionNode);
+
+ /* Root Element: <app name="mDNSResponder" version="XXX"> */
+
+ CFStringRef appKeys[2] = { CFSTR("name"), CFSTR("version") };
+ CFStringRef appValues[2] = { CFStringCreateWithCString(NULL, "mDNSResponder", kCFStringEncodingUTF8),
+ CFStringCreateWithCString(NULL, STRINGIFY(mDNSResponderVersion), kCFStringEncodingUTF8) };
+
+ CFDictionaryRef appDict = CFDictionaryCreate(NULL, (void*)appKeys, (void*)appValues, 2, &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (!appDict) { LogMsg("mDNSEReporterLogValidConfig: CFDictionaryCreate App failed"); goto cleanup; }
+
+ CFMutableArrayRef appAttr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (!appAttr) { LogMsg("mDNSEReporterLogValidConfig: CFArrayCreateMutable App failed"); goto cleanup; }
+
+ CFArrayAppendValue(appAttr, appKeys[0]);
+ CFArrayAppendValue(appAttr, appKeys[1]);
+
+ CFXMLElementInfo appInfo;
+ appInfo.attributes = (CFDictionaryRef) appDict;
+ appInfo.attributeOrder = (CFArrayRef) appAttr;
+ appInfo.isEmpty = mDNSfalse;
+ CFXMLNodeRef appNode = CFXMLNodeCreate ( kCFAllocatorDefault, kCFXMLNodeTypeElement, CFSTR("app"), &appInfo,
+ kCFXMLNodeCurrentVersion);
+ appTree = CFXMLTreeCreateWithNode(kCFAllocatorDefault, appNode);
+ CFTreeAppendChild(xmlDocument, appTree);
+ CFRelease(appNode);
+ CFRelease(appAttr);
+ CFRelease(appDict);
+ CFRelease(appValues[0]);
+ CFRelease(appValues[1]);
+ // appTree will be released at the end as we will be appeneding other nodes to appTree below
+
+ char uuidStr[37];
+ uuid_unparse(elog->uuid, uuidStr);
+ AddElementToTree(appTree, "UUID", uuidStr);
+
+ AddElementToTree(appTree, "Subdomain", elog->subdomain);
+ AddElementToTree(appTree, "Message", elog->message);
+
+ char tm_buffer[128];
+ time_t t = time(NULL);
+ struct tm *tm_t = gmtime(&t);
+ mDNS_snprintf(tm_buffer, sizeof(tm_buffer), "%4d-%02d-%02d %02d:%02d:%02d", tm_t->tm_year + 1900, tm_t->tm_mon + 1,
+ tm_t->tm_mday, tm_t->tm_hour, tm_t->tm_min, tm_t->tm_sec);
+ AddElementToTree(appTree, "Time", tm_buffer);
+
+ const CacheRecord *sps[3] = { mDNSNULL };
+ NetworkInterfaceInfo *intf;
+ mDNSBool SleepProxy = mDNSfalse;
+ for (intf = GetFirstActiveInterface(mDNSStorage.HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+ {
+ if (intf->NetWake)
+ {
+ FindSPSInCache(&mDNSStorage, &intf->NetWakeBrowse, sps);
+ if (sps[0])
{
- (*p)->ifinfo.NetWake = NetWake;
- // If this interface is already registered with mDNSCore, then we need to start or stop its NetWake browse on-the-fly.
- // If this interface is not already registered (i.e. it's a dormant interface we had in our list
- // from when we previously saw it) then we mustn't do that, because mDNSCore doesn't know about it yet.
- // In this case, the mDNS_RegisterInterface() call will take care of starting the NetWake browse if necessary.
- if ((*p)->Registered)
- {
- mDNS_Lock(m);
- if (NetWake) mDNS_ActivateNetWake_internal (m, &(*p)->ifinfo);
- else mDNS_DeactivateNetWake_internal(m, &(*p)->ifinfo);
- mDNS_Unlock(m);
- }
+ SleepProxy = mDNStrue;
+ break;
}
-
- return(*p);
}
+ else { LogInfo("mDNSEReporterValidConfig: NetWake is not set %p", intf->InterfaceID); }
+ }
+ AddElementToTree(appTree, "SPS", (SleepProxy ? "True" : "False"));
- NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *)mallocL("NetworkInterfaceInfoOSX", sizeof(*i));
- debugf("AddInterfaceToList: Making new interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, i);
- if (!i) return(mDNSNULL);
- mDNSPlatformMemZero(i, sizeof(NetworkInterfaceInfoOSX));
- i->ifinfo.InterfaceID = (mDNSInterfaceID)(uintptr_t)scope_id;
- i->ifinfo.ip = ip;
- i->ifinfo.mask = mask;
- strlcpy(i->ifinfo.ifname, ifa->ifa_name, sizeof(i->ifinfo.ifname));
- i->ifinfo.ifname[sizeof(i->ifinfo.ifname)-1] = 0;
- // We can be configured to disable multicast advertisement, but we want to to support
- // local-only services, which need a loopback address record.
- i->ifinfo.Advertise = m->DivertMulticastAdvertisements ? ((ifa->ifa_flags & IFF_LOOPBACK) ? mDNStrue : mDNSfalse) : m->AdvertiseLocalAddresses;
- i->ifinfo.McastTxRx = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList
+ if (elog->result != -1)
+ AddElementToTree(appTree, "Result", elog->result ? "fail" : "success");
- i->next = mDNSNULL;
- i->m = m;
- i->Exists = mDNStrue;
- 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->BPF_fd = -1;
- i->BPF_len = 0;
- i->Registered = mDNSNULL;
+ bodyData = CFXMLTreeCreateXMLData(NULL, xmlDocument);
+ if (!bodyData) { LogMsg("mDNSEReporterLogValidConfig: CFXMLTreeCreateData failed for bodyData"); goto cleanup; }
- // 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);
+ CFStringRef url = eReporterGetValueForKey(eReporterConfig.eRDict, "URL");
+ if (!url) { LogMsg("mDNSEReporterLogValidConfig: eReporterGetValueForKey failed for URL"); goto cleanup; }
- *p = i;
- return(i);
- }
+ CFStringRef uri = eReporterGetValueForKey(eReporterConfig.eRDict, "URI");
+ if (!uri) { LogMsg("mDNSEReporterLogValidConfig: eReporterGetValueForKey failed for URI"); goto cleanup; }
-#if USE_V6_ONLY_WHEN_NO_ROUTABLE_V4
-mDNSlocal NetworkInterfaceInfoOSX *FindRoutableIPv4(mDNS *const m, mDNSu32 scope_id)
- {
- NetworkInterfaceInfoOSX *i;
- for (i = m->p->InterfaceList; i; i = i->next)
- if (i->Exists && i->scope_id == scope_id && i->ifinfo.ip.type == mDNSAddrType_IPv4)
- if (!mDNSv4AddressIsLinkLocal(&i->ifinfo.ip.ip.v4))
- return(i);
- return(mDNSNULL);
- }
-#endif
+ finalURL = CFStringCreateMutable(NULL, 0);
+ if (!finalURL) { LogMsg("mDNSEReporterLogValidConfig: CFStringCreateMutable failed for finalURL"); goto cleanup; }
-#if APPLE_OSX_mDNSResponder
+ CFStringAppend(finalURL, url);
+ CFStringAppend(finalURL, uri);
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - AutoTunnel
-#endif
+ LoadTextName = CFStringCreateWithCString(NULL, "x-LoadText", kCFStringEncodingUTF8);
+ if (!LoadTextName) { LogMsg("mDNSEReporterLogValidConfig: CFStringCreateWithCString failed for LoadText"); goto cleanup; }
-#define kRacoonPort 4500
+ CFStringRef LoadTextValue = eReporterGetValueForKey(eReporterConfig.eRDict, "LoadText");
+ if (!LoadTextValue) { LogMsg("mDNSEReporterLogValidConfig: eReporterGetValueForKey failed for LoadTextValue"); goto cleanup; }
-static DomainAuthInfo* AnonymousRacoonConfig = mDNSNULL;
+ LogPOSTArgs(finalURL, LoadTextName, LoadTextValue, bodyData);
+
+ // we don't have a callback for the POST. If there is an error in POST, it will be logged
+ // by the callback of HTTPDataStream
+ HTTPDataStream(finalURL, HTTPPost, bodyData, LoadTextName, LoadTextValue, NULL, NULL, NULL, NULL);
+
+cleanup:
+ // Free whatever was allocated in this function
+ if (bodyData) CFRelease(bodyData);
+ if (finalURL) CFRelease(finalURL);
+ if (LoadTextName) CFRelease(LoadTextName);
+ if (appTree) CFRelease(appTree);
+ CFRelease(xmlDocument);
+ }
+
+mDNSlocal void mDNSEReporterLog(uuid_t *uuid, const char *subdomain, int result, char *message)
+ {
+ // We allocate ELogContext and free it at the end of the function. It is the
+ // responsibility of the called function to copy it if it needs to hold
+ // on to it
+ ELogContext *info = mallocL("ELogContext", sizeof (ELogContext));
+ if (!info) { LogMsg("mDNSEReporterLog: malloc failed"); return; }
+
+ // Take a local copy of all the log information
+ strlcpy(info->subdomain, subdomain, sizeof(info->subdomain));
+ strlcpy(info->message, message, sizeof(info->message));
+ info->result = result;
+ uuid_copy(info->uuid, *uuid);
+ if (eReporterConfig.eRState != ConfigValid)
+ {
+ // Currently we can't have two outstanding configuration fetches. If we have two quick
+ // back to back logs while the configuration is being fetched, we log only the first
+ // message to EReporter. If the configuration is valid (common case), then we don't
+ // drop any messages
+ if (!FetchEReporterConfiguration(info))
+ {
+ LogInfo("mDNSEReporterLog: Configuration being fetched.., Not logging");
+ }
+ freeL("ELogContext", info);
+ return;
+ }
+ mDNSReporterLogValidConfig(info);
+ freeL("ELogContext", info);
+ }
#ifndef NO_SECURITYFRAMEWORK
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)))
+ if (q->servAddr.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes(q->servAddr.ip.v4))
return mStatus_NoSuchRecord;
else if (q->state == LLQ_Poll)
return mStatus_PollingMode;
return mStatus_NoError;
}
+mDNSlocal mStatus UpdateLLQStatus(const mDNS *const m, char *buffer, int bufsz, const DomainAuthInfo *const info)
+ {
+ mStatus status = mStatus_NoError;
+ DNSQuestion* q, *worst_q = mDNSNULL;
+ for (q = m->Questions; q; q=q->next)
+ if (q->AuthInfo == info)
+ {
+ mStatus newStatus = CheckQuestionForStatus(q);
+ if (newStatus == mStatus_NoSuchRecord) { status = newStatus; worst_q = q; break; }
+ else if (newStatus == mStatus_PollingMode) { status = newStatus; worst_q = q; }
+ else if (newStatus == mStatus_TransientErr && status == mStatus_NoError) { status = newStatus; worst_q = q; }
+ }
+
+ if (status == mStatus_NoError) mDNS_snprintf(buffer, bufsz, "Success");
+ else if (status == mStatus_NoSuchRecord) mDNS_snprintf(buffer, bufsz, "GetZoneData %s: %##s", worst_q->nta ? "not yet complete" : "failed", worst_q->qname.c);
+ else if (status == mStatus_PollingMode) mDNS_snprintf(buffer, bufsz, "Query polling %##s", worst_q->qname.c);
+ else if (status == mStatus_TransientErr) mDNS_snprintf(buffer, bufsz, "Query not yet established %##s", worst_q->qname.c);
+ return status;
+ }
+
+mDNSlocal mStatus UpdateRRStatus(const mDNS *const m, char *buffer, int bufsz, const DomainAuthInfo *const info)
+ {
+ AuthRecord *r;
+
+ if (info->deltime) return mStatus_NoError;
+ for (r = m->ResourceRecords; r; r = r->next)
+ {
+ // This function is called from UpdateAutoTunnelDomainStatus which in turn may be called from
+ // a callback e.g., CheckNATMappings. GetAuthInfoFor_internal does not like that (reentrancy being 1),
+ // hence we inline the code here. We just need the lock to walk the list of AuthInfos which the caller
+ // has already checked
+ const domainname *n = r->resrec.name;
+ while (n->c[0])
+ {
+ DomainAuthInfo *ptr;
+ for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
+ if (SameDomainName(&ptr->domain, n))
+ {
+ if (ptr == info && r->updateError == mStatus_BadSig)
+ {
+ mDNS_snprintf(buffer, bufsz, "Resource record update failed for %##s", r->resrec.name);
+ return r->updateError;
+ }
+ }
+ n = (const domainname *)(n->c + 1 + n->c[0]);
+ }
+ }
+ return mStatus_NoError;
+ }
+
+#endif // ndef NO_SECURITYFRAMEWORK
+
// MUST be called with lock held
mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAuthInfo *const info)
{
CFNumberRef num = NULL;
mStatus status = mStatus_NoError;
+ if (!m->mDNS_busy) LogMsg("UpdateAutoTunnelDomainStatus: ERROR!! Lock not held");
if (!domainStatusDict)
{
domainStatusDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
}
- if (!llq && !tun)
+ // If we have a relay address, check the LLQ status as they don't go over the relay connection.
+ // If LLQs fail, then report failure. In future, when LLQs go over the relay connection, we don't
+ // need this logic
+ if (!mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
+ {
+ // If we have a bad signature error updating RR, it overrides any error as
+ // the user needs to be notified immediately
+ status = UpdateRRStatus(m, buffer, sizeof(buffer), info);
+ if (status == mStatus_NoError)
+ {
+ status = UpdateLLQStatus(m, buffer, sizeof(buffer), info);
+ if (status == mStatus_PollingMode)
+ {
+ // If we have a relay connection and we are in polling mode, report as success.
+ // This normally happens when we are behind Double NAT or NAT with UPnP/NAT-PMP
+ // disabled but we are able to successfully file share/screen share with the help
+ // of the relay connection. As it just affects the discovery/update of the other
+ // BTMM hosts, we consider it as minor issue and report it as success.
+ LogInfo("UpdateAutoTunnelDomainStatus:NonzeroRelayAddress: Polling reported as success");
+ status = mStatus_NoError;
+ mDNS_snprintf(buffer, sizeof(buffer), "Success");
+ }
+ }
+ LogInfo("UpdateAutoTunnelDomainStatus:NonzeroRelayAddress: Status %d, %s", status, buffer);
+ }
+ else if (!llq && !tun)
{
status = mStatus_NotInitializedErr;
mDNS_snprintf(buffer, sizeof(buffer), "Neither LLQ nor AutoTunnel NAT port mapping is currently active");
}
else
{
- DNSQuestion* q, *worst_q = mDNSNULL;
- for (q = m->Questions; q; q=q->next)
- if (q->AuthInfo == info)
- {
- mStatus newStatus = CheckQuestionForStatus(q);
- if (newStatus == mStatus_NoSuchRecord) { status = newStatus; worst_q = q; break; }
- else if (newStatus == mStatus_PollingMode) { status = newStatus; worst_q = q; }
- else if (newStatus == mStatus_TransientErr && status == mStatus_NoError) { status = newStatus; worst_q = q; }
- }
-
- if (status == mStatus_NoError) mDNS_snprintf(buffer, 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);
+ status = UpdateRRStatus(m, buffer, sizeof(buffer), info);
+ if (status == mStatus_NoError)
+ status = UpdateLLQStatus(m, buffer, sizeof(buffer), info);
+ LogInfo("UpdateAutoTunnelDomainStatus:ZeroRelayAddress: Status %d, %s", status, buffer);
}
num = CFNumberCreate(NULL, kCFNumberSInt32Type, &status);
static char statusBuf[16];
mDNS_snprintf(statusBuf, sizeof(statusBuf), "%d", (int)status);
mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.domainstatus", status ? "failure" : "success", statusBuf, "");
+ mDNSEReporterLog((uuid_t *)&m->asl_uuid, "autotunnel.domainstatus", status, statusBuf);
mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
}
}
CFRelease(domain);
CFRelease(dict);
+
debugf("UpdateAutoTunnelDomainStatus: %s", buffer);
#endif // def NO_SECURITYFRAMEWORK
}
#ifdef NO_SECURITYFRAMEWORK
(void)m;
#else
+ if (!m->mDNS_busy) LogMsg("UpdateAutoTunnelDomainStatuses: ERROR!! Lock not held");
DomainAuthInfo* info;
for (info = m->AuthInfoList; info; info = info->next)
if (info->AutoTunnel && !info->deltime)
// MUST be called with lock held
mDNSlocal mDNSBool TunnelServers(mDNS *const m)
{
- ServiceRecordSet *p;
- for (p = m->ServiceRegistrations; p; p = p->uDNS_next)
- {
- 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)
return(mDNSfalse);
}
-mDNSlocal void RegisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
+mDNSlocal void UpdateAnonymousRacoonConfig(mDNS *m) // Determine whether we need racoon to accept incoming connections
{
- if (info->AutoTunnelNAT.clientContext && !info->AutoTunnelNAT.Result && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) && AutoTunnelUnregistered(info))
+ DomainAuthInfo *info;
+
+ for (info = m->AuthInfoList; info; info = info->next)
+ if (info->AutoTunnel && !info->deltime && (!mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) || !mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr)))
+ break;
+
+ if (info != AnonymousRacoonConfig)
{
- mStatus err;
- LogInfo("RegisterAutoTunnelRecords %##s (%#s)", info->domain.c, m->hostlabel.c);
+ AnonymousRacoonConfig = info;
+ // Create or revert configuration file, and start (or SIGHUP) Racoon
+ (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, AnonymousRacoonConfig ? &AnonymousRacoonConfig->domain : mDNSNULL);
+ }
+ }
+
+// Caller should hold the lock. We don't call mDNS_Register (which acquires the lock) in this function because
+// sometimes the caller may already be holding the lock e.g., RegisterAutoTunnel6Record and sometimes
+// not e.g., RegisterAutoTunnelServiceRecord
+mDNSlocal void RegisterAutoTunnelHostRecord(mDNS *m, DomainAuthInfo *info)
+ {
+ mStatus err;
+ mDNSBool NATProblem;
+
+ if (!m->mDNS_busy) LogMsg("RegisterAutoTunnelHostRecord: ERROR!! Lock not held");
+
+ // We use AutoTunnelNAT.clientContext to infer that SetupLocalAutoTunnelInterface_internal has been
+ // called at least once with some Services/Records in the domain and hence it is safe to register
+ // records when this function is called.
+ if (!info->AutoTunnelNAT.clientContext) { LogInfo("RegisterAutoTunnelHostRecord: No services registered, not registering the record\n"); return; }
+
+ // Are we behind a NAT with no NAT-PMP support or behind a Double NAT ? Double NATs may have
+ // NAT-PMP support but it still does not provide inbound connectivity. If there is no NAT-PMP
+ // support, ExternalPort is zero. If we are behind a Double NAT, then the NATResult is non-zero.
+
+ NATProblem = mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) || info->AutoTunnelNAT.Result;
+
+ if (mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
+ {
+ // If we don't have a relay address, check to see if we are behind a Double NAT or NAT with no NAT-PMP
+ // support.
+ if (NATProblem)
+ {
+ LogInfo("RegisterAutoTunnelHostRecord %##s, not registering the Host Record, Neither AutoTunnel6 nor NAT is available, ClientContext %p, ExternalPort %d, NAT Result %d", info->domain.c, info->AutoTunnelNAT.clientContext, mDNSVal16(info->AutoTunnelNAT.ExternalPort), info->AutoTunnelNAT.Result);
+ return;
+ }
+ }
+ else
+ {
+ // Relay address may be non-zero but we might be going to sleep as the utun interface is not removed
+ // when going to sleep. If we are awake, we don't care about the NATProblem as the relay connnection
+ // is up. If we are going to sleep, we should not register the host record if we have a NAT problem.
+ if (m->SleepState != SleepState_Awake && NATProblem)
+ {
+ LogInfo("RegisterAutoTunnelHostRecord %##s, not registering the Host Record, Not in awake state(%d), and some NAT Problem, ClientContext %p, ExternalPort %d, NAT Result %d", info->domain.c, m->SleepState, info->AutoTunnelNAT.clientContext, mDNSVal16(info->AutoTunnelNAT.ExternalPort), info->AutoTunnelNAT.Result);
+ return;
+ }
+ }
- // 1. Set up our address record for the internal tunnel address
- // (User-visible user-friendly host name, used as target in AutoTunnel SRV records)
+ // Note:
+ //
+ // We use zero Requested port to infer that we should not be calling Register anymore as it might
+ // be shutdown or the DomainAuthInfo is going away.
+ //
+ // We can use a different set of state variables to track the above as the records registered in
+ // this function is not dependent on NAT traversal info. For the sake of simplicity, we just
+ // reuse the NAT variables.
+
+ // Set up our address record for the internal tunnel address
+ // (User-visible user-friendly host name, used as target in AutoTunnel SRV records)
+ if (!mDNSIPPortIsZero(info->AutoTunnelNAT.RequestedPort) && info->AutoTunnelHostRecord.resrec.RecordType == kDNSRecordTypeUnregistered)
+ {
info->AutoTunnelHostRecord.namestorage.c[0] = 0;
AppendDomainLabel(&info->AutoTunnelHostRecord.namestorage, &m->hostlabel);
AppendDomainName (&info->AutoTunnelHostRecord.namestorage, &info->domain);
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);
- // 2. Set up device info record
- ConstructServiceName(&info->AutoTunnelDeviceInfo.namestorage, &m->nicelabel, &DeviceInfoName, &info->domain);
- mDNSu8 len = m->HIHardware.c[0] < 255 - 6 ? m->HIHardware.c[0] : 255 - 6;
- mDNSPlatformMemCopy(info->AutoTunnelDeviceInfo.resrec.rdata->u.data + 1, "model=", 6);
- mDNSPlatformMemCopy(info->AutoTunnelDeviceInfo.resrec.rdata->u.data + 7, m->HIHardware.c + 1, len);
- info->AutoTunnelDeviceInfo.resrec.rdata->u.data[0] = 6 + len; // "model=" plus the device string
- info->AutoTunnelDeviceInfo.resrec.rdlength = 7 + len; // One extra for the length byte at the start of the string
- info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeKnownUnique;
- err = mDNS_Register(m, &info->AutoTunnelDeviceInfo);
- if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelDeviceInfo %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
+ err = mDNS_Register_internal(m, &info->AutoTunnelHostRecord);
+
+ if (err) LogMsg("RegisterAutoTunnelHostRecord error %d registering AutoTunnelHostRecord %##s", err, info->AutoTunnelHostRecord.namestorage.c);
+ else
+ {
+ // Make sure we trigger the registration of all SRV records in regState_NoTarget again
+ m->NextSRVUpdate = NonZeroTime(m->timenow);
+ LogInfo("RegisterAutoTunnelHostRecord registering AutoTunnelHostRecord %##s", info->AutoTunnelHostRecord.namestorage.c);
+ }
+ }
+ else LogInfo("RegisterAutoTunnelHostRecord: Not registering Context %p Port %d Type %d", info->AutoTunnelNAT.clientContext, mDNSVal16(info->AutoTunnelNAT.RequestedPort), info->AutoTunnelHostRecord.resrec.RecordType);
+ }
+
+mDNSlocal void DeregisterAutoTunnelHostRecord(mDNS *m, DomainAuthInfo *info)
+ {
+ LogInfo("DeregisterAutoTunnelHostRecord %##s", info->domain.c);
+
+ // Don't deregister if we have the AutoTunnel6 or AutoTunnelService records are registered.
+ // They indicate that BTMM is working
+ if (info->AutoTunnel6Record.resrec.RecordType > kDNSRecordTypeDeregistering ||
+ info->AutoTunnelService.resrec.RecordType > kDNSRecordTypeDeregistering)
+ {
+ LogInfo("DeregisterAutoTunnelHostRecord %##s, not deregistering the Host Record AutoTunnel6 RecordType:%d AutoTunnel RecordType: %d", info->domain.c,
+ info->AutoTunnel6Record.resrec.RecordType, info->AutoTunnelService.resrec.RecordType);
+ return;
+ }
+
+ if (info->AutoTunnelHostRecord.resrec.RecordType > kDNSRecordTypeDeregistering)
+ {
+ mStatus err = mDNS_Deregister(m, &info->AutoTunnelHostRecord);
+ if (err)
+ {
+ info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeUnregistered;
+ LogMsg("DeregisterAutoTunnelHostRecord error %d deregistering AutoTunnelHostRecord %##s", err, info->AutoTunnelHostRecord.namestorage.c);
+ }
+ else LogInfo("DeregisterAutoTunnelHostRecord: Deregistered AutoTunnel Host Record");
+ }
+ else LogInfo("DeregisterAutoTunnelHostRecord: Not deregistering Host Record state:%d", info->AutoTunnelHostRecord.resrec.RecordType);
+ }
+
+mDNSlocal void RegisterAutoTunnelServiceRecords(mDNS *m, DomainAuthInfo *info)
+ {
+ mStatus err;
+
+ //if (m->mDNS_busy) LogMsg("RegisterAutoTunnelServiceRecords: ERROR!! Lock already held");
+
+ if (info->AutoTunnelNAT.clientContext && !info->AutoTunnelNAT.Result && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) && info->AutoTunnelTarget.resrec.RecordType == kDNSRecordTypeUnregistered)
+ {
+ LogInfo("RegisterAutoTunnelServiceRecords %##s (%#s)", info->domain.c, m->hostlabel.c);
- // 3. Set up our address record for the external tunnel address
+ // 1. Set up our address record for the external tunnel address
// (Constructed name, not generally user-visible, used as target in IKE tunnel's SRV record)
info->AutoTunnelTarget.namestorage.c[0] = 0;
AppendDomainLabel(&info->AutoTunnelTarget.namestorage, &m->AutoTunnelLabel);
AppendDomainName (&info->AutoTunnelTarget.namestorage, &info->domain);
+ info->AutoTunnelTarget.resrec.rdata->u.ipv4 = info->AutoTunnelNAT.ExternalAddress;
info->AutoTunnelTarget.resrec.RecordType = kDNSRecordTypeKnownUnique;
- mDNS_Lock(m);
- mDNS_AddDynDNSHostName(m, &info->AutoTunnelTarget.namestorage, mDNSNULL, info);
- mDNS_Unlock(m);
+ err = mDNS_Register(m, &info->AutoTunnelTarget);
+ if (err) LogMsg("RegisterAutoTunnelServiceRecords error %d registering AutoTunnelTarget %##s", err, info->AutoTunnelTarget.namestorage.c);
+ else LogInfo("RegisterAutoTunnelServiceRecords registering AutoTunnelTarget %##s", info->AutoTunnelTarget.namestorage.c);
+
+ }
- // 4. Set up IKE tunnel's SRV record: "AutoTunnelHostRecord SRV 0 0 port AutoTunnelTarget"
+ if (info->AutoTunnelNAT.clientContext && !info->AutoTunnelNAT.Result && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) && info->AutoTunnelService.resrec.RecordType == kDNSRecordTypeUnregistered)
+ {
+ // 2. Set up IKE tunnel's SRV record: "AutoTunnelHostRecord SRV 0 0 port AutoTunnelTarget"
AssignDomainName (&info->AutoTunnelService.namestorage, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
AppendDomainLabel(&info->AutoTunnelService.namestorage, &m->hostlabel);
AppendDomainName (&info->AutoTunnelService.namestorage, &info->domain);
AssignDomainName(&info->AutoTunnelService.resrec.rdata->u.srv.target, &info->AutoTunnelTarget.namestorage);
info->AutoTunnelService.resrec.RecordType = kDNSRecordTypeKnownUnique;
err = mDNS_Register(m, &info->AutoTunnelService);
- if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
+ if (err) LogMsg("RegisterAutoTunnelServiceRecords error %d registering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
+ else LogInfo("RegisterAutoTunnelServiceRecords registering AutoTunnelService %##s", info->AutoTunnelService.namestorage.c);
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);
}
+ mDNS_Lock(m);
+ RegisterAutoTunnelHostRecord(m, info);
+ mDNS_Unlock(m);
}
-mDNSlocal void DeregisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
+mDNSlocal void DeregisterAutoTunnelServiceRecords(mDNS *m, DomainAuthInfo *info)
{
- LogInfo("DeregisterAutoTunnelRecords %##s", info->domain.c);
- if (info->AutoTunnelService.resrec.RecordType > kDNSRecordTypeDeregistering)
+ LogInfo("DeregisterAutoTunnelServiceRecords %##s", info->domain.c);
+ if (info->AutoTunnelTarget.resrec.RecordType > kDNSRecordTypeDeregistering)
{
- mStatus err = mDNS_Deregister(m, &info->AutoTunnelService);
+ mStatus err = mDNS_Deregister(m, &info->AutoTunnelTarget);
if (err)
{
- info->AutoTunnelService.resrec.RecordType = kDNSRecordTypeUnregistered;
- LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
+ info->AutoTunnelTarget.resrec.RecordType = kDNSRecordTypeUnregistered;
+ LogMsg("DeregisterAutoTunnelServiceRecords error %d deregistering AutoTunnelTarget %##s", err, info->AutoTunnelTarget.namestorage.c);
}
+ else LogInfo("DeregisterAutoTunnelServiceRecords: Deregistered AutoTunnel Target Record");
- mDNS_Lock(m);
- mDNS_RemoveDynDNSHostName(m, &info->AutoTunnelTarget.namestorage);
- mDNS_Unlock(m);
}
+ else LogInfo("DeregisterAutoTunnelServiceRecords: Not deregistering Target record state:%d", info->AutoTunnelService.resrec.RecordType);
- if (info->AutoTunnelHostRecord.resrec.RecordType > kDNSRecordTypeDeregistering)
+ if (info->AutoTunnelService.resrec.RecordType > kDNSRecordTypeDeregistering)
{
- mStatus err = mDNS_Deregister(m, &info->AutoTunnelHostRecord);
+ mStatus err = mDNS_Deregister(m, &info->AutoTunnelService);
if (err)
{
- info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeUnregistered;
- LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelHostRecord %##s", err, info->AutoTunnelHostRecord.namestorage.c);
+ info->AutoTunnelService.resrec.RecordType = kDNSRecordTypeUnregistered;
+ LogMsg("DeregisterAutoTunnelServiceRecords error %d deregistering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
}
+ else LogInfo("DeregisterAutoTunnelServiceRecords: Deregistered AutoTunnel Service Record");
+
+ }
+ else LogInfo("DeregisterAutoTunnelServiceRecords: Not deregistering service records state:%d", info->AutoTunnelService.resrec.RecordType);
+
+ DeregisterAutoTunnelHostRecord(m, info);
+ }
+
+// Caller should hold the lock. We don't call mDNS_Register (which acquires the lock) in this function because
+// sometimes the caller may already be holding the lock e.g., SetupLocalAutoTunnelInterface_internal and sometimes
+// not e.g., AutoTunnelHostNameChanged
+mDNSlocal void RegisterAutoTunnelDevInfoRecord(mDNS *m, DomainAuthInfo *info)
+ {
+ mStatus err;
+
+ if (!m->mDNS_busy) LogMsg("RegisterAutoTunnelDevInfoRecord: Lock not held");
+ // Note:
+ // a. We use AutoTunnelNAT.clientContext to infer that SetupLocalAutoTunnelInterface_internal has been
+ // called at least once with some Services/Records in the domain and hence it is safe to register
+ // records when this function is called.
+ //
+ // b. We use zero Requested port to infer that we should not be calling Register anymore as it might
+ // be shutdown or the DomainAuthInfo is going away.
+ //
+ // We can use a different set of state variables to track the above as the records registered in
+ // this function is not dependent on NAT traversal info. For the sake of simplicity, we just
+ // reuse the NAT variables.
+
+ // Set up device info record
+ if (info->AutoTunnelNAT.clientContext && !mDNSIPPortIsZero(info->AutoTunnelNAT.RequestedPort) && info->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered)
+ {
+ ConstructServiceName(&info->AutoTunnelDeviceInfo.namestorage, &m->nicelabel, &DeviceInfoName, &info->domain);
+ mDNSu8 len = m->HIHardware.c[0] < 255 - 6 ? m->HIHardware.c[0] : 255 - 6;
+ mDNSPlatformMemCopy(info->AutoTunnelDeviceInfo.resrec.rdata->u.data + 1, "model=", 6);
+ mDNSPlatformMemCopy(info->AutoTunnelDeviceInfo.resrec.rdata->u.data + 7, m->HIHardware.c + 1, len);
+ info->AutoTunnelDeviceInfo.resrec.rdata->u.data[0] = 6 + len; // "model=" plus the device string
+ info->AutoTunnelDeviceInfo.resrec.rdlength = 7 + len; // One extra for the length byte at the start of the string
+ info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeKnownUnique;
+
+ err = mDNS_Register_internal(m, &info->AutoTunnelDeviceInfo);
+ if (err) LogMsg("RegisterAutoTunnelDevInfoRecord error %d registering AutoTunnelDeviceInfo %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
+ else LogInfo("RegisterAutoTunnelDevInfoRecord registering AutoTunnelDeviceInfo %##s", info->AutoTunnelDeviceInfo.namestorage.c);
}
+ }
+
+#ifndef NO_SECURITYFRAMEWORK
+mDNSlocal void DeregisterAutoTunnelDevInfoRecord(mDNS *m, DomainAuthInfo *info)
+ {
+ LogInfo("DeregisterAutoTunnelDevInfoRecord %##s", info->domain.c);
if (info->AutoTunnelDeviceInfo.resrec.RecordType > kDNSRecordTypeDeregistering)
{
if (err)
{
info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeUnregistered;
- LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelDeviceInfo %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
+ LogMsg("DeregisterAutoTunnelDevInfoRecord error %d deregistering AutoTunnelDeviceInfo %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
+ }
+ else LogInfo("DeregisterAutoTunnelDevInfoRecord: Deregistered AutoTunnel Device Info");
+ }
+ else LogInfo("DeregisterAutoTunnelDevInfoRecord: Not deregistering DeviceInfo Record state:%d", info->AutoTunnelDeviceInfo.resrec.RecordType);
+ }
+#endif
+
+
+// Caller should hold the lock. We don't call mDNS_Register (which acquires the lock) in this function because
+// sometimes the caller may already be holding the lock e.g., SetupLocalAutoTunnelInterface_internal and sometimes
+// not e.g., AutoTunnelHostNameChanged
+mDNSlocal void RegisterAutoTunnel6Record(mDNS *m, DomainAuthInfo *info)
+ {
+ mStatus err;
+
+ if (!m->mDNS_busy) LogMsg("RegisterAutoTunnel6Record: ERROR!! Lock not held");
+
+ // We deregister the AutoTunnel6Record during sleep and come back here (AutoTunnelRecordCallback) to
+ // register the address if needed. During that time, we might get a network change event which finds
+ // that the utun interface exists and tries to register the AutoTunnel6Record which should be stopped.
+ // Also the RelayAddress is reinitialized during that process which in turn causes the AutoTunnelRecordCallback
+ // to re-register again. To stop these, we check for the SleepState and register only if we are awake.
+ if (m->SleepState != SleepState_Awake)
+ {
+ LogInfo("RegisterAutoTunnel6Record: Not in awake state, SleepState %d", m->SleepState);
+ return;
+ }
+
+ // if disabled administratively, don't register
+ // if disabled administratively, don't register
+ if (!m->RegisterAutoTunnel6 || DisableInboundRelayConnection)
+ {
+ LogInfo("RegisterAutoTunnel6Record: registration Disabled RegisterAutoTunnel6 %d, DisableInbound %d",
+ m->RegisterAutoTunnel6, DisableInboundRelayConnection);
+ return;
+ }
+ //
+ // If we have a valid Relay address, we need to register it now. When we got a valid address, we may not
+ // have registered it because it was waiting for at least one service to become active in the BTMM domain.
+ // During network change event, we might be called multiple times while the "Connectivity" key did not
+ // change, so check to see if the value has changed. This can also be zero when we are deregistering and
+ // getting called from the AutoTunnelRecordCallback
+
+ if (mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
+ {
+ LogInfo("RegisterAutoTunnel6Record: Relay address is zero, not registering");
+ return;
+ }
+
+ if ((info->AutoTunnel6Record.resrec.RecordType > kDNSRecordTypeDeregistering) &&
+ (mDNSSameIPv6Address(info->AutoTunnel6Record.resrec.rdata->u.ipv6, m->AutoTunnelRelayAddr)))
+ {
+ LogInfo("RegisterAutoTunnel6Record: Relay address %.16a same, not registering", &m->AutoTunnelRelayAddr);
+ return;
+ }
+
+ // Note:
+ // a. We use AutoTunnelNAT.clientContext to infer that SetupLocalAutoTunnelInterface_internal has been
+ // called at least once with some Services/Records in the domain and hence it is safe to register
+ // records when this function is called.
+ //
+ // b. We use zero Requested port to infer that we should not be calling Register anymore as it might
+ // be shutdown or the DomainAuthInfo is going away.
+ //
+ // We can use a different set of state variables to track the above as the records registered in
+ // this function is not dependent on NAT traversal info. For the sake of simplicity, we just
+ // reuse the NAT variables.
+
+ if (info->AutoTunnelNAT.clientContext && !mDNSIPPortIsZero(info->AutoTunnelNAT.RequestedPort) &&
+ info->AutoTunnel6Record.resrec.RecordType == kDNSRecordTypeUnregistered)
+ {
+ AssignDomainName (&info->AutoTunnel6Record.namestorage, (const domainname*) "\x0C" "_autotunnel6");
+ AppendDomainLabel(&info->AutoTunnel6Record.namestorage, &m->hostlabel);
+ AppendDomainName (&info->AutoTunnel6Record.namestorage, &info->domain);
+ info->AutoTunnel6Record.resrec.rdata->u.ipv6 = m->AutoTunnelRelayAddr;
+ info->AutoTunnel6Record.resrec.RecordType = kDNSRecordTypeKnownUnique;
+
+ err = mDNS_Register_internal(m, &info->AutoTunnel6Record);
+ if (err) LogMsg("RegisterAutoTunnel6Record error %d registering AutoTunnel6 Record %##s", err, info->AutoTunnel6Record.namestorage.c);
+ else LogInfo("RegisterAutoTunnel6Record registering AutoTunnel6 Record %##s", info->AutoTunnel6Record.namestorage.c);
+
+ LogInfo("AutoTunnel6 server listening for connections on %##s[%.16a] :%##s[%.16a]",
+ info->AutoTunnel6Record.namestorage.c, &m->AutoTunnelRelayAddr,
+ info->AutoTunnelHostRecord.namestorage.c, &m->AutoTunnelHostAddr);
+
+ } else {LogInfo("RegisterAutoTunnel6Record: client context %p, RequestedPort %d, Address %.16a, record type %d", info->AutoTunnelNAT.clientContext, info->AutoTunnelNAT.RequestedPort, &m->AutoTunnelRelayAddr, info->AutoTunnel6Record.resrec.RecordType);}
+
+ RegisterAutoTunnelHostRecord(m, info);
+ // When the AutoTunnel6 record comes up, we need to kick racoon and update the status.
+ // If we had a port mapping, we would have done it in RegisterAutoTunnelServiceRecords.
+ // If we don't have a port mapping, we need to do it here.
+ UpdateAnonymousRacoonConfig(m); // Determine whether we need racoon to accept incoming connections
+ UpdateAutoTunnelDomainStatus(m, info);
+ }
+
+mDNSlocal void DeregisterAutoTunnel6Record(mDNS *m, DomainAuthInfo *info)
+ {
+ LogInfo("DeregisterAutoTunnel6Record %##s", info->domain.c);
+
+ if (info->AutoTunnel6Record.resrec.RecordType > kDNSRecordTypeDeregistering)
+ {
+ mStatus err = mDNS_Deregister(m, &info->AutoTunnel6Record);
+ if (err)
+ {
+ info->AutoTunnel6Record.resrec.RecordType = kDNSRecordTypeUnregistered;
+ info->AutoTunnel6Record.resrec.rdata->u.ipv6 = zerov6Addr;
+ LogMsg("DeregisterAutoTunnel6Record error %d deregistering AutoTunnel6Record %##s", err, info->AutoTunnel6Record.namestorage.c);
}
+ else LogInfo("DeregisterAutoTunnel6Record: Deregistered AutoTunnel6 Record");
}
+ else LogInfo("DeregisterAutoTunnel6Record: Not deregistering AuoTunnel6 record state:%d", info->AutoTunnel6Record.resrec.RecordType);
+
+ DeregisterAutoTunnelHostRecord(m, info);
+ // UpdateAutoTunnelDomainStatus is careful enough not to turn it on if we don't have
+ // a external port mapping. Otherwise, it will be turned off.
+ mDNS_Lock(m);
+ UpdateAutoTunnelDomainStatus(m, info);
+ mDNS_Unlock(m);
}
mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
{
rr->namestorage.c[0] = 0;
m->NextSRVUpdate = NonZeroTime(m->timenow);
+ LogInfo("AutoTunnelRecordCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
+ }
+ if (m->ShutdownTime) {LogInfo("AutoTunnelRecordCallback: Shutdown, returning");return;}
+ if (rr == &info->AutoTunnelHostRecord)
+ {
+ LogInfo("AutoTunnelRecordCallback: calling RegisterAutoTunnelHostRecord");
+ RegisterAutoTunnelHostRecord(m,info);
+ }
+ else if (rr == &info->AutoTunnelDeviceInfo)
+ {
+ LogInfo("AutoTunnelRecordCallback: Calling RegisterAutoTunnelDevInfoRecord");
+ RegisterAutoTunnelDevInfoRecord(m,info);
+ }
+ else if (rr == &info->AutoTunnelService || rr == &info->AutoTunnelTarget)
+ {
+ LogInfo("AutoTunnelRecordCallback: Calling RegisterAutoTunnelServiceRecords");
+ RegisterAutoTunnelServiceRecords(m,info);
+ }
+ else if (rr == &info->AutoTunnel6Record)
+ {
+ LogInfo("AutoTunnelRecordCallback: Calling RegisterAutoTunnel6Record");
+ info->AutoTunnel6Record.resrec.rdata->u.ipv6 = zerov6Addr;
+ RegisterAutoTunnel6Record(m,info);
}
- RegisterAutoTunnelRecords(m,info);
}
}
-// Determine whether we need racoon to accept incoming connections
-mDNSlocal void UpdateConfigureServer(mDNS *m)
+#ifndef NO_SECURITYFRAMEWORK
+mDNSlocal void AutoTunnelDeleteAuthInfoState(mDNS *m, DomainAuthInfo *info)
{
- 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);
- }
+ LogInfo("AutoTunnelDeleteAuthInfoState: Cleaning up state releated to Domain AuthInfo %##s", info->domain.c);
+
+ m->NextSRVUpdate = NonZeroTime(m->timenow);
+ DeregisterAutoTunnelDevInfoRecord(m, info);
+ DeregisterAutoTunnelServiceRecords(m, info);
+ DeregisterAutoTunnel6Record(m, info);
+ UpdateAnonymousRacoonConfig(m); // Determine whether we need racoon to accept incoming connections
+ UpdateAutoTunnelDomainStatus(m, info);
}
-
+#endif // ndef NO_SECURITYFRAMEWORK
+
mDNSlocal void AutoTunnelNATCallback(mDNS *m, NATTraversalInfo *n)
{
DomainAuthInfo *info = (DomainAuthInfo *)n->clientContext;
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);
+ LogInfo("AutoTunnelNATCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
+
+ DeregisterAutoTunnelServiceRecords(m, info);
+ RegisterAutoTunnelServiceRecords(m, info);
- UpdateConfigureServer(m);
+ UpdateAnonymousRacoonConfig(m); // Determine whether we need racoon to accept incoming connections
UpdateAutoTunnelDomainStatus(m, (DomainAuthInfo *)n->clientContext);
}
LogMsg("AbortDeregistration ERROR RecordType %02X for %s", ARDisplayString(m, rr));
}
+mDNSlocal void AutoTunnelHostNameChanged(mDNS *m, DomainAuthInfo *info)
+ {
+ LogInfo("AutoTunnelHostNameChanged %#s.%##s", m->hostlabel.c, info->domain.c);
+
+ DeregisterAutoTunnelDevInfoRecord(m, info);
+ DeregisterAutoTunnelServiceRecords(m, info);
+ DeregisterAutoTunnel6Record(m, info);
+ RegisterAutoTunnelServiceRecords(m, info);
+
+ mDNS_Lock(m);
+ RegisterAutoTunnelDevInfoRecord(m, info);
+ RegisterAutoTunnel6Record(m, info);
+ m->NextSRVUpdate = NonZeroTime(m->timenow);
+ mDNS_Unlock(m);
+ }
+
+mDNSlocal void SetupLocalAutoTunnel6Records(mDNS *const m, DomainAuthInfo *info)
+ {
+ AbortDeregistration(m, &info->AutoTunnelDeviceInfo);
+ AbortDeregistration(m, &info->AutoTunnel6Record);
+
+ // When the BTMM is turned on/off too quickly, following things happen.
+ //
+ // 1. Turning off BTMM triggers deregistration of the DevInfo/AutoTunnel6 etc. records
+ // 2. While (1) is in progress, the BTMM is turned on
+ //
+ // At step (2), mDNS_SetSecretForDomain clears info->deltime indicating that the domain is valid
+ // while we have not processed the turning off BTMM completely. Hence, we end up calling this
+ // function to re-register the records. AbortDeregistration above aborts the Deregistration as the
+ // records are still in Deregistering state and in AutoTunnelRecordCallback we end up registering
+ // again. So, we have to be careful below to not call mDNS_SetupResourceRecord again which will
+ // reset the state to Unregistered and registering again will lead to error as it is registered
+ // and already in the list. Hence, register below only if needed.
+
+ if (info->AutoTunnelDeviceInfo.resrec.RecordType != kDNSRecordTypeUnregistered ||
+ info->AutoTunnel6Record.resrec.RecordType != kDNSRecordTypeUnregistered)
+ {
+ LogInfo("SetupLocalAutoTunnel6Records: AutoTunnel Records not in Unregistered state: Device: %d, AutoTunnel6:%d",
+ info->AutoTunnelDeviceInfo.resrec.RecordType, info->AutoTunnel6Record.resrec.RecordType);
+ }
+
+ if (info->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered)
+ {
+ mDNS_SetupResourceRecord(&info->AutoTunnelDeviceInfo, mDNSNULL, mDNSInterface_Any, kDNSType_TXT, kStandardTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
+ RegisterAutoTunnelDevInfoRecord(m, info);
+ }
+ if (info->AutoTunnel6Record.resrec.RecordType == kDNSRecordTypeUnregistered)
+ {
+ mDNS_SetupResourceRecord(&info->AutoTunnel6Record, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
+ RegisterAutoTunnel6Record(m, info);
+ }
+
+ UpdateAnonymousRacoonConfig(m); // Determine whether we need racoon to accept incoming connections
+
+ UpdateAutoTunnelDomainStatus(m, info);
+ m->NextSRVUpdate = NonZeroTime(m->timenow);
+ }
+
// Before SetupLocalAutoTunnelInterface_internal is called,
// m->AutoTunnelHostAddr.b[0] must be non-zero, and there must be at least one TunnelClient or TunnelServer
// Must be called with the lock held
-mDNSexport void SetupLocalAutoTunnelInterface_internal(mDNS *const m)
+mDNSexport void SetupLocalAutoTunnelInterface_internal(mDNS *const m, mDNSBool servicesStarting)
{
- LogInfo("SetupLocalAutoTunnelInterface");
-
- // 1. Configure the local IPv6 address
+ // 1. Configure the local IPv6 ULA BTMM address
if (!m->AutoTunnelHostAddrActive)
{
m->AutoTunnelHostAddrActive = mDNStrue;
- LogInfo("Setting up AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
+ LogInfo("SetupLocalAutoTunnelInterface_internal: Setting up AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
(void)mDNSAutoTunnelInterfaceUpDown(kmDNSUp, m->AutoTunnelHostAddr.b);
}
// 2. If we have at least one server (pending) listening, publish our records
- if (TunnelServers(m))
+ // The services may not be in the list when it is first trying to resolve the target of the SRV record.
+ // servicesStarting is an indication of that. Use that instead of looking up in the list of Services/Records.
+ if (servicesStarting || TunnelServers(m))
{
DomainAuthInfo *info;
for (info = m->AuthInfoList; info; info = info->next)
{
if (info->AutoTunnel && !info->deltime && !info->AutoTunnelNAT.clientContext)
{
- // If we just resurrected a DomainAuthInfo that is still deregistering, we need to abort the deregistration process before re-using the AuthRecord memory
- AbortDeregistration(m, &info->AutoTunnelHostRecord);
- AbortDeregistration(m, &info->AutoTunnelDeviceInfo);
+ // If we just resurrected a DomainAuthInfo that is still deregistering, we need to abort the
+ // deregistration process before re-using the AuthRecord memory
+ //
+ // Note: We don't need the same caution as in SetupLocalAutoTunnel6Records (see the comments there)
+ // as AutoTunnelRecordCallback (called as a result of AbortDeregistration) will not end up registering
+ // the records because clientContext is still NULL
+
+ AbortDeregistration(m, &info->AutoTunnelTarget);
AbortDeregistration(m, &info->AutoTunnelService);
+ AbortDeregistration(m, &info->AutoTunnelHostRecord);
- mDNS_SetupResourceRecord(&info->AutoTunnelHostRecord, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
- mDNS_SetupResourceRecord(&info->AutoTunnelDeviceInfo, mDNSNULL, mDNSInterface_Any, kDNSType_TXT, kStandardTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
- mDNS_SetupResourceRecord(&info->AutoTunnelTarget, mDNSNULL, mDNSInterface_Any, kDNSType_A, kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
- mDNS_SetupResourceRecord(&info->AutoTunnelService, mDNSNULL, mDNSInterface_Any, kDNSType_SRV, kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
+ mDNS_SetupResourceRecord(&info->AutoTunnelTarget, mDNSNULL, mDNSInterface_Any, kDNSType_A, kHostNameTTL,
+ kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
+ mDNS_SetupResourceRecord(&info->AutoTunnelService, mDNSNULL, mDNSInterface_Any, kDNSType_SRV, kHostNameTTL,
+ kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
+ mDNS_SetupResourceRecord(&info->AutoTunnelHostRecord, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL,
+ kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
// Try to get a NAT port mapping for the AutoTunnelService
info->AutoTunnelNAT.clientCallback = AutoTunnelNATCallback;
info->AutoTunnelNAT.clientContext = info;
info->AutoTunnelNAT.Protocol = NATOp_MapUDP;
- info->AutoTunnelNAT.IntPort = mDNSOpaque16fromIntVal(kRacoonPort);
- info->AutoTunnelNAT.RequestedPort = mDNSOpaque16fromIntVal(kRacoonPort);
+ info->AutoTunnelNAT.IntPort = IPSECPort;
+ info->AutoTunnelNAT.RequestedPort = IPSECPort;
info->AutoTunnelNAT.NATLease = 0;
mStatus err = mDNS_StartNATOperation_internal(m, &info->AutoTunnelNAT);
- if (err) LogMsg("SetupLocalAutoTunnelInterface_internal error %d starting NAT mapping", err);
+ if (err) LogMsg("SetupLocalAutoTunnelInterface_internal: error %d starting NAT mapping", err);
+
+ // Register the records that can be done without communicating with the NAT
+ //
+ // Note: This should be done after we setup the AutoTunnelNAT information
+ // as some of the fields in that structure are used to infer other information
+ // e.g., is it okay to register now ?
+
+ SetupLocalAutoTunnel6Records(m, info);
+
+ }
+ }
+ }
+ }
+
+mDNSlocal mStatus AutoTunnelSetKeys(ClientTunnel *tun, mDNSBool AddNew)
+ {
+ mDNSv6Addr loc_outer6;
+ mDNSv6Addr rmt_outer6;
+
+ // When we are tunneling over IPv6 Relay address, the port number is zero
+ if (mDNSIPPortIsZero(tun->rmt_outer_port))
+ {
+ loc_outer6 = tun->loc_outer6;
+ rmt_outer6 = tun->rmt_outer6;
+ }
+ else
+ {
+ loc_outer6 = zerov6Addr;
+ loc_outer6.b[0] = tun->loc_outer.b[0];
+ loc_outer6.b[1] = tun->loc_outer.b[1];
+ loc_outer6.b[2] = tun->loc_outer.b[2];
+ loc_outer6.b[3] = tun->loc_outer.b[3];
+
+ rmt_outer6 = zerov6Addr;
+ rmt_outer6.b[0] = tun->rmt_outer.b[0];
+ rmt_outer6.b[1] = tun->rmt_outer.b[1];
+ rmt_outer6.b[2] = tun->rmt_outer.b[2];
+ rmt_outer6.b[3] = tun->rmt_outer.b[3];
+ }
+
+ return(mDNSAutoTunnelSetKeys(AddNew ? kmDNSAutoTunnelSetKeysReplace : kmDNSAutoTunnelSetKeysDelete, tun->loc_inner.b, loc_outer6.b, kRacoonPort, tun->rmt_inner.b, rmt_outer6.b, mDNSVal16(tun->rmt_outer_port), SkipLeadingLabels(&tun->dstname, 1)));
+ }
+
+// If the EUI-64 part of the IPv6 ULA matches, then that means the two addresses point to the same machine
+#define mDNSSameClientTunnel(A,B) ((A)->l[2] == (B)->l[2] && (A)->l[3] == (B)->l[3])
+
+mDNSlocal void ReissueBlockedQuestionWithType(mDNS *const m, domainname *d, mDNSBool success, mDNSu16 qtype)
+ {
+ DNSQuestion *q = m->Questions;
+ while (q)
+ {
+ if (q->NoAnswer == NoAnswer_Suspended && q->qtype == qtype && q->AuthInfo && q->AuthInfo->AutoTunnel && SameDomainName(&q->qname, d))
+ {
+ LogInfo("Restart %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ mDNSQuestionCallback *tmp = q->QuestionCallback;
+ q->QuestionCallback = AutoTunnelCallback; // Set QuestionCallback to suppress another call back to AddNewClientTunnel
+ mDNS_StopQuery(m, q);
+ mDNS_StartQuery(m, q);
+ q->QuestionCallback = tmp; // Restore QuestionCallback back to the real value
+ if (!success) q->NoAnswer = NoAnswer_Fail;
+ // When we call mDNS_StopQuery, it's possible for other subordinate questions like the GetZoneData query to be cancelled too.
+ // In general we have to assume that the question list might have changed in arbitrary ways.
+ // This code is itself called from a question callback, so the m->CurrentQuestion mechanism is
+ // already in use. The safest solution is just to go back to the start of the list and start again.
+ // In principle this sounds like an n^2 algorithm, but in practice we almost always activate
+ // just one suspended question, so it's really a 2n algorithm.
+ q = m->Questions;
+ }
+ else
+ q = q->next;
+ }
+ }
+
+mDNSlocal void ReissueBlockedQuestions(mDNS *const m, domainname *d, mDNSBool success)
+ {
+ // 1. We deliberately restart AAAA queries before A queries, because in the common case where a BTTM host has
+ // a v6 address but no v4 address, we prefer the caller to get the positive AAAA response before the A NXDOMAIN.
+ // 2. In the case of AAAA queries, if our tunnel setup failed, then we return a deliberate failure indication to the caller --
+ // even if the name does have a valid AAAA record, we don't want clients trying to connect to it without a properly encrypted tunnel.
+ // 3. For A queries we never fabricate failures -- if a BTTM service is really using raw IPv4, then it doesn't need the IPv6 tunnel.
+ ReissueBlockedQuestionWithType(m, d, success, kDNSType_AAAA);
+ ReissueBlockedQuestionWithType(m, d, mDNStrue, kDNSType_A);
+ }
+
+mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun, mDNSBool success)
+ {
+ ClientTunnel **p = &m->TunnelClients;
+ while (*p != tun && *p) p = &(*p)->next;
+ if (*p) *p = tun->next;
+ ReissueBlockedQuestions(m, &tun->dstname, success);
+ LogInfo("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
+ freeL("ClientTunnel", tun);
+ }
+
+mDNSlocal mDNSBool TunnelClientDeleteMatching(mDNS *const m, ClientTunnel *tun, mDNSBool v6Tunnel)
+ {
+ ClientTunnel **p;
+ mDNSBool needSetKeys = mDNStrue;
+
+ p = &tun->next;
+ while (*p)
+ {
+ // Is this a tunnel to the same host that we are trying to setup now?
+ if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
+ else
+ {
+ ClientTunnel *old = *p;
+ if (v6Tunnel)
+ {
+ if (!mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue; }
+ LogInfo("TunnelClientDeleteMatching: Found existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ if (old->q.ThisQInterval >= 0)
+ {
+ LogInfo("TunnelClientDeleteMatching: Stopping query on IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ mDNS_StopQuery(m, &old->q);
+ }
+ else if (!mDNSSameIPv6Address((*p)->rmt_inner, tun->rmt_inner) ||
+ !mDNSSameIPv6Address(old->loc_inner, tun->loc_inner) ||
+ !mDNSSameIPv6Address(old->loc_outer6, tun->loc_outer6) ||
+ !mDNSSameIPv6Address(old->rmt_outer6, tun->rmt_outer6))
+ {
+ // Delete the old tunnel if the current tunnel to the same host does not have the same ULA or
+ // the other parameters of the tunnel are different
+ LogInfo("TunnelClientDeleteMatching: Deleting existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ AutoTunnelSetKeys(old, mDNSfalse);
+ }
+ else
+ {
+ // Reusing the existing tunnel means that we reuse the IPsec SAs and the policies. We delete the old
+ // as "tun" and "old" are identical
+ LogInfo("TunnelClientDeleteMatching: Reusing the existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c,
+ &old->rmt_inner);
+ needSetKeys = mDNSfalse;
+ }
+ }
+ else
+ {
+ if (mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue; }
+ LogInfo("TunnelClientDeleteMatching: Found existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ if (old->q.ThisQInterval >= 0)
+ {
+ LogInfo("TunnelClientDeleteMatching: Stopping query on IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ mDNS_StopQuery(m, &old->q);
+ }
+ else if (!mDNSSameIPv6Address((*p)->rmt_inner, tun->rmt_inner) ||
+ !mDNSSameIPv6Address(old->loc_inner, tun->loc_inner) ||
+ !mDNSSameIPv4Address(old->loc_outer, tun->loc_outer) ||
+ !mDNSSameIPv4Address(old->rmt_outer, tun->rmt_outer) ||
+ !mDNSSameIPPort(old->rmt_outer_port, tun->rmt_outer_port))
+ {
+ // Delete the old tunnel if the current tunnel to the same host does not have the same ULA or
+ // the other parameters of the tunnel are different
+ LogInfo("TunnelClientDeleteMatching: Deleting existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ AutoTunnelSetKeys(old, mDNSfalse);
+ }
+ else
+ {
+ // Reusing the existing tunnel means that we reuse the IPsec SAs and the policies. We delete the old
+ // as "tun" and "old" are identical
+ LogInfo("TunnelClientDeleteMatching: Reusing the existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c,
+ &old->rmt_inner);
+ needSetKeys = mDNSfalse;
+ }
+ }
+
+ *p = old->next;
+ LogInfo("TunnelClientDeleteMatching: Disposing ClientTunnel %p", old);
+ freeL("ClientTunnel", old);
+ }
+ }
+ return needSetKeys;
+ }
+
+// v6Tunnel indicates whether to delete a tunnel whose outer header is IPv6. If false, outer IPv4
+// tunnel will be deleted
+mDNSlocal void TunnelClientDeleteAny(mDNS *const m, ClientTunnel *tun, mDNSBool v6Tunnel)
+ {
+ ClientTunnel **p;
+
+ p = &tun->next;
+ while (*p)
+ {
+ // If there is more than one client tunnel to the same host, delete all of them.
+ // We do this by just checking against the EUI64 rather than the full address
+ if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
+ else
+ {
+ ClientTunnel *old = *p;
+ if (v6Tunnel)
+ {
+ if (!mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue;}
+ LogInfo("TunnelClientDeleteAny: Found existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ }
+ else
+ {
+ if (mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue;}
+ LogInfo("TunnelClientDeleteAny: Found existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ }
+ if (old->q.ThisQInterval >= 0)
+ {
+ LogInfo("TunnelClientDeleteAny: Stopping query on AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ mDNS_StopQuery(m, &old->q);
+ }
+ else
+ {
+ LogInfo("TunnelClientDeleteAny: Deleting existing AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+ AutoTunnelSetKeys(old, mDNSfalse);
}
+ *p = old->next;
+ LogInfo("TunnelClientDeleteAny: Disposing ClientTunnel %p", old);
+ freeL("ClientTunnel", old);
}
}
}
-mDNSlocal mStatus AutoTunnelSetKeys(ClientTunnel *tun, mDNSBool AddNew)
+mDNSlocal void TunnelClientFinish(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer)
{
- 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)));
- }
+ mDNSBool needSetKeys = mDNStrue;
+ ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
+ mDNSBool v6Tunnel = mDNSfalse;
-// If the EUI-64 part of the IPv6 ULA matches, then that means the two addresses point to the same machine
-#define mDNSSameClientTunnel(A,B) ((A)->l[2] == (B)->l[2] && (A)->l[3] == (B)->l[3])
+ // If the port is zero, then we have a relay address of the peer
+ if (mDNSIPPortIsZero(tun->rmt_outer_port))
+ v6Tunnel = mDNStrue;
-mDNSlocal void ReissueBlockedQuestionWithType(mDNS *const m, domainname *d, mDNSBool success, mDNSu16 qtype)
- {
- DNSQuestion *q = m->Questions;
- while (q)
+ if (v6Tunnel)
{
- if (q->NoAnswer == NoAnswer_Suspended && q->qtype == qtype && q->AuthInfo && q->AuthInfo->AutoTunnel && SameDomainName(&q->qname, d))
- {
- LogInfo("Restart %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- mDNSQuestionCallback *tmp = q->QuestionCallback;
- q->QuestionCallback = AutoTunnelCallback; // Set QuestionCallback to suppress another call back to AddNewClientTunnel
- mDNS_StopQuery(m, q);
- mDNS_StartQuery(m, q);
- q->QuestionCallback = tmp; // Restore QuestionCallback back to the real value
- if (!success) q->NoAnswer = NoAnswer_Fail;
- // When we call mDNS_StopQuery, it's possible for other subordinate questions like the GetZoneData query to be cancelled too.
- // In general we have to assume that the question list might have changed in arbitrary ways.
- // This code is itself called from a question callback, so the m->CurrentQuestion mechanism is
- // already in use. The safest solution is just to go back to the start of the list and start again.
- // In principle this sounds like an n^2 algorithm, but in practice we almost always activate
- // just one suspended question, so it's really a 2n algorithm.
- q = m->Questions;
- }
- else
- q = q->next;
+ LogInfo("TunnelClientFinish: Relay address %.16a", &answer->rdata->u.ipv6);
+ tun->rmt_outer6 = answer->rdata->u.ipv6;
+ tun->loc_outer6 = m->AutoTunnelRelayAddr;
+ }
+ else
+ {
+ LogInfo("TunnelClientFinish: SRV target address %.4a", &answer->rdata->u.ipv4);
+ tun->rmt_outer = answer->rdata->u.ipv4;
+ mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
+ tmpDst.ip.v4 = tun->rmt_outer;
+ mDNSAddr tmpSrc = zeroAddr;
+ mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
+ if (tmpSrc.type == mDNSAddrType_IPv4) tun->loc_outer = tmpSrc.ip.v4;
+ else tun->loc_outer = m->AdvertisedV4.ip.v4;
}
- }
-mDNSlocal void ReissueBlockedQuestions(mDNS *const m, domainname *d, mDNSBool success)
- {
- // 1. We deliberately restart AAAA queries before A queries, because in the common case where a BTTM host has
- // a v6 address but no v4 address, we prefer the caller to get the positive AAAA response before the A NXDOMAIN.
- // 2. In the case of AAAA queries, if our tunnel setup failed, then we return a deliberate failure indication to the caller --
- // even if the name does have a valid AAAA record, we don't want clients trying to connect to it without a properly encrypted tunnel.
- // 3. For A queries we never fabricate failures -- if a BTTM service is really using raw IPv4, then it doesn't need the IPv6 tunnel.
- ReissueBlockedQuestionWithType(m, d, success, kDNSType_AAAA);
- ReissueBlockedQuestionWithType(m, d, mDNStrue, kDNSType_A);
- }
+ question->ThisQInterval = -1; // So we know this tunnel setup has completed
+ tun->loc_inner = m->AutoTunnelHostAddr;
-mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun, mDNSBool success)
- {
- ClientTunnel **p = &m->TunnelClients;
- while (*p != tun && *p) p = &(*p)->next;
- if (*p) *p = tun->next;
- ReissueBlockedQuestions(m, &tun->dstname, success);
- LogInfo("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
- freeL("ClientTunnel", tun);
+ // If we found a v6Relay address for our peer, delete all the v4Tunnels for our peer and
+ // look for existing tunnels to see whether they have the same information for our peer.
+ // If not, delete them and need to create a new tunnel. If they are same, just use the
+ // same tunnel. Do the similar thing if we found a v4Tunnel end point for our peer.
+ TunnelClientDeleteAny(m, tun, !v6Tunnel);
+ needSetKeys = TunnelClientDeleteMatching(m, tun, v6Tunnel);
+
+ if (needSetKeys) LogInfo("TunnelClientFinish: New %s AutoTunnel for %##s %.16a", (v6Tunnel ? "IPv6" : "IPv4"), tun->dstname.c, &tun->rmt_inner);
+ else LogInfo("TunnelClientFinish: Reusing exiting %s AutoTunnel for %##s %.16a", (v6Tunnel ? "IPv6" : "IPv4"), tun->dstname.c, &tun->rmt_inner);
+
+ if (m->AutoTunnelHostAddr.b[0]) { mDNS_Lock(m); SetupLocalAutoTunnelInterface_internal(m, mDNSfalse); mDNS_Unlock(m); };
+
+ mStatus result = needSetKeys ? AutoTunnelSetKeys(tun, mDNStrue) : mStatus_NoError;
+ static char msgbuf[32];
+ mDNS_snprintf(msgbuf, sizeof(msgbuf), "Client AutoTunnel setup - %d", result);
+ mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", result ? "failure" : "success", msgbuf, "");
+ mDNSEReporterLog((uuid_t *)&m->asl_uuid, "autotunnel.config", result, msgbuf);
+ // Kick off any questions that were held pending this tunnel setup
+ ReissueBlockedQuestions(m, &tun->dstname, (result == mStatus_NoError) ? mDNStrue : mDNSfalse);
}
mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
+
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)
+ // If we are looking up the AAAA record for _autotunnel6, don't consider it as failure.
+ // The code below will look for _autotunnel._udp SRV record followed by A record
+ if (tun->tc_state != TC_STATE_AAAA_PEER_RELAY && !answer->rdlength)
{
LogInfo("AutoTunnelCallback NXDOMAIN %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
static char msgbuf[16];
mDNS_snprintf(msgbuf, sizeof(msgbuf), "%s lookup", DNSTypeName(question->qtype));
mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", "failure", msgbuf, "");
+ mDNSEReporterLog((uuid_t *)&m->asl_uuid, "autotunnel.config", 1, msgbuf);
UnlinkAndReissueBlockedQuestions(m, tun, mDNSfalse);
return;
}
- if (question->qtype == kDNSType_AAAA)
- {
- if (mDNSSameIPv6Address(answer->rdata->u.ipv6, m->AutoTunnelHostAddr))
- {
- LogInfo("AutoTunnelCallback: suppressing tunnel to self %.16a", &answer->rdata->u.ipv6);
- UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
- return;
- }
-
- tun->rmt_inner = answer->rdata->u.ipv6;
- 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;
- mDNS_StartQuery(m, &tun->q);
- }
- else if (question->qtype == kDNSType_SRV)
+ switch (tun->tc_state)
{
- 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;
- mDNS_StartQuery(m, &tun->q);
- }
- else if (question->qtype == kDNSType_A)
- {
- ClientTunnel *old = mDNSNULL;
- 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;
- mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
- tmpDst.ip.v4 = tun->rmt_outer;
- mDNSAddr tmpSrc = zeroAddr;
- mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
- if (tmpSrc.type == mDNSAddrType_IPv4) tun->loc_outer = tmpSrc.ip.v4;
- else tun->loc_outer = m->AdvertisedV4.ip.v4;
-
- ClientTunnel **p = &tun->next;
- mDNSBool needSetKeys = mDNStrue;
- while (*p)
- {
- if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
+ case TC_STATE_AAAA_PEER:
+ if (question->qtype != kDNSType_AAAA)
+ {
+ LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_AAAA_PEER", question->qtype);
+ }
+ if (mDNSSameIPv6Address(answer->rdata->u.ipv6, m->AutoTunnelHostAddr))
+ {
+ LogInfo("AutoTunnelCallback: suppressing tunnel to self %.16a", &answer->rdata->u.ipv6);
+ UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
+ return;
+ }
+ tun->rmt_inner = answer->rdata->u.ipv6;
+ LogInfo("AutoTunnelCallback:TC_STATE_AAAA_PEER: dst host %.16a", &tun->rmt_inner);
+ if (!mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
+ {
+ LogInfo("AutoTunnelCallback: Looking up _autotunnel6 AAAA");
+ tun->tc_state = TC_STATE_AAAA_PEER_RELAY;
+ question->qtype = kDNSType_AAAA;
+ AssignDomainName(&question->qname, (const domainname*) "\x0C" "_autotunnel6");
+ }
else
{
- LogInfo("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);
- else if (!mDNSSameIPv6Address(old->loc_inner, tun->loc_inner) ||
- !mDNSSameIPv4Address(old->loc_outer, tun->loc_outer) ||
- !mDNSSameIPv6Address(old->rmt_inner, tun->rmt_inner) ||
- !mDNSSameIPv4Address(old->rmt_outer, tun->rmt_outer) ||
- !mDNSSameIPPort(old->rmt_outer_port, tun->rmt_outer_port))
- {
- LogInfo("Deleting existing AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
- AutoTunnelSetKeys(old, mDNSfalse);
- }
- else needSetKeys = mDNSfalse;
-
- LogInfo("AutoTunnelCallback: Disposing ClientTunnel %p", tun);
- freeL("ClientTunnel", old);
+ LogInfo("AutoTunnelCallback: Looking up _autotunnel._udp SRV");
+ tun->tc_state = TC_STATE_SRV_PEER;
+ question->qtype = kDNSType_SRV;
+ AssignDomainName(&question->qname, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
}
- }
-
- 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);
+ AppendDomainName(&question->qname, &tun->dstname);
+ mDNS_StartQuery(m, &tun->q);
+ return;
+ case TC_STATE_AAAA_PEER_RELAY:
+ if (question->qtype != kDNSType_AAAA)
+ {
+ LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_AAAA_PEER_RELAY", question->qtype);
+ }
+ // If it failed, look for the SRV record.
+ if (!answer->rdlength)
+ {
+ LogInfo("AutoTunnelCallback: Looking up _autotunnel6 AAAA failed, trying SRV");
+ tun->tc_state = TC_STATE_SRV_PEER;
+ AssignDomainName(&question->qname, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
+ AppendDomainName(&question->qname, &tun->dstname);
+ question->qtype = kDNSType_SRV;
+ mDNS_StartQuery(m, &tun->q);
+ return;
+ }
+ TunnelClientFinish(m, question, answer);
+ return;
+ case TC_STATE_SRV_PEER:
+ if (question->qtype != kDNSType_SRV)
+ {
+ LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_SRV_PEER", question->qtype);
+ }
+ LogInfo("AutoTunnelCallback: SRV target name %##s", answer->rdata->u.srv.target.c);
+ tun->tc_state = TC_STATE_ADDR_PEER;
+ AssignDomainName(&tun->q.qname, &answer->rdata->u.srv.target);
+ tun->rmt_outer_port = answer->rdata->u.srv.port;
+ question->qtype = kDNSType_A;
+ mDNS_StartQuery(m, &tun->q);
+ return;
+ case TC_STATE_ADDR_PEER:
+ if (question->qtype != kDNSType_A)
+ {
+ LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_ADDR_PEER", question->qtype);
+ }
+ TunnelClientFinish(m, question, answer);
+ return;
+ default:
+ LogMsg("AutoTunnelCallback: Unknown question %p", question);
}
- else
- LogMsg("AutoTunnelCallback: Unknown question %p", question);
}
// Must be called with the lock held
p->MarkedForDeletion = mDNSfalse;
p->loc_inner = zerov6Addr;
p->loc_outer = zerov4Addr;
+ p->loc_outer6 = zerov6Addr;
p->rmt_inner = zerov6Addr;
p->rmt_outer = zerov4Addr;
+ p->rmt_outer6 = zerov6Addr;
p->rmt_outer_port = zeroIPPort;
+ p->tc_state = TC_STATE_AAAA_PEER;
p->next = m->TunnelClients;
m->TunnelClients = p; // We intentionally build list in reverse order
p->q.ExpectUnique = mDNStrue;
p->q.ForceMCast = mDNSfalse;
p->q.ReturnIntermed = mDNStrue;
+ p->q.SuppressUnusable = mDNSfalse;
p->q.QuestionCallback = AutoTunnelCallback;
p->q.QuestionContext = p;
{
DomainAuthInfo *info;
for (info = m->AuthInfoList; info; info = info->next)
- if (info->AutoTunnelNAT.clientContext && !mDNSIPv4AddressIsOnes(info->AutoTunnelNAT.ExternalAddress))
- AutoTunnelNATCallback(m, &info->AutoTunnelNAT);
+ if (info->AutoTunnel) AutoTunnelHostNameChanged(m, info);
}
#endif // APPLE_OSX_mDNSResponder
return (a->search_order < b->search_order) ? -1 : (a->search_order == b->search_order) ? 0 : 1;
}
+mDNSlocal void ConfigResolvers(mDNS *const m, dns_config_t *config, mDNSBool scope, mDNSBool setsearch, mDNSBool setservers)
+ {
+ int i;
+ domainname d;
+#if DNSINFO_VERSION >= 20091104
+ dns_resolver_t **resolver = scope ? config->scoped_resolver : config->resolver;
+ int nresolvers = scope ? config->n_scoped_resolver : config->n_resolver;
+#else
+ (void) scope; // unused
+ dns_resolver_t **resolver = config->resolver;
+ int nresolvers = config->n_resolver;
+#endif
+
+ // Currently we don't support search lists for scoped resolvers. The WAB support for this will be added later.
+ if (setsearch && !scope && nresolvers)
+ {
+ // 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.
+ //
+ // Note: Starting DNSINFO_VERSION 20091104, search list is present only in the first resolver (resolver 0).
+ // i.e., n_search for the first resolver is always non-zero. We don't guard it with #ifs for better readability
+
+ if (resolver[0]->n_search == 0)
+ {
+ LogInfo("ConfigResolvers: (%s) configuring zeroth domain as search list %s", scope ? "Scoped" : "Non-scoped", resolver[0]->domain);
+ mDNS_AddSearchDomain_CString(resolver[0]->domain);
+ }
+ else
+ {
+ for (i = 0; i < resolver[0]->n_search; i++)
+ {
+ LogInfo("ConfigResolvers: (%s) configuring search list %s", scope ? "Scoped" : "Non-scoped", resolver[0]->search[i]);
+ mDNS_AddSearchDomain_CString(resolver[0]->search[i]);
+ }
+ }
+ }
+
+ if (!setservers) return;
+
+ // 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).
+ //
+ // Note: Starting DNSINFO_VERSION 20091104, domain value of this first resolver (resolver 0) is always NULL.
+ // We don't guard it with #ifs for better readability
+ //
+ if ((nresolvers != 0) && resolver[0]->domain)
+ resolver[0]->domain[0] = 0; // don't stop pointing at the memory, just change the first byte
+
+ qsort(resolver, nresolvers, sizeof(dns_resolver_t*), compare_dns_configs);
+
+ for (i = 0; i < nresolvers; i++)
+ {
+ int n;
+ dns_resolver_t *r = resolver[i];
+ mDNSInterfaceID interface = mDNSInterface_Any;
+ int disabled = 0;
+
+ LogInfo("ConfigResolvers: %s resolver[%d] domain %s n_nameserver %d", scope ? "Scoped" : "", i, r->domain, r->n_nameserver);
+
+ // 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"
+ // 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("ConfigResolvers: config->resolver[%d] bad domain %s", i, r->domain); continue; }
+
+ // DNS server option parsing
+ if (r->options != NULL)
+ {
+ char *nextOption = r->options;
+ char *currentOption = NULL;
+ while ((currentOption = strsep(&nextOption, " ")) != NULL && currentOption[0] != 0)
+ {
+ // 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("ConfigResolvers: RegisterSplitDNS interface specific - interface %s not found", ifname); continue; }
+ LogInfo("ConfigResolvers: interface specific entry: %s on %s (%d)", 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("ConfigResolvers: RegisterSplitDNS interface specific - index %d (%s) not found", ifindex, ifname);
+ continue;
+ }
+ }
+ }
+ }
+
+ // flags and if_index are defined only from this DNSINFO_VERSION onwards. Currently these
+ // fields are zero for non-scoped resolvers. For now, these fields have non-zero values only
+ // for scoped_resolvers.
+#if DNSINFO_VERSION >= 20091104
+ if (scope && (r->flags & DNS_RESOLVER_FLAGS_SCOPED) && (r->if_index != 0))
+ {
+ NetworkInterfaceInfoOSX *ni;
+ interface = mDNSNULL;
+ for (ni = m->p->InterfaceList; ni; ni = ni->next)
+ if (ni->ifinfo.InterfaceID && ni->scope_id == r->if_index) break;
+ if (ni != NULL) interface = ni->ifinfo.InterfaceID;
+ if (interface == mDNSNULL)
+ {
+ disabled = 1;
+ LogMsg("ConfigResolvers: interface specific index %d not found", r->if_index);
+ continue;
+ }
+ }
+#endif
+
+ for (n = 0; n < r->n_nameserver; n++)
+ if (r->nameserver[n]->sa_family == AF_INET || r->nameserver[n]->sa_family == AF_INET6)
+ {
+ mDNSAddr saddr;
+ // mDNSAddr saddr = { mDNSAddrType_IPv4, { { { 192, 168, 1, 1 } } } }; // for testing
+ if (SetupAddr(&saddr, r->nameserver[n])) LogMsg("RegisterSplitDNS: bad IP address");
+ else
+ {
+ mDNSBool scopedDNS = mDNSfalse;
+ DNSServer *s;
+#if DNSINFO_VERSION >= 20091104
+ // By setting scoped, this DNSServer can only be picked if the right interfaceID
+ // is given in the question
+ if (scope && (r->flags & DNS_RESOLVER_FLAGS_SCOPED) && (interface == mDNSNULL))
+ LogMsg("ConfigResolvers: ERROR: scoped is set but if_index %d is invalid for DNSServer %#a:%d", r->if_index, &saddr, mDNSVal16(r->port ? mDNSOpaque16fromIntVal(r->port) : UnicastDNSPort));
+ else
+ scopedDNS = (scope && (r->flags & DNS_RESOLVER_FLAGS_SCOPED)) ? mDNStrue : mDNSfalse;
+#endif
+ s = mDNS_AddDNSServer(m, &d, interface, &saddr, r->port ? mDNSOpaque16fromIntVal(r->port) : UnicastDNSPort, scopedDNS);
+ if (s)
+ {
+ if (disabled) s->teststate = DNSServer_Disabled;
+ LogInfo("ConfigResolvers: DNS server %#a:%d for domain %##s from slot %d,%d", &s->addr, mDNSVal16(s->port), d.c, i, n);
+ }
+ }
+ }
+ }
+ }
+
mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains)
{
int i;
else
{
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
}
#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 n;
- dns_resolver_t *r = config->resolver[i];
- 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"
- // 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)
- {
- char *nextOption = r->options;
- char *currentOption = NULL;
- while ((currentOption = strsep(&nextOption, " ")) != NULL && currentOption[0] != 0)
- {
- // 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; }
- }
- }
- }
-
- for (n = 0; n < r->n_nameserver; n++)
- if (r->nameserver[n]->sa_family == AF_INET || r->nameserver[n]->sa_family == AF_INET6)
- {
- mDNSAddr saddr;
- // mDNSAddr saddr = { mDNSAddrType_IPv4, { { { 192, 168, 1, 1 } } } }; // for testing
- 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)
- {
- 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);
- }
- }
- }
-
- }
- }
-
+ ConfigResolvers(m, config, mDNSfalse, setsearch, setservers);
+#if DNSINFO_VERSION >= 20091104
+ ConfigResolvers(m, config, mDNStrue, setsearch, setservers);
+#endif
dns_configuration_free(config);
setservers = mDNSfalse; // Done these now -- no need to fetch the same data from SCDynamicStore
setsearch = mDNSfalse;
CFArrayRef values = CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses);
if (values)
{
- LogInfo("DNS Server Address values: %d", CFArrayGetCount(values));
+ LogInfo("DNS Server Address values: %d", (int)CFArrayGetCount(values));
for (i = 0; i < CFArrayGetCount(values); i++)
{
CFStringRef s = CFArrayGetValueAtIndex(values, i);
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);
+ mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, &addr, UnicastDNSPort, mDNSfalse);
}
}
}
mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *r)
{
char buf[256];
- mStatus err = 0;
(void)m; // Unused
SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformGetPrimaryInterface"), NULL, NULL);
}
CFRelease(store);
}
- return err;
+ return mStatus_NoError;
}
mDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
// The CFDictionary for each FQDN holds (at present) a single name/value pair,
// where the name is "Status" and the value is a CFNumber giving an errror code (with zero meaning success).
- const CFStringRef StateKeys [1] = { CFSTR("HostNames") };
- const CFStringRef HostKeys [1] = { CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8) };
- const CFStringRef StatusKeys[1] = { CFSTR("Status") };
- if (!HostKeys[0]) LogMsg("SetDDNSNameStatus: CFStringCreateWithCString(%s) failed", uname);
+ const CFStringRef StateKeys [1] = { CFSTR("HostNames") };
+ const CFStringRef HostKeys [1] = { CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8) };
+ const CFStringRef StatusKeys[1] = { CFSTR("Status") };
+ if (!HostKeys[0]) LogMsg("SetDDNSNameStatus: CFStringCreateWithCString(%s) failed", uname);
+ else
+ {
+ const CFNumberRef StatusVals[1] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &status) };
+ if (!StatusVals[0]) LogMsg("SetDDNSNameStatus: CFNumberCreate(%d) failed", status);
+ else
+ {
+ const CFDictionaryRef HostVals[1] = { CFDictionaryCreate(NULL, (void*)StatusKeys, (void*)StatusVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
+ if (HostVals[0])
+ {
+ const CFDictionaryRef StateVals[1] = { CFDictionaryCreate(NULL, (void*)HostKeys, (void*)HostVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
+ if (StateVals[0])
+ {
+ CFDictionaryRef StateDict = CFDictionaryCreate(NULL, (void*)StateKeys, (void*)StateVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (StateDict)
+ {
+ mDNSDynamicStoreSetConfig(kmDNSDynamicConfig, mDNSNULL, StateDict);
+ CFRelease(StateDict);
+ }
+ CFRelease(StateVals[0]);
+ }
+ CFRelease(HostVals[0]);
+ }
+ CFRelease(StatusVals[0]);
+ }
+ CFRelease(HostKeys[0]);
+ }
+ }
+
+#if APPLE_OSX_mDNSResponder
+#if ! NO_AWACS
+
+// checks whether a domain is present in Setup:/Network/BackToMyMac. Just because there is a key in the
+// keychain for a domain, it does not become a valid BTMM domain. If things get inconsistent, this will
+// help catch it
+mDNSlocal mDNSBool IsBTMMDomain(domainname *d)
+ {
+ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:IsBTMMDomain"), NULL, NULL);
+ if (!store)
+ {
+ LogMsg("IsBTMMDomain: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+ return mDNSfalse;
+ }
+ CFDictionaryRef btmm = SCDynamicStoreCopyValue(store, NetworkChangedKey_BackToMyMac);
+ if (btmm)
+ {
+ CFIndex size = CFDictionaryGetCount(btmm);
+ char buf[MAX_ESCAPED_DOMAIN_NAME]; // Max legal C-string name, including terminating NUL
+ const void *key[size];
+ const void *val[size];
+ domainname dom;
+ int i;
+ CFDictionaryGetKeysAndValues(btmm, key, val);
+ for (i = 0; i < size; i++)
+ {
+ LogInfo("BackToMyMac %d", i);
+ if (!CFStringGetCString(key[i], buf, sizeof(buf), kCFStringEncodingUTF8))
+ LogMsg("IsBTMMDomain: ERROR!! Can't read BackToMyMac %d key %s", i, buf);
+ else
+ {
+ mDNSu32 uid = atoi(buf);
+ if (!CFStringGetCString(val[i], buf, sizeof(buf), kCFStringEncodingUTF8))
+ LogMsg("IsBTMMDomain: Can't read BackToMyMac %d val %s", i, buf);
+ else if (MakeDomainNameFromDNSNameString(&dom, buf) && dom.c[0])
+ {
+ if (SameDomainName(&dom, d))
+ {
+ LogInfo("IsBTMMDomain: Domain %##s is a btmm domain, uid %u", d->c, uid);
+ CFRelease(btmm);
+ CFRelease(store);
+ return mDNStrue;
+ }
+ }
+ }
+ }
+ CFRelease(btmm);
+ }
+ CFRelease(store);
+ LogInfo("IsBTMMDomain: Domain %##s not a btmm domain", d->c);
+ return mDNSfalse;
+ }
+
+// Appends data to the buffer
+mDNSlocal int AddOneItem(char *buf, int bufsz, char *data, int *currlen)
+ {
+ int len;
+
+ len = strlcpy(buf + *currlen, data, bufsz - *currlen);
+ if (len >= (bufsz - *currlen))
+ {
+ // if we have exceeded the space in buf, it has already been NULL terminated
+ // and we have nothing more to do. Set currlen to the last byte so that the caller
+ // knows to do the right thing
+ LogMsg("AddOneItem: Exceeded the max buffer size currlen %d, len %d", *currlen, len);
+ *currlen = bufsz - 1;
+ return -1;
+ }
+ else { (*currlen) += len; }
+
+ buf[*currlen] = ',';
+ if (*currlen >= bufsz)
+ {
+ LogMsg("AddOneItem: ERROR!! How can currlen be %d", *currlen);
+ *currlen = bufsz - 1;
+ buf[*currlen] = 0;
+ return -1;
+ }
+ // if we have filled up the buffer exactly, then there is no more work to do
+ if (*currlen == bufsz - 1) { buf[*currlen] = 0; return -1; }
+ (*currlen)++;
+ return *currlen;
+ }
+
+// If we have at least one BTMM domain, then trigger the connection to the relay. If we have no
+// BTMM domains, then bring down the connection to the relay.
+mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
+ {
+ DomainAuthInfo *BTMMDomain = mDNSNULL;
+ DomainAuthInfo *FoundInList;
+ static mDNSBool AWACSDConnected = mDNSfalse;
+ char AllUsers[1024]; // maximum size of mach message
+ char AllPass[1024]; // maximum size of mach message
+ char username[MAX_DOMAIN_LABEL + 1];
+ int currulen = 0;
+ int currplen = 0;
+
+ // if a domain is being deleted, we want to send a disconnect. If we send a disconnect now,
+ // we may not be able to send the dns queries over the relay connection which may be needed
+ // for sending the deregistrations. Hence, we need to delay sending the disconnect. But we
+ // need to make sure that we send the disconnect before attempting the next connect as the
+ // awacs connections are redirected based on usernames.
+ //
+ // For now we send a disconnect immediately. When we start sending dns queries over the relay
+ // connection, we will need to fix this.
+
+ for (FoundInList = m->AuthInfoList; FoundInList; FoundInList = FoundInList->next)
+ if (!FoundInList->deltime && FoundInList->AutoTunnel && IsBTMMDomain(&FoundInList->domain))
+ {
+ // We need the passwd from the first domain.
+ BTMMDomain = FoundInList;
+ ConvertDomainLabelToCString_unescaped((domainlabel *)BTMMDomain->domain.c, username);
+ LogInfo("UpdateBTMMRelayConnection: user %s for domain %##s", username, BTMMDomain->domain.c);
+ if (AddOneItem(AllUsers, sizeof(AllUsers), username, &currulen) == -1) break;
+ if (AddOneItem(AllPass, sizeof(AllPass), BTMMDomain->b64keydata, &currplen) == -1) break;
+ }
+
+ if (BTMMDomain)
+ {
+ // In the normal case (where we neither exceed the buffer size nor write bytes that
+ // fit exactly into the buffer), currulen/currplen should be a different size than
+ // (AllUsers - 1) / (AllPass - 1). In that case, we need to override the "," with a NULL byte.
+
+ if (currulen != (int)(sizeof(AllUsers) - 1)) AllUsers[currulen - 1] = 0;
+ if (currplen != (int)(sizeof(AllPass) - 1)) AllPass[currplen - 1] = 0;
+
+ LogInfo("UpdateBTMMRelayConnection: AWS_Connect for user %s", AllUsers);
+ AWACS_Connect(AllUsers, AllPass, "hello.connectivity.me.com");
+ AWACSDConnected = mDNStrue;
+ }
else
{
- const CFNumberRef StatusVals[1] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &status) };
- if (!StatusVals[0]) LogMsg("SetDDNSNameStatus: CFNumberCreate(%d) failed", status);
- else
+ // Disconnect only if we connected previously
+ if (AWACSDConnected)
{
- const CFDictionaryRef HostVals[1] = { CFDictionaryCreate(NULL, (void*)StatusKeys, (void*)StatusVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
- if (HostVals[0])
- {
- const CFDictionaryRef StateVals[1] = { CFDictionaryCreate(NULL, (void*)HostKeys, (void*)HostVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
- if (StateVals[0])
- {
- CFDictionaryRef StateDict = CFDictionaryCreate(NULL, (void*)StateKeys, (void*)StateVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- if (StateDict)
- {
- mDNSDynamicStoreSetConfig(kmDNSDynamicConfig, mDNSNULL, StateDict);
- CFRelease(StateDict);
- }
- CFRelease(StateVals[0]);
- }
- CFRelease(HostVals[0]);
- }
- CFRelease(StatusVals[0]);
+ LogInfo("UpdateBTMMRelayConnection: AWS_Disconnect");
+ AWACS_Disconnect();
+ AWACSDConnected = mDNSfalse;
}
- CFRelease(HostKeys[0]);
+ else LogInfo("UpdateBTMMRelayConnection: Not calling AWS_Disconnect");
}
}
+#else
+mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
+ {
+ (void) m; // Unused
+ LogInfo("UpdateBTMMRelayConnection: AWACS connection not started, no AWACS library");
+ }
+#endif // ! NO_AWACS
+#endif // APPLE_OSX_mDNSResponder
// MUST be called holding the lock -- this routine calls SetupLocalAutoTunnelInterface_internal()
mDNSexport void SetDomainSecrets(mDNS *m)
mDNS_StopNATOperation_internal(m, &info->AutoTunnelNAT);
if (info->AutoTunnelNAT.clientCallback)
{
- // Reset port and let the AutoTunnelNATCallback handle cleanup
+ // Reset port and cleanup the state
info->AutoTunnelNAT.ExternalAddress = m->ExternalAddress;
info->AutoTunnelNAT.ExternalPort = zeroIPPort;
+ info->AutoTunnelNAT.RequestedPort = zeroIPPort;
info->AutoTunnelNAT.Lifetime = 0;
info->AutoTunnelNAT.Result = mStatus_NoError;
mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback
- info->AutoTunnelNAT.clientCallback(m, &info->AutoTunnelNAT);
+ AutoTunnelDeleteAuthInfoState(m, info);
mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again
}
info->AutoTunnelNAT.clientContext = mDNSNULL;
(void)mDNSAutoTunnelInterfaceUpDown(kmDNSDown, m->AutoTunnelHostAddr.b);
mDNSPlatformMemZero(m->AutoTunnelHostAddr.b, sizeof(m->AutoTunnelHostAddr.b));
}
-
- UpdateConfigureServer(m);
if (m->AutoTunnelHostAddr.b[0])
if (TunnelClients(m) || TunnelServers(m))
- SetupLocalAutoTunnelInterface_internal(m);
+ SetupLocalAutoTunnelInterface_internal(m, mDNSfalse);
+
+ UpdateAnonymousRacoonConfig(m); // Determine whether we need racoon to accept incoming connections
+ UpdateBTMMRelayConnection(m);
}
#endif // APPLE_OSX_mDNSResponder
+ CheckSuppressUnusableQuestions(m);
+
#endif /* NO_SECURITYFRAMEWORK */
}
if (!store) LogMsg("GetCurrentPMSetting: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
else
{
- CFDictionaryRef dict = SCDynamicStoreCopyValue(store, CFSTR("State:/IOKit/PowerManagement/CurrentSettings"));
+ CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_PowerSettings);
if (!dict) LogSPS("GetCurrentPMSetting: Could not get IOPM CurrentSettings dict");
else
{
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>");
+ mDNS_Lock(m);
+ mDNS_UpdateAllowSleep(m);
+ mDNS_Unlock(m);
+
if (answer && SPSMetric(answer->rdata->u.name.c) > 999999) return; // Ignore instances with invalid names
if (!spsStatusDict)
LogMsg("GetSystemSleepTimerSetting: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
else
{
- CFDictionaryRef dict = SCDynamicStoreCopyValue(store, CFSTR("State:/IOKit/PowerManagement/CurrentSettings"));
+ CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_PowerSettings);
if (dict)
{
CFNumberRef number = CFDictionaryGetValue(dict, CFSTR("System Sleep Timer"));
if (!SCPreferencesSetCallback(SCPrefs, InternetSharingChanged, &context))
{ LogMsg("SCPreferencesSetCallback failed: %s", SCErrorString(SCError())); CFRelease(SCPrefs); return(mStatus_NoMemoryErr); }
+#ifdef __LIB_DISPATCH__
+ if (!SCPreferencesSetDispatchQueue( SCPrefs, dispatch_get_main_queue()))
+ { LogMsg("SCPreferencesSetDispatchQueue failed: %s", SCErrorString(SCError())); return(mStatus_NoMemoryErr); }
+#else
if (!SCPreferencesScheduleWithRunLoop(SCPrefs, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
{ LogMsg("SCPreferencesScheduleWithRunLoop failed: %s", SCErrorString(SCError())); CFRelease(SCPrefs); return(mStatus_NoMemoryErr); }
+#endif
m->p->SCPrefs = SCPrefs;
return(mStatus_NoError);
}
// If Back to My Mac is on, also wake for packets to the IPSEC UDP port (4500)
- if (trans == mDNSTransport_UDP && TunnelServers(m))
+ if (trans == mDNSTransport_UDP && TunnelServers(m))
{
LogSPS("GetPortArray Back to My Mac at %d", count);
if (portarray) portarray[count] = IPSECPort;
}
#endif
-mDNSexport mStatus ActivateLocalProxy(mDNS *const m, char *ifname)
+mDNSexport mStatus ActivateLocalProxy(mDNS *const m, char *ifname) // Called with the lock held
{
mStatus result = mStatus_UnknownErr;
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching(kIOMasterPortDefault, 0, ifname));
CFBooleanRef clamshellStop = NULL;
mDNSBool retnow = mDNSfalse;
+ if (DisableSleepProxyClient) { LogSPS("SystemWakeForNetworkAccess: Sleep Proxy Client disabled by command-line option"); return mDNSfalse; }
+
GetCurrentPMSetting(CFSTR("Wake On LAN"), &val);
LogSPS("SystemWakeForNetworkAccess: Wake On LAN: %d", val);
if (!val) return mDNSfalse;
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);
+ 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;
}
+mDNSlocal mDNSBool SystemSleepOnlyIfWakeOnLAN(void)
+ {
+ mDNSs32 val = 0;
+ GetCurrentPMSetting(CFSTR("Idle Sleep Requires Network Proxy"), &val);
+ return val != 0 ? mDNStrue : mDNSfalse;
+ }
+
+#if APPLE_OSX_mDNSResponder
+// If the _autotunnel6 record is still there in the list, we are waiting for the ack from
+// the server.
+//
+// If we are behind a double-NAT or NAT with no NAT-PMP support, we should make sure that all our
+// BTMM records are deregistered so that it does not appear on the Finder sidebar of our peers
+// when we go to sleep. First _autotunnel6 and the host record gets deregistered, then SRV
+// (UpdateAllSrvRecords) and then PTR and TXT
+//
+// Note: We wait up to a maximum of 10 seconds before we ack the sleep. So, returning "false"
+// here does not necessarily mean that it will be honored.
+mDNSexport mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr)
+ {
+ if (!AuthRecord_uDNS(rr)) return mDNStrue;
+
+ if (SameDomainLabel(rr->namestorage.c, (const mDNSu8 *)"\x0c_autotunnel6"))
+ {
+ LogInfo("RecordReadyForSleep: %s not ready for sleep", ARDisplayString(m, rr));
+ return mDNSfalse;
+ }
+ // Just check for the SRV record alone as the PTR and TXT records are dependent on SRV
+ // and will get deregistered together in a single update. We also don't check for TXT
+ // records as _kerberos TXT record is always there even when there are no services
+ // and we don't want to delay the sleep in that case.
+ if (mDNSIPPortIsZero(m->LLQNAT.ExternalPort) || m->LLQNAT.Result)
+ {
+ if ((rr->resrec.rrtype == kDNSType_SRV) && rr->state != regState_NoTarget && rr->zone)
+ {
+ DomainAuthInfo *info = GetAuthInfoForName_internal(m, rr->zone);
+ if (info && info->AutoTunnel)
+ {
+ LogInfo("RecordReadyForSleep: %s not ready for sleep", ARDisplayString(m, rr));
+ return mDNSfalse;
+ }
+ }
+ }
+ return mDNStrue;
+ }
+
+// Note: BTMMDict needs to be retained by the caller if needed
+mDNSlocal CFDictionaryRef ParseBackToMyMacKey(CFDictionaryRef connd)
+ {
+ CFDictionaryRef BTMMDict = CFDictionaryGetValue(connd, CFSTR("BackToMyMac"));
+ if (!BTMMDict)
+ {
+ LogInfo("ParseBackToMyMacKey: CFDictionaryGetValue No value for BackToMyMac");
+ return NULL;
+ }
+
+ // Non-dictionary is treated as non-existent dictionary
+ if (CFGetTypeID(BTMMDict) != CFDictionaryGetTypeID())
+ {LogMsg("ERROR: ParseBackToMyMacKey: CFDictionaryGetValue BackToMyMac not a dictionary"); CFRelease(BTMMDict); return NULL;}
+
+ return BTMMDict;
+ }
+
+mDNSlocal void ParseBTMMInterfaceKey(CFDictionaryRef BTMMDict, char *buf, int buflen)
+ {
+ CFTypeRef string;
+ mDNSBool ifExists;
+
+ ifExists = CFDictionaryGetValueIfPresent(BTMMDict, CFSTR("Interface"), &string);
+ if (ifExists)
+ {
+ if (!CFStringGetCString(string, buf, buflen, kCFStringEncodingUTF8))
+ {
+ LogMsg("ERROR: ParseBTMMInterfaceKey: Could not convert Interface to CString");
+ if (buflen) buf[0] = 0;
+ return;
+ }
+ else
+ debugf("ParseBTMMInterfaceKey: Interface Key exists %s", buf);
+ }
+ else
+ {
+ if (buflen) buf[0] = 0;
+ debugf("ParseBTMMInterfaceKey: Interface Key does not exist");
+ }
+ }
+
+mDNSexport void RemoveAutoTunnel6Record(mDNS *const m)
+ {
+ DomainAuthInfo *info;
+ char buf[IFNAMSIZ];
+
+ // Did we parse a non-empty dictionary before ?
+ if (!m->p->ConndBTMMDict || (CFDictionaryGetCount(m->p->ConndBTMMDict) == 0))
+ {
+ LogInfo("RemoveAutoTunnel6Record: Never registered any records before, not deregistering %p", m->p->ConndBTMMDict);
+ return;
+ }
+
+ // Did we have a non-NULL Interface name before ?
+ ParseBTMMInterfaceKey(m->p->ConndBTMMDict, buf, sizeof(buf));
+ if (!strlen(buf))
+ {
+ LogInfo("RemoveAutoTunnel6Record: Interface name already NULL, not deregistering");
+ return;
+ }
+
+ // Set the address to zero before calling DeregisterAutoTunnel6Record. If we call
+ // Deregister too quickly before the previous Register completed (just scheduled
+ // to be sent out) and when DeregisterAutoTunnel6Record calls mDNS_Register_internal,
+ // it invokes the AutoTunnelRecordCallback immediately and AutoTunnelRelayAddr should
+ // be zero so that we don't register again.
+ m->AutoTunnelRelayAddr = zerov6Addr;
+ if (!m->AuthInfoList) LogInfo("RemoveAutoTunnel6Record: No Domain AuthInfo");
+ for (info = m->AuthInfoList; info; info = info->next)
+ {
+ if (!info->AutoTunnel) { LogInfo("RemoveAutoTunnel6Record: Domain %##s not an AutoTunnel", info->domain.c); continue;}
+
+ if (info->deltime) {LogInfo("RemoveAutoTunnel6Record: Domain %##s about to be deleted", info->domain.c); continue;}
+
+ LogInfo("RemoveAutoTunnel6Record: Deregistering records for domain %##s", info->domain.c);
+ DeregisterAutoTunnel6Record(m, info);
+ }
+ CFRelease(m->p->ConndBTMMDict);
+ m->p->ConndBTMMDict = NULL;
+ }
+
+// Returns zero on success
+mDNSlocal int GetIPv6AddressForIfname(char *ifname, mDNSv6Addr *ipv6Addr)
+ {
+ struct ifaddrs *ifa;
+ struct ifaddrs *ifaddrs;
+ mDNSAddr addr;
+
+ if (if_nametoindex(ifname) == 0) {LogInfo("GetIPv6AddressForIfname: Invalid name %s", ifname); return (-1);}
+
+ if (getifaddrs(&ifaddrs) < 0) {LogInfo("GetIPv6AddressForIfname: getifaddrs failed"); return (-1);}
+
+ /*
+ * Find the ifaddr entry corresponding to the interface name,
+ * and return the first matching non-linklocal IPv6 address.
+ */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next)
+ {
+ if (strncmp(ifa->ifa_name, ifname, IFNAMSIZ) != 0)
+ continue;
+ if (ifa->ifa_flags & IFF_UP && ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)ifa->ifa_addr;
+ if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr))
+ continue;
+ if (SetupAddr(&addr, ifa->ifa_addr) != mStatus_NoError)
+ {
+ LogInfo("GetIPv6AddressForIfname: SetupAddr error, continuing to the next address");
+ continue;
+ }
+ else
+ {
+ *ipv6Addr = *(mDNSv6Addr *)&addr.ip.v6;
+ LogInfo("GetIPv6AddressForIfname: Returning IPv6 address %.16a", ipv6Addr);
+ freeifaddrs(ifaddrs);
+ return 0;
+ }
+ }
+ }
+ LogInfo("GetIPv6AddressForIfname: No Valid IPv6 address");
+ freeifaddrs(ifaddrs);
+ return (-1);
+ }
+
+mDNSlocal void AddAutoTunnel6Record(mDNS *const m, char *ifname, CFDictionaryRef BTMMDict)
+ {
+ mDNSv6Addr v6addr;
+ DomainAuthInfo *info;
+
+ if (GetIPv6AddressForIfname(ifname, &v6addr) != 0)
+ {
+ LogInfo("AddAutoTunnel6Record: No Valid IPv6 addresses found for %s", ifname);
+ // If the interface does not exist but the dictionary has the value, we treat
+ // this case as though the dictionary does not have the value
+ RemoveAutoTunnel6Record(m);
+ // If awacsd crashes or exits for some reason, restart the relay connection
+ UpdateBTMMRelayConnection(m);
+ return;
+ }
+
+ m->AutoTunnelRelayAddr = v6addr;
+
+ if (!m->AuthInfoList) LogInfo("AddAutoTunnel6Record: No Domain AuthInfo");
+ for (info = m->AuthInfoList; info; info = info->next)
+ {
+ // clientContext for a domain tells us that we are listening for at least one Service/Record
+ // in a domain and SetLocalAutoTunnelInterface_internal was called
+ if (!info->AutoTunnel) { LogInfo("AddAutoTunnel6Record: Domain %##s not an AutoTunnel", info->domain.c); continue;}
+
+ if (!info->AutoTunnelNAT.clientContext) {LogInfo("AddAutoTunnel6Record: Domain %##s has no services", info->domain.c); continue;}
+
+ if (info->deltime) {LogInfo("AddAutoTunnel6Record: Domain %##s about to be deleted", info->domain.c); continue;}
+
+ LogInfo("AddAutoTunnel6Record: Registering records for domain %##s", info->domain.c);
+ mDNS_Lock(m);
+ RegisterAutoTunnel6Record(m, info);
+ mDNS_Unlock(m);
+ }
+ if (m->p->ConndBTMMDict) CFRelease(m->p->ConndBTMMDict);
+ m->p->ConndBTMMDict = CFRetain(BTMMDict);
+ }
+
+mDNSlocal void ParseBackToMyMac(mDNS *const m, CFDictionaryRef connd)
+ {
+ CFDictionaryRef BTMMDict;
+ char buf[IFNAMSIZ];
+
+ BTMMDict = ParseBackToMyMacKey(connd);
+ if (!BTMMDict)
+ {
+ LogInfo("ParseBackToMyMac: CFDictionaryGetValue No value for BackToMyMac, Removing autotunnel6");
+ RemoveAutoTunnel6Record(m);
+ return;
+ }
+
+ ParseBTMMInterfaceKey(BTMMDict, buf, sizeof(buf));
+ if (!strlen(buf))
+ {
+ LogInfo("ParseBackToMyMac: NULL value for Interface, Removing autotunnel6");
+ RemoveAutoTunnel6Record(m);
+ // We don't have a utun interface, start the relay connection if possible
+ UpdateBTMMRelayConnection(m);
+ }
+ else
+ {
+ LogInfo("ParseBackToMyMac: non-NULL value for Interface, Adding autotunnel6");
+ AddAutoTunnel6Record(m, buf, BTMMDict);
+ }
+ }
+
+mDNSexport void SetupConndConfigChanges(mDNS *const m)
+ {
+ CFDictionaryRef connd;
+ SCDynamicStoreRef store;
+
+ store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:SetupConndConfigChanges"), NULL, NULL);
+ if (!store) {LogMsg("SetupConndConfigChanges: SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); return;}
+
+ connd = SCDynamicStoreCopyValue(store, NetworkChangedKey_BTMMConnectivity);
+ if (!connd)
+ {LogInfo("SetupConndConfigChanges: SCDynamicStoreCopyValue failed: %s", SCErrorString(SCError())); CFRelease(store); return;}
+ else
+ {
+ ParseBackToMyMac(m, connd);
+ }
+ CFRelease(connd);
+ CFRelease(store);
+ }
+#endif /* APPLE_OSX_mDNSResponder */
+
+
mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
{
LogInfo("*** Network Configuration Change *** (%d)%s",
m->p->NetworkChanged = 0; // If we received a network change event and deferred processing, we're now dealing with it
mDNSs32 utc = mDNSPlatformUTC();
m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
+ m->SystemSleepOnlyIfWakeOnLAN = SystemSleepOnlyIfWakeOnLAN();
MarkAllInterfacesInactive(m, utc);
UpdateInterfaceList(m, utc);
ClearInactiveInterfaces(m, utc);
#if APPLE_OSX_mDNSResponder
+ SetupConndConfigChanges(m);
+
if (m->AutoTunnelHostAddr.b[0])
{
mDNS_Lock(m);
if (TunnelClients(m) || TunnelServers(m))
- SetupLocalAutoTunnelInterface_internal(m);
+ SetupLocalAutoTunnelInterface_internal(m, mDNSfalse);
mDNS_Unlock(m);
}
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))
+ if (!mDNSIPPortIsZero(p->rmt_outer_port))
{
- AutoTunnelSetKeys(p, mDNSfalse);
- p->loc_inner = m->AutoTunnelHostAddr;
- p->loc_outer = tmpSrc.ip.v4;
- AutoTunnelSetKeys(p, mDNStrue);
+ 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);
+ }
}
+ else
+ {
+ if (!mDNSSameIPv6Address(p->loc_inner, m->AutoTunnelHostAddr) ||
+ !mDNSSameIPv6Address(p->loc_outer6, m->AutoTunnelRelayAddr))
+ {
+ AutoTunnelSetKeys(p, mDNSfalse);
+ p->loc_inner = m->AutoTunnelHostAddr;
+ p->loc_outer6 = m->AutoTunnelRelayAddr;
+ AutoTunnelSetKeys(p, mDNStrue);
+ }
+ }
}
+
SetSPS(m);
NetworkInterfaceInfoOSX *i;
}
else // else, we're Sleep Proxy Server; open BPF fds
{
- if (i->Exists && i->Registered == i && !(i->ifa_flags & IFF_LOOPBACK) && i->BPF_fd == -1)
+ if (i->Exists && i->Registered == i && i->ifinfo.McastTxRx && !(i->ifa_flags & IFF_LOOPBACK) && i->BPF_fd == -1)
{ LogSPS("%s requesting BPF", i->ifinfo.ifname); i->BPF_fd = -2; mDNSRequestBPF(); }
}
}
}
+// Copy the fourth slash-delimited element from either:
+// State:/Network/Interface/<bsdname>/IPv4
+// or
+// Setup:/Network/Service/<servicename>/Interface
+mDNSlocal CFStringRef CopyNameFromKey(CFStringRef key)
+ {
+ CFArrayRef a;
+ CFStringRef name = NULL;
+
+ a = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/"));
+ if (a && CFArrayGetCount(a) == 5) name = CFRetain(CFArrayGetValueAtIndex(a, 3));
+ if (a != NULL) CFRelease(a);
+
+ return name;
+ }
+
+// Whether a key from a network change notification corresponds to
+// an IP service that is explicitly configured for IPv4 Link Local
+mDNSlocal mDNSBool ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
+ {
+ SCDynamicStoreRef store = NULL;
+ CFDictionaryRef dict = NULL;
+ CFMutableArrayRef a;
+ const void **keys = NULL, **vals = NULL;
+ CFStringRef pattern = NULL;
+ int i, ic, j, jc;
+ mDNSBool found = mDNSfalse;
+
+ jc = CFArrayGetCount(inkeys);
+ if (!jc) goto done;
+
+ store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:ChangedKeysHaveIPv4LL"), NULL, NULL);
+ if (store == NULL) goto done;
+
+ a = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (a == NULL) goto done;
+
+ // Setup:/Network/Service/[^/]+/Interface
+ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface);
+ if (pattern == NULL) goto done;
+ CFArrayAppendValue(a, pattern);
+ CFRelease(pattern);
+
+ // Setup:/Network/Service/[^/]+/IPv4
+ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetIPv4);
+ if (pattern == NULL) goto done;
+ CFArrayAppendValue(a, pattern);
+ CFRelease(pattern);
+
+ dict = SCDynamicStoreCopyMultiple(store, NULL, a);
+ CFRelease(a);
+
+ if (!dict)
+ {
+ LogMsg("ChangedKeysHaveIPv4LL: Empty dictionary");
+ goto done;
+ }
+
+ ic = CFDictionaryGetCount(dict);
+ vals = mDNSPlatformMemAllocate(sizeof (void *) * ic);
+ keys = mDNSPlatformMemAllocate(sizeof (void *) * ic);
+ CFDictionaryGetKeysAndValues(dict, keys, vals);
+
+ for (j = 0; j < jc && !found; j++)
+ {
+ CFStringRef key = CFArrayGetValueAtIndex(inkeys, j);
+ CFStringRef ifname = NULL;
+
+ char buf[256];
+
+ // It would be nice to use a regex here
+ if (!CFStringHasPrefix(key, CFSTR("State:/Network/Interface/")) || !CFStringHasSuffix(key, kSCEntNetIPv4)) continue;
+
+ if ((ifname = CopyNameFromKey(key)) == NULL) continue;
+ if (mDNS_LoggingEnabled)
+ {
+ if (!CFStringGetCString(ifname, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
+ LogInfo("ChangedKeysHaveIPv4LL: potential ifname %s", buf);
+ }
+
+ for (i = 0; i < ic; i++)
+ {
+ CFDictionaryRef ipv4dict;
+ CFStringRef name;
+ CFStringRef serviceid;
+ CFStringRef configmethod;
+
+ if (!CFStringHasSuffix(keys[i], kSCEntNetInterface)) continue;
+
+ if (CFDictionaryGetTypeID() != CFGetTypeID(vals[i])) continue;
+
+ if ((name = CFDictionaryGetValue(vals[i], kSCPropNetInterfaceDeviceName)) == NULL) continue;
+
+ if (!CFEqual(ifname, name)) continue;
+
+ if ((serviceid = CopyNameFromKey(keys[i])) == NULL) continue;
+ if (mDNS_LoggingEnabled)
+ {
+ if (!CFStringGetCString(serviceid, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
+ LogInfo("ChangedKeysHaveIPv4LL: found serviceid %s", buf);
+ }
+
+ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceid, kSCEntNetIPv4);
+ CFRelease(serviceid);
+ if (pattern == NULL) continue;
+
+ ipv4dict = CFDictionaryGetValue(dict, pattern);
+ CFRelease(pattern);
+ if (!ipv4dict || CFDictionaryGetTypeID() != CFGetTypeID(ipv4dict)) continue;
+
+ configmethod = CFDictionaryGetValue(ipv4dict, kSCPropNetIPv4ConfigMethod);
+ if (!configmethod) continue;
+
+ if (mDNS_LoggingEnabled)
+ {
+ if (!CFStringGetCString(configmethod, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
+ LogInfo("ChangedKeysHaveIPv4LL: configmethod %s", buf);
+ }
+
+ if (CFEqual(configmethod, kSCValNetIPv4ConfigMethodLinkLocal)) { found = mDNStrue; break; }
+ }
+
+ CFRelease(ifname);
+ }
+
+ done:
+ if (vals != NULL) mDNSPlatformMemFree(vals);
+ if (keys != NULL) mDNSPlatformMemFree(keys);
+ if (dict != NULL) CFRelease(dict);
+ if (store != NULL) CFRelease(store);
+
+ return found;
+ }
+
mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
{
(void)store; // Parameter not used
mDNS_Unlock(m);
// If DNS settings changed, immediately force a reconfig (esp. cache flush)
- if (c4) mDNSMacOSXNetworkChanged(m);
+ // Similarly, if an interface changed that is explicitly IPv4 link local, immediately force a reconfig
+ if (c4 || ChangedKeysHaveIPv4LL(changedKeys)) mDNSMacOSXNetworkChanged(m);
KQueueUnlock(m, "NetworkChanged");
}
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(keys, NetworkChangedKey_PowerSettings); // should remove as part of <rdar://problem/6751656>
+ CFArrayAppendValue(keys, NetworkChangedKey_BTMMConnectivity);
CFArrayAppendValue(patterns, pattern1);
CFArrayAppendValue(patterns, pattern2);
CFArrayAppendValue(patterns, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns))
{ LogMsg("SCDynamicStoreSetNotificationKeys failed: %s", SCErrorString(SCError())); goto error; }
+#ifdef __LIB_DISPATCH__
+ if (!SCDynamicStoreSetDispatchQueue(store, dispatch_get_main_queue()))
+ { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
+#else
m->p->StoreRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
if (!m->p->StoreRLS) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
-
CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
+#endif
m->p->Store = store;
err = 0;
goto exit;
{
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); }
+ { LogMsg("WatchForSysEvents: socket failed error %d errno %d (%s)", m->p->SysEventNotifier, errno, strerror(errno)); return(mStatus_NoMemoryErr); }
struct kev_request kev_req = { KEV_VENDOR_APPLE, KEV_NETWORK_CLASS, KEV_DL_SUBCLASS };
int err = ioctl(m->p->SysEventNotifier, SIOCSKEVFILT, &kev_req);
if (err < 0)
{
- LogMsg("WatchForNetworkChanges: SIOCSKEVFILT failed %s errno %d (%s)", errno, strerror(errno));
+ LogMsg("WatchForSysEvents: SIOCSKEVFILT failed error %d errno %d (%s)", err, errno, strerror(errno));
close(m->p->SysEventNotifier);
m->p->SysEventNotifier = -1;
return(mStatus_UnknownErr);
}
#endif
-#ifndef NO_IOPOWER
mDNSlocal void PowerOn(mDNS *const m)
{
mDNSCoreMachineSleep(m, false); // Will set m->SleepState = SleepState_Awake;
case kIOMessageSystemWillRestart: LogInfo("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310
case kIOMessageSystemWillPowerOn: LogInfo("PowerChanged kIOMessageSystemWillPowerOn"); // E0000320
+ #if ! TARGET_OS_EMBEDDED
// 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
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);
}
+ #endif
// Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
if (m->SleepState != SleepState_Sleeping)
KQueueUnlock(m, "PowerChanged Sleep/Wake");
}
-#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+// iPhone OS doesn't currently have SnowLeopard's IO Power Management
+// but it does define kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+#if defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements) && !TARGET_OS_EMBEDDED
mDNSlocal void SnowLeopardPowerChanged(void *refcon, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities eventDescriptor)
{
mDNS *const m = (mDNS *const)refcon;
if (eventDescriptor & kIOPMSystemPowerStateCapabilityCPU)
{
+ // We might be in Sleeping or Transferring state. When we go from "wakeup" to "sleep" state, we don't
+ // go directly to sleep state, but transfer in to the sleep state during which SleepState is set to
+ // SleepState_Transferring. During that time, we might get another wakeup before we transition to Sleeping
+ // state. In that case, we need to acknowledge the previous "sleep" before we acknowledge the wakeup.
+ if (m->SleepLimit)
+ {
+ LogSPS("SnowLeopardPowerChanged: Waking up, Acking old Sleep, SleepLimit %d SleepState %d", m->SleepLimit, m->SleepState);
+ IOPMConnectionAcknowledgeEvent(connection, m->p->SleepCookie);
+ m->SleepLimit = 0;
+ }
+ LogSPS("SnowLeopardPowerChanged: Waking up, Acking Wakeup, SleepLimit %d SleepState %d", m->SleepLimit, m->SleepState);
// CPU Waking. Note: Can get this message repeatedly, as other subsystems power up or down.
- if (m->SleepState == SleepState_Sleeping) PowerOn(m);
+ if (m->SleepState != SleepState_Awake) PowerOn(m);
IOPMConnectionAcknowledgeEvent(connection, token);
}
else
}
#endif
-#endif /* NO_IOPOWER */
-
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
#pragma mark - Initialization & Teardown
int get_model[2] = { CTL_HW, HW_MODEL };
size_t len_model = sizeof(HINFO_HWstring_buffer);
- // 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, ','))
+
+ // Normal Apple model names are of the form "iPhone2,1", and
+ // internal code names are strings containing no commas, e.g. "N88AP".
+ // We used to ignore internal code names, but Apple now uses these internal code names
+ // even in released shipping products, so we no longer ignore strings containing no commas.
+// if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0 && strchr(HINFO_HWstring_buffer, ','))
+ if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0)
HINFO_HWstring = HINFO_HWstring_buffer;
HINFO_HWstring_prefixlen = strcspn(HINFO_HWstring, "0123456789");
if (OSXVers < OSXVers_10_3_Panther ) m->KnownBugs |= mDNS_KnownBug_PhantomInterfaces;
+ if (OSXVers <= OSXVers_10_6_SnowLeopard ) m->KnownBugs |= mDNS_KnownBug_LimitedIPv6;
if (OSXVers >= OSXVers_10_6_SnowLeopard ) m->KnownBugs |= mDNS_KnownBug_LossySyslog;
if (mDNSPlatformInit_CanReceiveUnicast()) m->CanReceiveUnicastOn5353 = mDNStrue;
m->p->permanentsockets.port = MulticastDNSPort;
m->p->permanentsockets.m = m;
- m->p->permanentsockets.sktv4 = m->p->permanentsockets.sktv6 = -1;
- m->p->permanentsockets.kqsv4.KQcallback = m->p->permanentsockets.kqsv6.KQcallback = myKQSocketCallBack;
- m->p->permanentsockets.kqsv4.KQcontext = m->p->permanentsockets.kqsv6.KQcontext = &m->p->permanentsockets;
- m->p->permanentsockets.kqsv4.KQtask = m->p->permanentsockets.kqsv6.KQtask = "UDP packet reception";
+ m->p->permanentsockets.sktv4 = -1;
+ m->p->permanentsockets.kqsv4.KQcallback = myKQSocketCallBack;
+ m->p->permanentsockets.kqsv4.KQcontext = &m->p->permanentsockets;
+ m->p->permanentsockets.kqsv4.KQtask = "UDP packet reception";
+#ifndef NO_IPV6
+ m->p->permanentsockets.sktv6 = -1;
+ m->p->permanentsockets.kqsv6.KQcallback = myKQSocketCallBack;
+ m->p->permanentsockets.kqsv6.KQcontext = &m->p->permanentsockets;
+ m->p->permanentsockets.kqsv6.KQtask = "UDP packet reception";
+#endif
err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET, mDNSNULL);
#ifndef NO_IPV6
m->p->InterfaceList = mDNSNULL;
m->p->userhostlabel.c[0] = 0;
m->p->usernicelabel.c[0] = 0;
+ m->p->prevoldnicelabel.c[0] = 0;
+ m->p->prevnewnicelabel.c[0] = 0;
+ m->p->prevoldhostlabel.c[0] = 0;
+ m->p->prevnewhostlabel.c[0] = 0;
m->p->NotifyUser = 0;
m->p->KeyChainBugTimer = 0;
m->p->WakeAtUTC = 0;
#endif
m->AutoTunnelHostAddr.b[0] = 0; // Zero out AutoTunnelHostAddr so UpdateInterfaceList() know it has to set it up
+ m->AutoTunnelRelayAddr = zerov6Addr;
NetworkChangedKey_IPv4 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
NetworkChangedKey_IPv6 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
if (err) { LogMsg("mDNSPlatformInit_setup: SecKeychainAddCallback failed %d", err); return(err); }
#endif
-#ifndef NO_IOPOWER
-
-#ifndef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+#if !defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements) || TARGET_OS_EMBEDDED
LogMsg("Note: Compiled without SnowLeopard Fine-Grained Power Management support");
#else
IOPMConnection c;
{
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);
+ else
+ {
+#ifdef __LIB_DISPATCH__
+ IONotificationPortSetDispatchQueue(m->p->PowerPortRef, dispatch_get_main_queue());
+#else
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
+#endif /* __LIB_DISPATCH__ */
+ }
}
-#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 */; }
+ // Apple TVs, AirPort base stations, and Time Capsules do not actually weigh 3kg, but we assign them
+ // higher 'nominal' masses to indicate they should be treated as being relatively less portable than a laptop
+ if (!strncasecmp(HINFO_HWstring, "Xserve", 6)) { SPMetricPortability = 25 /* 30kg */; SPMetricMarginalPower = 84 /* 250W */; SPMetricTotalPower = 85 /* 300W */; }
+ else if (!strncasecmp(HINFO_HWstring, "RackMac", 7)) { SPMetricPortability = 25 /* 30kg */; SPMetricMarginalPower = 84 /* 250W */; SPMetricTotalPower = 85 /* 300W */; }
+ else if (!strncasecmp(HINFO_HWstring, "MacPro", 6)) { SPMetricPortability = 27 /* 20kg */; SPMetricMarginalPower = 84 /* 250W */; SPMetricTotalPower = 85 /* 300W */; }
+ else if (!strncasecmp(HINFO_HWstring, "PowerMac", 8)) { SPMetricPortability = 27 /* 20kg */; SPMetricMarginalPower = 82 /* 160W */; SPMetricTotalPower = 83 /* 200W */; }
+ else if (!strncasecmp(HINFO_HWstring, "iMac", 4)) { SPMetricPortability = 30 /* 10kg */; SPMetricMarginalPower = 77 /* 50W */; SPMetricTotalPower = 78 /* 60W */; }
+ else if (!strncasecmp(HINFO_HWstring, "Macmini", 7)) { SPMetricPortability = 33 /* 5kg */; SPMetricMarginalPower = 73 /* 20W */; SPMetricTotalPower = 74 /* 25W */; }
+ else if (!strncasecmp(HINFO_HWstring, "TimeCapsule", 11)) { SPMetricPortability = 34 /* 4kg */; SPMetricMarginalPower = 10 /* ~0W */; SPMetricTotalPower = 70 /* 13W */; }
+ else if (!strncasecmp(HINFO_HWstring, "AirPort", 7)) { SPMetricPortability = 35 /* 3kg */; SPMetricMarginalPower = 10 /* ~0W */; SPMetricTotalPower = 70 /* 12W */; }
+ else if (!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); }
+
+ m->p->ConndBTMMDict = mDNSNULL;
#endif // APPLE_OSX_mDNSResponder
+#ifdef __LIB_DISPATCH__
+ // Currently this is not defined. SSL code will eventually fix this. If it becomes
+ // critical, we will define this to workaround the bug in SSL.
+#ifdef __SSL_NEEDS_SERIALIZATION__
+ SSLqueue = dispatch_queue_create("com.apple.mDNSResponder.SSLQueue", NULL);
+#else
+ SSLqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+#endif
+ if (SSLqueue == mDNSNULL) LogMsg("dispatch_queue_create: SSL queue NULL");
+#endif
return(mStatus_NoError);
}
#if APPLE_OSX_mDNSResponder
m->SPSBrowseCallback = UpdateSPSStatus;
-#endif
+#endif // APPLE_OSX_mDNSResponder
mStatus result = mDNSPlatformInit_setup(m);
// We don't do asynchronous initialization on OS X, so by the time we get here the setup will already
// have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately
- if (result == mStatus_NoError) mDNSCoreInitComplete(m, mStatus_NoError);
+ if (result == mStatus_NoError)
+ {
+ mDNSCoreInitComplete(m, mStatus_NoError);
+
+#if ! NO_D2D
+ // We only initialize if mDNSCore successfully initialized.
+ CHECK_D2D_FUNCTION(D2DInitialize)
+ {
+ D2DStatus ds = D2DInitialize(m->p->CFRunLoop, xD2DServiceCallback, m) ;
+ if (ds != kD2DSuccess)
+ LogMsg("D2DInitialiize failed: %d", ds);
+ else
+ LogMsg("D2DInitialize succeeded");
+ }
+#endif // ! NO_D2D
+
+ }
return(result);
}
{
if (m->p->PowerConnection)
{
+#ifdef __LIB_DISPATCH__
+ IONotificationPortSetDispatchQueue(m->p->PowerPortRef, NULL);
+#else
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
-#ifndef NO_IOPOWER
+#endif
// According to <http://developer.apple.com/qa/qa2004/qa1340.html>, a single call
// to IORegisterForSystemPower creates *three* objects that need to be disposed individually:
IODeregisterForSystemPower(&m->p->PowerNotifier);
IOServiceClose ( m->p->PowerConnection);
IONotificationPortDestroy ( m->p->PowerPortRef);
-#endif /* NO_IOPOWER */
m->p->PowerConnection = 0;
}
if (m->p->Store)
{
+#ifdef __LIB_DISPATCH__
+ if (!SCDynamicStoreSetDispatchQueue(m->p->Store, NULL))
+ LogMsg("mDNSPlatformClose: SCDynamicStoreSetDispatchQueue failed");
+#else
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
CFRunLoopSourceInvalidate(m->p->StoreRLS);
CFRelease(m->p->StoreRLS);
+ m->p->StoreRLS = NULL;
+#endif
CFRelease(m->p->Store);
m->p->Store = NULL;
- m->p->StoreRLS = NULL;
}
if (m->p->PMRLS)
if (m->p->SysEventNotifier >= 0) { close(m->p->SysEventNotifier); m->p->SysEventNotifier = -1; }
+#if ! NO_D2D
+ CHECK_D2D_FUNCTION(D2DTerminate)
+ {
+ D2DStatus ds = D2DTerminate();
+ if (ds != kD2DSuccess)
+ LogMsg("D2DTerminate failed: %d", ds);
+ else
+ LogMsg("D2DTerminate succeeded");
+ }
+#endif // ! NO_D2D
+
mDNSs32 utc = mDNSPlatformUTC();
MarkAllInterfacesInactive(m, utc);
ClearInactiveInterfaces(m, utc);
LogInfo("mDNSPlatformClose: Removing AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
(void)mDNSAutoTunnelInterfaceUpDown(kmDNSDown, m->AutoTunnelHostAddr.b);
}
+ if (m->p->ConndBTMMDict) CFRelease(m->p->ConndBTMMDict);
#endif // APPLE_OSX_mDNSResponder
}
mDNSexport void * mDNSPlatformMemAllocate(mDNSu32 len) { return(mallocL("mDNSPlatformMemAllocate", len)); }
#endif
mDNSexport void mDNSPlatformMemFree (void *mem) { freeL("mDNSPlatformMemFree", mem); }
+
+mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep)
+ {
+ if (allowSleep && m->p->IOPMAssertion)
+ {
+ LogInfo("%s Destroying NoIdleSleep power assertion", __FUNCTION__);
+ IOPMAssertionRelease(m->p->IOPMAssertion);
+ m->p->IOPMAssertion = 0;
+ }
+ else if (!allowSleep && m->p->IOPMAssertion == 0)
+ {
+ IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, CFSTR("mDNSResponder"), &m->p->IOPMAssertion);
+ LogInfo("%s Creating NoIdleSleep power assertion", __FUNCTION__);
+ }
+ }
* 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: 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
-
-Revision 1.78 2008/07/25 22:34:11 mcguire
-fix sizecheck issues for 64bit
-
-Revision 1.77 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.76 2008/07/01 01:40:01 mcguire
-<rdar://problem/5823010> 64-bit fixes
-
-Revision 1.75 2007/12/14 00:45:21 cheshire
-Add SleepLimit and SleepCookie, for when we need to delay sleep until TLS/TCP record deregistration completes
-
-Revision 1.74 2007/11/02 20:18:13 cheshire
-<rdar://problem/5575583> BTMM: Work around keychain notification bug <rdar://problem/5124399>
-
-Revision 1.73 2007/10/17 18:42:06 cheshire
-Export SetDomainSecrets so its callable from other files
-
-Revision 1.72 2007/08/01 16:09:14 cheshire
-Removed unused NATTraversalInfo substructure from AuthRecord; reduced structure sizecheck values accordingly
-
-Revision 1.71 2007/07/27 23:57:23 cheshire
-Added compile-time structure size checks
-
-Revision 1.70 2007/07/11 02:55:50 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-Remove unused DefaultRegDomainChanged/DefaultBrowseDomainChanged
-
-Revision 1.69 2007/05/08 00:56:17 cheshire
-<rdar://problem/4118503> Share single socket instead of creating separate socket for each active interface
-
-Revision 1.68 2007/04/24 00:10:15 cheshire
-Increase WatchDogReportingThreshold to 250ms for customer builds
-
-Revision 1.67 2007/04/21 21:47:47 cheshire
-<rdar://problem/4376383> Daemon: Add watchdog timer
-
-Revision 1.66 2007/04/07 01:01:48 cheshire
-<rdar://problem/5095167> mDNSResponder periodically blocks in SSLRead
-
-Revision 1.65 2007/03/07 02:50:50 cheshire
-<rdar://problem/4574528> Name conflict dialog doesn't appear if Bonjour is persistantly unable to find an available hostname
-
-Revision 1.64 2007/03/06 23:29:50 cheshire
-<rdar://problem/4331696> Need to call IONotificationPortDestroy on shutdown
-
-Revision 1.63 2007/02/07 19:32:00 cheshire
-<rdar://problem/4980353> All mDNSResponder components should contain version strings in SCCS-compatible format
-
-Revision 1.62 2007/01/05 08:30:49 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.61 2006/08/14 23:24:40 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.60 2006/07/27 03:24:35 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-Further refinement: Declare KQueueEntry parameter "const"
-
-Revision 1.59 2006/07/27 02:59:25 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-Further refinements: CFRunLoop thread needs to explicitly wake the kqueue thread
-after releasing BigMutex, in case actions it took have resulted in new work for the
-kqueue thread (e.g. NetworkChanged events may result in the kqueue thread having to
-add new active interfaces to its list, and consequently schedule queries to be sent).
-
-Revision 1.58 2006/07/22 06:08:29 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-Further changes
-
-Revision 1.57 2006/07/22 03:43:26 cheshire
-<rdar://problem/4049048> Convert mDNSResponder to use kqueue
-
-Revision 1.56 2006/07/05 23:37:26 cheshire
-Remove unused LegacyNATInit/LegacyNATDestroy declarations
-
-Revision 1.55 2006/06/29 05:33:30 cheshire
-<rdar://problem/4607043> mDNSResponder conditional compilation options
-
-Revision 1.54 2006/03/19 03:27:49 cheshire
-<rdar://problem/4118624> Suppress "interface flapping" logic for loopback
-
-Revision 1.53 2006/03/19 02:00:09 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.52 2006/01/05 21:41:49 cheshire
-<rdar://problem/4108164> Reword "mach_absolute_time went backwards" dialog
-
-*/
+ */
#ifndef __mDNSOSX_h
#define __mDNSOSX_h
#include <netinet/in.h>
#include "mDNSEmbeddedAPI.h" // for domain name structure
+//#define __LIB_DISPATCH__
+#ifdef __LIB_DISPATCH__
+#include <dispatch/dispatch.h>
+#endif
+
typedef struct NetworkInterfaceInfoOSX_struct NetworkInterfaceInfoOSX;
typedef void (*KQueueEventCallback)(int fd, short filter, void *context);
KQueueEventCallback KQcallback;
void *KQcontext;
const char const *KQtask; // For debugging messages
+#ifdef __LIB_DISPATCH__
+ dispatch_source_t readSource;
+ dispatch_source_t writeSource;
+ mDNSBool fdClosed;
+#endif
} KQueueEntry;
typedef struct
mDNS *m;
int sktv4;
KQueueEntry kqsv4;
+#ifndef NO_IPV6
int sktv6;
KQueueEntry kqsv6;
+#endif
int *closeFlag;
} KQSocketSet;
mDNSEthAddr BSSID; // BSSID of 802.11 base station, if applicable
u_short sa_family;
int BPF_fd; // -1 uninitialized; -2 requested BPF; -3 failed
+ int BPF_mcfd; // Socket for our IPv6 ND group membership
u_int BPF_len;
+#ifdef __LIB_DISPATCH__
+ dispatch_source_t BPF_source;
+#else
CFSocketRef BPF_cfs;
CFRunLoopSourceRef BPF_rls;
+#endif
NetworkInterfaceInfoOSX *Registered; // non-NULL means registered with mDNS Core
};
KQSocketSet permanentsockets;
domainlabel userhostlabel; // The hostlabel as it was set in System Preferences the last time we looked
domainlabel usernicelabel; // The nicelabel as it was set in System Preferences the last time we looked
+ // Following four variables are used for optimization where the helper is not
+ // invoked when not needed. It records the state of what we told helper the
+ // last time we invoked mDNSPreferencesSetName
+ domainlabel prevoldhostlabel; // Previous m->p->userhostlabel
+ domainlabel prevnewhostlabel; // Previous m->hostlabel
+ domainlabel prevoldnicelabel; // Previous m->p->usernicelabel
+ domainlabel prevnewnicelabel; // Previous m->nicelabel
mDNSs32 NotifyUser;
mDNSs32 HostNameConflict; // Time we experienced conflict on our link-local host name
mDNSs32 NetworkChanged;
#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
IOPMConnection IOPMConnection;
#endif
+ IOPMAssertionID IOPMAssertion;
SCPreferencesRef SCPrefs;
long SleepCookie; // Cookie we need to pass to IOAllowPowerChange()
long WakeAtUTC;
mDNSs32 RequestReSleep;
+#ifdef __LIB_DISPATCH__
+ dispatch_source_t timer;
+ dispatch_source_t custom;
+#else
pthread_mutex_t BigMutex;
+#endif
mDNSs32 BigMutexStartTime;
int WakeKQueueLoopFD;
+#if APPLE_OSX_mDNSResponder
+ CFDictionaryRef ConndBTMMDict; // Dictionary of tunnel name/value pairs
+#endif
};
extern int OfferSleepProxyService;
+extern int DisableSleepProxyClient;
+extern mDNSBool DisableInboundRelayConnection;
extern int OSXVers;
#define OSXVers_Base 4
#define OSXVers_10_0_Cheetah 4
extern int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring);
extern NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(const mDNS *const m, mDNSInterfaceID ifindex);
+#ifdef __LIB_DISPATCH__
+extern int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef);
+mDNSexport void TriggerEventCompletion(void);
+#else
extern int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *const entryRef);
+#endif
// When events are processed on the non-kqueue thread (i.e. CFRunLoop notifications like Sleep/Wake,
// Interface changes, Keychain changes, etc.) they must use KQueueLock/KQueueUnlock to lock out the kqueue thread
extern void KQueueLock(mDNS *const m);
extern void KQueueUnlock(mDNS *const m, const char const *task);
+extern void mDNSPlatformCloseFD(KQueueEntry *kq, int fd);
extern mDNSBool DictionaryIsEnabled(CFDictionaryRef dict);
// 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) <= 7000) ? 1 : -1];
- char sizecheck_mDNS_PlatformSupport [(sizeof(mDNS_PlatformSupport) <= 476) ? 1 : -1];
+ char sizecheck_mDNS_PlatformSupport [(sizeof(mDNS_PlatformSupport) <= 768) ? 1 : -1];
};
#ifdef __cplusplus
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
-; $Log: mDNSResponder.sb,v $
-; 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
-;
-; Revision 1.24 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
-;
-; Revision 1.23 2007/09/04 22:26:18 mcguire
-; <rdar://problem/5442826> Seatbelt: mDNSResponder needs to be allowed to access "/Library/Security/Trust Settings/" etc.
-;
-; Revision 1.22 2007/08/24 22:01:56 mcguire
-; <rdar://problem/5141606> BTMM: Task: Change mDNSResponder Seatbelt settings to "deny default" instead of "signal FPE" just prior to GM candidate
-;
-; Revision 1.21 2007/08/18 01:02:03 mcguire
-; <rdar://problem/5415593> No Bonjour services are getting registered at boot
-;
-; Revision 1.20 2007/08/08 22:34:59 mcguire
-; <rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
-;
-; Revision 1.19 2007/07/02 23:37:50 cheshire
-; <rdar://problem/5267615> Need to list of allowed mach-lookup operations explicitly in mDNSResponder.sb
-;
-; Revision 1.18 2007/06/28 20:43:35 cheshire
-; <rdar://problem/5298202> Seatbelt: mDNSResponder needs to be able to access /dev/autofs_nowait
-;
-; Revision 1.17 2007/06/28 20:34:45 cheshire
-; Updated comments to reflect new seatbelt language syntax
-;
-; Revision 1.16 2007/05/29 23:32:46 cheshire
-; Rearrange file so SPI warning isn't deleted when CVS history is trimmed from installed copy
-;
-; Revision 1.15 2007/05/25 22:45:17 jvidrine
-; <rdar://problem/5227658> Update mDNSResponder.sb to Seatbelt Profile Language version 1
-;
-; Revision 1.14 2007/05/23 17:40:08 cheshire
-; <rdar://problem/5221397> Seatbelt killed mDNSResponder trying to read X509Anchors and X509Certificates
-;
-; Revision 1.13 2007/05/23 01:47:59 cheshire
-; Need to list fs_read_data permission explicitly --
-; unlike fs_read/fs_write, fs_read_data does NOT automatically inherit from fs_write_data
-;
-; Revision 1.12 2007/05/21 23:52:27 cheshire
-; <rdar://problem/5216638> Seatbelt killed mDNSResponder generating Module Directory Services cache
-;
-; Revision 1.11 2007/05/20 16:29:06 cheshire
-; <rdar://problem/5213725> Seatbelt killed mDNSResponder trying to access /usr/share/icu/icudt36l.dat
-;
-; Revision 1.10 2007/05/15 00:21:39 cheshire
-; <rdar://problem/5202374> Seatbelt killed mDNSResponder reading /private/var/root/Library/Preferences/com.apple.security.plist
-;
-; Revision 1.9 2007/05/14 22:08:26 cheshire
-; <rdar://problem/5200986> Seatbelt: Need to escape literal dots in filename patterns
-;
-; Revision 1.8 2007/05/14 19:39:31 cheshire
-; <rdar://problem/5198345> Seatbelt killed mDNSResponder in CFTimeZoneCopyDefault
-; <rdar://problem/5199456> Seatbelt killed mDNSResponder in SecKeychainOpen
-;
-; Revision 1.7 2007/05/12 01:57:56 cheshire
-; <rdar://problem/5197938> Seatbelt: mDNSResponder needs to be able to access preferences.plist-lock
-;
-; Revision 1.6 2007/05/10 21:12:14 cheshire
-; <rdar://problem/5149833> Start using "debug deny" mode in Seatbelt
-;
-; Revision 1.5 2007/05/10 19:41:25 cheshire
-; <rdar://problem/5182549> Have to use "deny mach_lookup_default" because "signal" doesn't work
-;
-; Revision 1.4 2007/04/27 20:46:31 cheshire
-; Additional requirements: allow mDNSResponder to read /dev/random and /System/Library/Keychains/System.*
-;
-; Revision 1.3 2007/04/20 19:42:14 cheshire
-; Condense rules a bit to bring file under Seatbelt's 4K limit
-;
-; Revision 1.2 2007/04/19 01:47:49 cheshire
-; Refinements to sandbox profile, e.g. allow writing to /dev/console early in the boot process
-;
-; Revision 1.1 2007/04/18 00:50:47 cheshire
-; <rdar://problem/5141540> Sandbox mDNSResponder
-;
;############################################################################
-; WARNING! SEATBELT CURRENTLY CAN'T HANDLE PROFILES LARGER THAN 16K
-; MAKE SURE THE SIZE OF THIS FILE FROM "version" TO THE END DOESN'T EXCEED 16K
-
(version 1)
; WARNING: The sandbox rule capabilities and syntax used in this file are currently an
"com.apple.system.DirectoryService.libinfo_v1"
"com.apple.system.DirectoryService.membership_v1"
"com.apple.system.notification_center"
- "com.apple.system.logger"))
+ "com.apple.system.logger"
+ "com.apple.webcontentfilter.dns"
+ "com.apple.server.bluetooth"
+ "com.apple.awacs"
+ "com.apple.blued"))
; Rules to allow the operations mDNSResponder needs start here
(if (defined? 'system-socket)
(allow system-socket)) ; To create raw sockets
(allow sysctl-read) ; To get hardware model information
+(allow sysctl-write) ; Needed for CFSocket
(allow file-read-metadata) ; Needed for dyld to work
(allow ipc-posix-shm) ; Needed for POSIX shared memory
(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 file-read-data (regex #"^/private/var/preferences/SystemConfiguration/preferences\.plist$"))
; Allow access to System Keychain
(allow file-read-data (regex #"^/System/Library/Security$"))
(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(/|$)"))
+(allow file-read* file-write* (regex #"^/private/var/folders/[^/]+/[^/]+/C/mds(/|$)"))
+(allow file-read* file-write* (regex #"^/private/var/folders/[^/]+/[^/]+/-Caches-/mds(/|$)")) ; Required on 10.5 and 10.6
; CRL Cache for SSL/TLS connections
(allow file-read-data (regex #"^/private/var/db/crls/crlcache\.db$"))
+
+; For mDNS sleep proxy offload
+(allow iokit-open (iokit-user-client-class "NVEthernetUserClientMDNS"))
+(allow iokit-open (iokit-user-client-class "mDNSOffloadUserClient"))
+
+; For IOPMConnectionCreate
+(allow iokit-open (iokit-user-client-class "RootDomainUserClient"))
+
+; For D2D
+(allow file-read-data (regex #"^/System/Library/PrivateFrameworks/DeviceToDeviceManager.framework(/|$)"))
+(allow file-read-data (regex #"^/System/Library/PrivateFrameworks/MobileBluetooth.framework(/|$)"))
+(allow file-read-data (regex #"^/System/Library/Frameworks/CoreFoundation.framework(/|$)"))
+(allow file-read-data (regex #"^/System/Library/Frameworks/CoreServices.framework(/|$)"))
+(allow file-read-data (regex #"^/System/Library/Frameworks/SystemConfiguration.framework(/|$)"))
+(allow file-read-data (regex #"^/System/Library/Frameworks/IOKit.framework(/|$)"))
+(allow file-read-data (regex #"^/System/Library/Frameworks/Security.framework(/|$)"))
+(allow file-read-data file-write-data file-ioctl (regex #"^/dev/dtracehelper$"))
+
+; For WebFilterDNS framework
+(allow file-read-data (regex #"^/System/Library/PrivateFrameworks/WebFilterDNS.framework(/|$)"))
archiveVersion = 1;
classes = {
};
- objectVersion = 42;
+ objectVersion = 45;
objects = {
/* Begin PBXAggregateTarget section */
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 21E53F0F1219D1B3003EEE05 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E53F0E1219D1B3003EEE05 /* CoreServices.framework */; };
+ 21E53F141219D1CA003EEE05 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E53F0E1219D1B3003EEE05 /* CoreServices.framework */; };
2E0405F50C3195F700F13B59 /* helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405F40C3195F700F13B59 /* helper.c */; };
2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; settings = {ATTRIBUTES = (Server, Client, ); COMPILER_FLAGS = "-Wno-error"; }; };
2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E0406140C3197CB00F13B59 /* libbsm.dylib */; };
FFA5724A0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.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 */; };
+ FFAE66F0105F0CD900162116 /* ddnswriteconfig in Resources */ = {isa = PBXBuildFile; fileRef = D284BEE80ADD80A70027CCDF /* ddnswriteconfig */; };
FFB437150EB165BD00E17C68 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
FFC22AA20B00F42A00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
FFC22AA30B00F42B00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
remoteGlobalIDString = FFA572650AF190F10055A0F1;
remoteInfo = SystemLibraries;
};
+ FFAE66F8105F0CF100162116 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D284BEDB0ADD80A70027CCDF;
+ remoteInfo = ddnswriteconfig;
+ };
FFB7657C0AEED97F00583A2C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
);
runOnlyForDeploymentPostprocessing = 1;
};
- FF93944E0AF193B900C5D655 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 8;
- dstPath = /usr/include;
- dstSubfolderSpec = 0;
- files = (
- FFA572640AF190C80055A0F1 /* dns_sd.h in CopyFiles */,
- );
- runOnlyForDeploymentPostprocessing = 1;
- };
FFA572500AF190070055A0F1 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
000753D303367C1C0CCA2C71 /* mDNSMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mDNSMacOSX.h; sourceTree = "<group>"; };
00CA213D02786FC30CCA2C71 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+ 21E53F0E1219D1B3003EEE05 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
+ 21F432971134AA6800581B69 /* WebFilterDNS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebFilterDNS.framework; path = /System/Library/PrivateFrameworks/WebFilterDNS.framework; sourceTree = "<absolute>"; };
2E0405EB0C3190DC00F13B59 /* helpermsg.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = helpermsg.defs; sourceTree = "<group>"; };
2E0405F00C31955500F13B59 /* mDNSResponderHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponderHelper; sourceTree = BUILT_PRODUCTS_DIR; };
2E0405F40C3195F700F13B59 /* helper.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = helper.c; sourceTree = "<group>"; };
2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "helper-stubs.c"; sourceTree = "<group>"; };
2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "helpermsg-types.h"; sourceTree = "<group>"; };
2EDC5E720C39EA640092701B /* helper-server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "helper-server.h"; sourceTree = "<group>"; };
+ 4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = uds_daemon.h; path = ../mDNSShared/uds_daemon.h; sourceTree = SOURCE_ROOT; };
+ 4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DeviceToDeviceManager.framework; path = /System/Library/PrivateFrameworks/DeviceToDeviceManager.framework; sourceTree = "<absolute>"; };
4A8202510C56C36500DDFD48 /* ipsec_strerror.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipsec_strerror.h; sourceTree = "<group>"; };
4A8202520C56C36500DDFD48 /* libpfkey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libpfkey.h; sourceTree = "<group>"; };
4A8202530C56C36600DDFD48 /* pfkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pfkey.c; sourceTree = "<group>"; };
4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mDNSResponderHelper.8; sourceTree = SOURCE_ROOT; };
+ 4ADB5F230F6AB9F400B95BF3 /* helper-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "helper-entitlements.plist"; sourceTree = "<group>"; };
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>"; };
D284BED90ADD80A20027CCDF /* dnsextd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dnsextd; sourceTree = BUILT_PRODUCTS_DIR; };
D284BEE80ADD80A70027CCDF /* ddnswriteconfig */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ddnswriteconfig; sourceTree = BUILT_PRODUCTS_DIR; };
D284BF0C0ADD80B00027CCDF /* Bonjour.prefPane */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Bonjour.prefPane; sourceTree = BUILT_PRODUCTS_DIR; };
- D284C04D0ADD95D30027CCDF /* Info-PreferencePane.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "Info-PreferencePane.plist"; path = "PreferencePane/Info-PreferencePane.plist"; sourceTree = "<group>"; };
+ D284C04D0ADD95D30027CCDF /* Info-PreferencePane.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Info-PreferencePane.plist"; path = "PreferencePane/Info-PreferencePane.plist"; sourceTree = "<group>"; };
DB2CC4430662DD1100335AB3 /* BaseListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = BaseListener.java; path = ../mDNSShared/Java/BaseListener.java; sourceTree = SOURCE_ROOT; };
DB2CC4440662DD1100335AB3 /* BrowseListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = BrowseListener.java; path = ../mDNSShared/Java/BrowseListener.java; sourceTree = SOURCE_ROOT; };
DB2CC4450662DD1100335AB3 /* DNSRecord.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSRecord.java; path = ../mDNSShared/Java/DNSRecord.java; sourceTree = SOURCE_ROOT; };
D284BE660ADD80740027CCDF /* SystemConfiguration.framework in Frameworks */,
D284BE670ADD80740027CCDF /* IOKit.framework in Frameworks */,
D284BE680ADD80740027CCDF /* Security.framework in Frameworks */,
+ 21E53F0F1219D1B3003EEE05 /* CoreServices.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D284BE8E0ADD80800027CCDF /* SystemConfiguration.framework in Frameworks */,
D284BE8F0ADD80800027CCDF /* IOKit.framework in Frameworks */,
D284BE900ADD80800027CCDF /* Security.framework in Frameworks */,
+ 21E53F141219D1CA003EEE05 /* CoreServices.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FFFB0DA407B43BED00B88D48 /* PreferencePane */,
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
19C28FBDFE9D53C911CA2CBB /* Products */,
+ 21E53F0E1219D1B3003EEE05 /* CoreServices.framework */,
);
name = mDNSResponder;
sourceTree = "<group>";
08FB7795FE84155DC02AAC07 /* mDNS Server Sources */ = {
isa = PBXGroup;
children = (
+ 4ADB5F230F6AB9F400B95BF3 /* helper-entitlements.plist */,
+ 4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */,
4AE9B0480F39448B0080B59D /* safe_vproc.c */,
4AE9B0490F39448B0080B59D /* safe_vproc.h */,
4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */,
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
isa = PBXGroup;
children = (
+ 4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */,
2E8165F60C59835F00485EB2 /* libipsec.dylib */,
65713D46025A293200000109 /* SystemConfiguration.framework */,
2E0406140C3197CB00F13B59 /* libbsm.dylib */,
DB2CC4680662DFF500335AB3 /* JavaVM.framework */,
FF2609FA07B4433800CE10E5 /* Cocoa.framework */,
FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */,
+ 21F432971134AA6800581B69 /* WebFilterDNS.framework */,
);
name = "External Frameworks and Libraries";
sourceTree = "<group>";
buildRules = (
);
dependencies = (
+ FFAE66F9105F0CF100162116 /* PBXTargetDependency */,
);
name = PreferencePane;
productInstallPath = "${SYSTEM_LIBRARY_DIR}/PreferencePanes";
FFB765810AEED9C700583A2C /* Sources */,
FFB765820AEED9C700583A2C /* Frameworks */,
FFA572500AF190070055A0F1 /* CopyFiles */,
- FF93944E0AF193B900C5D655 /* CopyFiles */,
+ 21DE714D115831CB00DD4BD1 /* ShellScript */,
);
buildRules = (
);
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */;
- compatibilityVersion = "Xcode 2.4";
+ compatibilityVersion = "Xcode 3.1";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* mDNSResponder */;
projectDirPath = "";
D284BEF90ADD80B00027CCDF /* InfoPlist.strings in Resources */,
D284BEFB0ADD80B00027CCDF /* inprogress.tiff in Resources */,
D284BEFC0ADD80B00027CCDF /* installtool in Resources */,
+ FFAE66F0105F0CD900162116 /* ddnswriteconfig in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
shellPath = /bin/sh;
shellScript = "if [ -e \"${SDKROOT}/usr/include/vproc.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nelse\ntouch \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/lib/libipsec.dylib\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libipsec.a\"\nelse\necho \"#define MDNS_NO_IPSEC 1\" > ${CONFIGURATION_TEMP_DIR}/ipsec_options.h\ntouch \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/empty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libipsec.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n";
};
+ 21DE714D115831CB00DD4BD1 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "sed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"";
+ };
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\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";
+ shellScript = "if [ -e \"${SDKROOT}/usr/local/include/dnsinfo.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.h\ntouch \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/empty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/sandbox.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/vproc.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nelse\ntouch \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/Frameworks/IOKit.framework/PrivateHeaders/pwr_mgt/IOPMLibPrivate.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/IOKit\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt\"\ntouch \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt/IOPMLibPrivate.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/DeviceToDeviceManager.framework/Headers/DeviceToDeviceManager.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\necho \"#define NO_D2D 1\" > \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager/DeviceToDeviceManager.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/WebFilterDNS.framework/Headers/WebFilterDNS.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\necho \"#define NO_WCF 1\" > \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS/WebFilterDNS.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/local/include/AWACS.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nelse\necho \"#define NO_AWACS 1\" > \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfi\n";
};
D284BE6C0ADD80740027CCDF /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
- shellPath = /bin/tcsh;
- shellScript = "# Install mDNSResponder.bundle containing language localizations\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices\ncp -R ${SRCROOT}/mDNSResponder-bundle ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle\n\n# Remove unwanted CVS directories\nfind ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -depth -name CVS -exec rm -rf {} \\;\n\n# Expand UTF-8 files to UTF-16 (at one time this appeared to be necessary, but it's not, so we don't do it any more)\n#foreach file (`find ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -name Localizable.strings`)\n#iconv -f utf-8 -t utf-16 ${file} > ${file}.new\n#mv -f ${file}.new ${file}\n#end\n\n# Remove French localization (not wanted for Apple B&I builds)\nrm -rf ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle/Resources/French.lproj\n\n# Copy Sandbox profile, stripping initial license header to make the file fit in the ~16kB Sandbox profile limit\n(umask 022; mkdir -p -m 0755 ${DSTROOT}/usr/share/sandbox)\n(umask 222; awk '/^\\(version 1\\)$/,EOF' ${SRCROOT}/mDNSResponder.sb > ${DSTROOT}/usr/share/sandbox/mDNSResponder.sb)\n";
+ shellPath = /bin/bash;
+ shellScript = "# Install mDNSResponder.bundle containing language localizations\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices\ncp -R ${SRCROOT}/mDNSResponder-bundle ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle\n\n# Remove unwanted CVS directories\nfind ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -depth -name CVS -exec rm -rf {} \\;\n\n# Expand UTF-8 files to UTF-16 (at one time this appeared to be necessary, but it's not, so we don't do it any more)\n#foreach file (`find ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -name Localizable.strings`)\n#iconv -f utf-8 -t utf-16 ${file} > ${file}.new\n#mv -f ${file}.new ${file}\n#end\n\n# Remove French localization (not wanted for Apple B&I builds)\nrm -rf ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle/Resources/French.lproj\n";
};
D284BE760ADD80800027CCDF /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "if [ -e \"${SDKROOT}/usr/local/include/dnsinfo.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.h\ntouch \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/empty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/sandbox.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/vproc.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nelse\ntouch \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/Frameworks/IOKit.framework/PrivateHeaders/pwr_mgt/IOPMLibPrivate.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/IOKit\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt\"\ntouch \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt/IOPMLibPrivate.h\"\nfi\n";
+ shellScript = "if [ -e \"${SDKROOT}/usr/local/include/dnsinfo.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.h\ntouch \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/empty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/sandbox.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/vproc.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nelse\ntouch \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/Frameworks/IOKit.framework/PrivateHeaders/pwr_mgt/IOPMLibPrivate.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/IOKit\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt\"\ntouch \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt/IOPMLibPrivate.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/DeviceToDeviceManager.framework/Headers/DeviceToDeviceManager.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\necho \"#define NO_D2D 1\" > \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager/DeviceToDeviceManager.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/WebFilterDNS.framework/Headers/WebFilterDNS.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\necho \"#define NO_WCF 1\" > \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS/WebFilterDNS.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/local/include/AWACS.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nelse\necho \"#define NO_AWACS 1\" > \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfi";
};
FF045B6A0C7E4AA600448140 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
- shellPath = /bin/tcsh;
- shellScript = "# Install plists to tell launchd how to start mDNSResponder and mDNSResponderHelper\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons\n\nif (${MACOSX_DEPLOYMENT_TARGET} == \"10.4\") then\ncp ${SRCROOT}/LaunchDaemonInfo-Tiger.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\ncp ${SRCROOT}/LaunchDaemonInfo-Tiger.helper.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponderHelper.plist\nelse\ncp ${SRCROOT}/LaunchDaemonInfo.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\ncp ${SRCROOT}/LaunchDaemonInfo.helper.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponderHelper.plist\nendif\n";
+ shellPath = /bin/sh;
+ shellScript = "# Install plists to tell launchd how to start mDNSResponder and mDNSResponderHelper\n\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons\n\nif [ \"${MACOSX_DEPLOYMENT_TARGET}\" == \"10.4\" ] ; then\ncp ${SRCROOT}/LaunchDaemonInfo-Tiger.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\ncp ${SRCROOT}/LaunchDaemonInfo-Tiger.helper.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponderHelper.plist\nelse\ncp ${SRCROOT}/LaunchDaemonInfo.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\ncp ${SRCROOT}/LaunchDaemonInfo.helper.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponderHelper.plist\nfi\n\nif [ ! -z \"${IPHONEOS_DEPLOYMENT_TARGET}\" ] ; then\nplutil -convert binary1 ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\nplutil -convert binary1 ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponderHelper.plist\nfi\n\n\n# Install Sandbox profile\n\nif [ ! -z \"${IPHONEOS_DEPLOYMENT_TARGET}\" ] ; then\n SANDBOXDST=\"${DSTROOT}/usr/local/share/sandbox/profiles/embedded/builtin\"\nelse\n SANDBOXDST=\"${DSTROOT}/usr/share/sandbox\"\nfi\n\n(umask 022; mkdir -p -m 0755 \"$SANDBOXDST\")\n\nif [[ \"${MACOSX_DEPLOYMENT_TARGET}\" == 10.[0-6] ]] ; then\n sed '/iokit-open/d' \"${SRCROOT}/mDNSResponder.sb\" > \"${SANDBOXDST}/mDNSResponder.sb\"\nelse\n cp \"${SRCROOT}/mDNSResponder.sb\" \"${SANDBOXDST}/mDNSResponder.sb\"\nfi\n";
};
FF37FAAD0BC581780044A5CF /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
target = FFA572650AF190F10055A0F1 /* SystemLibraries */;
targetProxy = FFA572700AF191230055A0F1 /* PBXContainerItemProxy */;
};
+ FFAE66F9105F0CF100162116 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D284BEDB0ADD80A70027CCDF /* ddnswriteconfig */;
+ targetProxy = FFAE66F8105F0CF100162116 /* PBXContainerItemProxy */;
+ };
FFB7657D0AEED97F00583A2C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 00AD62BB032D7A0C0CCA2C71 /* Build More */;
2E0405F20C31955500F13B59 /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "helper-entitlements.plist";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)";
COPY_PHASE_STRIP = NO;
INSTALL_PATH = /usr/sbin;
LD_MAP_FILE_PATH = "$(TARGET_TEMP_DIR)/$(PRODUCT_NAME)-LinkMap-$(CURRENT_VARIANT)-$(CURRENT_ARCH).txt";
LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
- MACOSX_DEPLOYMENT_TARGET = 10.4;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
+ "$(inherited)",
+ "-mthumb",
+ );
OTHER_LDFLAGS = (
"$(inherited)",
"-lipsec",
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
DEAD_CODE_STRIPPING = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
+ "_DNS_SD_LIBDISPATCH=1",
"APPLE_OSX_mDNSResponder=1",
"__MigTypeCheck=1",
"mDNSResponderVersion=${MVERS}",
buildSettings = {
CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
- FRAMEWORK_SEARCH_PATHS = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
+ );
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
);
INSTALL_PATH = /usr/sbin;
LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
- MACOSX_DEPLOYMENT_TARGET = 10.4;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
ORDER_FILE = "${SRCROOT}/mDNSResponder.order";
OTHER_CFLAGS = (
"$(inherited)",
"-no-cpp-precomp",
);
- OTHER_LDFLAGS = "-ldnsinfo";
+ "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
+ "$(inherited)",
+ "-mthumb",
+ );
+ OTHER_LDFLAGS = "";
+ "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = (
+ "-weak_framework",
+ DeviceToDeviceManager,
+ );
+ "OTHER_LDFLAGS[sdk=macosx10.6][arch=*]" = "-lAWACS";
+ "OTHER_LDFLAGS[sdk=macosx10.7][arch=*]" = (
+ "-lAWACS",
+ "-weak_framework",
+ WebFilterDNS,
+ "-weak_framework",
+ DeviceToDeviceManager,
+ );
OTHER_REZFLAGS = "";
PRODUCT_NAME = mDNSResponder;
REZ_EXECUTABLE = YES;
buildSettings = {
CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
- FRAMEWORK_SEARCH_PATHS = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
+ );
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
"${CONFIGURATION_TEMP_DIR}",
);
LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
- MACOSX_DEPLOYMENT_TARGET = 10.4;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
OTHER_CFLAGS = (
"$(inherited)",
"-no-cpp-precomp",
);
- OTHER_LDFLAGS = "-ldnsinfo";
+ OTHER_LDFLAGS = "";
+ "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = (
+ "-weak_framework",
+ DeviceToDeviceManager,
+ );
+ "OTHER_LDFLAGS[sdk=macosx10.6][arch=*]" = "-lAWACS";
+ "OTHER_LDFLAGS[sdk=macosx10.7][arch=*]" = (
+ "-lAWACS",
+ "-weak_framework",
+ WebFilterDNS,
+ "-weak_framework",
+ DeviceToDeviceManager,
+ );
OTHER_REZFLAGS = "";
PRODUCT_NAME = mDNSResponder.debug;
REZ_EXECUTABLE = YES;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
INSTALL_PATH = /usr/bin;
- MACOSX_DEPLOYMENT_TARGET = 10.4;
OTHER_CFLAGS = "-no-cpp-precomp";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
"-no-cpp-precomp",
"-UAPPLE_OSX_mDNSResponder",
);
- OTHER_LDFLAGS = "-ldnsinfo";
+ OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = dnsextd;
REZ_EXECUTABLE = YES;
D284BEE60ADD80A70027CCDF /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
INSTALL_PATH = "/Library/Application Support/Bonjour";
- MACOSX_DEPLOYMENT_TARGET = "";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
D284BF090ADD80B00027CCDF /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
EXPORTED_SYMBOLS_FILE = "";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_ENABLE_OBJC_GC = supported;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist";
INSTALL_PATH = /AppleInternal/Library/PreferencePanes;
- MACOSX_DEPLOYMENT_TARGET = "";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "-twolevel_namespace";
OTHER_REZFLAGS = "";
"$(inherited)",
"__DARWIN_NON_CANCELABLE=1",
);
+ HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
INSTALL_PATH = /usr/local/lib/system;
PRODUCT_NAME = dns_sd_debug;
};
"__DARWIN_NON_CANCELABLE=1",
);
GENERATE_PROFILING_CODE = YES;
+ HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
INSTALL_PATH = /usr/local/lib/system;
PRODUCT_NAME = dns_sd_profile;
};
"$(inherited)",
"__DARWIN_NON_CANCELABLE=1",
);
+ HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+ INSTALLHDRS_COPY_PHASE = YES;
+ INSTALLHDRS_SCRIPT_PHASE = YES;
INSTALL_PATH = /usr/local/lib/system;
PRODUCT_NAME = dns_sd;
};
.\" See the License for the specific language governing permissions and
.\" limitations under the License.
.\"
-.\" $Log: mDNSResponderHelper.8,v $
-.\" Revision 1.1 2007/08/08 22:34:59 mcguire
-.\" <rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
-.\"
-.\"
-.\"
.Dd August 2007 \" Date
.Dt mDNSResponderHelper 8 \" Document Title
.Os Darwin \" Operating System
#include <string.h>
#include <errno.h>
#include <stdio.h>
+#include <TargetConditionals.h>
#include "ipsec_strerror.h"
#include "libpfkey.h"
#include "ipsec_options.h"
+#if TARGET_OS_EMBEDDED
+#ifndef MDNS_NO_IPSEC
+#define MDNS_NO_IPSEC 1
+#endif
+#endif
+
#ifndef MDNS_NO_IPSEC
#define CALLOC(size, cast) (cast)calloc(1, (size))
* 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 <vproc.h>
#include "safe_vproc.h"
#include "mDNSDebug.h"
+#include <TargetConditionals.h>
-#ifdef VPROC_HAS_TRANSACTIONS
+#if defined(VPROC_HAS_TRANSACTIONS) && !TARGET_OS_EMBEDDED
static vproc_transaction_t transaction = NULL;
#else
+#if ! TARGET_OS_EMBEDDED
#include <stdio.h>
#include <CoreFoundation/CFString.h>
}
}
+#else
+
+void safe_vproc_transaction_begin(void) { }
+
+#endif
+
void safe_vproc_transaction_end(void) { }
#endif
* 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
* 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: 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
-
-Revision 1.19 2007/04/16 20:49:39 cheshire
-Fix compile errors for mDNSPosix build
-
-Revision 1.18 2006/08/14 23:24:46 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.17 2006/06/12 18:22:42 cheshire
-<rdar://problem/4580067> mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux
-
-Revision 1.16 2005/02/04 01:00:53 cheshire
-Add '-d' command-line option to specify domain to browse
-
-Revision 1.15 2004/12/16 20:17:11 cheshire
-<rdar://problem/3324626> Cache memory management improvements
-
-Revision 1.14 2004/11/30 22:37:00 cheshire
-Update copyright dates and add "Mode: C; tab-width: 4" headers
-
-Revision 1.13 2004/10/19 21:33:20 cheshire
-<rdar://problem/3844991> Cannot resolve non-local registrations using the mach API
-Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name
-doesn't force multicast unless you set this flag to indicate explicitly that this is what you want
-
-Revision 1.12 2004/09/17 01:08:53 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.11 2003/11/17 20:14:32 cheshire
-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 (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
-
-Revision 1.8 2003/08/12 19:56:26 cheshire
-Update to APSL 2.0
-
-Revision 1.7 2003/07/02 21:19:58 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.6 2003/06/18 05:48:41 cheshire
-Fix warnings
-
-Revision 1.5 2003/05/06 00:00:50 cheshire
-<rdar://problem/3248914> Rationalize naming of domainname manipulation functions
-
-Revision 1.4 2002/12/23 22:13:31 jgraessl
-
-Reviewed by: Stuart Cheshire
-Initial IPv6 support for mDNSResponder.
-
-Revision 1.3 2002/09/21 20:44:53 zarzycki
-Added APSL info
-
-Revision 1.2 2002/09/19 04:20:44 cheshire
-Remove high-ascii characters that confuse some systems
-
-Revision 1.1 2002/09/17 06:24:35 cheshire
-First checkin
-
-*/
+ */
#include <assert.h>
#include <signal.h>
* 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: ExampleClientApp.c,v $
-Revision 1.14 2006/08/14 23:24:46 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.13 2006/02/23 23:38:43 cheshire
-<rdar://problem/4427969> On FreeBSD 4 "arpa/inet.h" requires "netinet/in.h" be included first
-
-Revision 1.12 2004/11/30 22:37:00 cheshire
-Update copyright dates and add "Mode: C; tab-width: 4" headers
-
-Revision 1.11 2004/09/17 01:08:53 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.10 2004/09/16 01:58:22 cheshire
-Fix compiler warnings
-
-Revision 1.9 2003/08/12 19:56:26 cheshire
-Update to APSL 2.0
-
-Revision 1.8 2003/07/02 21:19:58 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.7 2003/06/18 05:48:41 cheshire
-Fix warnings
-
-Revision 1.6 2003/03/31 22:44:36 cheshire
-Add log header
-
*/
#include <stdio.h> // For printf()
* 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: ExampleClientApp.h,v $
-Revision 1.7 2006/08/14 23:24:46 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.6 2004/11/30 22:37:00 cheshire
-Update copyright dates and add "Mode: C; tab-width: 4" headers
-
-Revision 1.5 2003/08/12 19:56:26 cheshire
-Update to APSL 2.0
-
-Revision 1.4 2003/07/02 21:19:58 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.3 2003/03/31 22:49:35 cheshire
-Add "$Log" header
-
*/
extern void ExampleClientEventLoop(mDNS *const m);
* thinking that variables x and y are both of type "char*" -- and anyone who doesn't
* understand why variable y is not of type "char*" just proves the point that poor code
* layout leads people to unfortunate misunderstandings about how the C language really works.)
-
- 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
-
-Revision 1.41 2007/04/16 20:49:39 cheshire
-Fix compile errors for mDNSPosix build
-
-Revision 1.40 2007/02/28 01:51:22 cheshire
-Added comment about reverse-order IP address
-
-Revision 1.39 2007/01/05 08:30:51 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.38 2007/01/04 20:57:48 cheshire
-Rename ReturnCNAME to ReturnIntermed (for ReturnIntermediates)
-
-Revision 1.37 2006/10/27 01:32:08 cheshire
-Set ReturnIntermed to mDNStrue
-
-Revision 1.36 2006/08/14 23:24:46 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.35 2006/06/12 18:22:42 cheshire
-<rdar://problem/4580067> mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux
-
-*/
+ */
//*************************************************************************************************************
// Incorporate mDNS.c functionality
# If "make os=xxx" gives lots of errors like "Missing dependency operator",
# 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)
-#
-# Revision 1.77 2007/10/22 20:04:51 cheshire
-# Need to include PlatformCommon.c.o in embedded targets
-#
-# Revision 1.76 2007/07/31 23:39:02 mcguire
-# Don't bail on errors in flex-generated .c files
-#
-# Revision 1.75 2006/08/24 22:41:23 herscher
-# <rdar://problem/4580067> POSIX: dnsextd_parser doesn't compile on Linux
-#
-# Revision 1.74 2006/08/14 23:07:11 cheshire
-# Added "tab-width" emacs header line
-#
-# Revision 1.73 2006/07/07 00:54:08 cheshire
-# <rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-# Put intermediate files into "objects" folder instead of mDNSShared source code folder
-#
-# Revision 1.72 2006/07/05 23:53:58 cheshire
-# <rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-#
-# Revision 1.71 2006/06/20 23:07:04 rpantos
-# <rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
-#
-# Revision 1.70 2006/05/03 23:35:10 cheshire
-# Add missing dependency: NetMonitor.c textually imports mDNS.c
-#
-# Revision 1.69 2006/02/26 23:18:50 cheshire
-# <rdar://problem/4427969> FreeBSD 4 requires "-pthread" option to compile threaded code
-#
-# Revision 1.68 2006/02/26 01:36:54 cheshire
-# Rename the poorly named "LIBFLAGS" as "LINKOPTS"
-#
-# Revision 1.67 2006/02/25 23:14:29 cheshire
-# Add comment suggesting using "gmake" command
-#
-# Revision 1.66 2006/01/06 01:06:17 cheshire
-# <rdar://problem/3978979> Compile library and client programs in one pass
-#
-# Revision 1.65 2005/12/21 21:15:57 cheshire
-# Add missing dependency: Identify.c textually imports mDNS.c
-#
-# Revision 1.64 2005/10/25 23:55:47 cheshire
-# Add tiger to list of target platforms
-#
-# Revision 1.63 2005/10/11 21:30:44 cheshire
-# Add "-Wunreachable-code" (commented out for now)
-#
-# Revision 1.62 2005/06/30 21:46:55 cheshire
-# <rdar://problem/4167287> Solaris should use unix domain sockets, not loopback
-#
-# Revision 1.61 2005/06/30 20:46:05 cheshire
-# Added Makefile rule to build threadsafe object files where necessary using "-D_REENTRANT".
-#
-# Revision 1.60 2005/06/30 10:42:38 cheshire
-# Turn on "-Werror" and "-O" for better error reporting
-#
-# Revision 1.59 2005/04/14 21:07:10 rpantos
-# Bug #: 4089257, Clean build broken for Java support on POSIX
-# Submitted by: Roger Pantos
-# Reviewed by: Kiren Sekar
-#
-# Revision 1.58 2005/04/08 21:37:57 ksekar
-# <rdar://problem/3792767> get_ifi_info doesn't return IPv6 interfaces on Linux
-#
-# Revision 1.57 2005/03/17 04:02:28 cheshire
-# <rdar://problem/3986419> mDNSResponder won't compile with gcc4 on Tiger
-# Changed Makefile to link using gcc instead of libtool
-#
-# Revision 1.56 2005/02/02 02:25:21 cheshire
-# <rdar://problem/3980388> /var/run/mDNSResponder should be /var/run/mdnsd on Linux
-#
-# Revision 1.55 2005/01/27 22:55:00 cheshire
-# Add "make os=tiger" target which uses gcc4 and "-Wdeclaration-after-statement"
-#
-# Revision 1.54 2004/12/17 19:33:03 cheshire
-# Add "-lresolv" for Solaris
-#
-# Revision 1.53 2004/12/01 20:04:31 cheshire
-# Tidy up alignment
-#
-# Revision 1.52 2004/12/01 19:46:12 cheshire
-# Add install case for Suse 9 (rc*.d directories *inside* the init.d directory)
-#
-# Revision 1.51 2004/12/01 03:30:29 cheshire
-# <rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
-#
-# Revision 1.50 2004/12/01 01:14:20 cheshire
-# Add $(LIBFLAGS) to cc command to build dnsextd (required for Solaris)
-#
-# Revision 1.49 2004/11/11 01:44:52 cheshire
-# Updated error message
-#
-# Revision 1.48 2004/10/06 02:22:19 cheshire
-# Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
-#
-# Revision 1.47 2004/10/01 22:15:54 rpantos
-# rdar://problem/3824265: Replace APSL in client lib with BSD license.
-#
-# Revision 1.46 2004/09/24 21:15:25 cheshire
-# <rdar://problem/3724985> Library "libmdns" misnamed; should be "libdns_sd"
-#
-# Revision 1.45 2004/09/22 16:23:41 cheshire
-# Modify installation for compatibility with Gentoo Linux
-# (Thanks to David Black for this information)
-#
-# Revision 1.44 2004/09/17 01:08:53 cheshire
-# Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
-# The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
-# declared in that file are ONLY appropriate to single-address-space embedded applications.
-# For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-#
-# Revision 1.43 2004/09/17 00:30:11 cheshire
-# Added some '@' signs to make build output less verbose --
-# when there's too much on the screen it's easy to miss build errors and warnings
-#
-# Revision 1.42 2004/08/24 22:04:37 cheshire
-# Need to specify -lpthread for building dnsextd
-#
-# Revision 1.41 2004/08/11 00:43:26 ksekar
-# <rdar://problem/3722542>: DNS Extension daemon for DNS Update Lease
-#
-# Revision 1.40 2004/07/08 21:45:55 cheshire
-# Make nss_mdns only build on Linux. We can add it to other targets (Solaris,
-# FreeBSD, etc., as we verify them). In particular, NSS is NOT supported on
-# OS X, so including it for "os=jaguar" or "os=panther" broke those builds.
-#
-# Revision 1.39 2004/06/29 03:34:28 cheshire
-# Add 'dot-local' Name Service Switch support from Andrew White at NICTA
-#
-# Revision 1.38 2004/06/25 02:19:40 rpantos
-# And FreeBSD...
-#
-# Revision 1.37 2004/06/25 00:51:09 rpantos
-# And fix the Java build for Posix on Solaris, too.
-#
-# Revision 1.36 2004/06/25 00:26:27 rpantos
-# Changes to fix the Posix build on Solaris.
-#
-# Revision 1.35 2004/06/18 18:51:31 cheshire
-# Add (commented out) "-pedantic" for when we want to check for "mixed declarations and code" warnings
-#
-# Revision 1.34 2004/05/25 18:29:33 cheshire
-# Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c,
-# so that it's also accessible to dnssd_clientshim.c (single address space) clients.
-#
-# Revision 1.33 2004/04/30 16:46:32 rpantos
-# Add support for building Java libraries.
-#
-# Revision 1.32 2004/04/14 23:09:29 ksekar
-# Support for TSIG signed dynamic updates.
-#
-# Revision 1.31 2004/03/15 19:07:06 cheshire
-# Fix error message
-#
-# Revision 1.30 2004/03/11 18:58:29 rpantos
-# Fix Kill /etc/rc scripts so they run at halt & reboot.
-#
-# Revision 1.29 2004/03/04 23:35:41 cheshire
-# Instead of using a dummy target to generate an error message, use "$(error text...)"
-#
-# Revision 1.28 2004/03/04 23:33:42 cheshire
-# Fixes from Alfred Perlstein for FreeBSD's benefit
-#
-# Revision 1.27 2004/02/11 21:00:21 cheshire
-# Update URL for GNU Make manual page
-#
-# Revision 1.26 2004/02/05 21:28:30 cheshire
-# Fixes so that "sudo make install" works on *BSD
-#
-# Revision 1.25 2004/02/05 20:00:22 cheshire
-# Define mdnsd's PID file to be /var/run/mdnsd.pid on Posix builds
-#
-# Revision 1.24 2004/02/05 01:00:01 rpantos
-# Fix some issues that turned up when building for FreeBSD.
-#
-# Revision 1.23 2004/02/04 01:50:54 cheshire
-# Make InstalledStartup conditional, so it automatically installs into
-# either /etc/init.d/ or /etc/rc.d/init.d/ as appropriate
-#
-# Revision 1.22 2004/01/20 01:41:21 rpantos
-# Define USES_NETLINK for Linux builds.
-#
-# Revision 1.21 2003/12/17 00:51:22 cheshire
-# Changed mDNSNetMonitor and mDNSIdentify to link the object files
-# instead of #including the "DNSCommon.c" "uDNS.c" and source files
-#
-# Revision 1.20 2003/12/13 03:05:28 ksekar
-# Bug #: <rdar://problem/3192548>: DynDNS: Unicast query of service records
-#
-# Revision 1.19 2003/12/11 19:42:13 cheshire
-# Change name "mDNSResponderd" to "mdnsd" for consistency with standard Linux (Unix) naming conventions
-#
-# Revision 1.18 2003/12/11 19:38:34 cheshire
-# Add APSL
-#
-# Revision 1.17 2003/12/11 03:16:49 rpantos
-# One more change for OS X build: make install work a little better.
-#
-# Revision 1.16 2003/12/11 03:03:51 rpantos
-# Clean up mDNSPosix so that it builds on OS X again.
-#
-# Revision 1.15 2003/12/08 20:47:02 rpantos
-# Add support for mDNSResponder on Linux.
-#
-# Revision 1.14 2003/11/14 20:59:09 cheshire
-# Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
-# Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
-#
-# Revision 1.13 2003/08/06 18:20:51 cheshire
-# Makefile cleanup
-#
-# Revision 1.12 2003/08/01 02:20:02 cheshire
-# Add mDNSIdentify tool, used to discover what version of mDNSResponder a particular host is running
-#
-# Revision 1.11 2003/07/14 18:11:54 cheshire
-# Fix stricter compiler warnings
-#
-# Revision 1.10 2003/06/18 05:47:41 cheshire
-# Enable stricter warnings on Jaguar and Panther builds
-#
-# Revision 1.9 2003/06/04 18:34:45 ksekar
-# Bug #: <rdar://problem/3218120>: mDNSPosix does not build on Panther that has socklen_t
-# Changed build targets "osx10.2" and "osx10.3" to "jaguar" and "panther".
-#
-# Revision 1.8 2003/06/04 00:23:12 ksekar
-# Bug #: <rdar://problem/3218120>: mDNSPosix does not build on Panther that has socklen_t
-# Created separate target OS's for 10.2 and 10.3.
-#
-# Revision 1.7 2003/04/16 02:11:37 cheshire
-# Remove unnecessary $(CFLAGS) from linking rules
-#
-# Revision 1.6 2003/04/04 01:37:14 cheshire
-# Added NetMonitor.c
-#
-
# This Makefile builds an mDNSResponder daemon and a libdns_sd.so shared library
# for Linux. It also builds several example programs for embedded systems.
#
* thinking that variables x and y are both of type "char*" -- and anyone who doesn't
* understand why variable y is not of type "char*" just proves the point that poor code
* layout leads people to unfortunate misunderstandings about how the C language really works.)
-
- Change History (most recent first):
-
-$Log: NetMonitor.c,v $
-Revision 1.96 2009/07/16 00:08:57 cheshire
-Display any stray Update (Authority) records in query packets
-
-Revision 1.95 2009/07/09 22:24:52 herscher
-<rdar://problem/3775717> SDK: Port mDNSNetMonitor to Windows
-
-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
-
-Revision 1.88 2007/04/22 20:16:25 cheshire
-Fix compiler errors (const parameter declarations)
-
-Revision 1.87 2007/04/16 20:49:39 cheshire
-Fix compile errors for mDNSPosix build
-
-Revision 1.86 2007/03/22 18:31:48 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.85 2007/02/28 01:51:22 cheshire
-Added comment about reverse-order IP address
-
-Revision 1.84 2007/01/05 08:30:52 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.83 2006/11/18 05:01:32 cheshire
-Preliminary support for unifying the uDNS and mDNS code,
-including caching of uDNS answers
-
-Revision 1.82 2006/08/14 23:24:46 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.81 2006/07/06 00:01:44 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Update mDNSSendDNSMessage() to use uDNS_TCPSocket type instead of "int"
-
-Revision 1.80 2006/06/12 18:22:42 cheshire
-<rdar://problem/4580067> mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux
-
-Revision 1.79 2006/04/26 20:48:33 cheshire
-Make final count of unique source addresses show IPv4 and IPv6 counts separately
-
-Revision 1.78 2006/04/25 00:42:24 cheshire
-Add ability to specify a single interface index to capture on,
-e.g. typically "-i 4" for Ethernet and "-i 5" for AirPort
-
-Revision 1.77 2006/03/02 21:50:45 cheshire
-Removed strange backslash at the end of a line
-
-Revision 1.76 2006/02/23 23:38:43 cheshire
-<rdar://problem/4427969> On FreeBSD 4 "arpa/inet.h" requires "netinet/in.h" be included first
-
-Revision 1.75 2006/01/05 22:33:58 cheshire
-Use IFNAMSIZ (more portable) instead of IF_NAMESIZE
-
-*/
+ */
//*************************************************************************************************************
// Incorporate mDNS.c functionality
#include <time.h> // For "struct tm" etc.
#include <signal.h> // For SIGINT, SIGTERM
#if defined(WIN32)
+// Both mDNS.c and mDNSWin32.h declare UDPSocket_struct type resulting in a compile-time error, so
+// trick the compiler when including mDNSWin32.h
+# define UDPSocket_struct _UDPSocket_struct
# include <mDNSEmbeddedAPI.h>
# include <mDNSWin32.h>
-# include <uds_daemon.h>
# include <PosixCompat.h>
-# include <Service.h>
# define IFNAMSIZ 256
-
-// Stub these functions out
-mDNSexport int udsserver_init(dnssd_sock_t skts[], mDNSu32 count) { return 0; }
-mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent) { return 0; }
-mDNSexport void udsserver_handle_configchange(mDNS *const m) {}
-mDNSexport int udsserver_exit(void) { return 0; }
+static HANDLE gStopEvent = INVALID_HANDLE_VALUE;
+static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ) { SetEvent( gStopEvent ); return TRUE; }
void setlinebuf( FILE * fp ) {}
#else
# include <netdb.h> // For gethostbyname()
const mDNSu8 *p2 = ptr;
ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, pkt);
if (!ptr) break;
- if (ResourceRecordAnswersQuestion(&pkt->r.resrec, q)) return(p2);
+ if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && ResourceRecordAnswersQuestion(&pkt->r.resrec, q)) return(p2);
}
return(mDNSNULL);
}
mDNSu8 *rdend = (mDNSu8 *)rd + pktrr->rdlength;
int n = mprintf("%#-16a %-5s %-5s%5lu %##s -> ", srcaddr, op, DNSTypeName(pktrr->rrtype), pktrr->rroriginalttl, pktrr->name->c);
+ if (pktrr->RecordType == kDNSRecordTypePacketNegative) { mprintf("**** ERROR: FAILED TO READ RDATA ****\n"); return; }
+
+ // The kDNSType_OPT case below just calls GetRRDisplayString_rdb
+ // Perhaps more (or all?) of the cases should do that?
switch(pktrr->rrtype)
{
case kDNSType_A: n += mprintf("%.4a", &rd->ipv4); break;
} 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_OPT: {
+ char b[MaxMsg];
+ // Quick hack: we don't want the prefix that GetRRDisplayString_rdb puts at the start of its
+ // string, because it duplicates the name and rrtype we already display, so we compute the
+ // length of that prefix and strip that many bytes off the beginning of the string we display.
+ mDNSu32 striplen = mDNS_snprintf(b, MaxMsg-1, "%4d %##s %s ", pktrr->rdlength, pktrr->name->c, DNSTypeName(pktrr->rrtype));
+ GetRRDisplayString_rdb(pktrr, &pktrr->rdata->u, b);
+ n += mprintf("%.*s", MaxWidth - n, b + striplen);
+ } break;
case kDNSType_NSEC: {
int i;
for (i=0; i<255; i++)
{
LargeCacheRecord pkt;
ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &pkt);
- if (pkt.r.resrec.rroriginalttl && entry) RecordHostInfo(entry, &pkt.r.resrec);
+ if (ptr && pkt.r.resrec.rroriginalttl && entry) RecordHostInfo(entry, &pkt.r.resrec);
}
}
gettimeofday(&tv_start, NULL);
#if defined( WIN32 )
- RunDirect( 0, NULL );
+ status = SetupInterfaceList(&mDNSStorage);
+ if (status) return(status);
+ gStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (gStopEvent == INVALID_HANDLE_VALUE) return mStatus_UnknownErr;
+ if (!SetConsoleCtrlHandler(ConsoleControlHandler, TRUE)) return mStatus_UnknownErr;
+ SetSocketEventsEnabled(&mDNSStorage, TRUE);
+ while (WaitForSingleObjectEx(gStopEvent, INFINITE, TRUE) == WAIT_IO_COMPLETION);
+ SetSocketEventsEnabled(&mDNSStorage, FALSE);
+ if (!SetConsoleCtrlHandler(ConsoleControlHandler, FALSE)) return mStatus_UnknownErr;
+ CloseHandle(gStopEvent);
#else
mDNSPosixListenForSignalInEventLoop(SIGINT);
mDNSPosixListenForSignalInEventLoop(SIGTERM);
const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
int i;
mStatus status;
-
+
+#if defined(WIN32)
+ HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
+#endif
+
setlinebuf(stdout); // Want to see lines as they appear, not block buffered
for (i=1; i<argc; i++)
usage:
fprintf(stderr, "\nmDNS traffic monitor\n");
- fprintf(stderr, "Usage: %s (<host>)\n", progname);
- fprintf(stderr, "Optional <host> parameter displays only packets from that host\n");
+ fprintf(stderr, "Usage: %s [-i index] [host]\n", progname);
+ fprintf(stderr, "Optional [-i index] parameter displays only packets from that interface index\n");
+ fprintf(stderr, "Optional [host] parameter displays only packets from that host\n");
fprintf(stderr, "\nPer-packet header output:\n");
fprintf(stderr, "-Q- Multicast Query from mDNS client that accepts multicast responses\n");
Contains: main & associated Application layer for mDNSResponder on Linux.
- 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
-
-Revision 1.42 2007/09/18 19:09:02 cheshire
-<rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
-
-Revision 1.41 2007/09/04 17:02:25 cheshire
-<rdar://problem/5458929> False positives in changed files list in nightly builds
-Added MDNS_VERSIONSTR_NODTS option at the reqest of Rishi Srivatsavai (Sun)
-
-Revision 1.40 2007/07/31 23:08:34 mcguire
-<rdar://problem/5329542> BTMM: Make AutoTunnel mode work with multihoming
-
-Revision 1.39 2007/03/21 00:30:44 cheshire
-Remove obsolete mDNS_DeleteDNSServers() call
-
-Revision 1.38 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
-
-Revision 1.37 2007/02/07 19:32:00 cheshire
-<rdar://problem/4980353> All mDNSResponder components should contain version strings in SCCS-compatible format
-
-Revision 1.36 2007/02/06 19:06:48 cheshire
-<rdar://problem/3956518> Need to go native with launchd
-
-Revision 1.35 2007/01/05 08:30:52 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.34 2007/01/05 05:46:08 cheshire
-Add mDNS *const m parameter to udsserver_handle_configchange()
-
-Revision 1.33 2006/12/21 00:10:53 cheshire
-Make mDNS_PlatformSupport PlatformStorage a static global instead of a stack variable
-
-Revision 1.32 2006/11/03 22:28:50 cheshire
-PosixDaemon needs to handle mStatus_ConfigChanged and mStatus_GrowCache messages
-
-Revision 1.31 2006/08/14 23:24:46 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.30 2006/07/07 01:09:12 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-Only use mallocL/freeL debugging routines when building mDNSResponder, not dnsextd
-
-*/
+#if __APPLE__
+// In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated”
+// error, which prevents compilation because we build with "-Werror".
+// Since this is supposed to be portable cross-platform code, we don't care that daemon is
+// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
+#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
+#endif
#include <stdio.h>
#include <string.h>
#include <pwd.h>
#include <sys/types.h>
+#if __APPLE__
+#undef daemon
+extern int daemon(int, int);
+#endif
+
#include "mDNSEmbeddedAPI.h"
#include "mDNSPosix.h"
#include "mDNSUNP.h" // For daemon()
// uds_daemon support ////////////////////////////////////////////////////////////
-mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context)
+mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context, void **platform_data)
/* Support routine for uds_daemon.c */
{
// Depends on the fact that udsEventCallback == mDNSPosixEventCallback
+ (void) platform_data;
return mDNSPosixAddFDToEventLoop(fd, callback, context);
}
-mStatus udsSupportRemoveFDFromEventLoop(int fd) // Note: This also CLOSES the file descriptor
+int udsSupportReadFD(dnssd_sock_t fd, char *buf, int len, int flags, void *platform_data)
+ {
+ (void) platform_data;
+ return recv(fd, buf, len, flags);
+ }
+
+mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data) // Note: This also CLOSES the file descriptor
{
mStatus err = mDNSPosixRemoveFDFromEventLoop(fd);
+ (void) platform_data;
close(fd);
return err;
}
* 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: 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)
-
-Revision 1.43 2007/04/16 20:49:39 cheshire
-Fix compile errors for mDNSPosix build
-
-Revision 1.42 2007/03/06 22:45:53 cheshire
-
-<rdar://problem/4138615> argv buffer overflow issues
-
-Revision 1.41 2007/02/28 01:51:22 cheshire
-Added comment about reverse-order IP address
-
-Revision 1.40 2007/01/05 04:32:13 cheshire
-Change "(domainname *)" cast to "(const domainname *)"
-
-Revision 1.39 2006/08/14 23:24:46 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.38 2006/06/12 18:22:42 cheshire
-<rdar://problem/4580067> mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux
-
-Revision 1.37 2006/02/23 23:38:43 cheshire
-<rdar://problem/4427969> On FreeBSD 4 "arpa/inet.h" requires "netinet/in.h" be included first
-
-Revision 1.36 2005/08/04 03:12:47 mkrochma
-<rdar://problem/4199236> Register reverse PTR record using multicast
-
-Revision 1.35 2004/12/16 20:17:11 cheshire
-<rdar://problem/3324626> Cache memory management improvements
-
-Revision 1.34 2004/12/01 04:27:28 cheshire
-<rdar://problem/3872803> Darwin patches for Solaris and Suse
-Don't use uint32_t, etc. -- they require stdint.h, which doesn't exist on FreeBSD 4.x, Solaris, etc.
-
-Revision 1.33 2004/11/30 22:37:01 cheshire
-Update copyright dates and add "Mode: C; tab-width: 4" headers
-
-Revision 1.32 2004/10/26 03:59:41 cheshire
-Update comments
-
-Revision 1.31 2004/09/17 01:08:53 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.30 2004/09/17 00:31:52 cheshire
-For consistency with ipv6, renamed rdata field 'ip' to 'ipv4'
-
-Revision 1.29 2004/09/16 01:58:22 cheshire
-Fix compiler warnings
-
-Revision 1.28 2004/06/25 00:26:27 rpantos
-Changes to fix the Posix build on Solaris.
-
-Revision 1.27 2004/03/12 08:03:14 cheshire
-Update comments
-
-Revision 1.26 2004/01/25 00:00:39 cheshire
-Change to use mDNSOpaque16fromIntVal() instead of shifting and masking
-
-Revision 1.25 2003/12/08 20:47:02 rpantos
-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 (1009) instead of 256-byte buffers.
-
-Revision 1.23 2003/10/30 19:39:28 cheshire
-Fix warnings on certain compilers
-
-Revision 1.22 2003/08/14 02:19:55 cheshire
-<rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
-
-Revision 1.21 2003/08/12 19:56:26 cheshire
-Update to APSL 2.0
-
-Revision 1.20 2003/07/23 00:00:04 cheshire
-Add comments
-
-Revision 1.19 2003/07/15 01:55:16 cheshire
-<rdar://problem/3315777> Need to implement service registration with subtypes
-
-Revision 1.18 2003/07/02 21:19:58 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.17 2003/05/26 03:21:29 cheshire
-Tidy up address structure naming:
-mDNSIPAddr => mDNSv4Addr (for consistency with mDNSv6Addr)
-mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
-mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
-
-Revision 1.16 2003/05/26 03:01:28 cheshire
-<rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
-
-Revision 1.15 2003/05/06 00:00:50 cheshire
-<rdar://problem/3248914> Rationalize naming of domainname manipulation functions
-
-Revision 1.14 2003/04/25 01:45:57 cheshire
-<rdar://problem/3240002> mDNS_RegisterNoSuchService needs to include a host name
-
-Revision 1.13 2003/04/18 22:46:12 cheshire
-Fix mistake in 1.8 -- INADDR_NONE is 0xFFFFFFFF, not 0
-
-Revision 1.12 2003/04/16 02:11:07 cheshire
-Fixed mDNS_RegisterNoSuchService non-existence function so that it works again
-
-Revision 1.11 2003/03/31 22:49:35 cheshire
-Add "$Log" header
-
*/
#include <stdio.h> // For printf()
* 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: 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
-
-Revision 1.32 2006/08/14 23:24:46 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.31 2006/06/12 18:22:42 cheshire
-<rdar://problem/4580067> mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux
-
-Revision 1.30 2005/10/26 22:21:16 cheshire
-<rdar://problem/4149841> Potential buffer overflow in mDNSResponderPosix
-
-Revision 1.29 2005/03/04 21:35:33 cheshire
-<rdar://problem/4037201> Services.txt file not parsed properly when it contains more than one service
-
-Revision 1.28 2005/01/11 01:55:26 ksekar
-Fix compile errors in Posix debug build
-
-Revision 1.27 2004/12/01 04:28:43 cheshire
-<rdar://problem/3872803> Darwin patches for Solaris and Suse
-Use version of daemon() provided in mDNSUNP.c instead of local copy
-
-Revision 1.26 2004/11/30 22:37:01 cheshire
-Update copyright dates and add "Mode: C; tab-width: 4" headers
-
-Revision 1.25 2004/11/11 02:00:51 cheshire
-Minor fixes to getopt, error message
-
-Revision 1.24 2004/11/09 19:32:10 rpantos
-Suggestion from Ademar de Souza Reis Jr. to allow comments in services file
-
-Revision 1.23 2004/09/17 01:08:54 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.22 2004/09/16 01:58:22 cheshire
-Fix compiler warnings
-
-Revision 1.21 2004/06/15 03:48:07 cheshire
-Update mDNSResponderPosix to take multiple name=val arguments in a sane way
-
-Revision 1.20 2004/05/18 23:51:26 cheshire
-Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
-
-Revision 1.19 2004/03/12 08:03:14 cheshire
-Update comments
-
-Revision 1.18 2004/01/25 00:00:55 cheshire
-Change to use mDNSOpaque16fromIntVal() instead of shifting and masking
-
-Revision 1.17 2003/12/11 19:11:55 cheshire
-Fix compiler warning
-
-Revision 1.16 2003/08/14 02:19:55 cheshire
-<rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
-
-Revision 1.15 2003/08/12 19:56:26 cheshire
-Update to APSL 2.0
-
-Revision 1.14 2003/08/06 18:20:51 cheshire
-Makefile cleanup
-
-Revision 1.13 2003/07/23 00:00:04 cheshire
-Add comments
-
-Revision 1.12 2003/07/15 01:55:16 cheshire
-<rdar://problem/3315777> Need to implement service registration with subtypes
-
-Revision 1.11 2003/07/14 18:11:54 cheshire
-Fix stricter compiler warnings
-
-Revision 1.10 2003/07/10 20:27:31 cheshire
-<rdar://problem/3318717> mDNSResponder Posix version is missing a 'b' in the getopt option string
-
-Revision 1.9 2003/07/02 21:19:59 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.8 2003/06/18 05:48:41 cheshire
-Fix warnings
-
-Revision 1.7 2003/05/06 00:00:50 cheshire
-<rdar://problem/3248914> Rationalize naming of domainname manipulation functions
-
-Revision 1.6 2003/03/08 00:35:56 cheshire
-Switched to using new "mDNS_Execute" model (see "mDNSCore/Implementer Notes.txt")
-
-Revision 1.5 2003/02/20 06:48:36 cheshire
-<rdar://problem/3169535> Xserve RAID needs to do interface-specific registrations
-Reviewed by: Josh Graessley, Bob Bradley
-
-Revision 1.4 2003/01/28 03:07:46 cheshire
-Add extra parameter to mDNS_RenameAndReregisterService(),
-and add support for specifying a domain other than dot-local.
-
-Revision 1.3 2002/09/21 20:44:53 zarzycki
-Added APSL info
-
-Revision 1.2 2002/09/19 04:20:44 cheshire
-Remove high-ascii characters that confuse some systems
-
-Revision 1.1 2002/09/17 06:24:35 cheshire
-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()
+ */
+
+#if __APPLE__
+// In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated”
+// error, which prevents compilation because we build with "-Werror".
+// Since this is supposed to be portable cross-platform code, we don't care that daemon is
+// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
+#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
+#endif
#include <assert.h>
#include <stdio.h> // For printf()
#include <signal.h>
#include <fcntl.h>
+#if __APPLE__
+#undef daemon
+extern int daemon(int, int);
+#endif
+
+#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()
+
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark ***** Globals
#endif
-.\" $Id: libnss_mdns.8,v 1.1 2004/06/29 03:34:28 cheshire Exp $
.\"
.\" See section LICENSE for license information.
.\"
* thinking that variables x and y are both of type "char*" -- and anyone who doesn't
* understand why variable y is not of type "char*" just proves the point that poor code
* layout leads people to unfortunate misunderstandings about how the C language really works.)
-
- 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
-
-Revision 1.102 2007/09/12 19:23:17 cheshire
-Get rid of unnecessary mDNSPlatformTCPIsConnected() routine
-
-Revision 1.101 2007/07/20 00:54:23 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
-
-Revision 1.100 2007/07/19 21:45:30 cheshire
-Fixed code spacing
-
-Revision 1.99 2007/07/11 02:56:51 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-Remove unused mDNSPlatformDefaultRegDomainChanged
-
-Revision 1.98 2007/06/20 01:10:13 cheshire
-<rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
-
-Revision 1.97 2007/04/26 00:35:16 cheshire
-<rdar://problem/5140339> uDNS: Domain discovery not working over VPN
-Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server
-inside the firewall may give answers where a public one gives none, and vice versa.)
-
-Revision 1.96 2007/04/22 20:29:59 cheshire
-Fix locking error
-
-Revision 1.95 2007/04/22 20:15:46 cheshire
-Add missing parameters for mDNSPosixEventCallback
-
-Revision 1.94 2007/04/17 19:21:29 cheshire
-<rdar://problem/5140339> Domain discovery not working over VPN
-
-Revision 1.93 2007/04/16 20:49:40 cheshire
-Fix compile errors for mDNSPosix build
-
-Revision 1.92 2007/04/05 20:40:37 cheshire
-Remove unused mDNSPlatformTCPGetFlags()
-
-Revision 1.91 2007/03/22 18:31:48 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.90 2007/03/21 00:31:45 cheshire
-Remove unnecessary (and unimplemented) platform functions
-
-Revision 1.89 2007/03/20 17:07:15 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.88 2007/03/07 00:30:18 mkrochma
-<rdar://problem/5034370> POSIX: kDNSServiceInterfaceIndexAny not correctly handled
-Thanks goes to Aidan Williams of Audinate who did a lot of work in diagnosing this
-
-Revision 1.87 2007/02/08 21:12:28 cheshire
-<rdar://problem/4386497> Stop reading /etc/mDNSResponder.conf on every sleep/wake
-
-Revision 1.86 2007/01/05 08:30:52 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.85 2007/01/04 23:12:20 cheshire
-Remove unused mDNSPlatformDefaultBrowseDomainChanged
-
-Revision 1.84 2006/12/22 21:07:35 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.83 2006/12/21 00:09:46 cheshire
-Use mDNSPlatformMemZero instead of bzero
-
-Revision 1.82 2006/12/19 22:43:55 cheshire
-Fix compiler warnings
-
-Revision 1.81 2006/08/14 23:24:46 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.80 2006/07/22 03:05:33 cheshire
-Improve error reporting for socket creation failures
-
-Revision 1.79 2006/07/06 00:02:16 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-
-Revision 1.78 2006/06/28 09:12:22 cheshire
-Added debugging message
-
-Revision 1.77 2006/03/19 02:00:11 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.76 2006/01/09 19:29:16 cheshire
-<rdar://problem/4403128> Cap number of "sendto failed" messages we allow mDNSResponder to log
-
-Revision 1.75 2006/01/05 22:04:57 cheshire
-<rdar://problem/4399479> Log error message when send fails with "operation not permitted"
-
-Revision 1.74 2006/01/05 21:45:27 cheshire
-<rdar://problem/4400118> Fix uninitialized structure member in IPv6 code
-
-*/
+ */
#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
#include "DNSCommon.h"
return -1;
}
-mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID,
+mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname, mDNSInterfaceID InterfaceID,
TCPConnectionCallback callback, void *context)
{
(void)sock; // Unused
(void)dst; // Unused
(void)dstport; // Unused
+ (void)hostname; // Unused
(void)InterfaceID; // Unused
(void)callback; // Unused
(void)context; // Unused
(void)InterfaceID; // Unused
}
-mDNSexport void mDNSPlatformSetLocalARP(const mDNSv4Addr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
+mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
{
+ (void)m; // Unused
(void)tpa; // Unused
(void)tha; // Unused
(void)InterfaceID; // Unused
mDNSAddr DNSAddr;
DNSAddr.type = mDNSAddrType_IPv4;
DNSAddr.ip.v4.NotAnInteger = ina.s_addr;
- mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, &DNSAddr, UnicastDNSPort);
+ mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, &DNSAddr, UnicastDNSPort, mDNSfalse);
numOfServers++;
}
}
assert(m != NULL);
if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
+ if (index == kDNSServiceInterfaceIndexP2P ) return(mDNSInterface_P2P);
if (index == kDNSServiceInterfaceIndexAny ) return(mDNSInterface_Any);
intf = (PosixNetworkInterface*)(m->HostInterfaces);
assert(m != NULL);
if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
+ if (id == mDNSInterface_P2P ) return(kDNSServiceInterfaceIndexP2P);
if (id == mDNSInterface_Any ) return(kDNSServiceInterfaceIndexAny);
intf = (PosixNetworkInterface*)(m->HostInterfaces);
* 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: mDNSPosix.h,v $
-Revision 1.19 2007/04/22 20:15:46 cheshire
-Add missing parameters for mDNSPosixEventCallback
-
-Revision 1.18 2006/08/14 23:24:47 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.17 2005/02/04 00:39:59 cheshire
-Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
-
-Revision 1.16 2004/11/30 22:37:01 cheshire
-Update copyright dates and add "Mode: C; tab-width: 4" headers
-
-Revision 1.15 2004/02/06 01:19:51 cheshire
-Conditionally exclude IPv6 code unless HAVE_IPV6 is set
-
-Revision 1.14 2004/01/28 21:12:15 cheshire
-Reconcile mDNSIPv6Support & HAVE_IPV6 into a single flag (HAVE_IPV6)
-
-Revision 1.13 2004/01/24 05:12:03 cheshire
-<rdar://problem/3534352>: Need separate socket for issuing unicast queries
-
-Revision 1.12 2004/01/23 21:37:08 cheshire
-For consistency, rename multicastSocket to multicastSocket4, and multicastSocketv6 to multicastSocket6
-
-Revision 1.11 2003/12/11 03:03:51 rpantos
-Clean up mDNSPosix so that it builds on OS X again.
-
-Revision 1.10 2003/12/08 20:47:02 rpantos
-Add support for mDNSResponder on Linux.
-
-Revision 1.9 2003/10/30 19:25:19 cheshire
-Fix warning on certain compilers
-
-Revision 1.8 2003/08/12 19:56:26 cheshire
-Update to APSL 2.0
-
-Revision 1.7 2003/07/02 21:19:59 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.6 2003/03/13 03:46:21 cheshire
-Fixes to make the code build on Linux
-
-Revision 1.5 2003/03/08 00:35:56 cheshire
-Switched to using new "mDNS_Execute" model (see "mDNSCore/Implementer Notes.txt")
-
-Revision 1.4 2002/12/23 22:13:31 jgraessl
-
-Reviewed by: Stuart Cheshire
-Initial IPv6 support for mDNSResponder.
-
-Revision 1.3 2002/09/21 20:44:53 zarzycki
-Added APSL info
-
-Revision 1.2 2002/09/19 04:20:44 cheshire
-Remove high-ascii characters that confuse some systems
-
-Revision 1.1 2002/09/17 06:24:34 cheshire
-First checkin
-
-*/
+ */
#ifndef __mDNSPlatformPosix_h
#define __mDNSPlatformPosix_h
* 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: 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
-
-Revision 1.35 2007/11/15 21:36:19 cheshire
-<rdar://problem/5289340> POSIX: Off by one overflow in get_ifi_info_linuxv6()
-
-Revision 1.34 2006/08/14 23:24:47 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.33 2006/03/13 23:14:21 cheshire
-<rdar://problem/4427969> Compile problems on FreeBSD
-Use <netinet/in_var.h> instead of <netinet6/in6_var.h>
-
-Revision 1.32 2005/12/21 02:56:43 cheshire
-<rdar://problem/4243433> get_ifi_info() should fake ifi_index when SIOCGIFINDEX undefined
-
-Revision 1.31 2005/12/21 02:46:05 cheshire
-<rdar://problem/4243514> mDNSUNP.c needs to include <sys/param.h> on 4.4BSD Lite
-
-Revision 1.30 2005/11/29 20:03:02 mkrochma
-Wrapped sin_len with #ifndef NOT_HAVE_SA_LEN
-
-Revision 1.29 2005/11/12 02:23:10 cheshire
-<rdar://problem/4317680> mDNSUNP.c needs to deal with lame results from SIOCGIFNETMASK, SIOCGIFBRDADDR and SIOCGIFDSTADDR
-
-Revision 1.28 2005/10/31 22:09:45 cheshire
-Buffer "char addr6[33]" was seven bytes too small
-
-Revision 1.27 2005/06/29 15:54:21 cheshire
-<rdar://problem/4113742> mDNSResponder-107.1 does not work on FreeBSD
-Refine last checkin so that it (hopefully) doesn't break get_ifi_info() for every other OS
-
-Revision 1.26 2005/04/08 21:43:59 ksekar
-<rdar://problem/4083426> mDNSPosix (v98) retrieve interface list bug on AMD64 architecture
-Submitted by Andrew de Quincey
-
-Revision 1.25 2005/04/08 21:37:57 ksekar
-<rdar://problem/3792767> get_ifi_info doesn't return IPv6 interfaces on Linux
-
-Revision 1.24 2005/04/08 21:30:16 ksekar
-<rdar://problem/4007457> Compiling problems with mDNSResponder-98 on Solaris/Sparc v9
-Patch submitted by Bernd Kuhls
-
-Revision 1.23 2004/12/01 04:25:05 cheshire
-<rdar://problem/3872803> Darwin patches for Solaris and Suse
-Provide daemon() for platforms that don't have it
-
-Revision 1.22 2004/11/30 22:37:01 cheshire
-Update copyright dates and add "Mode: C; tab-width: 4" headers
-
-Revision 1.21 2004/11/08 22:13:59 rpantos
-Create sockf6 lazily when v6 interface found.
-
-Revision 1.20 2004/10/16 00:17:01 cheshire
-<rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
-
-Revision 1.19 2004/07/20 01:47:36 rpantos
-NOT_HAVE_SA_LEN applies to v6, too. And use more-portable s6_addr.
-
-Revision 1.18 2004/07/08 21:30:21 rpantos
-
-Revision 1.17 2004/06/25 00:26:27 rpantos
-Changes to fix the Posix build on Solaris.
-
-Revision 1.16 2004/03/20 05:37:09 cheshire
-Fix contributed by Terry Lambert & Alfred Perlstein:
-Don't use uint8_t -- it requires stdint.h, which doesn't exist on FreeBSD 4.x
-
-Revision 1.15 2004/02/14 01:09:45 rpantos
-Just use HAVE_IPV6 rather than defined(HAVE_IPV6).
-
-Revision 1.14 2003/12/11 18:53:40 cheshire
-Fix compiler warning reported by Paul Guyot
-
-Revision 1.13 2003/12/08 20:47:02 rpantos
-Add support for mDNSResponder on Linux.
-
-Revision 1.12 2003/09/02 20:47:13 cheshire
-Fix signed/unsigned warning
-
-Revision 1.11 2003/08/12 19:56:26 cheshire
-Update to APSL 2.0
-
-Revision 1.10 2003/08/06 18:20:51 cheshire
-Makefile cleanup
-
-Revision 1.9 2003/07/14 18:11:54 cheshire
-Fix stricter compiler warnings
-
-Revision 1.8 2003/07/02 21:19:59 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.7 2003/03/20 21:10:31 cheshire
-Fixes done at IETF 56 to make mDNSProxyResponderPosix run on Solaris
-
-Revision 1.6 2003/03/13 03:46:21 cheshire
-Fixes to make the code build on Linux
-
-Revision 1.5 2003/02/07 03:02:02 cheshire
-Submitted by: Mitsutaka Watanabe
-The code saying "index += 1;" was effectively making up random interface index values.
-The right way to find the correct interface index is if_nametoindex();
-
-Revision 1.4 2002/12/23 22:13:31 jgraessl
-
-Reviewed by: Stuart Cheshire
-Initial IPv6 support for mDNSResponder.
-
-Revision 1.3 2002/09/21 20:44:53 zarzycki
-Added APSL info
-
-Revision 1.2 2002/09/19 04:20:44 cheshire
-Remove high-ascii characters that confuse some systems
-
-Revision 1.1 2002/09/17 06:24:34 cheshire
-First checkin
-
-*/
+ */
#include "mDNSUNP.h"
int bits_in_block=16; /* Bits per IPv6 block */
for(i=0;i<=colons;i++) {
int block, ones=0xffff, ones_in_block;
- if(plen>bits_in_block) ones_in_block=bits_in_block;
- else ones_in_block=plen;
+ if (plen>bits_in_block) ones_in_block=bits_in_block;
+ else ones_in_block=plen;
block = ones & (ones << (bits_in_block-ones_in_block));
i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
plen -= ones_in_block;
#endif
#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
- if(family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
+ if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
#endif
sockfd = -1;
* 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: mDNSUNP.h,v $
-Revision 1.19 2006/08/14 23:24:47 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.18 2005/04/08 21:37:57 ksekar
-<rdar://problem/3792767> get_ifi_info doesn't return IPv6 interfaces on Linux
-
-Revision 1.17 2004/12/17 19:32:43 cheshire
-Add missing semicolon
-
-Revision 1.16 2004/12/01 04:25:05 cheshire
-<rdar://problem/3872803> Darwin patches for Solaris and Suse
-Provide daemon() for platforms that don't have it
-
-Revision 1.15 2004/11/30 22:37:01 cheshire
-Update copyright dates and add "Mode: C; tab-width: 4" headers
-
-Revision 1.14 2004/10/16 00:17:01 cheshire
-<rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
-
-Revision 1.13 2004/03/20 05:37:09 cheshire
-Fix contributed by Terry Lambert & Alfred Perlstein:
-Don't use uint8_t -- it requires stdint.h, which doesn't exist on FreeBSD 4.x
-
-Revision 1.12 2004/01/28 21:12:15 cheshire
-Reconcile mDNSIPv6Support & HAVE_IPV6 into a single flag (HAVE_IPV6)
-
-Revision 1.11 2003/12/13 05:43:09 bradley
-Fixed non-sa_len and non-IPv6 version of GET_SA_LEN macro to cast as sockaddr to access
-sa_family so it works with any sockaddr-compatible address structure (e.g. sockaddr_storage).
-
-Revision 1.10 2003/12/11 03:03:51 rpantos
-Clean up mDNSPosix so that it builds on OS X again.
-
-Revision 1.9 2003/12/08 20:47:02 rpantos
-Add support for mDNSResponder on Linux.
-
-Revision 1.8 2003/08/12 19:56:26 cheshire
-Update to APSL 2.0
-
-Revision 1.7 2003/08/06 18:20:51 cheshire
-Makefile cleanup
-
-Revision 1.6 2003/07/02 21:19:59 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.5 2003/03/13 03:46:21 cheshire
-Fixes to make the code build on Linux
-
-Revision 1.4 2002/12/23 22:13:32 jgraessl
-
-Reviewed by: Stuart Cheshire
-Initial IPv6 support for mDNSResponder.
-
-Revision 1.3 2002/09/21 20:44:53 zarzycki
-Added APSL info
-
-Revision 1.2 2002/09/19 04:20:44 cheshire
-Remove high-ascii characters that confuse some systems
-
-Revision 1.1 2002/09/17 06:24:35 cheshire
-First checkin
-
-*/
+ */
#ifndef __mDNSUNP_h
#define __mDNSUNP_h
#
# Linux /etc/init.d script to start/stop the mdnsd daemon.
#
-# $Log: mdnsd.sh,v $
-# Revision 1.9 2006/09/05 20:00:14 cheshire
-# Moved Emacs settings to second line of file
-#
-# Revision 1.8 2006/08/29 16:42:01 mkrochma
-# Fix POSIX startup script
-#
-# Revision 1.7 2006/08/14 23:24:47 cheshire
-# Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-#
-# Revision 1.6 2004/12/07 20:30:45 cheshire
-# Fix start-stop-daemon for Suse Linux (don't use -s TERM)
-#
-# Revision 1.5 2004/06/29 22:13:45 cheshire
-# Fix from Andrew White at NICTA
-#
-# Revision 1.4 2004/02/05 20:23:10 cheshire
-# Fix mdnsd.sh to work on *BSD distributions
-#
-# Revision 1.3 2004/01/19 22:47:17 cheshire
-# Define killprocterm() to do "killproc $1 -TERM" for Linux
-#
-# Revision 1.2 2003/12/11 19:42:13 cheshire
-# Change name "mDNSResponderd" to "mdnsd" for consistency with standard Linux (Unix) naming conventions
-#
-# Revision 1.1 2003/12/08 20:47:02 rpantos
-# Add support for mDNSResponder on Linux.
-#
# The following lines are used by the *BSD rcorder system to decide
# the order it's going to run the rc.d scripts at startup time.
# PROVIDE: mdnsd
-.\" $Id: nss_mdns.conf.5,v 1.1 2004/06/29 03:34:28 cheshire Exp $
.\"
.\" See section LICENSE for license information.
.\"
# Filled orange circle: Probe (service starting) Hollow orange circle: First probe (requesting unicast reply)
# Filled green circle: Normal answer Hollow green circle: Goodbye message (record going away)
# Hollow blue circle: Legacy query (from old client)
-# $Log: parselog.py,v $
-# Revision 1.4 2006/09/05 20:00:14 cheshire
-# Moved Emacs settings to second line of file
-#
-# Revision 1.3 2006/08/14 23:24:47 cheshire
-# Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-#
-# Revision 1.2 2003/12/01 21:47:44 cheshire
-# APSL
-#
-# Revision 1.1 2003/10/10 02:14:17 cheshire
-# First checkin of parselog.py, a tool to create graphical representations of mDNSNetMonitor logs
from CoreGraphics import *
import math # for pi
{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
- 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}") = "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
{9CE2568A-3170-41C6-9F20-A0188A9EC114} = {9CE2568A-3170-41C6-9F20-A0188A9EC114}\r
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
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "DNSServiceBrowser.VB", "Clients\DNSServiceBrowser.VB\DNSServiceBrowser.VB.vbproj", "{FB79E297-5703-435C-A829-51AA51CD71C2}"\r
EndProject\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mDNSNetMonitor", "Clients\mDNSNetMonitor.VisualStudio\mDNSNetMonitor.vcproj", "{AF35C285-528D-46A1-8A0E-47B0733DC718}"\r
+ ProjectSection(ProjectDependencies) = postProject\r
+ {C1D98254-BA27-4427-A3BE-A68CA2CC5F69} = {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}\r
+ EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ControlPanelLocRes", "mDNSWindows\ControlPanel\ControlPanelLocRes.vcproj", "{4490229E-025A-478F-A2CF-51154DA83E39}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ControlPanelRes", "mDNSWindows\ControlPanel\ControlPanelRes.vcproj", "{5254AA9C-3D2E-4539-86D9-5EB0F4151215}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ControlPanel", "mDNSWindows\ControlPanel\ControlPanel.vcproj", "{F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}"\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}") = "FirefoxExtension", "Clients\FirefoxExtension\FirefoxExtension.vcproj", "{7826EA27-D4CC-4FAA-AD23-DF813823227B}"\r
+ ProjectSection(ProjectDependencies) = postProject\r
+ {3A2B6325-3053-4236-84BD-AA9BE2E323E5} = {3A2B6325-3053-4236-84BD-AA9BE2E323E5}\r
+ EndProjectSection\r
EndProject\r
Global\r
GlobalSection(SolutionConfigurationPlatforms) = preSolution\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|Any CPU.ActiveCfg = Debug|x64\r
- {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
- {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug|Mixed Platforms.Build.0 = Debug|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|Any CPU.ActiveCfg = Release|x64\r
- {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
- {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release|Mixed Platforms.Build.0 = Release|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|Any CPU.ActiveCfg = Debug|x64\r
{967F5375-0176-43D3-ADA3-22EE25551C37}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
{967F5375-0176-43D3-ADA3-22EE25551C37}.Debug|Mixed Platforms.Build.0 = Debug|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}.Debug|x64.Build.0 = Debug|x64\r
{9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release|Any CPU.ActiveCfg = Release|x64\r
{9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
{9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release|Mixed Platforms.Build.0 = Release|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
+ {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release|x64.Build.0 = Release|x64\r
{A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug|Any CPU.ActiveCfg = Debug|x64\r
{A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
{A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug|Mixed Platforms.Build.0 = 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|Any CPU.ActiveCfg = Debug|x64\r
- {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
- {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Debug|Mixed Platforms.Build.0 = Debug|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|Any CPU.ActiveCfg = Release|x64\r
- {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
- {0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}.Release|Mixed Platforms.Build.0 = Release|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|Any CPU.ActiveCfg = Debug|x64\r
{3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
{3A2B6325-3053-4236-84BD-AA9BE2E323E5}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
{AF35C285-528D-46A1-8A0E-47B0733DC718}.Release|Win32.ActiveCfg = Release|Win32\r
{AF35C285-528D-46A1-8A0E-47B0733DC718}.Release|Win32.Build.0 = Release|Win32\r
{AF35C285-528D-46A1-8A0E-47B0733DC718}.Release|x64.ActiveCfg = Release|Win32\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Debug|Any CPU.ActiveCfg = Debug|x64\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Debug|Win32.ActiveCfg = Debug|Win32\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Debug|Win32.Build.0 = Debug|Win32\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Debug|x64.ActiveCfg = Debug|x64\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Debug|x64.Build.0 = Debug|x64\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Release|Any CPU.ActiveCfg = Release|x64\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Release|Mixed Platforms.Build.0 = Release|x64\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Release|Win32.ActiveCfg = Release|Win32\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Release|Win32.Build.0 = Release|Win32\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Release|x64.ActiveCfg = Release|x64\r
+ {4490229E-025A-478F-A2CF-51154DA83E39}.Release|x64.Build.0 = Release|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Debug|Any CPU.ActiveCfg = Debug|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Debug|Win32.ActiveCfg = Debug|Win32\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Debug|Win32.Build.0 = Debug|Win32\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Debug|x64.ActiveCfg = Debug|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Debug|x64.Build.0 = Debug|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Release|Any CPU.ActiveCfg = Release|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Release|Mixed Platforms.Build.0 = Release|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Release|Win32.ActiveCfg = Release|Win32\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Release|Win32.Build.0 = Release|Win32\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Release|x64.ActiveCfg = Release|x64\r
+ {5254AA9C-3D2E-4539-86D9-5EB0F4151215}.Release|x64.Build.0 = Release|x64\r
+ {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug|Any CPU.ActiveCfg = Debug|x64\r
+ {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+ {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug|Mixed Platforms.Build.0 = Debug|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|Any CPU.ActiveCfg = Release|x64\r
+ {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+ {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release|Mixed Platforms.Build.0 = Release|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
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Debug|Any CPU.ActiveCfg = Debug|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Debug|Mixed Platforms.Build.0 = Debug|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Debug|Win32.ActiveCfg = Debug|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Debug|Win32.Build.0 = Debug|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Debug|x64.ActiveCfg = Debug|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Release|Any CPU.ActiveCfg = Release|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Release|Mixed Platforms.ActiveCfg = Release|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Release|Mixed Platforms.Build.0 = Release|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Release|Win32.ActiveCfg = Release|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Release|Win32.Build.0 = Release|Win32\r
+ {7826EA27-D4CC-4FAA-AD23-DF813823227B}.Release|x64.ActiveCfg = Release|Win32\r
EndGlobalSection\r
GlobalSection(SolutionProperties) = preSolution\r
HideSolutionNode = FALSE\r
* 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: 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
-
-Revision 1.7 2007/01/16 23:00:45 cheshire
-Don't need to include CoreServices.h
-
-Revision 1.6 2006/08/24 22:41:53 herscher
-<rdar://problem/4580067> POSIX: dnsextd_parser doesn't compile on Linux
-
-Revision 1.5 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.4 2006/07/05 22:43:21 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-
-Revision 1.3 2004/04/08 09:27:12 bradley
-Added macro for portable specification of callback calling conventions.
-
-Revision 1.2 2004/03/07 05:53:39 bradley
-Fixed NumVersion extraction macros. Updated error code mappings to match latest internal version.
-
-Revision 1.1 2004/01/30 02:25:59 bradley
-Common Services and portability support for various platforms.
-
-*/
+ */
//---------------------------------------------------------------------------------------------------------------------------
/*! @header CommonServices
* See the License for the specific language governing permissions and
* limitations under the License.
- Change History (most recent first):
-
-$Log: DebugServices.c,v $
-Revision 1.6 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.5 2004/09/17 01:08:57 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.4 2004/04/15 08:59:08 bradley
-Removed deprecated debug and log levels and replaced them with modern equivalents.
-
-Revision 1.3 2004/04/08 09:29:55 bradley
-Manually do host->network byte order conversion to avoid needing libraries for htons/htonl. Changed
-hex dumps to better separate hex and ASCII. Added support for %.8a syntax in DebugSNPrintF for Fibre
-Channel addresses (00:11:22:33:44:55:66:77). Fixed a few places where HeaderDoc was incorrect.
-
-Revision 1.2 2004/03/07 05:59:34 bradley
-Sync'd with internal version: Added expect macros, error codes, and CoreServices exclusion.
-
-Revision 1.1 2004/01/30 02:27:30 bradley
-Debugging support for various platforms.
-
-
To Do:
- Use StackWalk on Windows to optionally print stack frames.
* 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: DebugServices.h,v $
-Revision 1.5 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.4 2004/04/15 08:59:08 bradley
-Removed deprecated debug and log levels and replaced them with modern equivalents.
-
-Revision 1.3 2004/04/08 09:29:55 bradley
-Manually do host->network byte order conversion to avoid needing libraries for htons/htonl. Changed
-hex dumps to better separate hex and ASCII. Added support for %.8a syntax in DebugSNPrintF for Fibre
-Channel addresses (00:11:22:33:44:55:66:77). Fixed a few places where HeaderDoc was incorrect.
-
-Revision 1.2 2004/03/07 05:59:34 bradley
-Sync'd with internal version: Added expect macros, error codes, and CoreServices exclusion.
-
-Revision 1.1 2004/01/30 02:27:30 bradley
-Debugging support for various platforms.
-
-*/
+ */
//---------------------------------------------------------------------------------------------------------------------------
/*! @header DebugServices
work with GCC due to GCC allow a zero-length array. Using a -1 condition turned out to be more portable.
*/
+#ifndef check_compile_time
#define check_compile_time( X ) extern int debug_compile_time_name[ ( X ) ? 1 : -1 ]
+#endif
//---------------------------------------------------------------------------------------------------------------------------
/*! @defined check_compile_time_code
Version: 1.0
Tabs: 4 spaces
-
- Change History (most recent first):
-
-$Log: GenLinkedList.c,v $
-Revision 1.4 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2004/04/22 21:14:42 cheshire
-Fix comment spelling mistake
-
-Revision 1.2 2004/02/05 07:41:08 cheshire
-Add Log header
-
-*/
+ */
#include "GenLinkedList.h"
* 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.
-
- File: GenLinkedList.c
-
- Contains: interface to generic linked lists.
-
- Version: 1.0
- Tabs: 4 spaces
-
- Change History (most recent first):
-
-$Log: GenLinkedList.h,v $
-Revision 1.3 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/02/05 07:41:08 cheshire
-Add Log header
-
-*/
+ */
#ifndef __GenLinkedList__
#define __GenLinkedList__
* 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: BaseListener.java,v $
-Revision 1.3 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
*/
* 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: BrowseListener.java,v $
-Revision 1.3 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
*/
* 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: DNSRecord.java,v $
-Revision 1.3 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/12/11 03:00:59 rpantos
-<rdar://problem/3907498> Java DNSRecord API should be cleaned up
-
-Revision 1.1 2004/04/30 16:32:34 rpantos
-First checked in.
-
-
*/
* See the License for the specific language governing permissions and
* limitations under the License.
- 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
-
-Revision 1.14 2007/03/13 00:10:14 vazquez
-<rdar://problem/4455206> Java: 64 bit JNI patch
-
-Revision 1.13 2007/02/24 23:08:02 mkrochma
-<rdar://problem/5001673> Typo in Bonjour Java API document
-
-Revision 1.12 2007/02/09 00:33:02 cheshire
-Add missing error codes to kMessages array
-
-Revision 1.11 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.10 2006/06/20 23:05:55 rpantos
-<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
-
-Revision 1.9 2005/10/26 01:52:24 cheshire
-<rdar://problem/4316286> Race condition in Java code (doesn't work at all on Linux)
-
-Revision 1.8 2005/07/11 01:55:21 cheshire
-<rdar://problem/4175511> Race condition in Java API
-
-Revision 1.7 2005/07/05 13:01:52 cheshire
-<rdar://problem/4169791> If mDNSResponder daemon is stopped, Java API spins, burning CPU time
-
-Revision 1.6 2005/07/05 00:02:25 cheshire
-Add missing comma
-
-Revision 1.5 2005/07/04 21:13:47 cheshire
-Add missing error message strings
-
-Revision 1.4 2004/12/11 03:00:59 rpantos
-<rdar://problem/3907498> Java DNSRecord API should be cleaned up
-
-Revision 1.3 2004/11/12 03:23:08 rpantos
-rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex.
-
-Revision 1.2 2004/05/20 17:43:18 cheshire
-Fix invalid UTF-8 characters in file
-
-Revision 1.1 2004/04/30 16:32:34 rpantos
-First checked in.
-
-
This file declares and implements DNSSD, the central Java factory class
for doing DNS Service Discovery. It includes the mostly-abstract public
interface, as well as the Apple* implementation subclasses.
static protected final DNSSD getInstance()
{
SecurityManager sm = System.getSecurityManager();
- if ( sm != null)
+ if (sm != null)
sm.checkPermission( new RuntimePermission( "getDNSSDInstance"));
return fInstance;
}
try
{
String name = System.getProperty( "com.apple.dnssd.DNSSD" );
- if( name == null )
+ if (name == null)
name = "com.apple.dnssd.AppleDNSSD"; // Fall back to Apple-provided class.
- fInstance = (DNSSD) Class.forName( name ).newInstance();
+ fInstance = (DNSSD) Class.forName(name).newInstance();
}
catch( Exception e )
{
"NATPORTMAPPINGDISABLED"
};
- if ( fErrorCode <= UNKNOWN && fErrorCode > ( UNKNOWN - kMessages.length))
+ if (fErrorCode <= UNKNOWN && fErrorCode > ( UNKNOWN - kMessages.length))
{
return "DNS-SD Error " + String.valueOf( fErrorCode) + ": " + kMessages[ UNKNOWN - fErrorCode];
}
int libInitResult = InitLibrary( 2); // Current version number (must be sync'd with jnilib version)
- if ( libInitResult != DNSSDException.NO_ERROR)
+ if (libInitResult != DNSSDException.NO_ERROR)
throw new InternalError( "cannot instantiate DNSSD: " + new AppleDNSSDException( libInitResult).getMessage());
}
String[] responseHolder = new String[1]; // lame maneuver to get around Java's lack of reference parameters
int rc = ConstructName( serviceName, regType, domain, responseHolder);
- if ( rc != 0)
+ if (rc != 0)
throw new AppleDNSSDException( rc);
return responseHolder[0];
protected void ThrowOnErr( int rc) throws DNSSDException
{
- if ( rc != 0)
+ if (rc != 0)
throw new AppleDNSSDException( rc);
}
{
super(client);
this.ThrowOnErr( this.CreateBrowser( flags, ifIndex, regType, domain));
- if ( !AppleDNSSD.hasAutoCallbacks)
+ if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
{
super(client);
this.ThrowOnErr( this.CreateResolver( flags, ifIndex, serviceName, regType, domain));
- if ( !AppleDNSSD.hasAutoCallbacks)
+ if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
protected void ThrowOnErr( int rc) throws DNSSDException
{
- if ( rc != 0)
+ if (rc != 0)
throw new AppleDNSSDException( rc);
}
{
super(client);
this.ThrowOnErr( this.BeginRegister( ifIndex, flags, serviceName, regType, domain, host, port, txtRecord));
- if ( !AppleDNSSD.hasAutoCallbacks)
+ if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
{
super(listener);
this.ThrowOnErr( this.CreateConnection());
- if ( !AppleDNSSD.hasAutoCallbacks)
+ if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
{
super(client);
this.ThrowOnErr( this.CreateQuery( flags, ifIndex, serviceName, rrtype, rrclass));
- if ( !AppleDNSSD.hasAutoCallbacks)
+ if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
{
super(client);
this.ThrowOnErr( this.BeginEnum( flags, ifIndex));
- if ( !AppleDNSSD.hasAutoCallbacks)
+ if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
* 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: DNSSDException.java,v $
-Revision 1.6 2007/02/08 23:58:17 cheshire
-Added comment about updating kMessages array in AppleDNSSDException (DNSSD.java)
-
-Revision 1.5 2007/02/07 01:19:36 cheshire
-<rdar://problem/4849427> API: Reconcile conflicting error code values
-
-Revision 1.4 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2005/07/10 22:19:01 cheshire
-Add missing error codes to list of public static final ints
-
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
-*/
+ */
package com.apple.dnssd;
* 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.
-
- This file declares the public interface to DNSSDRecordRegistrar, a DNSSDService
- subclass that allows efficient registration of multiple individual records.
-
- Change History (most recent first):
-
-$Log: DNSSDRecordRegistrar.java,v $
-Revision 1.2 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2006/06/20 23:00:12 rpantos
-<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
-
*/
* 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: DNSSDRegistration.java,v $
-Revision 1.3 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/12/11 03:01:00 rpantos
-<rdar://problem/3907498> Java DNSRecord API should be cleaned up
-
-Revision 1.1 2004/04/30 16:32:34 rpantos
-First checked in.
-
-
- This file declares the public interface to DNSSDRegistration, a DNSSDService
- subclass that allows a client to control a service registration.
*/
* 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.java,v $
-Revision 1.3 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:32:34 rpantos
-First checked in.
-
*/
* 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: DomainListener.java,v $
-Revision 1.3 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
*/
* See the License for the specific language governing permissions and
* limitations under the License.
- Change History (most recent first):
-
-$Log: JNISupport.c,v $
-Revision 1.22 2007/11/30 23:38:53 cheshire
-Fix compiler warning:
-/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/jni.h:609: warning: declaration of 'index' shadows a global declaration
-
-Revision 1.21 2007/09/18 19:09:02 cheshire
-<rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
-
-Revision 1.20 2007/03/13 01:41:46 cheshire
-Fixed compile warnings when building 32-bit
-
-Revision 1.19 2007/03/13 00:28:03 vazquez
-<rdar://problem/4625928> Java: Rename exported symbols in libjdns_sd.jnilib
-
-Revision 1.18 2007/03/13 00:10:14 vazquez
-<rdar://problem/4455206> Java: 64 bit JNI patch
-
-Revision 1.17 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.16 2006/07/14 02:35:47 cheshire
-Added (commented out) syslog debugging messages
-
-Revision 1.15 2006/06/27 19:34:43 cheshire
-<rdar://problem/4430023> txtRecord parameter of DNSServiceResolveReply() should be unsigned char *
-
-Revision 1.14 2006/06/20 23:03:35 rpantos
-<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
-
-Revision 1.13 2005/10/26 01:52:24 cheshire
-<rdar://problem/4316286> Race condition in Java code (doesn't work at all on Linux)
-
-Revision 1.12 2005/07/13 19:20:32 cheshire
-<rdar://problem/4175511> Race condition in Java API
-Additional cleanup suggested by Roger -- NewContext() doesn't need ownerClass parameter any more
-
-Revision 1.11 2005/07/11 01:55:21 cheshire
-<rdar://problem/4175511> Race condition in Java API
-
-Revision 1.10 2005/07/05 13:01:52 cheshire
-<rdar://problem/4169791> If mDNSResponder daemon is stopped, Java API spins, burning CPU time
-
-Revision 1.9 2004/12/11 03:01:00 rpantos
-<rdar://problem/3907498> Java DNSRecord API should be cleaned up
-
-Revision 1.8 2004/11/30 23:51:05 cheshire
-Remove double semicolons
-
-Revision 1.7 2004/11/23 08:12:04 shersche
-Implement if_nametoindex and if_indextoname for Win32 platforms
-
-Revision 1.6 2004/11/23 03:41:14 cheshire
-Change JNISupport.c to call if_indextoname & if_nametoindex directly.
-(May require some additional glue code to work on Windows.)
-
-Revision 1.5 2004/11/17 17:07:44 cheshire
-Updated comment about AUTO_CALLBACKS
-
-Revision 1.4 2004/11/12 03:23:09 rpantos
-rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex.
-
-Revision 1.3 2004/06/18 04:44:17 rpantos
-Adapt to API unification on Windows
-
-Revision 1.2 2004/05/28 23:34:42 ksekar
-<rdar://problem/3672903>: Java project build errors
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
-
This file contains the platform support for DNSSD and related Java classes.
It is used to shim through to the underlying <dns_sd.h> API.
*/
}
#define LOCAL_ONLY_NAME "loo"
+#define P2P_NAME "p2p"
JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv *pEnv, jobject pThis _UNUSED,
jint ifIndex)
{
char *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE];
- if (ifIndex != (jint) kDNSServiceInterfaceIndexLocalOnly)
+ if (ifIndex == (jint) kDNSServiceInterfaceIndexP2P)
+ p = P2P_NAME;
+ else if (ifIndex != (jint) kDNSServiceInterfaceIndexLocalOnly)
p = if_indextoname( ifIndex, nameBuff );
return (*pEnv)->NewStringUTF( pEnv, p);
uint32_t ifIndex = kDNSServiceInterfaceIndexLocalOnly;
const char *nameStr = SafeGetUTFChars( pEnv, ifName);
- if (strcmp(nameStr, LOCAL_ONLY_NAME))
+ if (strcmp(nameStr, P2P_NAME) == 0)
+ ifIndex = kDNSServiceInterfaceIndexP2P;
+ else if (strcmp(nameStr, LOCAL_ONLY_NAME))
ifIndex = if_nametoindex( nameStr);
SafeReleaseUTFChars( pEnv, ifName, nameStr);
* 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: QueryListener.java,v $
-Revision 1.4 2007/03/12 23:43:08 vazquez
-<rdar://problem/4169128> Documentation: Error in Java queryAnswered doc
-
-Revision 1.3 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
*/
* 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: RegisterListener.java,v $
-Revision 1.3 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
*/
* 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: RegisterRecordListener.java,v $
-Revision 1.2 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2006/06/20 23:00:12 rpantos
-<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
-
-
*/
* 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: ResolveListener.java,v $
-Revision 1.3 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
-*/
+ */
package com.apple.dnssd;
* See the License for the specific language governing permissions and
* limitations under the License.
- Change History (most recent first):
-
-$Log: TXTRecord.java,v $
-Revision 1.8 2007/03/16 23:39:40 vazquez
-<rdar://problem/4612778> Java: Coding error in java wrappers, limited TXTRecord length
-
-Revision 1.7 2006/12/13 07:13:23 mkrochma
-<rdar://problem/4612778> Java: Coding error in java wrappers, limited TXTRecord length
-
-Revision 1.6 2006/08/14 23:25:08 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.5 2004/08/25 21:54:36 rpantos
-<rdar://problem/3773973> Fix getValue() for values containing '='.
-
-Revision 1.4 2004/08/04 01:04:50 rpantos
-<rdar://problems/3731579&3731582> Fix set(); add remove() & toString().
-
-Revision 1.3 2004/07/13 21:24:25 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
-
To do:
- implement remove()
- fix set() to replace existing values
* 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: 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
-
-Revision 1.16 2008/02/26 21:47:45 cheshire
-Added cast to avoid compiler warning
-
-Revision 1.15 2008/02/26 21:42:26 cheshire
-Added 'LogTimeStamps' option, to show ms-granularity timestamps on every log message
-
-Revision 1.14 2007/12/03 18:37:26 cheshire
-Moved mDNSPlatformWriteLogMsg & mDNSPlatformWriteDebugMsg
-from mDNSMacOSX.c to PlatformCommon.c, so that Posix build can use them
-
-Revision 1.13 2007/10/22 20:07:07 cheshire
-Moved mDNSPlatformSourceAddrForDest from mDNSMacOSX.c to PlatformCommon.c so
-Posix build can share the code (better than just pasting it into mDNSPosix.c)
-
-Revision 1.12 2007/10/16 17:19:53 cheshire
-<rdar://problem/3557903> Performance: Core code will not work on platforms with small stacks
-Cut ReadDDNSSettingsFromConfFile stack from 2112 to 1104 bytes
-
-Revision 1.11 2007/07/31 23:08:34 mcguire
-<rdar://problem/5329542> BTMM: Make AutoTunnel mode work with multihoming
-
-Revision 1.10 2007/07/11 02:59:58 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-Add AutoTunnel parameter to mDNS_SetSecretForDomain
-
-Revision 1.9 2007/01/09 22:37:44 cheshire
-Remove unused ClearDomainSecrets() function
-
-Revision 1.8 2006/12/22 20:59:51 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.7 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.6 2005/04/08 21:30:16 ksekar
-<rdar://problem/4007457> Compiling problems with mDNSResponder-98 on Solaris/Sparc v9
-Patch submitted by Bernd Kuhls
-
-Revision 1.5 2005/02/01 19:33:30 ksekar
-<rdar://problem/3985239> Keychain format too restrictive
-
-Revision 1.4 2005/01/19 19:19:21 ksekar
-<rdar://problem/3960191> Need a way to turn off domain discovery
-
-Revision 1.3 2004/12/13 17:46:52 cheshire
-Use sizeof(buf) instead of fixed constant 1024
-
-Revision 1.2 2004/12/01 03:30:29 cheshire
-<rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
-
-Revision 1.1 2004/12/01 01:51:35 cheshire
-Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
-
*/
#include <stdio.h> // Needed for fopen() etc.
* 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: PlatformCommon.h,v $
-Revision 1.8 2007/10/22 20:07:52 cheshire
-Deleted unused FindSourceAddrForIP() function
-
-Revision 1.7 2007/07/31 23:08:34 mcguire
-<rdar://problem/5329542> BTMM: Make AutoTunnel mode work with multihoming
-
-Revision 1.6 2007/01/09 22:37:43 cheshire
-Remove unused ClearDomainSecrets() function
-
-Revision 1.5 2006/12/22 20:59:51 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.4 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2005/01/19 19:19:21 ksekar
-<rdar://problem/3960191> Need a way to turn off domain discovery
-
-Revision 1.2 2004/12/01 03:30:29 cheshire
-<rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
-
-Revision 1.1 2004/12/01 01:51:35 cheshire
-Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
-
*/
extern void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled);
.\" See the License for the specific language governing permissions and
.\" limitations under the License.
.\"
-.\" $Log: dns-sd.1,v $
-.\" Revision 1.6 2006/08/14 23:24:56 cheshire
-.\" Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-.\"
-.\" Revision 1.5 2005/07/04 23:12:35 cheshire
-.\" <rdar://problem/4103628> The dns-sd command first appeared in Mac OS X 10.4 (Tiger)
-.\"
-.\" Revision 1.4 2005/02/16 02:29:32 cheshire
-.\" Update terminology
-.\"
-.\" Revision 1.3 2005/02/10 22:35:28 cheshire
-.\" <rdar://problem/3727944> Update name
-.\"
-.\" Revision 1.2 2004/09/24 18:33:05 cheshire
-.\" <rdar://problem/3561780> Update man pages to clarify that mDNS and dns-sd are not intended for script use
-.\"
-.\" Revision 1.1 2004/09/22 22:46:25 cheshire
-.\" Man page for dns-sd command-line tool
-.\"
-.\"
-.\"
.Dd April 2004 \" Date
.Dt dns-sd 1 \" Document Title
.Os Darwin \" Operating System
*/
#ifndef _DNS_SD_H
-#define _DNS_SD_H 2140302
+#define _DNS_SD_H 2581300
#ifdef __cplusplus
extern "C" {
#endif
+/* Set to 1 if libdispatch is supported
+ * Note: May also be set by project and/or Makefile
+ */
+#ifndef _DNS_SD_LIBDISPATCH
+#define _DNS_SD_LIBDISPATCH 0
+#endif /* ndef _DNS_SD_LIBDISPATCH */
+
/* standard calling convention under Win32 is __stdcall */
/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */
/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */
#include <stdint.h>
#endif
+#if _DNS_SD_LIBDISPATCH
+#include <dispatch/dispatch.h>
+#endif
+
/* DNSServiceRef, DNSRecordRef
*
* Opaque internal data types.
*/
kDNSServiceFlagsSuppressUnusable = 0x8000
- /* Placeholder definition, for future use
- */
+ /*
+ * This flag is meaningful only in DNSServiceQueryRecord which suppresses unusable queries on the
+ * wire. If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
+ * but this host has no routable IPv6 address, then the call will not try to look up IPv6 addresses
+ * for "hostname", since any addresses it found would be unlikely to be of any use anyway. Similarly,
+ * if this host has no routable IPv4 address, the call will not try to look up IPv4 addresses for
+ * "hostname".
+ */
+
};
/* Possible protocols for DNSServiceNATPortMappingCreate(). */
enum
{
- kDNSServiceType_A = 1, /* Host address. */
- kDNSServiceType_NS = 2, /* Authoritative server. */
- kDNSServiceType_MD = 3, /* Mail destination. */
- kDNSServiceType_MF = 4, /* Mail forwarder. */
- kDNSServiceType_CNAME = 5, /* Canonical name. */
- kDNSServiceType_SOA = 6, /* Start of authority zone. */
- kDNSServiceType_MB = 7, /* Mailbox domain name. */
- kDNSServiceType_MG = 8, /* Mail group member. */
- kDNSServiceType_MR = 9, /* Mail rename name. */
- kDNSServiceType_NULL = 10, /* Null resource record. */
- kDNSServiceType_WKS = 11, /* Well known service. */
- kDNSServiceType_PTR = 12, /* Domain name pointer. */
- kDNSServiceType_HINFO = 13, /* Host information. */
- kDNSServiceType_MINFO = 14, /* Mailbox information. */
- kDNSServiceType_MX = 15, /* Mail routing information. */
- kDNSServiceType_TXT = 16, /* One or more text strings (NOT "zero or more..."). */
- kDNSServiceType_RP = 17, /* Responsible person. */
- kDNSServiceType_AFSDB = 18, /* AFS cell database. */
- kDNSServiceType_X25 = 19, /* X_25 calling address. */
- kDNSServiceType_ISDN = 20, /* ISDN calling address. */
- kDNSServiceType_RT = 21, /* Router. */
- kDNSServiceType_NSAP = 22, /* NSAP address. */
- kDNSServiceType_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */
- kDNSServiceType_SIG = 24, /* Security signature. */
- kDNSServiceType_KEY = 25, /* Security key. */
- kDNSServiceType_PX = 26, /* X.400 mail mapping. */
- kDNSServiceType_GPOS = 27, /* Geographical position (withdrawn). */
- kDNSServiceType_AAAA = 28, /* IPv6 Address. */
- kDNSServiceType_LOC = 29, /* Location Information. */
- kDNSServiceType_NXT = 30, /* Next domain (security). */
- kDNSServiceType_EID = 31, /* Endpoint identifier. */
- kDNSServiceType_NIMLOC = 32, /* Nimrod Locator. */
- kDNSServiceType_SRV = 33, /* Server Selection. */
- kDNSServiceType_ATMA = 34, /* ATM Address */
- kDNSServiceType_NAPTR = 35, /* Naming Authority PoinTeR */
- kDNSServiceType_KX = 36, /* Key Exchange */
- kDNSServiceType_CERT = 37, /* Certification record */
- kDNSServiceType_A6 = 38, /* IPv6 Address (deprecated) */
- kDNSServiceType_DNAME = 39, /* Non-terminal DNAME (for IPv6) */
- kDNSServiceType_SINK = 40, /* Kitchen sink (experimental) */
- kDNSServiceType_OPT = 41, /* EDNS0 option (meta-RR) */
- kDNSServiceType_APL = 42, /* Address Prefix List */
- kDNSServiceType_DS = 43, /* Delegation Signer */
- kDNSServiceType_SSHFP = 44, /* SSH Key Fingerprint */
- kDNSServiceType_IPSECKEY = 45, /* IPSECKEY */
- kDNSServiceType_RRSIG = 46, /* RRSIG */
- kDNSServiceType_NSEC = 47, /* Denial of Existence */
- kDNSServiceType_DNSKEY = 48, /* DNSKEY */
- kDNSServiceType_DHCID = 49, /* DHCP Client Identifier */
- kDNSServiceType_NSEC3 = 50, /* Hashed Authenticated Denial of Existence */
- kDNSServiceType_NSEC3PARAM= 51, /* Hashed Authenticated Denial of Existence */
-
- kDNSServiceType_HIP = 55, /* Host Identity Protocol */
-
- kDNSServiceType_SPF = 99, /* Sender Policy Framework for E-Mail */
- kDNSServiceType_UINFO = 100, /* IANA-Reserved */
- kDNSServiceType_UID = 101, /* IANA-Reserved */
- kDNSServiceType_GID = 102, /* IANA-Reserved */
- kDNSServiceType_UNSPEC = 103, /* IANA-Reserved */
-
- kDNSServiceType_TKEY = 249, /* Transaction key */
- kDNSServiceType_TSIG = 250, /* Transaction signature. */
- kDNSServiceType_IXFR = 251, /* Incremental zone transfer. */
- kDNSServiceType_AXFR = 252, /* Transfer zone of authority. */
- kDNSServiceType_MAILB = 253, /* Transfer mailbox records. */
- kDNSServiceType_MAILA = 254, /* Transfer mail agent records. */
- kDNSServiceType_ANY = 255 /* Wildcard match. */
+ kDNSServiceType_A = 1, /* Host address. */
+ kDNSServiceType_NS = 2, /* Authoritative server. */
+ kDNSServiceType_MD = 3, /* Mail destination. */
+ kDNSServiceType_MF = 4, /* Mail forwarder. */
+ kDNSServiceType_CNAME = 5, /* Canonical name. */
+ kDNSServiceType_SOA = 6, /* Start of authority zone. */
+ kDNSServiceType_MB = 7, /* Mailbox domain name. */
+ kDNSServiceType_MG = 8, /* Mail group member. */
+ kDNSServiceType_MR = 9, /* Mail rename name. */
+ kDNSServiceType_NULL = 10, /* Null resource record. */
+ kDNSServiceType_WKS = 11, /* Well known service. */
+ kDNSServiceType_PTR = 12, /* Domain name pointer. */
+ kDNSServiceType_HINFO = 13, /* Host information. */
+ kDNSServiceType_MINFO = 14, /* Mailbox information. */
+ kDNSServiceType_MX = 15, /* Mail routing information. */
+ kDNSServiceType_TXT = 16, /* One or more text strings (NOT "zero or more..."). */
+ kDNSServiceType_RP = 17, /* Responsible person. */
+ kDNSServiceType_AFSDB = 18, /* AFS cell database. */
+ kDNSServiceType_X25 = 19, /* X_25 calling address. */
+ kDNSServiceType_ISDN = 20, /* ISDN calling address. */
+ kDNSServiceType_RT = 21, /* Router. */
+ kDNSServiceType_NSAP = 22, /* NSAP address. */
+ kDNSServiceType_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */
+ kDNSServiceType_SIG = 24, /* Security signature. */
+ kDNSServiceType_KEY = 25, /* Security key. */
+ kDNSServiceType_PX = 26, /* X.400 mail mapping. */
+ kDNSServiceType_GPOS = 27, /* Geographical position (withdrawn). */
+ kDNSServiceType_AAAA = 28, /* IPv6 Address. */
+ kDNSServiceType_LOC = 29, /* Location Information. */
+ kDNSServiceType_NXT = 30, /* Next domain (security). */
+ kDNSServiceType_EID = 31, /* Endpoint identifier. */
+ kDNSServiceType_NIMLOC = 32, /* Nimrod Locator. */
+ kDNSServiceType_SRV = 33, /* Server Selection. */
+ kDNSServiceType_ATMA = 34, /* ATM Address */
+ kDNSServiceType_NAPTR = 35, /* Naming Authority PoinTeR */
+ kDNSServiceType_KX = 36, /* Key Exchange */
+ kDNSServiceType_CERT = 37, /* Certification record */
+ kDNSServiceType_A6 = 38, /* IPv6 Address (deprecated) */
+ kDNSServiceType_DNAME = 39, /* Non-terminal DNAME (for IPv6) */
+ kDNSServiceType_SINK = 40, /* Kitchen sink (experimental) */
+ kDNSServiceType_OPT = 41, /* EDNS0 option (meta-RR) */
+ kDNSServiceType_APL = 42, /* Address Prefix List */
+ kDNSServiceType_DS = 43, /* Delegation Signer */
+ kDNSServiceType_SSHFP = 44, /* SSH Key Fingerprint */
+ kDNSServiceType_IPSECKEY = 45, /* IPSECKEY */
+ kDNSServiceType_RRSIG = 46, /* RRSIG */
+ kDNSServiceType_NSEC = 47, /* Denial of Existence */
+ kDNSServiceType_DNSKEY = 48, /* DNSKEY */
+ kDNSServiceType_DHCID = 49, /* DHCP Client Identifier */
+ kDNSServiceType_NSEC3 = 50, /* Hashed Authenticated Denial of Existence */
+ kDNSServiceType_NSEC3PARAM = 51, /* Hashed Authenticated Denial of Existence */
+
+ kDNSServiceType_HIP = 55, /* Host Identity Protocol */
+
+ kDNSServiceType_SPF = 99, /* Sender Policy Framework for E-Mail */
+ kDNSServiceType_UINFO = 100, /* IANA-Reserved */
+ kDNSServiceType_UID = 101, /* IANA-Reserved */
+ kDNSServiceType_GID = 102, /* IANA-Reserved */
+ kDNSServiceType_UNSPEC = 103, /* IANA-Reserved */
+
+ kDNSServiceType_TKEY = 249, /* Transaction key */
+ kDNSServiceType_TSIG = 250, /* Transaction signature. */
+ kDNSServiceType_IXFR = 251, /* Incremental zone transfer. */
+ kDNSServiceType_AXFR = 252, /* Transfer zone of authority. */
+ kDNSServiceType_MAILB = 253, /* Transfer mailbox records. */
+ kDNSServiceType_MAILA = 254, /* Transfer mail agent records. */
+ kDNSServiceType_ANY = 255 /* Wildcard match. */
};
/* possible error code values */
*
* The servicename may be up to 63 bytes of UTF-8 text (not counting the C-String
* terminating NULL at the end). The regtype is of the form _service._tcp or
- * _service._udp, where the "service" part is 1-14 characters, which may be
+ * _service._udp, where the "service" part is 1-15 characters, which may be
* letters, digits, or hyphens. The domain part of the three-part name may be
* any legal domain, providing that the resulting servicename+regtype+domain
* name does not exceed 256 bytes.
* accomplish this by inspecting the interfaceIndex of each service reported
* to their DNSServiceBrowseReply() callback function, and discarding those
* where the interface index is not kDNSServiceInterfaceIndexLocalOnly.
+ *
+ * kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord,
+ * and Resolve operations. It should not be used in other DNSService APIs.
+ *
+ * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceBrowse or
+ * DNSServiceQueryRecord, it restricts the operation to P2P.
+ *
+ * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceResolve, it is
+ * mapped internally to kDNSServiceInterfaceIndexAny, because resolving
+ * a P2P service may create and/or enable an interface whose index is not
+ * known a priori. The resolve callback will indicate the index of the
+ * interface via which the service can be accessed.
+ *
+ * If applications pass kDNSServiceInterfaceIndexAny to DNSServiceBrowse
+ * or DNSServiceQueryRecord, the operation will also include P2P. In this
+ * case, if a service instance or the record being queried is found over P2P,
+ * the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P as the
+ * interface index.
*/
#define kDNSServiceInterfaceIndexAny 0
#define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1)
#define kDNSServiceInterfaceIndexUnicast ((uint32_t)-2)
+#define kDNSServiceInterfaceIndexP2P ((uint32_t)-3)
typedef uint32_t DNSServiceFlags;
typedef uint32_t DNSServiceProtocol;
*
* regtype: The service type followed by the protocol, separated by a dot
* (e.g. "_ftp._tcp"). The service type must be an underscore, followed
- * by 1-14 characters, which may be letters, digits, or hyphens.
+ * by 1-15 characters, which may be letters, digits, or hyphens.
* The transport protocol must be "_tcp" or "_udp". New service types
* should be registered at <http://www.dns-sd.org/ServiceTypes.html>.
*
* % dns-sd -B _test._tcp,HasFeatureA # finds "Better" and "Best"
* % dns-sd -B _test._tcp,HasFeatureB # finds only "Best"
*
+ * Subtype labels may be up to 63 bytes long, and may contain any eight-
+ * bit byte values, including zero bytes. However, due to the nature of
+ * using a C-string-based API, conventional DNS escaping must be used for
+ * dots ('.'), commas (','), backslashes ('\') and zero bytes, as shown below:
+ *
+ * % dns-sd -R Test '_test._tcp,s\.one,s\,two,s\\three,s\000four' local 123
+ *
* domain: If non-NULL, specifies the domain on which to advertise the service.
* Most applications will not specify a domain, instead automatically
* registering in the default domain(s).
const char *regtype,
const char *domain, /* may be NULL */
const char *host, /* may be NULL */
- uint16_t port,
+ uint16_t port, /* In network byte order */
uint16_t txtLen,
const void *txtRecord, /* may be NULL */
DNSServiceRegisterReply callBack, /* may be NULL */
DNSServiceErrorType errorCode,
const char *fullname,
const char *hosttarget,
- uint16_t port,
+ uint16_t port, /* In network byte order */
uint16_t txtLen,
const unsigned char *txtRecord,
void *context
* unlikely to be of any use anyway. Similarly, if this host has no routable
* IPv4 address, the call will not try to look up IPv4 addresses for "hostname".
*
- * * If "hostname" is a link-local multicast DNS hostname (i.e. a ".local." name)
- * but this host has no IPv6 address of any kind, then it will not try to look
- * up IPv6 addresses for "hostname". Similarly, if this host has no IPv4 address
- * of any kind, the call will not try to look up IPv4 addresses for "hostname".
- *
* hostname: The fully qualified domain name of the host to be queried for.
*
* callBack: The function to be called when the query succeeds or fails asynchronously.
/* DNSServiceNATPortMappingCreate
*
* Request a port mapping in the NAT gateway, which maps a port on the local machine
- * to an external port on the NAT.
+ * to an external port on the NAT. The NAT should support either the NAT-PMP or the UPnP IGD
+ * protocol for this API to create a successful mapping.
*
* The port mapping will be renewed indefinitely until the client process exits, or
* explicitly terminates the port mapping request by calling DNSServiceRefDeallocate().
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 */
+ uint16_t internalPort, /* In network byte order */
+ uint16_t externalPort, /* In network byte order and may be different than the requested port */
+ uint32_t ttl, /* may be different than the requested ttl */
void *context
);
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
);
const void **value
);
-#ifdef __APPLE_API_PRIVATE
-
+#if _DNS_SD_LIBDISPATCH
/*
- * Mac OS X specific functionality
- * 3rd party clients of this API should not depend on future support or availability of this routine
- */
+* DNSServiceSetDispatchQueue
+*
+* Allows you to schedule a DNSServiceRef on a serial dispatch queue for receiving asynchronous
+* callbacks. It's the clients responsibility to ensure that the provided dispatch queue is running.
+*
+* A typical application that uses CFRunLoopRun or dispatch_main on its main thread will
+* usually schedule DNSServiceRefs on its main queue (which is always a serial queue)
+* using "DNSServiceSetDispatchQueue(sdref, dispatch_get_main_queue());"
+*
+* If there is any error during the processing of events, the application callback will
+* be called with an error code. For shared connections, each subordinate DNSServiceRef
+* will get its own error callback. Currently these error callbacks only happen
+* if the mDNSResponder daemon is manually terminated or crashes, and the error
+* code in this case is kDNSServiceErr_ServiceNotRunning. The application must call
+* DNSServiceRefDeallocate to free the DNSServiceRef when it gets such an error code.
+* These error callbacks are rare and should not normally happen on customer machines,
+* but application code should be written defensively to handle such error callbacks
+* gracefully if they occur.
+*
+* After using DNSServiceSetDispatchQueue on a DNSServiceRef, calling DNSServiceProcessResult
+* on the same DNSServiceRef will result in undefined behavior and should be avoided.
+*
+* Once the application successfully schedules a DNSServiceRef on a serial dispatch queue using
+* DNSServiceSetDispatchQueue, it cannot remove the DNSServiceRef from the dispatch queue, or use
+* DNSServiceSetDispatchQueue a second time to schedule the DNSServiceRef onto a different serial dispatch
+* queue. Once scheduled onto a dispatch queue a DNSServiceRef will deliver events to that queue until
+* the application no longer requires that operation and terminates it using DNSServiceRefDeallocate.
+*
+* service: DNSServiceRef that was allocated and returned to the application, when the
+* application calls one of the DNSService API.
+*
+* queue: dispatch queue where the application callback will be scheduled
+*
+* return value: Returns kDNSServiceErr_NoError on success.
+* Returns kDNSServiceErr_NoMemory if it cannot create a dispatch source
+* Returns kDNSServiceErr_BadParam if the service param is invalid or the
+* queue param is invalid
+*/
+
+DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
+ (
+ DNSServiceRef service,
+ dispatch_queue_t queue
+ );
+#endif //_DNS_SD_LIBDISPATCH
-/* DNSServiceSetDefaultDomainForUser()
- *
- * Set the default domain for the caller's UID. Future browse and registration
- * calls by this user that do not specify an explicit domain will browse and
- * register in this wide-area domain in addition to .local. In addition, this
- * domain will be returned as a Browse domain via domain enumeration calls.
- *
- * Parameters:
- *
- * flags: Pass kDNSServiceFlagsAdd to add a domain for a user. Call without
- * this flag set to clear a previously added domain.
- *
- * domain: The domain to be used for the caller's UID.
- *
- * return value: Returns kDNSServiceErr_NoError on success, otherwise returns
- * an error code indicating the error that occurred.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser
- (
- DNSServiceFlags flags,
- const char *domain
- );
+#ifdef __APPLE_API_PRIVATE
-/* Symbol defined to tell System Configuration Framework where to look in the Dynamic Store
- * for the list of PrivateDNS domains that need to be handed off to mDNSResponder
- * (the complete key is "State:/Network/PrivateDNS")
- */
#define kDNSServiceCompPrivateDNS "PrivateDNS"
#define kDNSServiceCompMulticastDNS "MulticastDNS"
.\" See the License for the specific language governing permissions and
.\" limitations under the License.
.\"
-.\" $Log: dnsextd.8,v $
-.\" Revision 1.2 2006/08/14 23:24:56 cheshire
-.\" Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-.\"
-.\" Revision 1.1 2004/08/15 18:49:18 cheshire
-.\" <rdar://problem/3763030> No man page for dnsextd
-.\"
-.\"
-.\"
.Dd August 2004 \" Date
.Dt dnsextd 8 \" Document Title
.Os Darwin \" Operating System
* 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.
+ */
+
+#if __APPLE__
+// In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated”
+// error, which prevents compilation because we build with "-Werror".
+// Since this is supposed to be portable cross-platform code, we don't care that daemon is
+// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
+#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
+#endif
- 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
-
-Revision 1.87 2007/12/17 23:34:50 cheshire
-Don't need to set ptr to result of DNSDigest_SignMessage -- ptr is updated anyway (it's passed by reference)
-
-Revision 1.86 2007/12/13 20:22:34 cheshire
-Got rid of redundant SameResourceRecord() routine; replaced calls to this
-with calls to IdenticalResourceRecord() which does exactly the same thing.
-
-Revision 1.85 2007/12/01 00:30:36 cheshire
-Fixed compile warning: declaration of 'time' shadows a global declaration
-
-Revision 1.84 2007/10/24 18:19:37 cheshire
-Fixed header byte order bug sending update responses
-
-Revision 1.83 2007/10/17 22:52:26 cheshire
-Get rid of unused mDNS_UpdateLLQs()
-
-Revision 1.82 2007/09/27 17:42:49 cheshire
-Fix naming: for consistency, "kDNSFlag1_RC" should be "kDNSFlag1_RC_Mask"
-
-Revision 1.81 2007/09/21 21:12:37 cheshire
-DNSDigest_SignMessage does not need separate "mDNSu16 *numAdditionals" parameter
-
-Revision 1.80 2007/09/18 19:09:02 cheshire
-<rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
-
-Revision 1.79 2007/07/11 02:59:58 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-Add AutoTunnel parameter to mDNS_SetSecretForDomain
-
-Revision 1.78 2007/06/20 01:10:13 cheshire
-<rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
-
-Revision 1.77 2007/05/15 21:57:17 cheshire
-<rdar://problem/4608220> Use dnssd_SocketValid(x) macro instead of just
-assuming that all negative values (or zero!) are invalid socket numbers
-
-Revision 1.76 2007/05/01 23:53:26 cheshire
-<rdar://problem/5175318> dnsextd should refuse updates without attached lease
-
-Revision 1.75 2007/05/01 00:18:12 cheshire
-Use "-launchd" instead of "-d" when starting via launchd
-(-d sets foreground mode, which writes errors to stderr, which is ignored when starting via launchd)
-
-Revision 1.74 2007/04/26 00:35:16 cheshire
-<rdar://problem/5140339> uDNS: Domain discovery not working over VPN
-Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server
-inside the firewall may give answers where a public one gives none, and vice versa.)
-
-Revision 1.73 2007/04/22 06:02:03 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.72 2007/04/05 22:55:37 cheshire
-<rdar://problem/5077076> Records are ending up in Lighthouse without expiry information
-
-Revision 1.71 2007/04/05 19:43:56 cheshire
-Added ProgramName and comment about '-d' option
-
-Revision 1.70 2007/04/05 18:34:40 cheshire
-<rdar://problem/4838930> dnsextd gives "bind - Address already in use" error
-
-Revision 1.69 2007/03/28 21:14:08 cheshire
-The rrclass field of an OPT pseudo-RR holds the sender's UDP payload size
-
-Revision 1.68 2007/03/28 18:20:50 cheshire
-Textual tidying
-
-Revision 1.67 2007/03/21 00:30:07 cheshire
-<rdar://problem/4789455> Multiple errors in DNameList-related code
-
-Revision 1.66 2007/03/20 17:07:16 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.65 2007/02/07 19:32:00 cheshire
-<rdar://problem/4980353> All mDNSResponder components should contain version strings in SCCS-compatible format
-
-Revision 1.64 2007/01/20 01:43:26 cheshire
-<rdar://problem/4058383> Should not write log messages to /dev/console
-
-Revision 1.63 2007/01/20 01:31:56 cheshire
-Update comments
-
-Revision 1.62 2007/01/17 22:06:03 cheshire
-Replace duplicated literal constant "{ { 0 } }" with symbol "zeroIPPort"
-
-Revision 1.61 2007/01/05 08:30:54 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.60 2007/01/05 08:07:29 cheshire
-Remove unnecessary dummy udsserver_default_reg_domain_changed() routine
-
-Revision 1.59 2007/01/05 05:46:47 cheshire
-Remove unnecessary dummy udsserver_automatic_browse_domain_changed() routine
-
-Revision 1.58 2007/01/04 23:11:54 cheshire
-udsserver_default_browse_domain_changed renamed to udsserver_automatic_browse_domain_changed
-
-Revision 1.57 2007/01/04 01:41:48 cheshire
-Use _dns-update-tls/_dns-query-tls/_dns-llq-tls instead of creating a new "_tls" subdomain
-
-Revision 1.56 2006/12/22 20:59:51 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.55 2006/11/30 23:08:39 herscher
-<rdar://problem/4765644> uDNS: Sync up with Lighthouse changes for Private DNS
-
-Revision 1.54 2006/11/18 05:01:33 cheshire
-Preliminary support for unifying the uDNS and mDNS code,
-including caching of uDNS answers
-
-Revision 1.53 2006/11/17 23:55:09 cheshire
-<rdar://problem/4842494> dnsextd byte-order bugs on Intel
-
-Revision 1.52 2006/11/17 04:27:51 cheshire
-<rdar://problem/4842494> dnsextd byte-order bugs on Intel
-
-Revision 1.51 2006/11/17 03:50:18 cheshire
-Add debugging loggin in SendPacket and UDPServerTransaction
-
-Revision 1.50 2006/11/17 03:48:57 cheshire
-<rdar://problem/4842493> dnsextd replying on wrong port
-
-Revision 1.49 2006/11/03 06:12:44 herscher
-Make sure all buffers passed to GetRRDisplayString_rdb are of length MaxMsg
-
-Revision 1.48 2006/10/20 19:18:35 cheshire
-<rdar://problem/4669228> dnsextd generates bogus SRV record with null target
-
-Revision 1.47 2006/10/20 05:43:51 herscher
-LookupLLQ() needs to match on the port number when looking up the LLQ
-
-Revision 1.46 2006/10/11 22:56:07 herscher
-Tidy up the implementation of ZoneHandlesName
-
-Revision 1.45 2006/08/22 03:28:57 herscher
-<rdar://problem/4678717> Long-lived queries aren't working well in TOT.
-
-Revision 1.44 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.43 2006/07/20 19:53:33 mkrochma
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-More fixes for private DNS
-
-Revision 1.42 2006/07/05 22:48:19 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-
-*/
-
-#include "dnsextd.h"
-#include "../mDNSShared/uds_daemon.h"
-#include "../mDNSShared/dnssd_ipc.h"
-#include "../mDNSCore/uDNS.h"
-#include "../mDNSShared/DebugServices.h"
#include <signal.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
+#if __APPLE__
+#undef daemon
+extern int daemon(int, int);
+#endif
+
// Solaris doesn't have daemon(), so we define it here
#ifdef NOT_HAVE_DAEMON
#include "../mDNSPosix/mDNSUNP.h" // For daemon()
#endif // NOT_HAVE_DAEMON
+#include "dnsextd.h"
+#include "../mDNSShared/uds_daemon.h"
+#include "../mDNSShared/dnssd_ipc.h"
+#include "../mDNSCore/uDNS.h"
+#include "../mDNSShared/DebugServices.h"
+
// Compatibility workaround
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
self->llq_addr.sin_addr.s_addr = zerov4Addr.NotAnInteger;
self->llq_addr.sin_port = ( self->llq_port.NotAnInteger ) ? self->llq_port.NotAnInteger : DNSEXTPort.NotAnInteger;
- self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 );
- require_action( dnssd_SocketValid(self->llq_tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
-
+ if (self->llq_addr.sin_port == self->addr.sin_port)
+ {
+ self->llq_tcpsd = self->tcpsd;
+ self->llq_udpsd = self->udpsd;
+ }
+ else
+ {
+ self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 );
+ require_action( dnssd_SocketValid(self->llq_tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
+
#if defined(SO_REUSEADDR)
- err = setsockopt(self->llq_tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
- require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_tcpsd" ) );
+ err = setsockopt(self->llq_tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
+ require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_tcpsd" ) );
#endif
-
- err = bind( self->llq_tcpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) );
- require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_tcpsd" ) );
-
- err = listen( self->llq_tcpsd, LISTENQ );
- require_action( !err, exit, LogErr( "SetupSockets", "listen" ) );
-
- self->llq_udpsd = socket( AF_INET, SOCK_DGRAM, 0 );
- require_action( dnssd_SocketValid(self->llq_udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
-
+
+ err = bind( self->llq_tcpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) );
+ require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_tcpsd" ) );
+
+ err = listen( self->llq_tcpsd, LISTENQ );
+ require_action( !err, exit, LogErr( "SetupSockets", "listen" ) );
+
+ self->llq_udpsd = socket( AF_INET, SOCK_DGRAM, 0 );
+ require_action( dnssd_SocketValid(self->llq_udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
+
#if defined(SO_REUSEADDR)
- err = setsockopt(self->llq_udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
- require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_udpsd" ) );
+ err = setsockopt(self->llq_udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
+ require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_udpsd" ) );
#endif
-
- err = bind(self->llq_udpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) );
- require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_udpsd" ) );
+
+ err = bind(self->llq_udpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) );
+ require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_udpsd" ) );
+ }
// set up Unix domain socket pair for LLQ polling thread to signal main thread that a change to the zone occurred
mDNSBool DeleteAllRRSets = mDNSfalse, DeleteOneRRSet = mDNSfalse, DeleteOneRR = mDNSfalse;
ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
- if (!ptr) { Log("UpdateLeaseTable: GetLargeResourceRecord returned NULL"); goto cleanup; }
+ if (!ptr || lcr.r.resrec.RecordType == kDNSRecordTypePacketNegative) { Log("UpdateLeaseTable: GetLargeResourceRecord failed"); goto cleanup; }
bucket = rr->namehash % d->nbuckets;
rptr = &d->table[bucket];
{
LargeCacheRecord lcr;
ptr = GetLargeResourceRecord(NULL, &request->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
- if (lcr.r.resrec.rroriginalttl) adds++; else dels++;
+ if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rroriginalttl) adds++; else dels++;
}
HdrHToN(request);
if (adds && !lease)
{
ansptr = GetLargeResourceRecord(NULL, &reply->msg, ansptr, end, 0, kDNSRecordTypePacketAns, &lcr);
if (!ansptr) { Log("AnswerQuestions: GetLargeResourceRecord returned NULL"); goto end; }
- if (lcr.r.resrec.rrtype != e->type || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->name))
- {
- Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d. Discarding",
- lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->name.c, e->type);
- }
- else
+ if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative)
{
- CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->name);
- if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; }
- cr->next = AnswerList;
- AnswerList = cr;
+ if (lcr.r.resrec.rrtype != e->type || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->name))
+ {
+ Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d. Discarding",
+ lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->name.c, e->type);
+ }
+ else
+ {
+ CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->name);
+ if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; }
+ cr->next = AnswerList;
+ AnswerList = cr;
+ }
}
}
{
aptr = GetLargeResourceRecord(NULL, &pkt->msg, aptr, end, 0, kDNSRecordTypePacketAdd, &opt);
if (!aptr) { Log("Malformatted LLQ from %s: could not get Additional record %d", addr, i); goto end; }
- if (opt.r.resrec.rrtype == kDNSType_OPT) break;
+ if (opt.r.resrec.RecordType != kDNSRecordTypePacketNegative && opt.r.resrec.rrtype == kDNSType_OPT) break;
}
// validate OPT
}
}
- hasTSIG = ( ptr && lcr.r.resrec.rrtype == kDNSType_TSIG );
+ hasTSIG = ( ptr && lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rrtype == kDNSType_TSIG );
}
else
{
Log("Using default file descriptor resource limit");
}
- if (!strcasecmp(argv[1], "-launchd"))
+ if (argc > 1 && !strcasecmp(argv[1], "-launchd"))
{
Log("started_via_launchd");
started_via_launchd = 1;
const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
const mDNSAddr *const dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID iid)
{ ( void ) m; ( void ) msg; ( void ) end; ( void ) srcaddr; ( void ) srcport; ( void ) dstaddr; ( void ) dstport; ( void ) iid; }
-DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port)
- { ( void ) m; ( void ) d; ( void ) interface; ( void ) addr; ( void ) port; return(NULL); }
+DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped)
+ { ( void ) m; ( void ) d; ( void ) interface; ( void ) addr; ( void ) port; ( void ) scoped; return(NULL); }
void mDNS_AddSearchDomain(const domainname *const domain) { (void)domain; }
void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext)
{ ( void ) m; ( void ) fqdn; ( void ) StatusCallback; ( void ) StatusContext; }
const domainname *domain, const domainname *keyname, const char *b64keydata, mDNSBool AutoTunnel)
{ ( void ) m; ( void ) info; ( void ) domain; ( void ) keyname; ( void ) b64keydata; ( void ) AutoTunnel; return 0; }
mStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question) { ( void ) m; ( void ) question; return 0; }
+void TriggerEventCompletion(void);
+void TriggerEventCompletion() {}
mDNS mDNSStorage;
* 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: dnsextd.h,v $
-Revision 1.5 2007/03/20 17:07:16 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.4 2006/12/22 20:59:51 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.3 2006/11/18 05:01:33 cheshire
-Preliminary support for unifying the uDNS and mDNS code,
-including caching of uDNS answers
-
-Revision 1.2 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2006/07/06 00:09:05 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-
-
*/
* 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: 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
-
-Revision 1.3 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2006/07/06 20:41:14 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-Use derived filename "dnsextd_parser.h" instead of "dnsextd_parser.y.h"
-
-Revision 1.1 2006/07/06 00:09:05 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-
*/
%{
* 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: 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
-
-Revision 1.7 2007/01/17 17:38:13 cheshire
-Need to include stdlib.h for malloc/free
-
-Revision 1.6 2006/12/22 20:59:51 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.5 2006/10/20 05:47:09 herscher
-Set the DNSZone pointer to NULL in ParseConfig() before parsing the configuration file.
-
-Revision 1.4 2006/08/16 00:35:39 mkrochma
-<rdar://problem/4386944> Get rid of NotAnInteger references
-
-Revision 1.3 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2006/07/14 02:03:37 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-private_port and llq_port should use htons, not htonl
-
-Revision 1.1 2006/07/06 00:09:05 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-
*/
%{
|
PRIVATE PORT NUMBER
{
- ( ( DaemonInfo* ) context )->private_port = mDNSOpaque16fromIntVal( NUMBER );
+ ( ( DaemonInfo* ) context )->private_port = mDNSOpaque16fromIntVal( $3 );
}
|
LLQ PORT NUMBER
{
- ( ( DaemonInfo* ) context )->llq_port = mDNSOpaque16fromIntVal( NUMBER );
+ ( ( DaemonInfo* ) context )->llq_port = mDNSOpaque16fromIntVal( $3 );
}
;
* 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.
-
- 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
-
-Revision 1.17 2007/10/02 19:36:04 cheshire
-<rdar://problem/5516444> TXTRecordGetValuePtr should be case-insenstive
-
-Revision 1.16 2007/09/18 19:09:02 cheshire
-<rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
-
-Revision 1.15 2007/07/28 00:00:43 cheshire
-Renamed CompileTimeAssertionCheck structure for consistency with others
-
-Revision 1.14 2007/03/20 17:07:16 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.13 2007/02/27 00:25:03 cheshire
-<rdar://problem/5010640> DNSServiceConstructFullName() doesn't handle empty string for instance name
-
-Revision 1.12 2007/02/07 19:32:00 cheshire
-<rdar://problem/4980353> All mDNSResponder components should contain version strings in SCCS-compatible format
-
-Revision 1.11 2006/08/14 23:05:53 cheshire
-Added "tab-width" emacs header line
-
-Revision 1.10 2005/04/06 02:06:56 shersche
-Add DNSSD_API macro to TXTRecord API calls
-
-Revision 1.9 2004/10/06 02:22:19 cheshire
-Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
-
-Revision 1.8 2004/10/01 22:15:55 rpantos
-rdar://problem/3824265: Replace APSL in client lib with BSD license.
-
-Revision 1.7 2004/06/26 03:16:34 shersche
-clean up warning messages on Win32 platform
-
-Submitted by: herscher
-
-Revision 1.6 2004/06/12 01:09:45 cheshire
-To be callable from the broadest range of clients on Windows (e.g. Visual Basic, C#, etc.)
-API routines have to be declared as "__stdcall", instead of the C default, "__cdecl"
-
-Revision 1.5 2004/05/25 18:29:33 cheshire
-Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c,
-so that it's also accessible to dnssd_clientshim.c (single address space) clients.
-
-Revision 1.4 2004/05/25 17:08:55 cheshire
-Fix compiler warning (doesn't make sense for function return type to be const)
-
-Revision 1.3 2004/05/21 21:41:35 cheshire
-Add TXT record building and parsing APIs
-
-Revision 1.2 2004/05/20 22:22:21 cheshire
-Enable code that was bracketed by "#if 0"
-
-Revision 1.1 2004/03/12 21:30:29 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
*/
#include <stdlib.h>
* The shim is responsible for two main things:
* - converting string parameters between C string format and native DNS format,
* - and for allocating and freeing memory.
-
- Change History (most recent first):
-
-$Log: dnssd_clientshim.c,v $
-Revision 1.16 2007/11/30 20:12:24 cheshire
-Removed unused "badparam:" label
-
-Revision 1.15 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
-
-Revision 1.14 2007/07/17 19:15:26 cheshire
-<rdar://problem/5297410> Crash in DNSServiceRegister() in dnssd_clientshim.c
-
-Revision 1.13 2007/01/04 20:57:49 cheshire
-Rename ReturnCNAME to ReturnIntermed (for ReturnIntermediates)
-
-Revision 1.12 2006/12/19 22:43:55 cheshire
-Fix compiler warnings
-
-Revision 1.11 2006/10/27 01:30:23 cheshire
-Need explicitly to set ReturnIntermed = mDNSfalse
-
-Revision 1.10 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.9 2006/07/24 23:45:55 cheshire
-<rdar://problem/4605276> DNSServiceReconfirmRecord() should return error code
-
-Revision 1.8 2004/12/16 20:47:34 cheshire
-<rdar://problem/3324626> Cache memory management improvements
-
-Revision 1.7 2004/12/10 04:08:43 cheshire
-Added comments about autoname and autorename
-
-Revision 1.6 2004/10/19 21:33:22 cheshire
-<rdar://problem/3844991> Cannot resolve non-local registrations using the mach API
-Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name
-doesn't force multicast unless you set this flag to indicate explicitly that this is what you want
-
-Revision 1.5 2004/09/21 23:29:51 cheshire
-<rdar://problem/3680045> DNSServiceResolve should delay sending packets
-
-Revision 1.4 2004/09/17 01:08:55 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.3 2004/05/27 06:26:31 cheshire
-Add shim for DNSServiceQueryRecord()
-
-Revision 1.2 2004/05/20 18:41:24 cheshire
-Fix build broken by removal of 'kDNSServiceFlagsRemove' from dns_sd.h
-
-Revision 1.1 2004/03/12 21:30:29 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
*/
#include "dns_sd.h" // Defines the interface to the client layer above
x->qTXT.ExpectUnique = mDNStrue;
x->qTXT.ForceMCast = mDNSfalse;
x->qTXT.ReturnIntermed = mDNSfalse;
+ x->qTXT.SuppressUnusable = mDNSfalse;
x->qTXT.QuestionCallback = FoundServiceInfo;
x->qTXT.QuestionContext = x;
x->q.ExpectUnique = mDNSfalse;
x->q.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0;
x->q.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
+ x->q.SuppressUnsable = (flags & kDNSServiceFlagsSuppressUnusable) != 0;
x->q.QuestionCallback = DNSServiceQueryRecordResponse;
x->q.QuestionContext = x;
return(err);
}
+//*************************************************************************************************************
+// DNSServiceGetAddrInfo
+
+static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP *op)
+ {
+ mDNS_DirectOP_GetAddrInfo *x = (mDNS_DirectOP_GetAddrInfo*)op;
+ if (x->aQuery) DNSServiceRefDeallocate(x->aQuery);
+ mDNSPlatformMemFree(x);
+ }
+
+static void DNSSD_API DNSServiceGetAddrInfoResponse(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inFullName,
+ uint16_t inRRType,
+ uint16_t inRRClass,
+ uint16_t inRDLen,
+ const void * inRData,
+ uint32_t inTTL,
+ void * inContext )
+ {
+ mDNS_DirectOP_GetAddrInfo * x = (mDNS_DirectOP_GetAddrInfo*)inContext;
+ struct sockaddr_in sa4;
+
+ mDNSPlatformMemZero(&sa4, sizeof(sa4));
+ if (inErrorCode == kDNSServiceErr_NoError && inRRType == kDNSServiceType_A)
+ {
+ sa4.sin_family = AF_INET;
+ mDNSPlatformMemCopy(&sa4.sin_addr.s_addr, inRData, 4);
+ }
+
+ x->callback((DNSServiceRef)x, inFlags, inInterfaceIndex, inErrorCode, inFullName,
+ (const struct sockaddr *) &sa4, inTTL, x->context);
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo(
+ DNSServiceRef * outRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceProtocol inProtocol,
+ const char * inHostName,
+ DNSServiceGetAddrInfoReply inCallback,
+ void * inContext )
+ {
+ const char * errormsg = "Unknown";
+ DNSServiceErrorType err;
+ mDNS_DirectOP_GetAddrInfo * x;
+
+ // Allocate memory, and handle failure
+ x = (mDNS_DirectOP_GetAddrInfo *)mDNSPlatformMemAllocate(sizeof(*x));
+ if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
+
+ // Set up object
+ x->disposefn = DNSServiceGetAddrInfoDispose;
+ x->callback = inCallback;
+ x->context = inContext;
+ x->aQuery = mDNSNULL;
+
+ // Start the query.
+ // (It would probably be more efficient to code this using mDNS_StartQuery directly,
+ // instead of wrapping DNSServiceQueryRecord, which then unnecessarily allocates
+ // more memory and then just calls through to mDNS_StartQuery. -- SC June 2010)
+ err = DNSServiceQueryRecord(&x->aQuery, inFlags, inInterfaceIndex, inHostName, kDNSServiceType_A,
+ kDNSServiceClass_IN, DNSServiceGetAddrInfoResponse, x);
+ if (err) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP*)x); errormsg = "DNSServiceQueryRecord"; goto fail; }
+
+ *outRef = (DNSServiceRef)x;
+ return(mStatus_NoError);
+
+fail:
+ LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName, inProtocol, errormsg, err);
+ return(err);
+ }
+
//*************************************************************************************************************
// DNSServiceReconfirmRecord
* 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.
-
- 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
-
-Revision 1.101 2008/02/20 21:18:21 cheshire
-<rdar://problem/5708953> DNSServiceGetAddrInfo doesn't set the scope ID of returned IPv6 link local addresses
-
-Revision 1.100 2007/11/02 17:56:37 cheshire
-<rdar://problem/5565787> Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails)
-Wrap hack code in "#if APPLE_OSX_mDNSResponder" since (as far as we know right now)
-we don't want to do this on 64-bit Linux, Solaris, etc.
-
-Revision 1.99 2007/11/02 17:29:40 cheshire
-<rdar://problem/5565787> Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails)
-To get 64-bit code that works, we need to NOT use the standard CMSG_* macros
-
-Revision 1.98 2007/11/01 19:52:43 cheshire
-Wrap debugging messages in "#if DEBUG_64BIT_SCM_RIGHTS"
-
-Revision 1.97 2007/11/01 19:45:55 cheshire
-Added "DEBUG_64BIT_SCM_RIGHTS" debugging code
-See <rdar://problem/5565787> Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails)
-
-Revision 1.96 2007/11/01 15:59:33 cheshire
-umask not being set and restored properly in USE_NAMED_ERROR_RETURN_SOCKET code
-(no longer used on OS X, but relevant for other platforms)
-
-Revision 1.95 2007/10/31 20:07:16 cheshire
-<rdar://problem/5541498> Set SO_NOSIGPIPE on client socket
-Refinement: the cleanup code still needs to close listenfd when necesssary
-
-Revision 1.94 2007/10/15 22:34:27 cheshire
-<rdar://problem/5541498> Set SO_NOSIGPIPE on client socket
-
-Revision 1.93 2007/10/10 00:48:54 cheshire
-<rdar://problem/5526379> Daemon spins in an infinite loop when it doesn't get the control message it's expecting
-
-Revision 1.92 2007/10/06 03:44:44 cheshire
-Testing code for <rdar://problem/5526374> kqueue does not get a kevent to wake it up when a control message arrives on a socket
-
-Revision 1.91 2007/10/04 20:53:59 cheshire
-Improved debugging message when sendmsg fails
-
-Revision 1.90 2007/09/30 00:09:27 cheshire
-<rdar://problem/5492315> Pass socket fd via SCM_RIGHTS sendmsg instead of using named UDS in the filesystem
-
-Revision 1.89 2007/09/19 23:53:12 cheshire
-Fixed spelling mistake in comment
-
-Revision 1.88 2007/09/07 23:18:27 cheshire
-<rdar://problem/5467542> Change "client_context" to be an incrementing 64-bit counter
-
-Revision 1.87 2007/09/07 22:50:09 cheshire
-Added comment explaining moreptr field in DNSServiceOp structure
-
-Revision 1.86 2007/09/07 20:21:22 cheshire
-<rdar://problem/5462371> Make DNSSD library more resilient
-Add more comments explaining the moreptr/morebytes logic; don't allow DNSServiceRefSockFD or
-DNSServiceProcessResult for subordinate DNSServiceRefs created using kDNSServiceFlagsShareConnection
-
-Revision 1.85 2007/09/06 21:43:23 cheshire
-<rdar://problem/5462371> Make DNSSD library more resilient
-Allow DNSServiceRefDeallocate from within DNSServiceProcessResult callback
-
-Revision 1.84 2007/09/06 18:31:47 cheshire
-<rdar://problem/5462371> Make DNSSD library more resilient against client programming errors
-
-Revision 1.83 2007/08/28 20:45:45 cheshire
-Typo: ctrl_path needs to be 64 bytes, not 44 bytes
-
-Revision 1.82 2007/08/28 19:53:52 cheshire
-<rdar://problem/5437423> Bonjour failures when /tmp is not writable (e.g. when booted from installer disc)
-
-Revision 1.81 2007/07/27 00:03:20 cheshire
-Fixed compiler warnings that showed up now we're building optimized ("-Os")
-
-Revision 1.80 2007/07/23 22:12:53 cheshire
-<rdar://problem/5352299> Make mDNSResponder more defensive against malicious local clients
-
-Revision 1.79 2007/07/23 19:58:24 cheshire
-<rdar://problem/5351640> Library: Leak in DNSServiceRefDeallocate
-
-Revision 1.78 2007/07/12 20:42:27 cheshire
-<rdar://problem/5280735> If daemon is killed, return kDNSServiceErr_ServiceNotRunning
-to clients instead of kDNSServiceErr_Unknown
-
-Revision 1.77 2007/07/02 23:07:13 cheshire
-<rdar://problem/5308280> Reduce DNS-SD client syslog error messages
-
-Revision 1.76 2007/06/22 20:12:18 cheshire
-<rdar://problem/5277024> Leak in DNSServiceRefDeallocate
-
-Revision 1.75 2007/05/23 18:59:22 cheshire
-Remove unnecessary IPC_FLAGS_REUSE_SOCKET
-
-Revision 1.74 2007/05/22 18:28:38 cheshire
-Fixed compile errors in posix build
-
-Revision 1.73 2007/05/22 01:20:47 cheshire
-To determine current operation, need to check hdr->op, not sdr->op
-
-Revision 1.72 2007/05/22 01:07:42 cheshire
-<rdar://problem/3563675> API: Need a way to get version/feature information
-
-Revision 1.71 2007/05/18 23:55:22 cheshire
-<rdar://problem/4454655> Allow multiple register/browse/resolve operations to share single Unix Domain Socket
-
-Revision 1.70 2007/05/17 20:58:22 cheshire
-<rdar://problem/4647145> DNSServiceQueryRecord should return useful information with NXDOMAIN
-
-Revision 1.69 2007/05/16 16:58:27 cheshire
-<rdar://problem/4471320> Improve reliability of kDNSServiceFlagsMoreComing flag on multiprocessor machines
-As long as select indicates that data is waiting, loop within DNSServiceProcessResult delivering additional results
-
-Revision 1.68 2007/05/16 01:06:52 cheshire
-<rdar://problem/4471320> Improve reliability of kDNSServiceFlagsMoreComing flag on multiprocessor machines
-
-Revision 1.67 2007/05/15 21:57:16 cheshire
-<rdar://problem/4608220> Use dnssd_SocketValid(x) macro instead of just
-assuming that all negative values (or zero!) are invalid socket numbers
-
-Revision 1.66 2007/03/27 22:23:04 cheshire
-Add "dnssd_clientstub" prefix onto syslog messages
-
-Revision 1.65 2007/03/21 22:25:23 cheshire
-<rdar://problem/4172796> Remove client retry logic now that mDNSResponder uses launchd for its Unix Domain Socket
-
-Revision 1.64 2007/03/21 19:01:56 cheshire
-<rdar://problem/5078494> IPC code not 64-bit-savvy: assumes long=32bits, and short=16bits
-
-Revision 1.63 2007/03/12 21:48:21 cheshire
-<rdar://problem/5000162> Scary unlink errors in system.log
-Code was using memory after it had been freed
-
-Revision 1.62 2007/02/28 01:44:30 cheshire
-<rdar://problem/5027863> Byte order bugs in uDNS.c, uds_daemon.c, dnssd_clientstub.c
-
-Revision 1.61 2007/02/09 03:09:42 cheshire
-<rdar://problem/3869251> Cleanup: Stop returning kDNSServiceErr_Unknown so often
-<rdar://problem/4177924> API: Should return kDNSServiceErr_ServiceNotRunning
-
-Revision 1.60 2007/02/08 20:33:44 cheshire
-<rdar://problem/4985095> Leak on error path in DNSServiceProcessResult
-
-Revision 1.59 2007/01/05 08:30:55 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.58 2006/10/27 00:38:22 cheshire
-Strip accidental trailing whitespace from lines
-
-Revision 1.57 2006/09/30 01:06:54 cheshire
-Protocol field should be uint32_t
-
-Revision 1.56 2006/09/27 00:44:16 herscher
-<rdar://problem/4249761> API: Need DNSServiceGetAddrInfo()
-
-Revision 1.55 2006/09/26 01:52:01 herscher
-<rdar://problem/4245016> NAT Port Mapping API (for both NAT-PMP and UPnP Gateway Protocol)
-
-Revision 1.54 2006/09/21 21:34:09 cheshire
-<rdar://problem/4100000> Allow empty string name when using kDNSServiceFlagsNoAutoRename
-
-Revision 1.53 2006/09/07 04:43:12 herscher
-Fix compile error on Win32 platform by moving inclusion of syslog.h
-
-Revision 1.52 2006/08/15 23:04:21 mkrochma
-<rdar://problem/4090354> Client should be able to specify service name w/o callback
-
-Revision 1.51 2006/07/24 23:45:55 cheshire
-<rdar://problem/4605276> DNSServiceReconfirmRecord() should return error code
-
-Revision 1.50 2006/06/28 08:22:27 cheshire
-<rdar://problem/4605264> dnssd_clientstub.c needs to report unlink failures in syslog
-
-Revision 1.49 2006/06/28 07:58:59 cheshire
-Minor textual tidying
-
-*/
+ */
#include <errno.h>
#include <stdlib.h>
int len;
char * buffer;
DWORD err = WSAGetLastError();
+ (void) priority;
va_start( args, message );
len = _vscprintf( message, args ) + 1;
buffer = malloc( len * sizeof(char) );
// When using kDNSServiceFlagsShareConnection, there is one primary _DNSServiceOp_t, and zero or more subordinates
// For the primary, the 'next' field points to the first subordinate, and its 'next' field points to the next, and so on.
// For the primary, the 'primary' field is NULL; for subordinates the 'primary' field points back to the associated primary
+//
+// _DNS_SD_LIBDISPATCH is defined where libdispatch/GCD is available. This does not mean that the application will use the
+// DNSServiceSetDispatchQueue API. Hence any new code guarded with _DNS_SD_LIBDISPATCH should still be backwards compatible.
struct _DNSServiceRef_t
{
- DNSServiceOp *next; // For shared connection
- DNSServiceOp *primary; // For shared connection
- dnssd_sock_t sockfd; // Connected socket between client and daemon
- dnssd_sock_t validator; // Used to detect memory corruption, double disposals, etc.
- client_context_t uid; // For shared connection requests, each subordinate DNSServiceRef has its own ID,
+ DNSServiceOp *next; // For shared connection
+ DNSServiceOp *primary; // For shared connection
+ dnssd_sock_t sockfd; // Connected socket between client and daemon
+ dnssd_sock_t validator; // Used to detect memory corruption, double disposals, etc.
+ client_context_t uid; // For shared connection requests, each subordinate DNSServiceRef has its own ID,
// unique within the scope of the same shared parent DNSServiceRef
- uint32_t op; // request_op_t or reply_op_t
- uint32_t max_index; // Largest assigned record index - 0 if no additional records registered
- uint32_t logcounter; // Counter used to control number of syslog messages we write
- int *moreptr; // Set while DNSServiceProcessResult working on this particular DNSServiceRef
- ProcessReplyFn ProcessReply; // Function pointer to the code to handle received messages
- void *AppCallback; // Client callback function and context
- void *AppContext;
+ uint32_t op; // request_op_t or reply_op_t
+ uint32_t max_index; // Largest assigned record index - 0 if no additional records registered
+ uint32_t logcounter; // Counter used to control number of syslog messages we write
+ int *moreptr; // Set while DNSServiceProcessResult working on this particular DNSServiceRef
+ ProcessReplyFn ProcessReply; // Function pointer to the code to handle received messages
+ void *AppCallback; // Client callback function and context
+ void *AppContext;
+ DNSRecord *rec;
+#if _DNS_SD_LIBDISPATCH
+ dispatch_source_t disp_source;
+ dispatch_queue_t disp_queue;
+#endif
};
struct _DNSRecordRef_t
{
+ DNSRecord *recnext;
void *AppContext;
DNSServiceRegisterRecordReply AppCallback;
DNSRecordRef recref;
};
// Write len bytes. Return 0 on success, -1 on error
-static int write_all(dnssd_sock_t sd, char *buf, int len)
+static int write_all(dnssd_sock_t sd, char *buf, size_t len)
{
// Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
//if (send(sd, buf, len, MSG_WAITALL) != len) return -1;
while (len)
{
- ssize_t num_written = send(sd, buf, len, 0);
- if (num_written < 0 || num_written > len)
+ ssize_t num_written = send(sd, buf, (long)len, 0);
+ if (num_written < 0 || (size_t)num_written > len)
{
// Should never happen. If it does, it indicates some OS bug,
// or that the mDNSResponder daemon crashed (which should never happen).
- syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%d %d %s", sd, num_written, len,
+ #if !defined(__ppc__) && defined(SO_ISDEFUNCT)
+ int defunct;
+ socklen_t dlen = sizeof (defunct);
+ if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
+ syslog(LOG_WARNING, "dnssd_clientstub write_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+ if (!defunct)
+ syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
+ (long)num_written, (long)len,
+ (num_written < 0) ? dnssd_errno : 0,
+ (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
+ else
+ syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd);
+ #else
+ syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
+ (long)num_written, (long)len,
(num_written < 0) ? dnssd_errno : 0,
(num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
+ #endif
return -1;
}
buf += num_written;
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
+// 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.
ssize_t num_read = recv(sd, buf, len, 0);
if ((num_read == 0) || (num_read < 0) || (num_read > len))
{
+ int printWarn = 0;
+ int defunct = 0;
// Should never happen. If it does, it indicates some OS bug,
// or that the mDNSResponder daemon crashed (which should never happen).
- 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) : "");
+#if defined(WIN32)
+ // <rdar://problem/7481776> Suppress logs for "A non-blocking socket operation
+ // could not be completed immediately"
+ if (WSAGetLastError() != WSAEWOULDBLOCK)
+ printWarn = 1;
+#endif
+#if !defined(__ppc__) && defined(SO_ISDEFUNCT)
+ {
+ socklen_t dlen = sizeof (defunct);
+ if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
+ syslog(LOG_WARNING, "dnssd_clientstub read_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+ }
+ if (!defunct)
+ printWarn = 1;
+#endif
+ if (printWarn)
+ syslog(LOG_WARNING, "dnssd_clientstub read_all(%d) failed %ld/%ld %d %s", sd,
+ (long)num_read, (long)len,
+ (num_read < 0) ? dnssd_errno : 0,
+ (num_read < 0) ? dnssd_strerror(dnssd_errno) : "");
+ else if (defunct)
+ syslog(LOG_INFO, "dnssd_clientstub read_all(%d) DEFUNCT", sd);
return (num_read < 0 && dnssd_errno == dnssd_EWOULDBLOCK) ? read_all_wouldblock : read_all_fail;
}
buf += num_read;
{
struct timeval tv = { 0, 0 };
fd_set readfds;
- FD_ZERO(&readfds);
- FD_SET(sd, &readfds);
- return(select(sd+1, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv) > 0);
+ fd_set *fs;
+ int ret;
+
+ if (sd < FD_SETSIZE)
+ {
+ fs = &readfds;
+ FD_ZERO(fs);
+ }
+ else
+ {
+ // Compute the number of integers needed for storing "sd". Internally fd_set is stored
+ // as an array of ints with one bit for each fd and hence we need to compute
+ // the number of ints needed rather than the number of bytes. If "sd" is 32, we need
+ // two ints and not just one.
+ int nfdbits = sizeof (int) * 8;
+ int nints = (sd/nfdbits) + 1;
+ fs = (fd_set *)calloc(nints, sizeof(int));
+ if (fs == NULL) { syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); return 0; }
+ }
+ FD_SET(sd, fs);
+ ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv);
+ if (fs != &readfds) free(fs);
+ return (ret > 0);
}
/* create_hdr
#if defined(USE_TCP_LOOPBACK)
*len += 2; // Allocate space for two-byte port number
#elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
- struct timeval time;
- if (gettimeofday(&time, NULL) < 0)
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL) < 0)
{ syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); return NULL; }
sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
- (unsigned long)(time.tv_sec & 0xFFF), (unsigned long)(time.tv_usec));
+ (unsigned long)(tv.tv_sec & 0xFFF), (unsigned long)(tv.tv_usec));
*len += strlen(ctrl_path) + 1;
#else
*len += 1; // Allocate space for single zero byte (empty C string)
return hdr;
}
+static void FreeDNSRecords(DNSServiceOp *sdRef)
+ {
+ DNSRecord *rec = sdRef->rec;
+ while (rec)
+ {
+ DNSRecord *next = rec->recnext;
+ free(rec);
+ rec = next;
+ }
+ }
+
static void FreeDNSServiceOp(DNSServiceOp *x)
{
- // We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed
+ // We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed
// then sockfd could legitimately contain a failing value (e.g. dnssd_InvalidSocket)
if ((x->sockfd ^ x->validator) != ValidatorBits)
syslog(LOG_WARNING, "dnssd_clientstub attempt to dispose invalid DNSServiceRef %p %08X %08X", x, x->sockfd, x->validator);
x->ProcessReply = NULL;
x->AppCallback = NULL;
x->AppContext = NULL;
+ x->rec = NULL;
+#if _DNS_SD_LIBDISPATCH
+ if (x->disp_source) dispatch_release(x->disp_source);
+ x->disp_source = NULL;
+ x->disp_queue = NULL;
+#endif
+ // DNSRecords may have been added to subordinate sdRef e.g., DNSServiceRegister/DNSServiceAddRecord
+ // or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiveRegisterRecord. DNSRecords may have
+ // been freed if the application called DNSRemoveRecord
+ FreeDNSRecords(x);
free(x);
}
}
sdr->ProcessReply = ProcessReply;
sdr->AppCallback = AppCallback;
sdr->AppContext = AppContext;
+ sdr->rec = NULL;
+#if _DNS_SD_LIBDISPATCH
+ sdr->disp_source = NULL;
+ sdr->disp_queue = NULL;
+#endif
if (flags & kDNSServiceFlagsShareConnection)
{
#else
saddr.sun_family = AF_LOCAL;
strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH);
+ #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
+ {
+ int defunct = 1;
+ if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
+ syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+ }
+ #endif
#endif
while (1)
{
errsd = sp[0]; // We'll read our four-byte error code from sp[0]
listenfd = sp[1]; // We'll send sp[1] to the daemon
+ #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
+ {
+ int defunct = 1;
+ if (setsockopt(errsd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
+ syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+ }
+ #endif
}
}
#endif
return (int) sdRef->sockfd;
}
+#if _DNS_SD_LIBDISPATCH
+static void CallbackWithError(DNSServiceRef sdRef, DNSServiceErrorType error)
+ {
+ DNSServiceOp *sdr = sdRef;
+ DNSServiceOp *sdrNext;
+ DNSRecord *rec;
+ DNSRecord *recnext;
+ int morebytes;
+
+ while (sdr)
+ {
+ // We can't touch the sdr after the callback as it can be deallocated in the callback
+ sdrNext = sdr->next;
+ morebytes = 1;
+ sdr->moreptr = &morebytes;
+ switch (sdr->op)
+ {
+ case resolve_request:
+ if (sdr->AppCallback)((DNSServiceResolveReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, sdr->AppContext);
+ break;
+ case query_request:
+ if (sdr->AppCallback)((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, 0, sdr->AppContext);
+ break;
+ case addrinfo_request:
+ if (sdr->AppCallback)((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, NULL, 0, sdr->AppContext);
+ break;
+ case browse_request:
+ if (sdr->AppCallback)((DNSServiceBrowseReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, NULL, sdr->AppContext);
+ break;
+ case reg_service_request:
+ if (sdr->AppCallback)((DNSServiceRegisterReply) sdr->AppCallback)(sdr, 0, error, NULL, 0, NULL, sdr->AppContext);
+ break;
+ case enumeration_request:
+ if (sdr->AppCallback)((DNSServiceDomainEnumReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, sdr->AppContext);
+ break;
+ case connection_request:
+ // This means Register Record, walk the list of DNSRecords to do the callback
+ rec = sdr->rec;
+ while (rec)
+ {
+ recnext = rec->recnext;
+ if (rec->AppCallback) ((DNSServiceRegisterRecordReply)rec->AppCallback)(sdr, 0, 0, error, rec->AppContext);
+ // The Callback can call DNSServiceRefDeallocate which in turn frees sdr and all the records.
+ // Detect that and return early
+ if (!morebytes){syslog(LOG_WARNING, "dnssdclientstub:Record: CallbackwithError morebytes zero"); return;}
+ rec = recnext;
+ }
+ break;
+ case port_mapping_request:
+ if (sdr->AppCallback)((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, 0, 0, error, 0, 0, 0, 0, 0, sdr->AppContext);
+ break;
+ default:
+ syslog(LOG_WARNING, "dnssd_clientstub CallbackWithError called with bad op %d", sdr->op);
+ }
+ // If DNSServiceRefDeallocate was called in the callback, morebytes will be zero. It means
+ // all other sdrefs have been freed. This happens for shared connections where the
+ // DNSServiceRefDeallocate on the first sdRef frees all other sdrefs.
+ if (!morebytes){syslog(LOG_WARNING, "dnssdclientstub:sdRef: CallbackwithError morebytes zero"); return;}
+ sdr = sdrNext;
+ }
+ }
+#endif // _DNS_SD_LIBDISPATCH
+
// Handle reply from server, calling application client callback. If there is no reply
// from the daemon on the socket contained in sdRef, the call will block.
DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
// return NoError on EWOULDBLOCK. This will handle the case
// where a non-blocking socket is told there is data, but it was a false positive.
// On error, read_all will write a message to syslog for us, so don't need to duplicate that here
- // Note: If we want to properly support using non-blocking sockets in the future
+ // Note: If we want to properly support using non-blocking sockets in the future
int result = read_all(sdRef->sockfd, (void *)&cbh.ipc_hdr, sizeof(cbh.ipc_hdr));
if (result == read_all_fail)
{
+ // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
+ // in the callback.
sdRef->ProcessReply = NULL;
+#if _DNS_SD_LIBDISPATCH
+ // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
+ // is not called by the application and hence need to communicate the error. Cancel the
+ // source so that we don't get any more events
+ if (sdRef->disp_source)
+ {
+ dispatch_source_cancel(sdRef->disp_source);
+ dispatch_release(sdRef->disp_source);
+ sdRef->disp_source = NULL;
+ CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning);
+ }
+#endif
+ // Don't touch sdRef anymore as it might have been deallocated
return kDNSServiceErr_ServiceNotRunning;
}
else if (result == read_all_wouldblock)
if (!data) return kDNSServiceErr_NoMemory;
if (read_all(sdRef->sockfd, data, cbh.ipc_hdr.datalen) < 0) // On error, read_all will write a message to syslog for us
{
- free(data);
+ // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
+ // in the callback.
sdRef->ProcessReply = NULL;
+#if _DNS_SD_LIBDISPATCH
+ // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
+ // is not called by the application and hence need to communicate the error. Cancel the
+ // source so that we don't get any more events
+ if (sdRef->disp_source)
+ {
+ dispatch_source_cancel(sdRef->disp_source);
+ dispatch_release(sdRef->disp_source);
+ sdRef->disp_source = NULL;
+ CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning);
+ }
+#endif
+ // Don't touch sdRef anymore as it might have been deallocated
+ free(data);
return kDNSServiceErr_ServiceNotRunning;
}
else
char *ptr;
size_t len = 0;
ipc_msg_hdr *hdr = create_hdr(cancel_request, &len, &ptr, 0, sdRef);
- ConvertHeaderBytes(hdr);
- write_all(sdRef->sockfd, (char *)hdr, len);
- free(hdr);
+ if (hdr)
+ {
+ ConvertHeaderBytes(hdr);
+ write_all(sdRef->sockfd, (char *)hdr, len);
+ free(hdr);
+ }
*p = sdRef->next;
FreeDNSServiceOp(sdRef);
}
}
else // else, make sure to terminate all subordinates as well
{
+#if _DNS_SD_LIBDISPATCH
+ // The cancel handler will close the fd if a dispatch source has been set
+ if (sdRef->disp_source)
+ {
+ // By setting the ProcessReply to NULL, we make sure that we never call
+ // the application callbacks ever, after returning from this function. We
+ // assume that DNSServiceRefDeallocate is called from the serial queue
+ // that was passed to DNSServiceSetDispatchQueue. Hence, dispatch_source_cancel
+ // should cancel all the blocks on the queue and hence there should be no more
+ // callbacks when we return from this function. Setting ProcessReply to NULL
+ // provides extra protection.
+ sdRef->ProcessReply = NULL;
+ dispatch_source_cancel(sdRef->disp_source);
+ dispatch_release(sdRef->disp_source);
+ sdRef->disp_source = NULL;
+ }
+ // if disp_queue is set, it means it used the DNSServiceSetDispatchQueue API. In that case,
+ // when the source was cancelled, the fd was closed in the handler. Currently the source
+ // is cancelled only when the mDNSResponder daemon dies
+ else if (!sdRef->disp_queue) dnssd_close(sdRef->sockfd);
+#else
dnssd_close(sdRef->sockfd);
+#endif
+ // Free DNSRecords added in DNSRegisterRecord if they have not
+ // been freed in DNSRemoveRecord
while (sdRef)
{
DNSServiceOp *p = sdRef;
get_string(&data, end, fullname, kDNSServiceMaxDomainName);
get_string(&data, end, target, kDNSServiceMaxDomainName);
- if (!data || data + 2 > end) data = NULL;
- else
- {
- port.b[0] = *data++;
- port.b[1] = *data++;
- }
+ if (!data || data + 2 > end) goto fail;
+
+ port.b[0] = *data++;
+ port.b[1] = *data++;
txtlen = get_uint16(&data, end);
txtrecord = (unsigned char *)get_rdata(&data, end, txtlen);
- if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_resolve_response: error reading result from daemon");
- else ((DNSServiceResolveReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, fullname, target, port.s, txtlen, txtrecord, sdr->AppContext);
+ if (!data) goto fail;
+ ((DNSServiceResolveReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, fullname, target, port.s, txtlen, txtrecord, sdr->AppContext);
+ return;
// MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+fail:
+ syslog(LOG_WARNING, "dnssd_clientstub handle_resolve_response: error reading result from daemon");
}
DNSServiceErrorType DNSSD_API DNSServiceResolve
return err;
}
+DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain);
DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain)
{
DNSServiceOp *tmp;
size_t len;
ipc_msg_hdr *hdr = NULL;
DNSRecordRef rref = NULL;
+ DNSRecord **p;
int f1 = (flags & kDNSServiceFlagsShared) != 0;
int f2 = (flags & kDNSServiceFlagsUnique) != 0;
if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
rref->AppCallback = callBack;
rref->record_index = sdRef->max_index++;
rref->sdr = sdRef;
+ rref->recnext = NULL;
*RecordRef = rref;
hdr->client_context.context = rref;
hdr->reg_index = rref->record_index;
+ p = &(sdRef)->rec;
+ while (*p) p = &(*p)->recnext;
+ *p = rref;
+
return deliver_request(hdr, sdRef); // Will free hdr for us
}
size_t len = 0;
char *ptr;
DNSRecordRef rref;
+ DNSRecord **p;
if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSRecordRef pointer"); return kDNSServiceErr_BadParam; }
rref->AppCallback = NULL;
rref->record_index = sdRef->max_index++;
rref->sdr = sdRef;
+ rref->recnext = NULL;
*RecordRef = rref;
hdr->reg_index = rref->record_index;
+ p = &(sdRef)->rec;
+ while (*p) p = &(*p)->recnext;
+ *p = rref;
+
return deliver_request(hdr, sdRef); // Will free hdr for us
}
hdr->reg_index = RecordRef->record_index;
put_flags(flags, &ptr);
err = deliver_request(hdr, sdRef); // Will free hdr for us
- if (!err) free(RecordRef);
+ if (!err)
+ {
+ // This RecordRef could have been allocated in DNSServiceRegisterRecord or DNSServiceAddRecord.
+ // If so, delink from the list before freeing
+ DNSRecord **p = &sdRef->rec;
+ while (*p && *p != RecordRef) p = &(*p)->recnext;
+ if (*p) *p = RecordRef->recnext;
+ free(RecordRef);
+ }
return err;
}
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;
+ uint8_t protocol;
union { uint16_t s; u_char b[2]; } internalPort;
union { uint16_t s; u_char b[2]; } externalPort;
- uint32_t ttl = 0;
-
- 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++;
- internalPort.b[0] = *data++;
- internalPort.b[1] = *data++;
- externalPort.b[0] = *data++;
- externalPort.b[1] = *data++;
- ttl = get_uint32(&data, end);
- }
+ uint32_t ttl;
- 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, internalPort.s, externalPort.s, ttl, sdr->AppContext);
+ if (!data || data + 13 > end) goto fail;
+
+ addr .b[0] = *data++;
+ addr .b[1] = *data++;
+ addr .b[2] = *data++;
+ addr .b[3] = *data++;
+ protocol = *data++;
+ internalPort.b[0] = *data++;
+ internalPort.b[1] = *data++;
+ externalPort.b[0] = *data++;
+ externalPort.b[1] = *data++;
+ ttl = get_uint32(&data, end);
+ if (!data) goto fail;
+
+ ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, addr.l, protocol, internalPort.s, externalPort.s, ttl, sdr->AppContext);
+ return;
// MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+
+fail:
+ syslog(LOG_WARNING, "dnssd_clientstub handle_port_mapping_response: error reading result from daemon");
}
DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
return err;
}
+
+#if _DNS_SD_LIBDISPATCH
+DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
+ (
+ DNSServiceRef service,
+ dispatch_queue_t queue
+ )
+ {
+ int dnssd_fd = DNSServiceRefSockFD(service);
+ if (dnssd_fd == dnssd_InvalidSocket) return kDNSServiceErr_BadParam;
+ if (!queue)
+ {
+ syslog(LOG_WARNING, "dnssd_clientstub: DNSServiceSetDispatchQueue dispatch queue NULL");
+ return kDNSServiceErr_BadParam;
+ }
+ if (service->disp_queue)
+ {
+ syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSetDispatchQueue dispatch queue set already");
+ return kDNSServiceErr_BadParam;
+ }
+ if (service->disp_source)
+ {
+ syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch source set already");
+ return kDNSServiceErr_BadParam;
+ }
+ service->disp_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, dnssd_fd, 0, queue);
+ if (!service->disp_source)
+ {
+ syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch_source_create failed");
+ return kDNSServiceErr_NoMemory;
+ }
+ service->disp_queue = queue;
+ dispatch_source_set_event_handler(service->disp_source, ^{DNSServiceProcessResult(service);});
+ dispatch_source_set_cancel_handler(service->disp_source, ^{dnssd_close(dnssd_fd);});
+ dispatch_resume(service->disp_source);
+ return kDNSServiceErr_NoError;
+ }
+#endif // _DNS_SD_LIBDISPATCH
* 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.
-
- 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
-
-Revision 1.19 2007/05/16 01:06:52 cheshire
-<rdar://problem/4471320> Improve reliability of kDNSServiceFlagsMoreComing flag on multiprocessor machines
-
-Revision 1.18 2007/03/21 19:01:57 cheshire
-<rdar://problem/5078494> IPC code not 64-bit-savvy: assumes long=32bits, and short=16bits
-
-Revision 1.17 2006/10/27 00:38:22 cheshire
-Strip accidental trailing whitespace from lines
-
-Revision 1.16 2006/08/14 23:05:53 cheshire
-Added "tab-width" emacs header line
-
-Revision 1.15 2005/01/27 22:57:56 cheshire
-Fix compile errors on gcc4
-
-Revision 1.14 2004/10/06 02:22:20 cheshire
-Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
-
-Revision 1.13 2004/10/01 22:15:55 rpantos
-rdar://problem/3824265: Replace APSL in client lib with BSD license.
-
-Revision 1.12 2004/09/16 23:14:24 cheshire
-Changes for Windows compatibility
-
-Revision 1.11 2004/06/18 04:56:09 rpantos
-casting goodness
-
-Revision 1.10 2004/06/12 01:08:14 cheshire
-Changes for Windows compatibility
-
-Revision 1.9 2004/05/18 23:51:27 cheshire
-Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
-
-Revision 1.8 2003/11/05 22:44:57 ksekar
-<rdar://problem/3335230>: No bounds checking when reading data from client
-Reviewed by: Stuart Cheshire
-
-Revision 1.7 2003/08/12 19:56:25 cheshire
-Update to APSL 2.0
-
*/
#include "dnssd_ipc.h"
* 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.
-
- 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"
-
-Revision 1.39 2007/08/18 01:02:04 mcguire
-<rdar://problem/5415593> No Bonjour services are getting registered at boot
-
-Revision 1.38 2007/08/08 22:34:59 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
-
-Revision 1.37 2007/07/28 00:00:43 cheshire
-Renamed CompileTimeAssertionCheck structure for consistency with others
-
-Revision 1.36 2007/07/23 22:12:53 cheshire
-<rdar://problem/5352299> Make mDNSResponder more defensive against malicious local clients
-
-Revision 1.35 2007/05/23 18:59:22 cheshire
-Remove unnecessary IPC_FLAGS_REUSE_SOCKET
-
-Revision 1.34 2007/05/22 01:07:42 cheshire
-<rdar://problem/3563675> API: Need a way to get version/feature information
-
-Revision 1.33 2007/05/18 23:55:22 cheshire
-<rdar://problem/4454655> Allow multiple register/browse/resolve operations to share single Unix Domain Socket
-
-Revision 1.32 2007/05/18 20:31:20 cheshire
-Rename port_mapping_create_request to port_mapping_request
-
-Revision 1.31 2007/05/18 17:56:20 cheshire
-Rename port_mapping_create_reply_op to port_mapping_reply_op
-
-Revision 1.30 2007/05/16 01:06:52 cheshire
-<rdar://problem/4471320> Improve reliability of kDNSServiceFlagsMoreComing flag on multiprocessor machines
-
-Revision 1.29 2007/05/15 21:57:16 cheshire
-<rdar://problem/4608220> Use dnssd_SocketValid(x) macro instead of just
-assuming that all negative values (or zero!) are invalid socket numbers
-
-Revision 1.28 2007/03/21 19:01:57 cheshire
-<rdar://problem/5078494> IPC code not 64-bit-savvy: assumes long=32bits, and short=16bits
-
-Revision 1.27 2006/10/27 00:38:22 cheshire
-Strip accidental trailing whitespace from lines
-
-Revision 1.26 2006/09/27 00:44:36 herscher
-<rdar://problem/4249761> API: Need DNSServiceGetAddrInfo()
-
-Revision 1.25 2006/09/26 01:51:07 herscher
-<rdar://problem/4245016> NAT Port Mapping API (for both NAT-PMP and UPnP Gateway Protocol)
-
-Revision 1.24 2006/09/18 19:21:42 cheshire
-<rdar://problem/4737048> gcc's structure padding breaks Bonjour APIs on
-64-bit clients; need to declare ipc_msg_hdr structure "packed"
-
-Revision 1.23 2006/08/14 23:05:53 cheshire
-Added "tab-width" emacs header line
-
-Revision 1.22 2006/06/28 08:56:26 cheshire
-Added "_op" to the end of the operation code enum values,
-to differentiate them from the routines with the same names
-
-Revision 1.21 2005/09/29 06:38:13 herscher
-Remove #define MSG_WAITALL on Windows. We don't use this macro anymore, and it's presence causes warnings to be emitted when compiling against the latest Microsoft Platform SDK.
-
-Revision 1.20 2005/03/21 00:39:31 shersche
-<rdar://problem/4021486> Fix build warnings on Win32 platform
-
-Revision 1.19 2005/02/02 02:25:22 cheshire
-<rdar://problem/3980388> /var/run/mDNSResponder should be /var/run/mdnsd on Linux
-
-Revision 1.18 2005/01/27 22:57:56 cheshire
-Fix compile errors on gcc4
-
-Revision 1.17 2004/11/23 03:39:47 cheshire
-Let interface name/index mapping capability live directly in JNISupport.c,
-instead of having to call through to the daemon via IPC to get this information.
-
-Revision 1.16 2004/11/12 03:21:41 rpantos
-rdar://problem/3809541 Add DNSSDMapIfIndexToName, DNSSDMapNameToIfIndex.
-
-Revision 1.15 2004/10/06 02:22:20 cheshire
-Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
-
-Revision 1.14 2004/10/01 22:15:55 rpantos
-rdar://problem/3824265: Replace APSL in client lib with BSD license.
-
-Revision 1.13 2004/09/16 23:14:25 cheshire
-Changes for Windows compatibility
-
-Revision 1.12 2004/09/16 21:46:38 ksekar
-<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area domain
-
-Revision 1.11 2004/08/10 06:24:56 cheshire
-Use types with precisely defined sizes for 'op' and 'reg_index', for better
-compatibility if the daemon and the client stub are built using different compilers
-
-Revision 1.10 2004/07/07 17:39:25 shersche
-Change MDNS_SERVERPORT from 5533 to 5354.
-
-Revision 1.9 2004/06/25 00:26:27 rpantos
-Changes to fix the Posix build on Solaris.
-
-Revision 1.8 2004/06/18 04:56:51 rpantos
-Add layer for platform code
-
-Revision 1.7 2004/06/12 01:08:14 cheshire
-Changes for Windows compatibility
-
-Revision 1.6 2003/08/12 19:56:25 cheshire
-Update to APSL 2.0
-
*/
#ifndef DNSSD_IPC_H
# define dnssd_strerror(X) win32_strerror(X)
# define ssize_t int
# define getpid _getpid
+# define unlink _unlink
+extern char *win32_strerror(int inErrorCode);
#else
# include <sys/types.h>
# include <unistd.h>
typedef enum
{
request_op_none = 0, // No request yet received on this connection
- connection_request = 1, // connected socket via DNSServiceConnect()
+ connection_request = 1, // connected socket via DNSServiceCreateConnection()
reg_record_request, // reg/remove record only valid for connected sockets
remove_record_request,
enumeration_request,
uint32_t op; // request_op_t or reply_op_t
client_context_t client_context; // context passed from client, returned by server in corresponding reply
uint32_t reg_index; // identifier for a record registered via DNSServiceRegisterRecord() on a
- // socket connected by DNSServiceConnect(). Must be unique in the scope of the connection, such that and
+ // socket connected by DNSServiceCreateConnection(). Must be unique in the scope of the connection, such that and
// index/socket pair uniquely identifies a record. (Used to select records for removal by DNSServiceRemoveRecord())
} ipc_msg_hdr;
.\" See the License for the specific language governing permissions and
.\" limitations under the License.
.\"
-.\" $Log: mDNS.1,v $
-.\" Revision 1.8 2006/08/14 23:24:56 cheshire
-.\" Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-.\"
-.\" Revision 1.7 2005/02/16 02:29:32 cheshire
-.\" Update terminology
-.\"
-.\" Revision 1.6 2005/02/10 22:35:28 cheshire
-.\" <rdar://problem/3727944> Update name
-.\"
-.\" Revision 1.5 2004/09/24 18:33:05 cheshire
-.\" <rdar://problem/3561780> Update man pages to clarify that mDNS and dns-sd are not intended for script use
-.\"
-.\" Revision 1.4 2004/09/22 22:18:48 cheshire
-.\" Update man page to cross-reference new dns-sd man page
-.\"
-.\" Revision 1.3 2004/05/19 00:31:28 cheshire
-.\" Add missing "name type domain" for -L option
-.\"
-.\" Revision 1.2 2004/05/18 18:58:29 cheshire
-.\" Refinements from Soren Spies
-.\"
-.\" Revision 1.1 2004/04/22 02:52:53 cheshire
-.\" <rdar://problem/3597463>: mDNSResponder missing man pages: mDNS
-.\"
-.\"
-.\"
.Dd April 2004 \" Date
.Dt mDNS 1 \" Document Title
.Os Darwin \" Operating System
Version: 1.0
- 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
-
-Revision 1.12 2007/10/01 19:06:19 cheshire
-Defined symbolic constant MDNS_LOG_INITIAL_LEVEL to set the logging level we start out at
-
-Revision 1.11 2007/07/27 20:19:56 cheshire
-For now, comment out unused log levels MDNS_LOG_ERROR, MDNS_LOG_WARN, MDNS_LOG_INFO, MDNS_LOG_DEBUG
-
-Revision 1.10 2007/06/15 21:54:51 cheshire
-<rdar://problem/4883206> Add packet logging to help debugging private browsing over TLS
-
-Revision 1.9 2007/04/05 19:52:32 cheshire
-Display correct ident in syslog messages (i.e. in dnsextd, ProgramName is not "mDNSResponder")
-
-Revision 1.8 2007/01/20 01:43:27 cheshire
-<rdar://problem/4058383> Should not write log messages to /dev/console
-
-Revision 1.7 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.6 2005/01/27 22:57:56 cheshire
-Fix compile errors on gcc4
-
-Revision 1.5 2004/09/17 01:08:55 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.4 2004/06/11 22:36:51 cheshire
-Fixes for compatibility with Windows
-
-Revision 1.3 2004/01/28 21:14:23 cheshire
-Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
-
-Revision 1.2 2003/12/09 01:30:40 rpantos
-Fix usage of ARGS... macros to build properly on Windows.
-
-Revision 1.1 2003/12/08 21:11:42; rpantos
-Changes necessary to support mDNSResponder on Linux.
-
-*/
+ */
#include "mDNSDebug.h"
// 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)
#endif
#if MDNS_DEBUGMSGS
-void debugf_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_DEBUG)
+void debugf_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_DEBUG)
#endif
// Log message with default "mDNSResponder" ident string at the start
.\" See the License for the specific language governing permissions and
.\" 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)
-.\"
-.\" Revision 1.7 2006/08/14 23:24:56 cheshire
-.\" Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-.\"
-.\" Revision 1.6 2005/02/10 22:35:28 cheshire
-.\" <rdar://problem/3727944> Update name
-.\"
-.\" Revision 1.5 2004/06/29 02:41:38 cheshire
-.\" Add note that mDNSResponder is called mdnsd on some systems
-.\"
-.\" Revision 1.4 2004/05/18 18:14:36 cheshire
-.\" Minor wording update
-.\"
-.\" Revision 1.3 2004/04/22 02:56:08 cheshire
-.\" <rdar://problem/3619494>: mDNSResponder man page format error
-.\"
-.\" Revision 1.2 2004/04/12 18:03:24 ksekar
-.\" <rdar://problem/3619494>: mDNSResponder man page format error
-.\"
-.\" Revision 1.1 2003/11/13 03:21:38 cheshire
-.\" <rdar://problem/3086886>: No man page for mDNSResponder
-.\"
-.\"
-.\"
.Dd April 2004 \" Date
.Dt mDNSResponder 8 \" Document Title
.Os Darwin \" Operating System
* 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: uds_daemon.c,v $
-Revision 1.463 2009/07/10 22:25:47 cheshire
-Updated syslog messages for debugging unresponsive clients:
-Will now log a warning message about an unresponsive client every ten seconds,
-and then after 60 messagess (10 minutes) will terminate connection to that client.
-
-Revision 1.462 2009/07/09 22:43:31 cheshire
-Improved log messages for debugging unresponsive clients
-
-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
-
-Revision 1.386 2008/02/26 20:23:15 cheshire
-Updated comments
-
-Revision 1.385 2008/02/19 21:50:52 cheshire
-Shortened some overly-long lines
-
-Revision 1.384 2007/12/22 01:38:05 cheshire
-Improve display of "Auth Records" SIGINFO output
-
-Revision 1.383 2007/12/07 00:45:58 cheshire
-<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
-
-Revision 1.382 2007/11/30 20:11:48 cheshire
-Fixed compile warning: declaration of 'remove' shadows a global declaration
-
-Revision 1.381 2007/11/28 22:02:52 cheshire
-Remove pointless "if (!domain)" check (domain is an array on the stack, so its address can never be null)
-
-Revision 1.380 2007/11/28 18:38:41 cheshire
-Fixed typo in log message: "DNSServiceResolver" -> "DNSServiceResolve"
-
-Revision 1.379 2007/11/01 19:32:14 cheshire
-Added "DEBUG_64BIT_SCM_RIGHTS" debugging code
-
-Revision 1.378 2007/10/31 19:21:40 cheshire
-Don't show Expire time for records and services that aren't currently registered
-
-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 LogClientOperations is turned off
-
-Revision 1.375 2007/10/26 22:51:38 cheshire
-Improved SIGINFO output to show timers for AuthRecords and ServiceRegistrations
-
-Revision 1.374 2007/10/25 22:45:02 cheshire
-Tidied up code for DNSServiceRegister callback status messages
-
-Revision 1.373 2007/10/25 21:28:43 cheshire
-Add ServiceRegistrations to SIGINFO output
-
-Revision 1.372 2007/10/25 21:21:45 cheshire
-<rdar://problem/5496734> BTMM: Need to retry registrations after failures
-Don't unlink_and_free_service_instance at the first error
-
-Revision 1.371 2007/10/18 23:34:40 cheshire
-<rdar://problem/5532821> Need "considerable burden on the network" warning in uds_daemon.c
-
-Revision 1.370 2007/10/17 18:44:23 cheshire
-<rdar://problem/5539930> Goodbye packets not being sent for services on shutdown
-
-Revision 1.369 2007/10/16 17:18:27 cheshire
-Fixed Posix compile errors
-
-Revision 1.368 2007/10/16 16:58:58 cheshire
-Improved debugging error messages in read_msg()
-
-Revision 1.367 2007/10/15 22:55:14 cheshire
-Make read_msg return "void" (since request_callback just ignores the redundant return value anyway)
-
-Revision 1.366 2007/10/10 00:48:54 cheshire
-<rdar://problem/5526379> Daemon spins in an infinite loop when it doesn't get the control message it's expecting
-
-Revision 1.365 2007/10/06 03:25:23 cheshire
-<rdar://problem/5525267> MacBuddy exits abnormally when clicking "Continue" in AppleConnect pane
-
-Revision 1.364 2007/10/06 03:20:16 cheshire
-Improved LogOperation debugging messages
-
-Revision 1.363 2007/10/05 23:24:52 cheshire
-Improved LogOperation messages about separate error return socket
-
-Revision 1.362 2007/10/05 22:11:58 cheshire
-Improved "send_msg ERROR" debugging message
-
-Revision 1.361 2007/10/04 20:45:18 cheshire
-<rdar://problem/5518381> Race condition in kDNSServiceFlagsShareConnection-mode call handling
-
-Revision 1.360 2007/10/01 23:24:46 cheshire
-SIGINFO output was mislabeling mDNSInterface_Any queries as unicast queries
-
-Revision 1.359 2007/09/30 00:09:27 cheshire
-<rdar://problem/5492315> Pass socket fd via SCM_RIGHTS sendmsg instead of using named UDS in the filesystem
-
-Revision 1.358 2007/09/29 20:08:06 cheshire
-Fixed typo in comment
-
-Revision 1.357 2007/09/27 22:10:04 cheshire
-Add LogOperation line for DNSServiceRegisterRecord callbacks
-
-Revision 1.356 2007/09/26 21:29:30 cheshire
-Improved question list SIGINFO output
-
-Revision 1.355 2007/09/26 01:54:34 mcguire
-Debugging: In SIGINFO output, show ClientTunnel query interval, which is how we determine whether a query is still active
-
-Revision 1.354 2007/09/26 01:26:31 cheshire
-<rdar://problem/5501567> BTMM: mDNSResponder crashes in free_service_instance enabling/disabling BTMM
-Need to call SendServiceRemovalNotification *before* backpointer is cleared
-
-Revision 1.353 2007/09/25 20:46:33 cheshire
-Include DNSServiceRegisterRecord operations in SIGINFO output
-
-Revision 1.352 2007/09/25 20:23:40 cheshire
-<rdar://problem/5501567> BTMM: mDNSResponder crashes in free_service_instance enabling/disabling BTMM
-Need to clear si->request backpointer before calling mDNS_DeregisterService(&mDNSStorage, &si->srs);
-
-Revision 1.351 2007/09/25 18:20:34 cheshire
-Changed name of "free_service_instance" to more accurate "unlink_and_free_service_instance"
-
-Revision 1.350 2007/09/24 23:54:52 mcguire
-Additional list checking in uds_validatelists()
-
-Revision 1.349 2007/09/24 06:01:00 cheshire
-Debugging: In SIGINFO output, show NAT Traversal time values in seconds rather than platform ticks
-
-Revision 1.348 2007/09/24 05:02:41 cheshire
-Debugging: In SIGINFO output, indicate explicitly when a given section is empty
-
-Revision 1.347 2007/09/21 02:04:33 cheshire
-<rdar://problem/5440831> BTMM: mDNSResponder crashes in free_service_instance enabling/disabling BTMM
-
-Revision 1.346 2007/09/19 22:47:25 cheshire
-<rdar://problem/5490182> Memory corruption freeing a "no such service" service record
-
-Revision 1.345 2007/09/19 20:32:29 cheshire
-<rdar://problem/5482322> BTMM: Don't advertise SMB with BTMM because it doesn't support IPv6
-
-Revision 1.344 2007/09/19 19:27:50 cheshire
-<rdar://problem/5492182> Improved diagnostics when daemon can't connect to error return path socket
-
-Revision 1.343 2007/09/18 21:42:30 cheshire
-To reduce programming mistakes, renamed ExtPort to RequestedPort
-
-Revision 1.342 2007/09/14 22:38:20 cheshire
-Additional list checking in uds_validatelists()
-
-Revision 1.341 2007/09/13 00:16:43 cheshire
-<rdar://problem/5468706> Miscellaneous NAT Traversal improvements
-
-Revision 1.340 2007/09/12 23:03:08 cheshire
-<rdar://problem/5476978> DNSServiceNATPortMappingCreate callback not giving correct interface index
-
-Revision 1.339 2007/09/12 19:22:21 cheshire
-Variable renaming in preparation for upcoming fixes e.g. priv/pub renamed to intport/extport
-Made NAT Traversal packet handlers take typed data instead of anonymous "mDNSu8 *" byte pointers
-
-Revision 1.338 2007/09/12 01:22:13 cheshire
-Improve validatelists() checking to detect when 'next' pointer gets smashed to ~0
-
-Revision 1.337 2007/09/07 23:05:04 cheshire
-Add display of client_context field in handle_cancel_request() LogOperation message
-While loop was checking client_context.u32[2] instead of client_context.u32[1]
-
-Revision 1.336 2007/09/07 20:56:03 cheshire
-Renamed uint32_t field in client_context_t from "ptr64" to more accurate name "u32"
-
-Revision 1.335 2007/09/05 22:25:01 vazquez
-<rdar://problem/5400521> update_record mDNSResponder leak
-
-Revision 1.334 2007/09/05 20:43:57 cheshire
-Added LogOperation message showing fd of socket listening for incoming Unix Domain Socket client requests
-
-Revision 1.333 2007/08/28 23:32:35 cheshire
-Added LogOperation messages for DNSServiceNATPortMappingCreate() operations
-
-Revision 1.332 2007/08/27 22:59:31 cheshire
-Show reg_index in DNSServiceRegisterRecord/DNSServiceRemoveRecord messages
-
-Revision 1.331 2007/08/27 20:29:57 cheshire
-Added SIGINFO listing of TunnelClients
-
-Revision 1.330 2007/08/24 23:46:50 cheshire
-Added debugging messages and SIGINFO listing of DomainAuthInfo records
-
-Revision 1.329 2007/08/18 01:02:04 mcguire
-<rdar://problem/5415593> No Bonjour services are getting registered at boot
-
-Revision 1.328 2007/08/15 20:18:28 vazquez
-<rdar://problem/5400521> update_record mDNSResponder leak
-Make sure we free all ExtraResourceRecords
-
-Revision 1.327 2007/08/08 22:34:59 mcguire
-<rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
-
-Revision 1.326 2007/08/01 16:09:14 cheshire
-Removed unused NATTraversalInfo substructure from AuthRecord; reduced structure sizecheck values accordingly
-
-Revision 1.325 2007/07/31 21:29:41 cheshire
-<rdar://problem/5372207> System Default registration domain(s) not listed in Domain Enumeration ("dns-sd -E")
-
-Revision 1.324 2007/07/31 01:56:21 cheshire
-Corrected function name in log message
-
-Revision 1.323 2007/07/27 23:57:23 cheshire
-Added compile-time structure size checks
-
-Revision 1.322 2007/07/27 19:37:19 cheshire
-Moved AutomaticBrowseDomainQ into main mDNS object
-
-Revision 1.321 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
-
-Revision 1.320 2007/07/27 00:48:27 cheshire
-<rdar://problem/4700198> BTMM: Services should only get registered in .Mac domain of current user
-<rdar://problem/4731180> BTMM: Only browse in the current user's .Mac domain by default
-
-Revision 1.319 2007/07/24 17:23:33 cheshire
-<rdar://problem/5357133> Add list validation checks for debugging
-
-Revision 1.318 2007/07/23 23:09:51 cheshire
-<rdar://problem/5351997> Reject oversized client requests
-
-Revision 1.317 2007/07/23 22:24:47 cheshire
-<rdar://problem/5352299> Make mDNSResponder more defensive against malicious local clients
-Additional refinements
-
-Revision 1.316 2007/07/23 22:12:53 cheshire
-<rdar://problem/5352299> Make mDNSResponder more defensive against malicious local clients
-
-Revision 1.315 2007/07/21 01:36:13 cheshire
-Need to also add ".local" as automatic browsing domain
-
-Revision 1.314 2007/07/20 20:12:37 cheshire
-Rename "mDNS_DomainTypeBrowseLegacy" as "mDNS_DomainTypeBrowseAutomatic"
-
-Revision 1.313 2007/07/20 00:54:21 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
-
-Revision 1.312 2007/07/11 03:06:43 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-
-Revision 1.311 2007/07/06 21:19:18 cheshire
-Add list of NAT traversals to SIGINFO output
-
-Revision 1.310 2007/07/03 19:56:50 cheshire
-Add LogOperation message for DNSServiceSetDefaultDomainForUser
-
-Revision 1.309 2007/06/29 23:12:49 vazquez
-<rdar://problem/5294103> Stop using generate_final_fatal_reply_with_garbage
-
-Revision 1.308 2007/06/29 00:10:07 vazquez
-<rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes)
-
-Revision 1.307 2007/05/25 00:25:44 cheshire
-<rdar://problem/5227737> Need to enhance putRData to output all current known types
-
-Revision 1.306 2007/05/24 22:31:35 vazquez
-Bug #: 4272956
-Reviewed by: Stuart Cheshire
-<rdar://problem/4272956> WWDC API: Return ADD/REMOVE events in registration callback
-
-Revision 1.305 2007/05/23 18:59:22 cheshire
-Remove unnecessary IPC_FLAGS_REUSE_SOCKET
-
-Revision 1.304 2007/05/22 01:07:42 cheshire
-<rdar://problem/3563675> API: Need a way to get version/feature information
-
-Revision 1.303 2007/05/22 00:32:58 cheshire
-Make a send_all() subroutine -- will be helpful for implementing DNSServiceGetProperty(DaemonVersion)
-
-Revision 1.302 2007/05/21 18:54:54 cheshire
-Add "Cancel" LogOperation message when we get a cancel_request command over the UDS
-
-Revision 1.301 2007/05/18 23:55:22 cheshire
-<rdar://problem/4454655> Allow multiple register/browse/resolve operations to share single Unix Domain Socket
-
-Revision 1.300 2007/05/18 21:27:11 cheshire
-Rename connected_registration_termination to connection_termination
-
-Revision 1.299 2007/05/18 21:24:34 cheshire
-Rename rstate to request
-
-Revision 1.298 2007/05/18 21:22:35 cheshire
-Convert uint16_t etc. to their locally-defined equivalents, like the rest of the core code
-
-Revision 1.297 2007/05/18 20:33:11 cheshire
-Avoid declaring lots of uninitialized variables in read_rr_from_ipc_msg
-
-Revision 1.296 2007/05/18 19:04:19 cheshire
-Rename msgdata to msgptr (may be modified); rename (currently unused) bufsize to msgend
-
-Revision 1.295 2007/05/18 17:57:13 cheshire
-Reorder functions in file to arrange them in logical groups; added "#pragma mark" headers for each group
-
-Revision 1.294 2007/05/17 20:58:22 cheshire
-<rdar://problem/4647145> DNSServiceQueryRecord should return useful information with NXDOMAIN
-
-Revision 1.293 2007/05/17 19:46:20 cheshire
-Routine name deliver_async_error() is misleading. What it actually does is write a message header
-(containing an error code) followed by 256 bytes of garbage zeroes onto a client connection,
-thereby trashing it and making it useless for any subsequent communication. It's destructive,
-and not very useful. Changing name to generate_final_fatal_reply_with_garbage().
-
-Revision 1.292 2007/05/16 01:06:52 cheshire
-<rdar://problem/4471320> Improve reliability of kDNSServiceFlagsMoreComing flag on multiprocessor machines
-
-Revision 1.291 2007/05/15 21:57:16 cheshire
-<rdar://problem/4608220> Use dnssd_SocketValid(x) macro instead of just
-assuming that all negative values (or zero!) are invalid socket numbers
-
-Revision 1.290 2007/05/10 23:30:57 cheshire
-<rdar://problem/4084490> Only one browse gets remove events when disabling browse domain
-
-Revision 1.289 2007/05/02 22:18:08 cheshire
-Renamed NATTraversalInfo_struct context to NATTraversalContext
-
-Revision 1.288 2007/04/30 21:33:39 cheshire
-Fix crash when a callback unregisters a service while the UpdateSRVRecords() loop
-is iterating through the m->ServiceRegistrations list
-
-Revision 1.287 2007/04/27 19:03:22 cheshire
-Check q->LongLived not q->llq to tell if a query is LongLived
-
-Revision 1.286 2007/04/26 16:00:01 cheshire
-Show interface number in DNSServiceBrowse RESULT output
-
-Revision 1.285 2007/04/22 19:03:39 cheshire
-Minor code tidying
-
-Revision 1.284 2007/04/22 06:02:03 cheshire
-<rdar://problem/4615977> Query should immediately return failure when no server
-
-Revision 1.283 2007/04/21 21:47:47 cheshire
-<rdar://problem/4376383> Daemon: Add watchdog timer
-
-Revision 1.282 2007/04/20 21:17:24 cheshire
-For naming consistency, kDNSRecordTypeNegative should be kDNSRecordTypePacketNegative
-
-Revision 1.281 2007/04/19 23:25:20 cheshire
-Added debugging message
-
-Revision 1.280 2007/04/17 19:21:29 cheshire
-<rdar://problem/5140339> Domain discovery not working over VPN
-
-Revision 1.279 2007/04/16 21:53:49 cheshire
-Improve display of negative cache entries
-
-Revision 1.278 2007/04/16 20:49:40 cheshire
-Fix compile errors for mDNSPosix build
-
-Revision 1.277 2007/04/05 22:55:36 cheshire
-<rdar://problem/5077076> Records are ending up in Lighthouse without expiry information
-
-Revision 1.276 2007/04/05 19:20:13 cheshire
-Non-blocking mode not being set correctly -- was clobbering other flags
-
-Revision 1.275 2007/04/04 21:21:25 cheshire
-<rdar://problem/4546810> Fix crash: In regservice_callback service_instance was being referenced after being freed
-
-Revision 1.274 2007/04/04 01:30:42 cheshire
-<rdar://problem/5075200> DNSServiceAddRecord is failing to advertise NULL record
-Add SIGINFO output lising our advertised Authoritative Records
-
-Revision 1.273 2007/04/04 00:03:27 cheshire
-<rdar://problem/5089862> DNSServiceQueryRecord is returning kDNSServiceErr_NoSuchRecord for empty rdata
-
-Revision 1.272 2007/04/03 20:10:32 cheshire
-Show ADD/RMV in DNSServiceQueryRecord log message instead of just "RESULT"
-
-Revision 1.271 2007/04/03 19:22:32 cheshire
-Use mDNSSameIPv4Address (and similar) instead of accessing internal fields directly
-
-Revision 1.270 2007/03/30 21:55:30 cheshire
-Added comments
-
-Revision 1.269 2007/03/29 01:31:44 cheshire
-Faulty logic was incorrectly suppressing some NAT port mapping callbacks
-
-Revision 1.268 2007/03/29 00:13:58 cheshire
-Remove unnecessary fields from service_instance structure: autoname, autorename, allowremotequery, name
-
-Revision 1.267 2007/03/28 20:59:27 cheshire
-<rdar://problem/4743285> Remove inappropriate use of IsPrivateV4Addr()
-
-Revision 1.266 2007/03/28 15:56:37 cheshire
-<rdar://problem/5085774> Add listing of NAT port mapping and GetAddrInfo requests in SIGINFO output
-
-Revision 1.265 2007/03/27 22:52:07 cheshire
-Fix crash in udsserver_automatic_browse_domain_changed
-
-Revision 1.264 2007/03/27 00:49:40 cheshire
-Should use mallocL, not plain malloc
-
-Revision 1.263 2007/03/27 00:45:01 cheshire
-Removed unnecessary "void *termination_context" pointer
-
-Revision 1.262 2007/03/27 00:40:43 cheshire
-Eliminate resolve_termination_t as a separately-allocated structure, and make it part of the request_state union
-
-Revision 1.261 2007/03/27 00:29:00 cheshire
-Eliminate queryrecord_request data as a separately-allocated structure, and make it part of the request_state union
-
-Revision 1.260 2007/03/27 00:18:42 cheshire
-Eliminate enum_termination_t and domain_enum_t as separately-allocated structures,
-and make them part of the request_state union
-
-Revision 1.259 2007/03/26 23:48:16 cheshire
-<rdar://problem/4848295> Advertise model information via Bonjour
-Refinements to reduce unnecessary transmissions of the DeviceInfo TXT record
-
-Revision 1.258 2007/03/24 00:40:04 cheshire
-Minor code cleanup
-
-Revision 1.257 2007/03/24 00:23:12 cheshire
-Eliminate port_mapping_info_t as a separately-allocated structure, and make it part of the request_state union
-
-Revision 1.256 2007/03/24 00:07:18 cheshire
-Eliminate addrinfo_info_t as a separately-allocated structure, and make it part of the request_state union
-
-Revision 1.255 2007/03/23 23:56:14 cheshire
-Move list of record registrations into the request_state union
-
-Revision 1.254 2007/03/23 23:48:56 cheshire
-Eliminate service_info as a separately-allocated structure, and make it part of the request_state union
-
-Revision 1.253 2007/03/23 23:04:29 cheshire
-Eliminate browser_info_t as a separately-allocated structure, and make it part of request_state
-
-Revision 1.252 2007/03/23 22:59:58 cheshire
-<rdar://problem/4848295> Advertise model information via Bonjour
-Use kStandardTTL, not kHostNameTTL
-
-Revision 1.251 2007/03/23 22:44:07 cheshire
-Instead of calling AbortUnlinkAndFree() haphazardly all over the place, make the handle* routines
-return an error code, and then request_callback() does all necessary cleanup in one place.
-
-Revision 1.250 2007/03/22 20:30:07 cheshire
-Remove pointless "if (request->ts != t_complete) ..." checks
-
-Revision 1.249 2007/03/22 20:13:27 cheshire
-Delete unused client_context field
-
-Revision 1.248 2007/03/22 20:03:37 cheshire
-Rename variables for clarity: instead of using variable rs for both request_state
-and reply_state, use req for request_state and rep for reply_state
-
-Revision 1.247 2007/03/22 19:31:42 cheshire
-<rdar://problem/4848295> Advertise model information via Bonjour
-Add missing "model=" at start of DeviceInfo data
-
-Revision 1.246 2007/03/22 18:31:48 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.245 2007/03/22 00:49:20 cheshire
-<rdar://problem/4848295> Advertise model information via Bonjour
-
-Revision 1.244 2007/03/21 21:01:48 cheshire
-<rdar://problem/4789793> Leak on error path in regrecord_callback, uds_daemon.c
-
-Revision 1.243 2007/03/21 19:01:57 cheshire
-<rdar://problem/5078494> IPC code not 64-bit-savvy: assumes long=32bits, and short=16bits
-
-Revision 1.242 2007/03/21 18:51:21 cheshire
-<rdar://problem/4549320> Code in uds_daemon.c passes function name instead of type name to mallocL/freeL
-
-Revision 1.241 2007/03/20 00:04:50 cheshire
-<rdar://problem/4837929> Should allow "udp" or "tcp" for protocol command-line arg
-Fix LogOperation("DNSServiceNATPortMappingCreate(...)") message to actually show client arguments
-
-Revision 1.240 2007/03/16 23:25:35 cheshire
-<rdar://problem/5067001> NAT-PMP: Parameter validation not working correctly
-
-Revision 1.239 2007/03/10 02:29:36 cheshire
-Added comment about port_mapping_create_reply()
-
-Revision 1.238 2007/03/07 00:26:48 cheshire
-<rdar://problem/4426754> DNSServiceRemoveRecord log message should include record type
-
-Revision 1.237 2007/02/28 01:44:29 cheshire
-<rdar://problem/5027863> Byte order bugs in uDNS.c, uds_daemon.c, dnssd_clientstub.c
-
-Revision 1.236 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
-
-Revision 1.235 2007/02/08 21:12:28 cheshire
-<rdar://problem/4386497> Stop reading /etc/mDNSResponder.conf on every sleep/wake
-
-Revision 1.234 2007/02/06 19:06:49 cheshire
-<rdar://problem/3956518> Need to go native with launchd
-
-Revision 1.233 2007/01/10 20:49:37 cheshire
-Remove unnecessary setting of q->Private fields
-
-Revision 1.232 2007/01/09 00:03:23 cheshire
-Call udsserver_handle_configchange() once at the end of udsserver_init()
-to set up the automatic registration and browsing domains.
-
-Revision 1.231 2007/01/06 02:50:19 cheshire
-<rdar://problem/4632919> Instead of copying SRV and TXT record data, just store pointers to cache entities
-
-Revision 1.230 2007/01/06 01:00:35 cheshire
-Improved SIGINFO output
-
-Revision 1.229 2007/01/05 08:30:56 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.228 2007/01/05 08:09:05 cheshire
-Reorder code into functional sections, with "#pragma mark" headers
-
-Revision 1.227 2007/01/05 07:04:24 cheshire
-Minor code tidying
-
-Revision 1.226 2007/01/05 05:44:35 cheshire
-Move automatic browse/registration management from uDNS.c to mDNSShared/uds_daemon.c,
-so that mDNSPosix embedded clients will compile again
-
-Revision 1.225 2007/01/04 23:11:15 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-When an automatic browsing domain is removed, generate appropriate "remove" events for legacy queries
-
-Revision 1.224 2007/01/04 20:57:49 cheshire
-Rename ReturnCNAME to ReturnIntermed (for ReturnIntermediates)
-
-Revision 1.223 2006/12/21 01:25:49 cheshire
-Tidy up SIGINFO state log
-
-Revision 1.222 2006/12/21 00:15:22 cheshire
-Get rid of gmDNS macro; fixed a crash in udsserver_info()
-
-Revision 1.221 2006/12/20 04:07:38 cheshire
-Remove uDNS_info substructure from AuthRecord_struct
-
-Revision 1.220 2006/12/19 22:49:25 cheshire
-Remove uDNS_info substructure from ServiceRecordSet_struct
-
-Revision 1.219 2006/12/14 03:02:38 cheshire
-<rdar://problem/4838433> Tools: dns-sd -G 0 only returns IPv6 when you have a routable IPv6 address
-
-Revision 1.218 2006/11/18 05:01:33 cheshire
-Preliminary support for unifying the uDNS and mDNS code,
-including caching of uDNS answers
-
-Revision 1.217 2006/11/15 19:27:53 mkrochma
-<rdar://problem/4838433> Tools: dns-sd -G 0 only returns IPv6 when you have a routable IPv6 address
-
-Revision 1.216 2006/11/10 00:54:16 cheshire
-<rdar://problem/4816598> Changing case of Computer Name doesn't work
-
-Revision 1.215 2006/10/27 01:30:23 cheshire
-Need explicitly to set ReturnIntermed = mDNSfalse
-
-Revision 1.214 2006/10/20 05:37:23 herscher
-Display question list information in udsserver_info()
-
-Revision 1.213 2006/10/05 03:54:31 herscher
-Remove embedded uDNS_info struct from DNSQuestion_struct
-
-Revision 1.212 2006/09/30 01:22:35 cheshire
-Put back UTF-8 curly quotes in log messages
-
-Revision 1.211 2006/09/27 00:44:55 herscher
-<rdar://problem/4249761> API: Need DNSServiceGetAddrInfo()
-
-Revision 1.210 2006/09/26 01:52:41 herscher
-<rdar://problem/4245016> NAT Port Mapping API (for both NAT-PMP and UPnP Gateway Protocol)
-
-Revision 1.209 2006/09/21 21:34:09 cheshire
-<rdar://problem/4100000> Allow empty string name when using kDNSServiceFlagsNoAutoRename
-
-Revision 1.208 2006/09/21 21:28:24 cheshire
-Code cleanup to make it consistent with daemon.c: change rename_on_memfree to renameonmemfree
-
-Revision 1.207 2006/09/15 21:20:16 cheshire
-Remove uDNS_info substructure from mDNS_struct
-
-Revision 1.206 2006/08/14 23:24:56 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.205 2006/07/20 22:07:30 mkrochma
-<rdar://problem/4633196> Wide-area browsing is currently broken in TOT
-More fixes for uninitialized variables
-
-Revision 1.204 2006/07/15 02:01:33 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-Fix broken "empty string" browsing
-
-Revision 1.203 2006/07/07 01:09:13 cheshire
-<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
-Only use mallocL/freeL debugging routines when building mDNSResponder, not dnsextd
-
-Revision 1.202 2006/07/05 22:00:10 cheshire
-Wide-area cleanup: Rename mDNSPlatformGetRegDomainList() to uDNS_GetDefaultRegDomainList()
-
-Revision 1.201 2006/06/29 03:02:47 cheshire
-<rdar://problem/4607042> mDNSResponder NXDOMAIN and CNAME support
-
-Revision 1.200 2006/06/28 08:56:26 cheshire
-Added "_op" to the end of the operation code enum values,
-to differentiate them from the routines with the same names
-
-Revision 1.199 2006/06/28 08:53:39 cheshire
-Added (commented out) debugging messages
-
-Revision 1.198 2006/06/27 20:16:07 cheshire
-Fix code layout
-
-Revision 1.197 2006/05/18 01:32:35 cheshire
-<rdar://problem/4472706> iChat: Lost connection with Bonjour
-(mDNSResponder insufficiently defensive against malformed browsing PTR responses)
-
-Revision 1.196 2006/05/05 07:07:13 cheshire
-<rdar://problem/4538206> mDNSResponder fails when UDS reads deliver partial data
-
-Revision 1.195 2006/04/25 20:56:28 mkrochma
-Added comment about previous checkin
-
-Revision 1.194 2006/04/25 18:29:36 mkrochma
-Workaround for warning: unused variable 'status' when building mDNSPosix
-
-Revision 1.193 2006/03/19 17:14:38 cheshire
-<rdar://problem/4483117> Need faster purging of stale records
-read_rr_from_ipc_msg was not setting namehash and rdatahash
-
-Revision 1.192 2006/03/18 20:58:32 cheshire
-Misplaced curly brace
-
-Revision 1.191 2006/03/10 22:19:43 cheshire
-Update debugging message in resolve_result_callback() to indicate whether event is ADD or RMV
-
-Revision 1.190 2006/03/10 21:56:12 cheshire
-<rdar://problem/4111464> After record update, old record sometimes remains in cache
-When service TXT and SRV record both change, clients with active resolve calls get *two* callbacks, one
-when the TXT data changes, and then immediately afterwards a second callback with the new port number
-This change suppresses the first unneccessary (and confusing) callback
-
-Revision 1.189 2006/01/06 00:56:31 cheshire
-<rdar://problem/4400573> Should remove PID file on exit
-
-*/
+ */
#if defined(_WIN32)
#include <process.h>
#endif
#endif
+#if APPLE_OSX_mDNSResponder
+#include <WebFilterDNS/WebFilterDNS.h>
+
+#if ! NO_WCF
+
+int WCFIsServerRunning(WCFConnection *conn) __attribute__((weak_import));
+int WCFNameResolvesToAddr(WCFConnection *conn, char* domainName, struct sockaddr* address, uid_t userid) __attribute__((weak_import));
+int WCFNameResolvesToName(WCFConnection *conn, char* fromName, char* toName, uid_t userid) __attribute__((weak_import));
+
+// Do we really need to define a macro for "if"?
+#define CHECK_WCF_FUNCTION(X) if (X)
+#endif // ! NO_WCF
+
+#else
+#define NO_WCF 1
+#endif // APPLE_OSX_mDNSResponder
+
// User IDs 0-500 are system-wide processes, not actual users in the usual sense
// User IDs for real user accounts start at 501 and count up from there
#define SystemUID(X) ((X) <= 500)
{
struct registered_record_entry *next;
mDNSu32 key;
- AuthRecord *rr; // Pointer to variable-sized AuthRecord
client_context_t regrec_client_context;
request_state *request;
+ mDNSBool external_advertise;
+ mDNSInterfaceID origInterfaceID;
+ AuthRecord *rr; // Pointer to variable-sized AuthRecord (Why a pointer? Why not just embed it here?)
} registered_record_entry;
// A single registered service: ServiceRecordSet + bookkeeping
mDNSBool renameonmemfree; // Set on config change when we deregister original name
mDNSBool clientnotified; // Has client been notified of successful registration yet?
mDNSBool default_local; // is this the "local." from an empty-string registration?
+ mDNSBool external_advertise; // is this is being advertised externally?
domainname domain;
ServiceRecordSet srs; // note -- variable-sized object -- must be last field in struct
} service_instance;
{
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 for the original DNSServiceCreateConnection() operation
dnssd_sock_t sd;
dnssd_sock_t errsd;
mDNSu32 uid;
+ void * platform_data;
// 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
const ResourceRecord *txt;
const ResourceRecord *srv;
mDNSs32 ReportTime;
+ mDNSBool external_advertise;
} resolve;
} u;
};
static dnssd_sock_t listenfd = dnssd_InvalidSocket;
static request_state *all_requests = NULL;
+// Note asymmetry here between registration and browsing.
+// For service registrations we only automatically register in domains that explicitly appear in local configuration data
+// (so AutoRegistrationDomains could equally well be called SCPrefRegDomains)
+// For service browsing we also learn automatic browsing domains from the network, so for that case we have:
+// 1. SCPrefBrowseDomains (local configuration data)
+// 2. LocalDomainEnumRecords (locally-generated local-only PTR records -- equivalent to slElem->AuthRecs in uDNS.c)
+// 3. AutoBrowseDomains, which is populated by tracking add/rmv events in AutomaticBrowseDomainChange, the callback function for our mDNS_GetDomains call.
+// By creating and removing our own LocalDomainEnumRecords, we trigger AutomaticBrowseDomainChange callbacks just like domains learned from the network would.
+
+mDNSexport DNameListElem *AutoRegistrationDomains; // Domains where we automatically register for empty-string registrations
+
static DNameListElem *SCPrefBrowseDomains; // List of automatic browsing domains read from SCPreferences for "empty string" browsing
static ARListElem *LocalDomainEnumRecords; // List of locally-generated PTR records to augment those we learn from the network
mDNSexport DNameListElem *AutoBrowseDomains; // List created from those local-only PTR records plus records we get from the network
-mDNSexport DNameListElem *AutoRegistrationDomains; // Domains where we automatically register for empty-string registrations
-
#define MSG_PAD_BYTES 5 // pad message buffer (read from client) with n zero'd bytes to guarantee
// n get_string() calls w/o buffer overrun
// initialization, setup/teardown functions
{ 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 this is actually a shared connection operation, then its req->terminate function will scan
+ // the all_requests list and terminate any subbordinate operations sharing this file descriptor
if (req->terminate) req->terminate(req);
if (!dnssd_SocketValid(req->sd))
{
if (req->errsd != req->sd) LogOperation("%3d: Removing FD and closing errsd %d", req->sd, req->errsd);
else LogOperation("%3d: Removing FD", req->sd);
- udsSupportRemoveFDFromEventLoop(req->sd); // Note: This also closes file descriptor req->sd for us
+ udsSupportRemoveFDFromEventLoop(req->sd, req->platform_data); // Note: This also closes file descriptor req->sd for us
if (req->errsd != req->sd) { dnssd_close(req->errsd); req->errsd = req->sd; }
while (req->replies) // free pending replies
if (!reply) FatalError("ERROR: malloc");
reply->next = mDNSNULL;
- reply->totallen = datalen + sizeof(ipc_msg_hdr);
+ reply->totallen = (mDNSu32)datalen + sizeof(ipc_msg_hdr);
reply->nwriten = 0;
reply->mhdr->version = VERSION;
- reply->mhdr->datalen = datalen;
+ reply->mhdr->datalen = (mDNSu32)datalen;
reply->mhdr->ipc_flags = 0;
reply->mhdr->op = op;
reply->mhdr->client_context = request->hdr.client_context;
}
#endif
+// ***************************************************************************
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - external helpers
+#endif
+
+mDNSlocal void external_start_advertising_helper(service_instance *const instance)
+ {
+ AuthRecord *st = instance->subtypes;
+ ExtraResourceRecord *e;
+ int i;
+
+ if (mDNSIPPortIsZero(instance->request->u.servicereg.port))
+ {
+ LogInfo("external_start_advertising_helper: Not registering service with port number zero");
+ return;
+ }
+
+ if (instance->external_advertise) LogMsg("external_start_advertising_helper: external_advertise already set!");
+
+ for ( i = 0; i < instance->request->u.servicereg.num_subtypes; i++)
+ external_start_advertising_service(&st[i].resrec);
+
+ external_start_advertising_service(&instance->srs.RR_PTR.resrec);
+ external_start_advertising_service(&instance->srs.RR_TXT.resrec);
+
+ for (e = instance->srs.Extras; e; e = e->next)
+ external_start_advertising_service(&e->r.resrec);
+
+ instance->external_advertise = mDNStrue;
+ }
+
+mDNSlocal void external_stop_advertising_helper(service_instance *const instance)
+ {
+ AuthRecord *st = instance->subtypes;
+ ExtraResourceRecord *e;
+ int i;
+
+ if (!instance->external_advertise) return;
+
+ for ( i = 0; i < instance->request->u.servicereg.num_subtypes; i++)
+ external_start_advertising_service(&st[i].resrec);
+
+ external_stop_advertising_service(&instance->srs.RR_PTR.resrec);
+ external_stop_advertising_service(&instance->srs.RR_TXT.resrec);
+
+ for (e = instance->srs.Extras; e; e = e->next)
+ external_stop_advertising_service(&e->r.resrec);
+
+ instance->external_advertise = mDNSfalse;
+ }
+
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
{
ExtraResourceRecord *e = srv->srs.Extras, *tmp;
+ external_stop_advertising_helper(srv);
+
// clear pointers from parent struct
if (srv->request)
{
int count = 0;
ResourceRecord *r = &srs->RR_SRV.resrec;
AuthRecord *rr;
- ServiceRecordSet *s;
for (rr = m->ResourceRecords; rr; rr=rr->next)
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) && !IdenticalSameNameRecord(&s->RR_SRV.resrec, r))
- count++;
-
verbosedebugf("%d peer registrations for %##s", count, r->name->c);
return(count);
}
{
mStatus err;
mDNSBool SuppressError = mDNSfalse;
- service_instance *instance = srs->ServiceContext;
+ service_instance *instance;
reply_state *rep;
- 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; }
+
+ instance = srs->ServiceContext;
if (!instance) { LogMsg("regservice_callback: srs->ServiceContext is NULL %d", result); return; }
// don't send errors up to client for wide-area, empty-string registrations
!instance->default_local)
SuppressError = mDNStrue;
- 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 (mDNS_LoggingEnabled)
+ {
+ const char *const fmt =
+ (result == mStatus_NoError) ? "%s DNSServiceRegister(%##s, %u) REGISTERED" :
+ (result == mStatus_MemFree) ? "%s DNSServiceRegister(%##s, %u) DEREGISTERED" :
+ (result == mStatus_NameConflict) ? "%s DNSServiceRegister(%##s, %u) NAME CONFLICT" :
+ "%s DNSServiceRegister(%##s, %u) %s %d";
+ char prefix[16] = "---:";
+ if (instance->request) mDNS_snprintf(prefix, sizeof(prefix), "%3d:", instance->request->sd);
+ LogOperation(fmt, prefix, 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; }
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.InterfaceID == mDNSInterface_P2P || (!instance->request->u.servicereg.InterfaceID && SameDomainName(&instance->domain, &localdomain)))
+ external_start_advertising_helper(instance);
if (instance->request->u.servicereg.autoname && CountPeerRegistrations(m, srs) == 0)
RecordUpdatedNiceLabel(m, 0); // Successfully got new name, tell user immediately
}
{
if (instance->request && instance->renameonmemfree)
{
+ external_stop_advertising_helper(instance);
instance->renameonmemfree = 0;
err = mDNS_RenameAndReregisterService(m, srs, &instance->request->u.servicereg.name);
if (err) LogMsg("ERROR: regservice_callback - RenameAndReregisterService returned %d", err);
{
if (instance->request->u.servicereg.autorename)
{
+ external_stop_advertising_helper(instance);
if (instance->request->u.servicereg.autoname && CountPeerRegistrations(m, srs) == 0)
{
// On conflict for an autoname service, rename and reregister *all* autoname services
unlink_and_free_service_instance(instance);
}
}
- else
+ else // Not mStatus_NoError, mStatus_MemFree, or mStatus_NameConflict
{
if (!SuppressError)
{
if (!rr->RecordContext) // parent struct already freed by termination callback
{
if (result == mStatus_NoError)
- LogMsg("Error: regrecord_callback: successful registration of orphaned record");
+ LogMsg("Error: regrecord_callback: successful registration of orphaned record %s", ARDisplayString(m, rr));
else
{
if (result != mStatus_MemFree) LogMsg("regrecord_callback: error %d received after parent termination", result);
{
registered_record_entry *re = rr->RecordContext;
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->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);
-
- LogOperation("%3d: DNSServiceRegisterRecord(%u) result %d", request->sd, request->hdr.reg_index, result);
+
+ if (mDNS_LoggingEnabled)
+ {
+ char *fmt = (result == mStatus_NoError) ? "%3d: DNSServiceRegisterRecord(%u %s) REGISTERED" :
+ (result == mStatus_MemFree) ? "%3d: DNSServiceRegisterRecord(%u %s) DEREGISTERED" :
+ (result == mStatus_NameConflict) ? "%3d: DNSServiceRegisterRecord(%u %s) NAME CONFLICT" :
+ "%3d: DNSServiceRegisterRecord(%u %s) %d";
+ LogOperation(fmt, request->sd, re->key, RRDisplayString(m, &rr->resrec), result);
+ }
+
+ if (result != mStatus_MemFree)
+ {
+ int len = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + sizeof(DNSServiceErrorType);
+ reply_state *reply = create_reply(reg_record_reply_op, len, request);
+ 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);
+ append_reply(request, reply);
+ }
+
if (result)
{
// unlink from list, free memory
freeL("registered_record_entry AuthRecord regrecord_callback", re->rr);
freeL("registered_record_entry regrecord_callback", re);
}
- append_reply(request, reply);
+ else
+ {
+ if (re->external_advertise) LogMsg("regrecord_callback: external_advertise already set!");
+ if (re->origInterfaceID == mDNSInterface_P2P || (!re->origInterfaceID && IsLocalDomain(&rr->namestorage)))
+ {
+ external_start_advertising_service(&rr->resrec);
+ re->external_advertise = mDNStrue;
+ }
+ }
}
}
mDNSlocal void connection_termination(request_state *request)
{
+ // When terminating a shared connection, we need to scan the all_requests list
+ // and terminate any subbordinate operations sharing this file descriptor
request_state **req = &all_requests;
+
+ LogOperation("%3d: DNSServiceCreateConnection STOP", request->sd);
+
while (*req)
{
if ((*req)->primary == request)
while (request->u.reg_recs)
{
registered_record_entry *ptr = request->u.reg_recs;
+ LogOperation("%3d: DNSServiceRegisterRecord(%u %s) STOP", request->sd, ptr->key, RRDisplayString(&mDNSStorage, &ptr->rr->resrec));
request->u.reg_recs = request->u.reg_recs->next;
ptr->rr->RecordContext = NULL;
+ if (ptr->external_advertise)
+ {
+ ptr->external_advertise = mDNSfalse;
+ external_stop_advertising_service(&ptr->rr->resrec);
+ }
mDNS_Deregister(&mDNSStorage, ptr->rr); // Will free ptr->rr for us
freeL("registered_record_entry/connection_termination", ptr);
}
// allocate registration entry, link into list
registered_record_entry *re = mallocL("registered_record_entry", sizeof(registered_record_entry));
if (!re) FatalError("ERROR: malloc");
- re->key = request->hdr.reg_index;
- re->rr = rr;
- re->request = request;
+ re->key = request->hdr.reg_index;
+ re->rr = rr;
re->regrec_client_context = request->hdr.client_context;
- rr->RecordContext = re;
- rr->RecordCallback = regrecord_callback;
+ re->request = request;
+ re->external_advertise = mDNSfalse;
+ rr->RecordContext = re;
+ rr->RecordCallback = regrecord_callback;
+
re->next = request->u.reg_recs;
request->u.reg_recs = re;
-
+
+ re->origInterfaceID = rr->resrec.InterfaceID;
+ if (rr->resrec.InterfaceID == mDNSInterface_P2P) rr->resrec.InterfaceID = mDNSInterface_Any;
#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);
- LogOperation("%3d: DNSServiceRegisterRecord(%u %s)", request->sd, request->hdr.reg_index, RRDisplayString(&mDNSStorage, &rr->resrec));
+ LogOperation("%3d: DNSServiceRegisterRecord(%u %s) START", request->sd, re->key, RRDisplayString(&mDNSStorage, &rr->resrec));
err = mDNS_Register(&mDNSStorage, rr);
}
return(err);
// 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));
+
+ external_stop_advertising_helper(p);
// 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
if (result) { freeL("ExtraResourceRecord/add_record_to_service", extra); return result; }
extra->ClientID = request->hdr.reg_index;
+ if (instance->external_advertise && (instance->request->u.servicereg.InterfaceID == mDNSInterface_P2P || (!instance->request->u.servicereg.InterfaceID && SameDomainName(&instance->domain, &localdomain))))
+ external_start_advertising_service(&extra->r.resrec);
return result;
}
return(result);
}
-mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd)
+mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd, mDNSu16 oldrdlen)
{
+ mDNSBool external_advertise = (rr->UpdateContext) ? *((mDNSBool *)rr->UpdateContext) : mDNSfalse;
(void)m; // Unused
+
+ // There are three cases.
+ //
+ // 1. We have updated the primary TXT record of the service
+ // 2. We have updated the TXT record that was added to the service using DNSServiceAddRecord
+ // 3. We have updated the TXT record that was registered using DNSServiceRegisterRecord
+ //
+ // external_advertise is set if we have advertised at least once during the initial addition
+ // of the record in all of the three cases above. We should have checked for InterfaceID/LocalDomain
+ // checks during the first time and hence we don't do any checks here
+ if (external_advertise)
+ {
+ ResourceRecord ext = rr->resrec;
+ if (ext.rdlength == oldrdlen && mDNSPlatformMemSame(&ext.rdata->u, &oldrd->u, oldrdlen)) goto exit;
+ SetNewRData(&ext, oldrd, oldrdlen);
+ external_stop_advertising_service(&ext);
+ external_start_advertising_service(&rr->resrec);
+ }
+exit:
if (oldrd != &rr->rdatastorage) freeL("RData/update_callback", oldrd);
}
-mDNSlocal mStatus update_record(AuthRecord *rr, mDNSu16 rdlen, const char *rdata, mDNSu32 ttl)
+mDNSlocal mStatus update_record(AuthRecord *rr, mDNSu16 rdlen, const char *rdata, mDNSu32 ttl, const mDNSBool *const external_advertise)
{
- int rdsize;
- RData *newrd;
mStatus result;
-
- if (rdlen > sizeof(RDataBody)) rdsize = rdlen;
- else rdsize = sizeof(RDataBody);
- newrd = mallocL("RData/update_record", sizeof(RData) - sizeof(RDataBody) + rdsize);
+ const int rdsize = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
+ RData *newrd = mallocL("RData/update_record", sizeof(RData) - sizeof(RDataBody) + rdsize);
if (!newrd) FatalError("ERROR: malloc");
newrd->MaxRDLength = (mDNSu16) rdsize;
mDNSPlatformMemCopy(&newrd->u, rdata, rdlen);
// since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
// Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
if (rr->resrec.rrtype == kDNSType_TXT && rdlen == 0) { rdlen = 1; newrd->u.txt.c[0] = 0; }
-
+
+ if (external_advertise) rr->UpdateContext = (void *)external_advertise;
+
result = mDNS_Update(&mDNSStorage, rr, ttl, rdlen, newrd, update_callback);
- if (result) { LogMsg("ERROR: mDNS_Update - %d", result); freeL("RData/update_record", newrd); }
+ if (result) { LogMsg("update_record: Error %d for %s", (int)result, ARDisplayString(&mDNSStorage, rr)); freeL("RData/update_record", newrd); }
return result;
}
{
if (reptr->key == hdr->reg_index)
{
- result = update_record(reptr->rr, rdlen, rdata, ttl);
+ result = update_record(reptr->rr, rdlen, rdata, ttl, &reptr->external_advertise);
+ LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s)",
+ request->sd, reptr->rr->resrec.name->c, reptr->rr ? DNSTypeName(reptr->rr->resrec.rrtype) : "<NONE>");
goto end;
}
}
}
if (!rr) { result = mStatus_BadReferenceErr; goto end; }
- result = update_record(rr, rdlen, rdata, ttl);
+ result = update_record(rr, rdlen, rdata, ttl, &i->external_advertise);
if (result && i->default_local) goto end;
else result = mStatus_NoError; // suppress non-local default errors
}
e = *ptr;
*ptr = e->next; // unlink
- LogOperation("%3d: DNSServiceRemoveRecord(%u %s)", request->sd, request->hdr.reg_index, RRDisplayString(&mDNSStorage, &e->rr->resrec));
+ LogOperation("%3d: DNSServiceRemoveRecord(%u %s)", request->sd, e->key, RRDisplayString(&mDNSStorage, &e->rr->resrec));
e->rr->RecordContext = NULL;
- err = mDNS_Deregister(&mDNSStorage, e->rr);
+ if (e->external_advertise)
+ {
+ external_stop_advertising_service(&e->rr->resrec);
+ e->external_advertise = mDNSfalse;
+ }
+ err = mDNS_Deregister(&mDNSStorage, e->rr); // Will free e->rr for us; we're responsible for freeing e
if (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);
return err;
}
if (ptr->ClientID == request->hdr.reg_index) // found match
{
*rrtype = ptr->r.resrec.rrtype;
- return mDNS_RemoveRecordFromService(&mDNSStorage, &serv->srs, ptr, FreeExtraRR, ptr);
+ if (serv->external_advertise) external_stop_advertising_service(&ptr->r.resrec);
+ err = mDNS_RemoveRecordFromService(&mDNSStorage, &serv->srs, ptr, FreeExtraRR, ptr);
+ break;
}
}
return err;
mDNSlocal mStatus register_service_instance(request_state *request, const domainname *domain)
{
service_instance **ptr, *instance;
- int instance_size;
+ const int extra_size = (request->u.servicereg.txtlen > sizeof(RDataBody)) ? (request->u.servicereg.txtlen - sizeof(RDataBody)) : 0;
+ const mDNSBool DomainIsLocal = SameDomainName(domain, &localdomain);
mStatus result;
+ mDNSInterfaceID interfaceID = request->u.servicereg.InterfaceID;
+
+ if (interfaceID == mDNSInterface_P2P) interfaceID = mDNSInterface_Any;
+
+ // If the client specified an interface, but no domain, then we honor the specified interface for the "local" (mDNS)
+ // registration but for the wide-area registrations we don't (currently) have any concept of a wide-area unicast
+ // registrations scoped to a specific interface, so for the automatic domains we add we must *not* specify an interface.
+ // (Specifying an interface with an apparently wide-area domain (i.e. something other than "local")
+ // currently forces the registration to use mDNS multicast despite the apparently wide-area domain.)
+ if (request->u.servicereg.default_domain && !DomainIsLocal) interfaceID = mDNSInterface_Any;
for (ptr = &request->u.servicereg.instances; *ptr; ptr = &(*ptr)->next)
{
}
}
- // Special-case hack: We don't advertise SMB service in AutoTunnel domains, because AutoTunnel
- // services have to support IPv6, and our SMB server does not
- // <rdar://problem/5482322> BTMM: Don't advertise SMB with BTMM because it doesn't support IPv6
- if (SameDomainName(&request->u.servicereg.type, (const domainname *) "\x4" "_smb" "\x4" "_tcp"))
+ if (mDNSStorage.KnownBugs & mDNS_KnownBug_LimitedIPv6)
{
- DomainAuthInfo *AuthInfo = GetAuthInfoForName(&mDNSStorage, domain);
- if (AuthInfo && AuthInfo->AutoTunnel) return(kDNSServiceErr_Unsupported);
+ // Special-case hack: On Mac OS X 10.6.x and earlier we don't advertise SMB service in AutoTunnel domains,
+ // because AutoTunnel services have to support IPv6, and in Mac OS X 10.6.x the SMB server does not.
+ // <rdar://problem/5482322> BTMM: Don't advertise SMB with BTMM because it doesn't support IPv6
+ if (SameDomainName(&request->u.servicereg.type, (const domainname *) "\x4" "_smb" "\x4" "_tcp"))
+ {
+ DomainAuthInfo *AuthInfo = GetAuthInfoForName(&mDNSStorage, domain);
+ if (AuthInfo && AuthInfo->AutoTunnel) return(kDNSServiceErr_Unsupported);
+ }
}
- instance_size = sizeof(*instance);
- if (request->u.servicereg.txtlen > sizeof(RDataBody)) instance_size += (request->u.servicereg.txtlen - sizeof(RDataBody));
- instance = mallocL("service_instance", instance_size);
+ instance = mallocL("service_instance", sizeof(*instance) + extra_size);
if (!instance) { my_perror("ERROR: malloc"); return mStatus_NoMemoryErr; }
- instance->next = mDNSNULL;
- instance->request = request;
- instance->subtypes = AllocateSubTypes(request->u.servicereg.num_subtypes, request->u.servicereg.type_as_string);
- instance->renameonmemfree = 0;
- instance->clientnotified = mDNSfalse;
- instance->default_local = (request->u.servicereg.default_domain && SameDomainName(domain, &localdomain));
+ instance->next = mDNSNULL;
+ instance->request = request;
+ instance->subtypes = AllocateSubTypes(request->u.servicereg.num_subtypes, request->u.servicereg.type_as_string);
+ instance->renameonmemfree = 0;
+ instance->clientnotified = mDNSfalse;
+ instance->default_local = (request->u.servicereg.default_domain && DomainIsLocal);
+ instance->external_advertise = mDNSfalse;
AssignDomainName(&instance->domain, domain);
if (request->u.servicereg.num_subtypes && !instance->subtypes)
request->u.servicereg.port,
request->u.servicereg.txtdata, request->u.servicereg.txtlen,
instance->subtypes, request->u.servicereg.num_subtypes,
- request->u.servicereg.InterfaceID, regservice_callback, instance);
+ interfaceID, regservice_callback, instance);
if (!result)
{
b->next = info->u.browser.browsers;
info->u.browser.browsers = b;
LogOperation("%3d: DNSServiceBrowse(%##s) START", info->sd, b->q.qname.c);
+ if (info->u.browser.interface_id == mDNSInterface_P2P || (!info->u.browser.interface_id && SameDomainName(&b->domain, &localdomain)))
+ {
+ domainname tmp;
+ ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &b->domain);
+ external_start_browsing_for_service(&mDNSStorage, &tmp, kDNSType_PTR);
+ }
}
return err;
}
while (info->u.browser.browsers)
{
browser_t *ptr = info->u.browser.browsers;
+
+ if (info->u.browser.interface_id == mDNSInterface_P2P || (!info->u.browser.interface_id && SameDomainName(&ptr->domain, &localdomain)))
+ {
+ domainname tmp;
+ ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &ptr->domain);
+ external_stop_browsing_for_service(&mDNSStorage, &tmp, kDNSType_PTR);
+ }
+
info->u.browser.browsers = ptr->next;
LogOperation("%3d: DNSServiceBrowse(%##s) STOP", info->sd, ptr->q.qname.c);
mDNS_StopBrowse(&mDNSStorage, &ptr->q); // no need to error-check result
// On shutdown, mDNS_Close automatically deregisters all records
// Since in this case no one has called DeregisterLocalOnlyDomainEnumPTR to cut the record
// from the LocalDomainEnumRecords list, we do this here before we free the memory.
+ // (This should actually no longer be necessary, now that we do the proper cleanup in
+ // udsserver_exit. To confirm this, we'll log an error message if we do find a record that
+ // hasn't been cut from the list yet. If these messages don't appear, we can delete this code.)
ARListElem **ptr = &LocalDomainEnumRecords;
while (*ptr && &(*ptr)->ar != rr) ptr = &(*ptr)->next;
- if (*ptr) *ptr = (*ptr)->next;
+ if (*ptr) { *ptr = (*ptr)->next; LogMsg("FreeARElemCallback: Have to cut %s", ARDisplayString(m, rr)); }
mDNSPlatformMemFree(rr->RecordContext);
}
}
+// RegisterLocalOnlyDomainEnumPTR and DeregisterLocalOnlyDomainEnumPTR largely duplicate code in
+// "FoundDomain" in uDNS.c for creating and destroying these special mDNSInterface_LocalOnly records.
+// We may want to turn the common code into a subroutine.
+
mDNSlocal void RegisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
{
// allocate/register legacy and non-legacy _browse PTR record
{
ptr->renameonmemfree = 1;
if (ptr->clientnotified) SendServiceRemovalNotification(&ptr->srs);
- if (mDNS_DeregisterService(m, &ptr->srs)) // If service was deregistered already
- regservice_callback(m, &ptr->srs, mStatus_MemFree); // we can re-register immediately
+ LogInfo("udsserver_handle_configchange: Calling deregister for Service %##s", ptr->srs.RR_PTR.resrec.name->c);
+ if (mDNS_DeregisterService_drt(m, &ptr->srs, mDNS_Dereg_rapid))
+ regservice_callback(m, &ptr->srs, mStatus_MemFree); // If service deregistered already, we can re-register immediately
}
}
LogOperation("%3d: DNSServiceResolve(%##s) STOP", request->sd, request->u.resolve.qtxt.qname.c);
mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qtxt);
mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
+ if (request->u.resolve.external_advertise) external_stop_resolving_service(&request->u.resolve.qsrv.qname);
}
mDNSlocal mStatus handle_resolve_request(request_state *request)
// extract the data from the message
DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
- mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
+ mDNSInterfaceID InterfaceID;
+ mDNSBool wasP2P = (interfaceIndex == kDNSServiceInterfaceIndexP2P);
+
+
+ if (wasP2P) interfaceIndex = kDNSServiceInterfaceIndexAny;
+
+ InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
if (interfaceIndex && !InterfaceID)
{ LogMsg("ERROR: handle_resolve_request bad interfaceIndex %d", interfaceIndex); return(mStatus_BadParamErr); }
request->u.resolve.qtxt.ExpectUnique = mDNStrue;
request->u.resolve.qtxt.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
request->u.resolve.qtxt.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
+ request->u.resolve.qtxt.SuppressUnusable = mDNSfalse;
request->u.resolve.qtxt.QuestionCallback = resolve_result_callback;
request->u.resolve.qtxt.QuestionContext = request;
request->u.resolve.ReportTime = NonZeroTime(mDNS_TimeNow(&mDNSStorage) + 130 * mDNSPlatformOneSecond);
+ request->u.resolve.external_advertise = mDNSfalse;
+
#if 0
if (!AuthorizedDomain(request, &fqdn, AutoBrowseDomains)) return(mStatus_NoError);
#endif
{
err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qtxt);
if (err) mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
- else request->terminate = resolve_termination_callback;
+ else
+ {
+ request->terminate = resolve_termination_callback;
+ // If the user explicitly passed in P2P, we don't restrict the domain in which we resolve.
+ if (wasP2P || (!InterfaceID && IsLocalDomain(&fqdn)))
+ { request->u.resolve.external_advertise = mDNStrue; external_start_resolving_service(&fqdn);}
+ }
}
return(err);
(void)m; // Unused
#if APPLE_OSX_mDNSResponder
- if (question == &req->u.queryrecord.q2)
+ if (question == &req->u.queryrecord.q2 && question->qtype != req->u.queryrecord.q.qtype && !SameDomainName(&question->qname, &req->u.queryrecord.q.qname))
{
mDNS_StopQuery(&mDNSStorage, question);
+ question->QuestionCallback = mDNSNULL;
// 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
+ if (answer->RecordType != kDNSRecordTypePacketNegative)
{
*question = req->u.queryrecord.q;
question->InterfaceID = mDNSInterface_Unicast;
question->ExpectUnique = mDNStrue;
+ LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) unicast", req->sd, question->qname.c, DNSTypeName(question->qtype));
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);
+ if (err) LogMsg("%3d: ERROR: queryrecord_result_callback %##s %s mDNS_StartQuery: %d", req->sd, question->qname.c, DNSTypeName(question->qtype), (int)err);
}
return;
}
put_uint32(AddRecord ? answer->rroriginalttl : 0, &data);
append_reply(req, rep);
+#if APPLE_OSX_mDNSResponder
+#if ! NO_WCF
+ CHECK_WCF_FUNCTION(WCFIsServerRunning)
+ {
+ struct xucred x;
+ socklen_t xucredlen = sizeof(x);
+
+ if (WCFIsServerRunning((WCFConnection *)m->WCF) && answer->rdlength != 0)
+ {
+ if (getsockopt(req->sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 &&
+ (x.cr_version == XUCRED_VERSION))
+ {
+ struct sockaddr_storage addr;
+ const RDataBody2 *const rdb = (RDataBody2 *)answer->rdata->u.data;
+ addr.ss_len = 0;
+ if (answer->rrtype == kDNSType_A || answer->rrtype == kDNSType_AAAA)
+ {
+ if (answer->rrtype == kDNSType_A)
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+ sin->sin_port = 0;
+ if (!putRData(mDNSNULL, (mDNSu8 *)&sin->sin_addr, (mDNSu8 *)(&sin->sin_addr + sizeof(rdb->ipv4)), answer))
+ LogMsg("queryrecord_result_callback: WCF AF_INET putRData failed");
+ else
+ {
+ addr.ss_len = sizeof (struct sockaddr_in);
+ addr.ss_family = AF_INET;
+ }
+ }
+ else if (answer->rrtype == kDNSType_AAAA)
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+ sin6->sin6_port = 0;
+ if (!putRData(mDNSNULL, (mDNSu8 *)&sin6->sin6_addr, (mDNSu8 *)(&sin6->sin6_addr + sizeof(rdb->ipv6)), answer))
+ LogMsg("queryrecord_result_callback: WCF AF_INET6 putRData failed");
+ else
+ {
+ addr.ss_len = sizeof (struct sockaddr_in6);
+ addr.ss_family = AF_INET6;
+ }
+ }
+ if (addr.ss_len)
+ {
+ debugf("queryrecord_result_callback: Name %s, uid %u, addr length %d", name, x.cr_uid, addr.ss_len);
+ CHECK_WCF_FUNCTION((WCFConnection *)WCFNameResolvesToAddr)
+ {
+ WCFNameResolvesToAddr(m->WCF, name, (struct sockaddr *)&addr, x.cr_uid);
+ }
+ }
+ }
+ else if (answer->rrtype == kDNSType_CNAME)
+ {
+ domainname cname;
+ char cname_cstr[MAX_ESCAPED_DOMAIN_NAME];
+ if (!putRData(mDNSNULL, cname.c, (mDNSu8 *)(cname.c + MAX_DOMAIN_NAME), answer))
+ LogMsg("queryrecord_result_callback: WCF CNAME putRData failed");
+ else
+ {
+ ConvertDomainNameToCString(&cname, cname_cstr);
+ CHECK_WCF_FUNCTION((WCFConnection *)WCFNameResolvesToAddr)
+ {
+ WCFNameResolvesToName(m->WCF, name, cname_cstr, x.cr_uid);
+ }
+ }
+ }
+ }
+ else my_perror("queryrecord_result_callback: ERROR: getsockopt LOCAL_PEERCRED");
+ }
+ }
+#endif
+#endif
}
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.q.InterfaceID == mDNSInterface_P2P || (!request->u.queryrecord.q.InterfaceID && SameDomainName((const domainname *)LastLabel(&request->u.queryrecord.q.qname), &localdomain)))
+ external_stop_browsing_for_service(&mDNSStorage, &request->u.queryrecord.q.qname, request->u.queryrecord.q.qtype);
if (request->u.queryrecord.q2.QuestionCallback) mDNS_StopQuery(&mDNSStorage, &request->u.queryrecord.q2);
}
q->ExpectUnique = mDNSfalse;
q->ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
q->ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
+ q->SuppressUnusable = (flags & kDNSServiceFlagsSuppressUnusable) != 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);
+ LogOperation("%3d: DNSServiceQueryRecord(%X, %d, %##s, %s) START", request->sd, flags, interfaceIndex, q->qname.c, DNSTypeName(q->qtype));
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;
+ else
+ {
+ request->terminate = queryrecord_termination_callback;
+ if (q->InterfaceID == mDNSInterface_P2P || (!q->InterfaceID && SameDomainName((const domainname *)LastLabel(&q->qname), &localdomain)))
+ external_start_browsing_for_service(&mDNSStorage, &q->qname, q->qtype);
+ }
#if APPLE_OSX_mDNSResponder
// Workaround for networks using Microsoft Active Directory using "local" as a private internal top-level domain
// 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.
+ // Note that in the "my-small-company.local" example above there will typically be an SOA record for
+ // "my-small-company.local" but *not* for "local", which is why the "local SOA" check would fail in that case.
if (labels == 2 && !SameDomainName(&q->qname, &ActiveDirectoryPrimaryDomain))
{
AssignDomainName(&q2->qname, &localdomain);
q2->ForceMCast = mDNSfalse;
q2->ReturnIntermed = mDNStrue;
}
+ LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) unicast", request->sd, q2->qname.c, DNSTypeName(q2->qtype));
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);
+ if (err) LogMsg("%3d: ERROR: DNSServiceQueryRecord %##s %s mDNS_StartQuery: %d", request->sd, q2->qname.c, DNSTypeName(q2->qtype), (int)err);
}
#endif // APPLE_OSX_mDNSResponder
mDNSlocal void handle_getproperty_request(request_state *request)
{
- const mStatus BadParamErr = dnssd_htonl(mStatus_BadParamErr);
+ const mStatus BadParamErr = dnssd_htonl((mDNSu32)mStatus_BadParamErr);
char prop[256];
if (get_string(&request->msgptr, request->msgend, prop, sizeof(prop)) >= 0)
{
DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
- mDNSu8 protocol = get_uint32(&request->msgptr, request->msgend);
+ mDNSu8 protocol = (mDNSu8)get_uint32(&request->msgptr, request->msgend);
(void)flags; // Unused
if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
if (request->msgptr + 8 > request->msgend) request->msgptr = NULL;
mDNSlocal void addrinfo_termination_callback(request_state *request)
{
+ LogOperation("%3d: DNSServiceGetAddrInfo(%##s) STOP", request->sd, request->u.addrinfo.q4.qname.c);
+
if (request->u.addrinfo.q4.QuestionContext)
{
mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q4);
domainname d;
mStatus err = 0;
- DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
mDNSPlatformMemZero(&request->u.addrinfo, sizeof(request->u.addrinfo));
if (!request->u.addrinfo.protocol)
{
- NetworkInterfaceInfo *i;
- if (IsLocalDomain(&d))
- {
- for (i = mDNSStorage.HostInterfaces; i; i = i->next)
- {
- if ((i->ip.type == mDNSAddrType_IPv4) && !mDNSIPv4AddressIsZero(i->ip.ip.v4)) request->u.addrinfo.protocol |= kDNSServiceProtocol_IPv4;
- else if ((i->ip.type == mDNSAddrType_IPv6) && !mDNSIPv6AddressIsZero(i->ip.ip.v6)) request->u.addrinfo.protocol |= kDNSServiceProtocol_IPv6;
- }
- }
- else
- {
- for (i = mDNSStorage.HostInterfaces; i; i = i->next)
- {
- if ((i->ip.type == mDNSAddrType_IPv4) && !mDNSv4AddressIsLinkLocal(&i->ip.ip.v4)) request->u.addrinfo.protocol |= kDNSServiceProtocol_IPv4;
- else if ((i->ip.type == mDNSAddrType_IPv6) && !mDNSv4AddressIsLinkLocal(&i->ip.ip.v6)) request->u.addrinfo.protocol |= kDNSServiceProtocol_IPv6;
- }
- }
+ flags |= kDNSServiceFlagsSuppressUnusable;
+ request->u.addrinfo.protocol = (kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6);
}
+ request->u.addrinfo.q4.InterfaceID = request->u.addrinfo.q6.InterfaceID = request->u.addrinfo.interface_id;
+ request->u.addrinfo.q4.Target = request->u.addrinfo.q6.Target = zeroAddr;
+ request->u.addrinfo.q4.qname = request->u.addrinfo.q6.qname = d;
+ request->u.addrinfo.q4.qclass = request->u.addrinfo.q6.qclass = kDNSServiceClass_IN;
+ request->u.addrinfo.q4.LongLived = request->u.addrinfo.q6.LongLived = (flags & kDNSServiceFlagsLongLivedQuery ) != 0;
+ request->u.addrinfo.q4.ExpectUnique = request->u.addrinfo.q6.ExpectUnique = mDNSfalse;
+ request->u.addrinfo.q4.ForceMCast = request->u.addrinfo.q6.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
+ request->u.addrinfo.q4.ReturnIntermed = request->u.addrinfo.q6.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
+ request->u.addrinfo.q4.SuppressUnusable = request->u.addrinfo.q6.SuppressUnusable = (flags & kDNSServiceFlagsSuppressUnusable ) != 0;
+
if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv4)
{
- request->u.addrinfo.q4.InterfaceID = request->u.addrinfo.interface_id;
- request->u.addrinfo.q4.Target = zeroAddr;
- request->u.addrinfo.q4.qname = d;
request->u.addrinfo.q4.qtype = kDNSServiceType_A;
- request->u.addrinfo.q4.qclass = kDNSServiceClass_IN;
- request->u.addrinfo.q4.LongLived = (flags & kDNSServiceFlagsLongLivedQuery ) != 0;
- request->u.addrinfo.q4.ExpectUnique = mDNSfalse;
- request->u.addrinfo.q4.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
- request->u.addrinfo.q4.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
request->u.addrinfo.q4.QuestionCallback = queryrecord_result_callback;
request->u.addrinfo.q4.QuestionContext = request;
-
err = mDNS_StartQuery(&mDNSStorage, &request->u.addrinfo.q4);
if (err != mStatus_NoError)
{
if (!err && (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv6))
{
- request->u.addrinfo.q6.InterfaceID = request->u.addrinfo.interface_id;
- request->u.addrinfo.q6.Target = zeroAddr;
- request->u.addrinfo.q6.qname = d;
request->u.addrinfo.q6.qtype = kDNSServiceType_AAAA;
- request->u.addrinfo.q6.qclass = kDNSServiceClass_IN;
- request->u.addrinfo.q6.LongLived = (flags & kDNSServiceFlagsLongLivedQuery ) != 0;
- request->u.addrinfo.q6.ExpectUnique = mDNSfalse;
- request->u.addrinfo.q6.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
- request->u.addrinfo.q6.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
request->u.addrinfo.q6.QuestionCallback = queryrecord_result_callback;
request->u.addrinfo.q6.QuestionContext = request;
-
err = mDNS_StartQuery(&mDNSStorage, &request->u.addrinfo.q6);
if (err != mStatus_NoError)
{
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
+ if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv4)
+ {
+ // If we started a query for IPv4, we need to cancel it
+ mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q4);
+ request->u.addrinfo.q4.QuestionContext = mDNSNULL;
+ }
}
}
- LogOperation("%3d: DNSServiceGetAddrInfo(%##s) START", request->sd, d.c);
+ LogOperation("%3d: DNSServiceGetAddrInfo(%X, %d, %d, %##s) START",
+ request->sd, flags, interfaceIndex, request->u.addrinfo.protocol, d.c);
if (!err) request->terminate = addrinfo_termination_callback;
if (req->ts == t_complete) // this must be death or something is wrong
{
char buf[4]; // dummy for death notification
- int nread = recv(req->sd, buf, 4, 0);
+ int nread = udsSupportReadFD(req->sd, buf, 4, 0, req->platform_data);
if (!nread) { req->ts = t_terminated; return; }
if (nread < 0) goto rerror;
LogMsg("%3d: ERROR: read data from a completed request", req->sd);
if (req->hdr_bytes < sizeof(ipc_msg_hdr))
{
mDNSu32 nleft = sizeof(ipc_msg_hdr) - req->hdr_bytes;
- int nread = recv(req->sd, (char *)&req->hdr + req->hdr_bytes, nleft, 0);
+ int nread = udsSupportReadFD(req->sd, (char *)&req->hdr + req->hdr_bytes, nleft, 0, req->platform_data);
if (nread == 0) { req->ts = t_terminated; return; }
if (nread < 0) goto rerror;
req->hdr_bytes += nread;
// 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; }
+ { LogMsg("%3d: ERROR: read_msg: hdr.datalen %u (0x%X) > 70000", req->sd, req->hdr.datalen, req->hdr.datalen); req->ts = t_error; return; }
req->msgbuf = mallocL("request_state msgbuf", req->hdr.datalen + MSG_PAD_BYTES);
if (!req->msgbuf) { my_perror("ERROR: malloc"); req->ts = t_error; return; }
req->msgptr = req->msgbuf;
msg.msg_flags = 0;
nread = recvmsg(req->sd, &msg, 0);
#else
- nread = recv(req->sd, (char *)req->msgbuf + req->data_bytes, nleft, 0);
+ nread = udsSupportReadFD(req->sd, (char *)req->msgbuf + req->data_bytes, nleft, 0, req->platform_data);
#endif
if (nread == 0) { req->ts = t_terminated; return; }
if (nread < 0) goto rerror;
dnssd_sockaddr_t cliaddr;
#if defined(USE_TCP_LOOPBACK)
mDNSOpaque16 port;
- int opt = 1;
+ u_long opt = 1;
port.b[0] = req->msgptr[0];
port.b[1] = req->msgptr[1];
req->msgptr += 2;
return;
}
+#if !defined(USE_TCP_LOOPBACK)
got_errfd:
+#endif
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)
{
mStatus err = 0;
request_state *req = info;
-#if defined(_WIN32)
- u_long opt = 1;
-#endif
mDNSs32 min_size = sizeof(DNSServiceFlags);
(void)fd; // Unused
(void)filter; // Unused
dnssd_socklen_t len = (dnssd_socklen_t) sizeof(cliaddr);
dnssd_sock_t sd = accept(fd, (struct sockaddr*) &cliaddr, &len);
#if defined(SO_NOSIGPIPE) || defined(_WIN32)
- const unsigned long optval = 1;
+ unsigned long optval = 1;
#endif
(void)filter; // Unused
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);
+ udsSupportAddFDToEventLoop(sd, request_callback, request, &request->platform_data);
}
}
return mDNSfalse;
}
- if (mStatus_NoError != udsSupportAddFDToEventLoop(skt, connect_callback, (void *) NULL))
+ if (mStatus_NoError != udsSupportAddFDToEventLoop(skt, connect_callback, (void *) NULL, (void **) NULL))
{
my_perror("ERROR: could not add listen socket to event loop");
return mDNSfalse;
dnssd_sockaddr_t laddr;
int ret;
mDNSu32 i = 0;
-#if defined(_WIN32)
- u_long opt = 1;
-#endif
LogInfo("udsserver_init");
#endif
// We start a "LocalOnly" query looking for Automatic Browse Domain records.
- // When Domain Enumeration in uDNS.c finds an "lb" record from the network, it creates a
- // "LocalOnly" record, which results in our AutomaticBrowseDomainChange callback being invoked
+ // When Domain Enumeration in uDNS.c finds an "lb" record from the network, its "FoundDomain" routine
+ // creates a "LocalOnly" record, which results in our AutomaticBrowseDomainChange callback being invoked
mDNS_GetDomains(&mDNSStorage, &mDNSStorage.AutomaticBrowseDomainQ, mDNS_DomainTypeBrowseAutomatic,
mDNSNULL, mDNSInterface_LocalOnly, AutomaticBrowseDomainChange, mDNSNULL);
mDNSexport int udsserver_exit(void)
{
+ // Cancel all outstanding client requests
+ while (all_requests) AbortUnlinkAndFree(all_requests);
+
+ // Clean up any special mDNSInterface_LocalOnly records we created, both the entries for "local" we
+ // created in udsserver_init, and others we created as a result of reading local configuration data
+ while (LocalDomainEnumRecords)
+ {
+ ARListElem *rem = LocalDomainEnumRecords;
+ LocalDomainEnumRecords = LocalDomainEnumRecords->next;
+ mDNS_Deregister(&mDNSStorage, &rem->ar);
+ }
+
// 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(listenfd))
return 0;
}
-mDNSlocal void LogClientInfo(mDNS *const m, request_state *req)
+mDNSlocal void LogClientInfo(mDNS *const m, const request_state *req)
{
+ char prefix[16];
+ if (req->primary) mDNS_snprintf(prefix, sizeof(prefix), " -> ");
+ else mDNS_snprintf(prefix, sizeof(prefix), "%3d:", req->sd);
+
+ usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
+
if (!req->terminate)
- LogMsgNoIdent("%3d: No operation yet on this socket", req->sd);
+ LogMsgNoIdent("%s No operation yet on this socket", prefix);
else if (req->terminate == connection_termination)
{
- registered_record_entry *p;
- LogMsgNoIdent("%3d: DNSServiceCreateConnection", req->sd);
+ int num_records = 0, num_ops = 0;
+ const registered_record_entry *p;
+ const request_state *r;
+ for (p = req->u.reg_recs; p; p=p->next) num_records++;
+ for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++;
+ LogMsgNoIdent("%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s", prefix,
+ num_records, num_records != 1 ? "s" : "",
+ num_ops, num_ops != 1 ? "s" : "");
for (p = req->u.reg_recs; p; p=p->next)
LogMsgNoIdent(" -> DNSServiceRegisterRecord %3d %s", p->key, ARDisplayString(m, p->rr));
+ for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfo(m, r);
}
else if (req->terminate == regservice_termination_callback)
{
service_instance *ptr;
for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
- LogMsgNoIdent("%3d: DNSServiceRegister %##s %u/%u",
- req->sd, ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port), SRS_PORT(&ptr->srs));
+ LogMsgNoIdent("%s DNSServiceRegister %##s %u/%u",
+ (ptr == req->u.servicereg.instances) ? prefix : " ",
+ ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port), SRS_PORT(&ptr->srs));
}
else if (req->terminate == browse_termination_callback)
{
browser_t *blist;
for (blist = req->u.browser.browsers; blist; blist = blist->next)
- LogMsgNoIdent("%3d: DNSServiceBrowse %##s", req->sd, blist->q.qname.c);
+ LogMsgNoIdent("%s DNSServiceBrowse %##s", (blist == req->u.browser.browsers) ? prefix : " ", blist->q.qname.c);
}
else if (req->terminate == resolve_termination_callback)
- LogMsgNoIdent("%3d: DNSServiceResolve %##s", req->sd, req->u.resolve.qsrv.qname.c);
+ LogMsgNoIdent("%s DNSServiceResolve %##s", prefix, req->u.resolve.qsrv.qname.c);
else if (req->terminate == queryrecord_termination_callback)
- LogMsgNoIdent("%3d: DNSServiceQueryRecord %##s (%s)", req->sd, req->u.queryrecord.q.qname.c, DNSTypeName(req->u.queryrecord.q.qtype));
+ LogMsgNoIdent("%s DNSServiceQueryRecord %##s (%s)", prefix, req->u.queryrecord.q.qname.c, DNSTypeName(req->u.queryrecord.q.qtype));
else if (req->terminate == enum_termination_callback)
- LogMsgNoIdent("%3d: DNSServiceEnumerateDomains %##s", req->sd, req->u.enumeration.q_all.qname.c);
+ LogMsgNoIdent("%s DNSServiceEnumerateDomains %##s", prefix, req->u.enumeration.q_all.qname.c);
else if (req->terminate == port_mapping_termination_callback)
- LogMsgNoIdent("%3d: DNSServiceNATPortMapping %.4a %s%s Int %d Req %d Ext %d Req TTL %d Granted TTL %d",
- req->sd,
+ LogMsgNoIdent("%s DNSServiceNATPortMapping %.4a %s%s Int %d Req %d Ext %d Req TTL %d Granted TTL %d",
+ prefix,
&req->u.pm.NATinfo.ExternalAddress,
req->u.pm.NATinfo.Protocol & NATOp_MapTCP ? "TCP" : " ",
req->u.pm.NATinfo.Protocol & NATOp_MapUDP ? "UDP" : " ",
req->u.pm.NATinfo.NATLease,
req->u.pm.NATinfo.Lifetime);
else if (req->terminate == addrinfo_termination_callback)
- LogMsgNoIdent("%3d: DNSServiceGetAddrInfo %s%s %##s", req->sd,
+ LogMsgNoIdent("%s DNSServiceGetAddrInfo %s%s %##s", prefix,
req->u.addrinfo.protocol & kDNSServiceProtocol_IPv4 ? "v4" : " ",
req->u.addrinfo.protocol & kDNSServiceProtocol_IPv6 ? "v6" : " ",
req->u.addrinfo.q4.qname.c);
else
- LogMsgNoIdent("%3d: Unrecognized operation %p", req->sd, req->terminate);
+ LogMsgNoIdent("%s Unrecognized operation %p", prefix, req->terminate);
}
mDNSlocal void LogAuthRecords(mDNS *const m, const mDNSs32 now, AuthRecord *ResourceRecords, int *proxy)
{
- if (!ResourceRecords) LogMsgNoIdent("<None>");
- else
+ mDNSBool showheader = mDNStrue;
+ const AuthRecord *ar;
+ OwnerOptData owner = zeroOwner;
+ for (ar = ResourceRecords; ar; ar=ar->next)
{
- const AuthRecord *ar;
- mDNSEthAddr owner = zeroEthAddr;
- LogMsgNoIdent(" Int Next Expire State");
- for (ar = ResourceRecords; ar; ar=ar->next)
+ const char *const ifname = InterfaceNameForID(m, ar->resrec.InterfaceID);
+ if ((ar->WakeUp.HMAC.l[0] != 0) == (proxy != mDNSNULL))
{
- char *ifname = InterfaceNameForID(m, ar->resrec.InterfaceID);
- if (ar->WakeUp.HMAC.l[0]) (*proxy)++;
- if (!mDNSSameEthAddress(&owner, &ar->WakeUp.HMAC))
+ if (showheader) { showheader = mDNSfalse; LogMsgNoIdent(" Int Next Expire State"); }
+ if (proxy) (*proxy)++;
+ if (!mDNSPlatformMemSame(&owner, &ar->WakeUp, sizeof(owner)))
{
- 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);
+ owner = ar->WakeUp;
+ if (owner.password.l[0])
+ LogMsgNoIdent("Proxying for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &owner.HMAC, &owner.IMAC, &owner.password, owner.seq);
+ else if (!mDNSSameEthAddress(&owner.HMAC, &owner.IMAC))
+ LogMsgNoIdent("Proxying for H-MAC %.6a I-MAC %.6a seq %d", &owner.HMAC, &owner.IMAC, owner.seq);
else
- LogMsgNoIdent("Proxying for %.6a seq %d", &ar->WakeUp.HMAC, ar->WakeUp.seq);
+ LogMsgNoIdent("Proxying for %.6a seq %d", &owner.HMAC, owner.seq);
}
if (AuthRecord_uDNS(ar))
LogMsgNoIdent("%7d %7d %7d %7d %s",
(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)
+ else if (ar->resrec.InterfaceID == mDNSInterface_LocalOnly)
+ LogMsgNoIdent(" LO %s", ARDisplayString(m, ar));
+ else if (ar->resrec.InterfaceID == mDNSInterface_P2P)
+ LogMsgNoIdent(" PP %s", ARDisplayString(m, ar));
+ else
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,
ifname ? ifname : "ALL",
ARDisplayString(m, ar));
- else
- LogMsgNoIdent(" LO %s", ARDisplayString(m, ar));
usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
}
}
+ if (showheader) LogMsgNoIdent("<None>");
}
mDNSexport void udsserver_info(mDNS *const m)
const CacheRecord *cr;
const DNSQuestion *q;
const DNameListElem *d;
+ const SearchListElem *s;
LogMsgNoIdent("Timenow 0x%08lX (%d)", (mDNSu32)now, now);
- LogMsgNoIdent("------------ Cache -------------");
+ LogMsgNoIdent("------------ Cache -------------");
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)
CacheUsed++; // Count one cache entity for the CacheGroup object
for (cr = cg->members; cr; cr=cr->next)
{
- mDNSs32 remain = cr->resrec.rroriginalttl - (now - cr->TimeRcvd) / mDNSPlatformOneSecond;
- char *ifname = InterfaceNameForID(m, cr->resrec.InterfaceID);
+ const mDNSs32 remain = cr->resrec.rroriginalttl - (now - cr->TimeRcvd) / mDNSPlatformOneSecond;
+ const char *ifname;
+ mDNSInterfaceID InterfaceID = cr->resrec.InterfaceID;
+ if (!InterfaceID && cr->resrec.rDNSServer)
+ InterfaceID = cr->resrec.rDNSServer->interface;
+ ifname = InterfaceNameForID(m, InterfaceID);
CacheUsed++;
if (cr->CRActiveQuestion) CacheActive++;
LogMsgNoIdent("%3d %s%8ld %-7s%s %-6s%s",
LogMsgNoIdent("Cache currently contains %lu entities; %lu referenced by active questions", CacheUsed, CacheActive);
LogMsgNoIdent("--------- Auth Records ---------");
- LogAuthRecords(m, now, m->ResourceRecords, &ProxyA);
+ LogAuthRecords(m, now, m->ResourceRecords, mDNSNULL);
LogMsgNoIdent("------ Duplicate Records -------");
- LogAuthRecords(m, now, m->DuplicateRecords, &ProxyD);
+ LogAuthRecords(m, now, m->DuplicateRecords, mDNSNULL);
- LogMsgNoIdent("----- ServiceRegistrations -----");
- if (!m->ServiceRegistrations) LogMsgNoIdent("<None>");
- else
- {
- ServiceRecordSet *s;
- LogMsgNoIdent(" Int Next Expire State");
- for (s = m->ServiceRegistrations; s; s = s->uDNS_next)
- LogMsgNoIdent("%7d %7d %7d %7d %s",
- s->RR_SRV.ThisAPInterval / mDNSPlatformOneSecond,
- (s->RR_SRV.LastAPTime + s->RR_SRV.ThisAPInterval - now) / mDNSPlatformOneSecond,
- s->RR_SRV.expire ? (s->RR_SRV.expire - now) / mDNSPlatformOneSecond : 0,
- s->state, ARDisplayString(m, &s->RR_SRV));
- }
+ LogMsgNoIdent("----- Auth Records Proxied -----");
+ LogAuthRecords(m, now, m->ResourceRecords, &ProxyA);
+
+ LogMsgNoIdent("-- Duplicate Records Proxied ---");
+ LogAuthRecords(m, now, m->DuplicateRecords, &ProxyD);
LogMsgNoIdent("---------- Questions -----------");
if (!m->Questions) LogMsgNoIdent("<None>");
{
CacheUsed = 0;
CacheActive = 0;
- LogMsgNoIdent(" Int Next if T NumAns Type Name");
+ LogMsgNoIdent(" Int Next if T NumAns VDNS Qptr DupOf SU SQ Type Name");
for (q = m->Questions; q; q=q->next)
{
mDNSs32 i = q->ThisQInterval / mDNSPlatformOneSecond;
- mDNSs32 n = (q->LastQTime + q->ThisQInterval - now) / mDNSPlatformOneSecond;
+ mDNSs32 n = (NextQSendTime(q) - now) / mDNSPlatformOneSecond;
char *ifname = InterfaceNameForID(m, q->InterfaceID);
CacheUsed++;
if (q->ThisQInterval) CacheActive++;
- LogMsgNoIdent("%6d%6d %-7s%s%s %5d %-6s%##s%s",
+ LogMsgNoIdent("%6d%6d %-7s%s%s %5d 0x%x%x 0x%p 0x%p %1d %2d %-5s%##s%s",
i, n,
ifname ? ifname : mDNSOpaque16IsZero(q->TargetQID) ? "" : "-U-",
mDNSOpaque16IsZero(q->TargetQID) ? (q->LongLived ? "l" : " ") : (q->LongLived ? "L" : "O"),
- q->AuthInfo ? "P" : " ",
- q->CurrentAnswers,
- DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
+ PrivateQuery(q) ? "P" : " ",
+ q->CurrentAnswers, q->validDNSServers.l[1], q->validDNSServers.l[0], q, q->DuplicateOf,
+ q->SuppressUnusable, q->SuppressQuery, DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
}
LogMsgNoIdent("%lu question%s; %lu active", CacheUsed, CacheUsed > 1 ? "s" : "", CacheActive);
if (!all_requests) LogMsgNoIdent("<None>");
else
{
- request_state *req;
+ const request_state *req, *r;
for (req = all_requests; req; req=req->next)
+ {
+ if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
+ {
+ for (r = all_requests; r && r != req; r=r->next) if (r == req->primary) goto foundparent;
+ LogMsgNoIdent("%3d: Orhpan operation %p; parent %p not found in request list", req->sd);
+ }
+ // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
LogClientInfo(m, req);
- usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
+ foundparent:;
+ }
}
LogMsgNoIdent("-------- NAT Traversals --------");
if (!m->NATTraversals) LogMsgNoIdent("<None>");
else
{
- NATTraversalInfo *nat;
+ const NATTraversalInfo *nat;
for (nat = m->NATTraversals; nat; nat=nat->next)
{
if (nat->Protocol)
if (!m->AuthInfoList) LogMsgNoIdent("<None>");
else
{
- DomainAuthInfo *a;
+ const DomainAuthInfo *a;
for (a = m->AuthInfoList; a; a = a->next)
LogMsgNoIdent("%##s %##s%s", a->domain.c, a->keyname.c, a->AutoTunnel ? " AutoTunnel" : "");
}
if (!m->TunnelClients) LogMsgNoIdent("<None>");
else
{
- ClientTunnel *c;
+ const ClientTunnel *c;
for (c = m->TunnelClients; c; c = c->next)
- 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);
+ LogMsgNoIdent("%##s local %.16a %.4a %.16a remote %.16a %.4a %5d %.16a interval %d",
+ c->dstname.c, &c->loc_inner, &c->loc_outer, &c->loc_outer6, &c->rmt_inner, &c->rmt_outer, mDNSVal16(c->rmt_outer_port), &c->rmt_outer6, c->q.ThisQInterval);
}
#endif // APPLE_OSX_mDNSResponder
LogMsgNoIdent("--- Auto Registration Domains --");
if (!AutoRegistrationDomains) LogMsgNoIdent("<None>");
else for (d=AutoRegistrationDomains; d; d=d->next) LogMsgNoIdent("%##s", d->name.c);
+
+ LogMsgNoIdent("--- Search Domains --");
+ if (!SearchList) LogMsgNoIdent("<None>");
+ else
+ {
+ for (s=SearchList; s; s=s->next)
+ {
+ LogMsgNoIdent("%##s", s->domain.c);
+ }
+ }
+ LogMsgNoIdent("---- Task Scheduling Timers ----");
+
+ if (!m->NewQuestions)
+ LogMsgNoIdent("NewQuestion <NONE>");
+ else
+ LogMsgNoIdent("NewQuestion DelayAnswering %d %d %##s (%s)",
+ m->NewQuestions->DelayAnswering, m->NewQuestions->DelayAnswering-now,
+ m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
+
+ if (!m->NewLocalOnlyQuestions)
+ LogMsgNoIdent("NewLocalOnlyQuestions <NONE>");
+ else
+ LogMsgNoIdent("NewLocalOnlyQuestions %##s (%s)",
+ m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
+
+ if (!m->NewLocalRecords)
+ LogMsgNoIdent("NewLocalRecords <NONE>");
+ else
+ LogMsgNoIdent("NewLocalRecords %02X %s", m->NewLocalRecords->resrec.RecordType, ARDisplayString(m, m->NewLocalRecords));
+
+ LogMsgNoIdent("SPSProxyListChanged%s", m->SPSProxyListChanged ? "" : " <NONE>");
+ LogMsgNoIdent("LocalRemoveEvents%s", m->LocalRemoveEvents ? "" : " <NONE>");
+
+#define LogTimer(MSG,T) LogMsgNoIdent( MSG " %08X %11d %08X %11d", (T), (T), (T)-now, (T)-now)
+
+ LogMsgNoIdent(" ABS (hex) ABS (dec) REL (hex) REL (dec)");
+ LogMsgNoIdent("m->timenow %08X %11d", now, now);
+ LogMsgNoIdent("m->timenow_adjust %08X %11d", m->timenow_adjust, m->timenow_adjust);
+ LogTimer("m->NextScheduledEvent ", m->NextScheduledEvent);
+
+#ifndef UNICAST_DISABLED
+ LogTimer("m->NextuDNSEvent ", m->NextuDNSEvent);
+ LogTimer("m->NextSRVUpdate ", m->NextSRVUpdate);
+ LogTimer("m->NextScheduledNATOp ", m->NextScheduledNATOp);
+ LogTimer("m->retryGetAddr ", m->retryGetAddr);
+#endif
+
+ LogTimer("m->NextCacheCheck ", m->NextCacheCheck);
+ LogTimer("m->NextScheduledSPS ", m->NextScheduledSPS);
+ LogTimer("m->NextScheduledSPRetry ", m->NextScheduledSPRetry);
+ LogTimer("m->DelaySleep ", m->DelaySleep);
+
+ LogTimer("m->NextScheduledQuery ", m->NextScheduledQuery);
+ LogTimer("m->NextScheduledProbe ", m->NextScheduledProbe);
+ LogTimer("m->NextScheduledResponse", m->NextScheduledResponse);
+
+ LogTimer("m->SuppressSending ", m->SuppressSending);
+ LogTimer("m->SuppressProbes ", m->SuppressProbes);
+ LogTimer("m->ProbeFailTime ", m->ProbeFailTime);
+ LogTimer("m->DelaySleep ", m->DelaySleep);
+ LogTimer("m->SleepLimit ", m->SleepLimit);
+ LogMsgNoIdent("m->RegisterAutoTunnel6 %08X", m->RegisterAutoTunnel6);
}
#if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
// 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) <= 2000) ? 1 : -1];
- char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <= 40) ? 1 : -1];
+ char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <= 60) ? 1 : -1];
char sizecheck_service_instance [(sizeof(service_instance) <= 6552) ? 1 : -1];
- char sizecheck_browser_t [(sizeof(browser_t) <= 992) ? 1 : -1];
+ char sizecheck_browser_t [(sizeof(browser_t) <= 1016) ? 1 : -1];
char sizecheck_reply_hdr [(sizeof(reply_hdr) <= 12) ? 1 : -1];
char sizecheck_reply_state [(sizeof(reply_state) <= 64) ? 1 : -1];
};
Version: 1.0
- 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
-
-Revision 1.23 2007/07/24 17:23:02 cheshire
-Rename DefRegList as AutoRegistrationDomains
-
-Revision 1.22 2007/07/11 02:58:04 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-
-Revision 1.21 2007/04/21 21:47:47 cheshire
-<rdar://problem/4376383> Daemon: Add watchdog timer
-
-Revision 1.20 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
-
-Revision 1.19 2007/02/07 19:32:00 cheshire
-<rdar://problem/4980353> All mDNSResponder components should contain version strings in SCCS-compatible format
-
-Revision 1.18 2007/02/06 19:06:49 cheshire
-<rdar://problem/3956518> Need to go native with launchd
-
-Revision 1.17 2007/01/05 05:46:07 cheshire
-Add mDNS *const m parameter to udsserver_handle_configchange()
-
-Revision 1.16 2007/01/04 23:11:15 cheshire
-<rdar://problem/4720673> uDNS: Need to start caching unicast records
-When an automatic browsing domain is removed, generate appropriate "remove" events for legacy queries
-
-Revision 1.15 2006/08/14 23:24:57 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.14 2005/01/27 17:48:39 cheshire
-Added comment about CFSocketInvalidate closing the underlying socket
-
-Revision 1.13 2004/12/10 05:27:26 cheshire
-<rdar://problem/3909147> Guard against multiple autoname services of the same type on the same machine
-
-Revision 1.12 2004/12/10 04:28:28 cheshire
-<rdar://problem/3914406> User not notified of name changes for services using new UDS API
-
-Revision 1.11 2004/12/06 21:15:23 ksekar
-<rdar://problem/3884386> mDNSResponder crashed in CheckServiceRegistrations
-
-Revision 1.10 2004/10/26 04:31:44 cheshire
-Rename CountSubTypes() as ChopSubTypes()
-
-Revision 1.9 2004/09/30 00:25:00 ksekar
-<rdar://problem/3695802> Dynamically update default registration domains on config change
-
-Revision 1.8 2004/09/21 21:05:11 cheshire
-Move duplicate code out of mDNSMacOSX/daemon.c and mDNSPosix/PosixDaemon.c,
-into mDNSShared/uds_daemon.c
-
-Revision 1.7 2004/09/17 01:08:55 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.6 2004/08/11 01:58:49 cheshire
-Remove "mDNS *globalInstance" parameter from udsserver_init()
-
-Revision 1.5 2004/06/18 04:44:58 rpantos
-Use platform layer for socket types
-
-Revision 1.4 2004/06/12 00:51:58 cheshire
-Changes for Windows compatibility
-
-Revision 1.3 2004/01/25 00:03:21 cheshire
-Change to use mDNSVal16() instead of private PORT_AS_NUM() macro
-
-Revision 1.2 2004/01/24 08:46:26 bradley
-Added InterfaceID<->Index platform interfaces since they are now used by all platforms for the DNS-SD APIs.
-
-Revision 1.1 2003/12/08 21:11:42 rpantos;
-Changes necessary to support mDNSResponder on Linux.
-
-*/
+ */
#include "mDNSEmbeddedAPI.h"
#include "dnssd_ipc.h"
/* Routines that uds_daemon expects to link against: */
typedef void (*udsEventCallback)(int fd, short filter, void *context);
-extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback callback, void *context);
-extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd); // Note: This also CLOSES the file descriptor as well
+extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback callback, void *context, void **platform_data);
+extern int udsSupportReadFD(dnssd_sock_t fd, char* buf, int len, int flags, void *platform_data);
+extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd, void *platform_data); // Note: This also CLOSES the file descriptor as well
extern void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay);
#if APPLE_OSX_mDNSResponder
extern void machserver_automatic_browse_domain_changed(const domainname *d, mDNSBool add);
extern void machserver_automatic_registration_domain_changed(const domainname *d, mDNSBool add);
-#endif
+// External support
+extern void external_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype);
+extern void external_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype);
+extern void external_start_advertising_service(const ResourceRecord *const resourceRecord);
+extern void external_stop_advertising_service(const ResourceRecord *const resourceRecord);
+extern void external_start_resolving_service(const domainname *const fqdn);
+extern void external_stop_resolving_service(const domainname *const fqdn);
+#else
+#define external_start_browsing_for_service(A,B,C) (void)(A)
+#define external_stop_browsing_for_service(A,B,C) (void)(A)
+#define external_start_advertising_service(A) (void)(A)
+#define external_stop_advertising_service(A) (void)(A)
+#define external_start_resolving_service(A) (void)(A)
+#define external_stop_resolving_service(A) (void)(A)
+#endif // APPLE_OSX_mDNSResponder
extern const char mDNSResponderVersionString_SCCS[];
#define mDNSResponderVersionString (mDNSResponderVersionString_SCCS+5)
* 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: 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
-
-Revision 1.32 2006/12/19 22:43:56 cheshire
-Fix compiler warnings
-
-Revision 1.31 2006/11/10 00:54:16 cheshire
-<rdar://problem/4816598> Changing case of Computer Name doesn't work
-
-Revision 1.30 2006/08/14 23:25:18 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.29 2006/03/19 02:00:12 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.28 2005/05/30 07:36:38 bradley
-New implementation of the mDNS platform plugin for VxWorks 5.5 or later with IPv6 support.
-
-*/
+ */
#if 0
#pragma mark == Configuration ==
* 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: mDNSVxWorks.h,v $
-Revision 1.5 2006/08/14 23:25:18 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.4 2005/05/30 07:36:38 bradley
-New implementation of the mDNS platform plugin for VxWorks 5.5 or later with IPv6 support.
-
-*/
+ */
#ifndef __MDNS_VXWORKS_H__
#define __MDNS_VXWORKS_H__
Copyright: Copyright (C) 2002-2004 Apple Computer, Inc., All Rights Reserved.
- 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
-
-Revision 1.30 2006/12/19 22:43:56 cheshire
-Fix compiler warnings
-
-Revision 1.29 2006/08/14 23:25:18 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.28 2006/03/19 02:00:12 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.27 2004/12/17 23:37:49 cheshire
-<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
-(and other repetitive configuration changes)
-
-Revision 1.26 2004/10/28 02:00:35 cheshire
-<rdar://problem/3841770> Call pipeDevDelete when disposing of commandPipe
-
-Revision 1.25 2004/10/16 00:17:01 cheshire
-<rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
-
-Revision 1.24 2004/09/21 21:02:56 cheshire
-Set up ifname before calling mDNS_RegisterInterface()
-
-Revision 1.23 2004/09/17 01:08:57 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.22 2004/09/17 00:19:11 cheshire
-For consistency with AllDNSLinkGroupv6, rename AllDNSLinkGroup to AllDNSLinkGroupv4
-
-Revision 1.21 2004/09/16 00:24:50 cheshire
-<rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
-
-Revision 1.20 2004/09/14 23:42:36 cheshire
-<rdar://problem/3801296> Need to seed random number generator from platform-layer data
-
-Revision 1.19 2004/09/14 23:16:09 cheshire
-mDNS_SetFQDNs has been renamed to mDNS_SetFQDN
-
-Revision 1.18 2004/08/14 03:22:42 cheshire
-<rdar://problem/3762579> Dynamic DNS UI <-> mDNSResponder glue
-Add GetUserSpecifiedDDNSName() routine
-Convert ServiceRegDomain to domainname instead of C string
-Replace mDNS_GenerateFQDN/mDNS_GenerateGlobalFQDN with mDNS_SetFQDNs
-
-Revision 1.17 2004/07/29 19:26:03 ksekar
-Plaform-level changes for NAT-PMP support
-
-Revision 1.16 2004/04/22 05:11:28 bradley
-Added mDNSPlatformUTC for TSIG signed dynamic updates.
-
-Revision 1.15 2004/04/21 02:49:12 cheshire
-To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
-
-Revision 1.14 2004/04/09 17:43:04 cheshire
-Make sure to set the McastTxRx field so that duplicate suppression works correctly
-
-Revision 1.13 2004/01/27 20:15:24 cheshire
-<rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
-
-Revision 1.12 2004/01/24 09:12:37 bradley
-Avoid TOS socket options to workaround a TOS routing problem with VxWorks and multiple interfaces
-when sending unicast responses, which resulted in packets going out the wrong interface.
-
-Revision 1.11 2004/01/24 04:59:16 cheshire
-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 (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.
-Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
-
-Revision 1.8 2003/10/28 10:08:27 bradley
-Removed legacy port 53 support as it is no longer needed.
-
-Revision 1.7 2003/08/20 05:58:54 bradley
-Removed dependence on modified mDNSCore: define structures/prototypes locally.
-
-Revision 1.6 2003/08/18 23:19:05 cheshire
-<rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformRawTime()
-
-Revision 1.5 2003/08/15 00:05:04 bradley
-Updated to use name/InterfaceID from new AuthRecord resrec field. Added output of new record sizes.
-
-Revision 1.4 2003/08/14 02:19:55 cheshire
-<rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
-
-Revision 1.3 2003/08/12 19:56:27 cheshire
-Update to APSL 2.0
-
-Revision 1.2 2003/08/05 23:58:34 cheshire
-Update code to compile with the new mDNSCoreReceive() function that requires a TTL
-Right now this platform layer just reports 255 instead of returning the real value -- we should fix this
-
-Revision 1.1 2003/08/02 10:06:48 bradley
-mDNS platform plugin for VxWorks.
-
-
Notes for non-Apple platforms:
TARGET_NON_APPLE should be defined to 1 to avoid relying on Apple-only header files, macros, or functions.
Copyright: Copyright (C) 2002-2003 Apple Computer, Inc., All Rights Reserved.
- Change History (most recent first):
-
-$Log: mDNSVxWorksIPv4Only.h,v $
-Revision 1.4 2006/08/14 23:25:18 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2004/09/17 01:08:57 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.2 2003/08/12 19:56:27 cheshire
-Update to APSL 2.0
-
-Revision 1.1 2003/08/02 10:06:49 bradley
-mDNS platform plugin for VxWorks.
-
-*/
+ */
#ifndef __MDNS_VXWORKS__
#define __MDNS_VXWORKS__
--- /dev/null
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BrowsingPage.h"
+#include "resource.h"
+
+#include "ConfigPropertySheet.h"
+
+#include <WinServices.h>
+
+#define MAX_KEY_LENGTH 255
+
+
+IMPLEMENT_DYNCREATE(CBrowsingPage, CPropertyPage)
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage::CBrowsingPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CBrowsingPage::CBrowsingPage()
+:
+ CPropertyPage(CBrowsingPage::IDD)
+{
+ //{{AFX_DATA_INIT(CBrowsingPage)
+ //}}AFX_DATA_INIT
+
+ m_firstTime = true;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage::~CBrowsingPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CBrowsingPage::~CBrowsingPage()
+{
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage::DoDataExchange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CBrowsingPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CBrowsingPage)
+ //}}AFX_DATA_MAP
+ DDX_Control(pDX, IDC_BROWSE_LIST, m_browseListCtrl);
+ DDX_Control(pDX, IDC_REMOVE_BROWSE_DOMAIN, m_removeButton);
+}
+
+BEGIN_MESSAGE_MAP(CBrowsingPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CBrowsingPage)
+ //}}AFX_MSG_MAP
+ ON_BN_CLICKED(IDC_ADD_BROWSE_DOMAIN, OnBnClickedAddBrowseDomain)
+ ON_BN_CLICKED(IDC_REMOVE_BROWSE_DOMAIN, OnBnClickedRemoveBrowseDomain)
+ ON_NOTIFY(LVN_ITEMCHANGED, IDC_BROWSE_LIST, OnLvnItemchangedBrowseList)
+END_MESSAGE_MAP()
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage::SetModified
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CBrowsingPage::SetModified( BOOL bChanged )
+{
+ m_modified = bChanged;
+
+ CPropertyPage::SetModified( bChanged );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage::OnSetActive
+//---------------------------------------------------------------------------------------------------------------------------
+
+BOOL
+CBrowsingPage::OnSetActive()
+{
+ CConfigPropertySheet * psheet;
+ HKEY key = NULL;
+ HKEY subKey = NULL;
+ DWORD dwSize;
+ DWORD enabled;
+ DWORD err;
+ TCHAR subKeyName[MAX_KEY_LENGTH];
+ DWORD cSubKeys = 0;
+ DWORD cbMaxSubKey;
+ DWORD cchMaxClass;
+ int nIndex;
+ DWORD i;
+ BOOL b = CPropertyPage::OnSetActive();
+
+ psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ m_modified = FALSE;
+
+ if ( m_firstTime )
+ {
+ m_browseListCtrl.SetExtendedStyle((m_browseListCtrl.GetStyle() & (~LVS_EX_GRIDLINES))|LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
+
+ m_browseListCtrl.InsertColumn(0, L"", LVCFMT_LEFT, 20 );
+ m_browseListCtrl.InsertColumn(1, L"", LVCFMT_LEFT, 345);
+
+ m_firstTime = false;
+ }
+
+ m_initialized = false;
+
+ // Clear out what's there
+
+ m_browseListCtrl.DeleteAllItems();
+
+ // Now populate the browse domain box
+
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
+ require_noerr( err, exit );
+
+ // Get information about this node
+
+ err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
+
+ for ( i = 0; i < cSubKeys; i++)
+ {
+ dwSize = MAX_KEY_LENGTH;
+
+ err = RegEnumKeyEx( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
+
+ err = RegOpenKey( key, subKeyName, &subKey );
+ require_noerr( err, exit );
+
+ dwSize = sizeof( DWORD );
+ err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+ require_noerr( err, exit );
+
+ nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L"");
+ m_browseListCtrl.SetItemText( nIndex, 1, subKeyName );
+ m_browseListCtrl.SetCheck( nIndex, enabled );
+
+ RegCloseKey( subKey );
+ subKey = NULL;
+ }
+
+ m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );
+
+ m_removeButton.EnableWindow( FALSE );
+
+exit:
+
+ if ( subKey )
+ {
+ RegCloseKey( subKey );
+ }
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+
+ m_initialized = true;
+
+ return b;
+}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage::OnOK
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CBrowsingPage::OnOK()
+{
+ if ( m_modified )
+ {
+ Commit();
+ }
+}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage::Commit
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CBrowsingPage::Commit()
+{
+ HKEY key = NULL;
+ HKEY subKey = NULL;
+ TCHAR subKeyName[MAX_KEY_LENGTH];
+ DWORD cSubKeys = 0;
+ DWORD cbMaxSubKey;
+ DWORD cchMaxClass;
+ DWORD dwSize;
+ int i;
+ DWORD err;
+
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
+ require_noerr( err, exit );
+
+ // First, remove all the entries that are there
+
+ err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
+
+ for ( i = 0; i < (int) cSubKeys; i++ )
+ {
+ dwSize = MAX_KEY_LENGTH;
+
+ err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
+
+ err = RegDeleteKey( key, subKeyName );
+ require_noerr( err, exit );
+ }
+
+ // Now re-populate
+
+ for ( i = 0; i < m_browseListCtrl.GetItemCount(); i++ )
+ {
+ DWORD enabled = (DWORD) m_browseListCtrl.GetCheck( i );
+
+ err = RegCreateKeyEx( key, m_browseListCtrl.GetItemText( i, 1 ), 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &subKey, NULL );
+ require_noerr( err, exit );
+
+ err = RegSetValueEx( subKey, L"Enabled", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
+ require_noerr( err, exit );
+
+ RegCloseKey( subKey );
+ subKey = NULL;
+ }
+
+exit:
+
+ if ( subKey )
+ {
+ RegCloseKey( subKey );
+ }
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage::OnBnClickedAddBrowseDomain
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CBrowsingPage::OnBnClickedAddBrowseDomain()
+{
+ CAddBrowseDomain dlg( GetParent() );
+
+ if ( ( dlg.DoModal() == IDOK ) && ( dlg.m_text.GetLength() > 0 ) )
+ {
+ int nIndex;
+
+ nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L"");
+ m_browseListCtrl.SetItemText( nIndex, 1, dlg.m_text );
+ m_browseListCtrl.SetCheck( nIndex, 1 );
+
+ m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );
+
+ m_browseListCtrl.Invalidate();
+
+ SetModified( TRUE );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage::OnBnClickedRemoveBrowseDomain
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CBrowsingPage::OnBnClickedRemoveBrowseDomain()
+{
+ UINT selectedCount = m_browseListCtrl.GetSelectedCount();
+ int nItem = -1;
+ UINT i;
+
+ // Update all of the selected items.
+
+ for ( i = 0; i < selectedCount; i++ )
+ {
+ nItem = m_browseListCtrl.GetNextItem( -1, LVNI_SELECTED );
+ check( nItem != -1 );
+
+ m_browseListCtrl.DeleteItem( nItem );
+
+ SetModified( TRUE );
+ }
+
+ m_removeButton.EnableWindow( FALSE );
+}
+
+
+void
+CBrowsingPage::OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
+{
+ if ( m_browseListCtrl.GetSelectedCount() )
+ {
+ m_removeButton.EnableWindow( TRUE );
+ }
+
+ if ( m_initialized )
+ {
+ NM_LISTVIEW * pNMListView = (NM_LISTVIEW*)pNMHDR;
+
+ BOOL bPrevState = (BOOL) ( ( ( pNMListView->uOldState & LVIS_STATEIMAGEMASK ) >> 12 ) - 1 );
+
+ if ( bPrevState < 0 )
+ {
+ bPrevState = 0;
+ }
+
+
+ BOOL bChecked = ( BOOL ) ( ( ( pNMListView->uNewState & LVIS_STATEIMAGEMASK ) >> 12) - 1 );
+
+ if ( bChecked < 0 )
+ {
+ bChecked = 0;
+ }
+
+ if ( bPrevState != bChecked )
+ {
+ SetModified( TRUE );
+ }
+ }
+
+ *pResult = 0;
+}
+
+
+
+int CALLBACK
+CBrowsingPage::SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+ CString str1;
+ CString str2;
+ int ret = 0;
+
+ CBrowsingPage * self = reinterpret_cast<CBrowsingPage*>( lParamSort );
+ require_quiet( self, exit );
+
+ str1 = self->m_browseListCtrl.GetItemText( (int) lParam1, 1 );
+ str2 = self->m_browseListCtrl.GetItemText( (int) lParam2, 1 );
+
+ ret = str1.Compare( str2 );
+
+exit:
+
+ return ret;
+}
+
+
+// CAddBrowseDomain dialog
+
+IMPLEMENT_DYNAMIC(CAddBrowseDomain, CDialog)
+CAddBrowseDomain::CAddBrowseDomain(CWnd* pParent /*=NULL*/)
+ : CDialog(CAddBrowseDomain::IDD, pParent)
+{
+}
+
+CAddBrowseDomain::~CAddBrowseDomain()
+{
+}
+
+void CAddBrowseDomain::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_COMBO1, m_comboBox);
+}
+
+
+BOOL
+CAddBrowseDomain::OnInitDialog()
+{
+ CConfigPropertySheet * psheet;
+ CConfigPropertySheet::StringList::iterator it;
+
+ BOOL b = CDialog::OnInitDialog();
+
+ psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ for ( it = psheet->m_browseDomains.begin(); it != psheet->m_browseDomains.end(); it++ )
+ {
+ CString text = *it;
+
+ if ( m_comboBox.FindStringExact( -1, *it ) == CB_ERR )
+ {
+ m_comboBox.AddString( *it );
+ }
+ }
+
+exit:
+
+ return b;
+}
+
+
+void
+CAddBrowseDomain::OnOK()
+{
+ m_comboBox.GetWindowText( m_text );
+
+ CDialog::OnOK();
+}
+
+
+
+BEGIN_MESSAGE_MAP(CAddBrowseDomain, CDialog)
+END_MESSAGE_MAP()
+
--- /dev/null
+/* -*- 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.
+ */
+
+#pragma once
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include <DebugServices.h>
+#include <list>
+#include "afxcmn.h"
+
+#include "afxwin.h"
+
+
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CBrowsingPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+class CBrowsingPage : public CPropertyPage
+{
+public:
+ CBrowsingPage();
+ ~CBrowsingPage();
+
+protected:
+
+ //{{AFX_DATA(CBrowsingPage)
+ enum { IDD = IDR_APPLET_PAGE3 };
+ //}}AFX_DATA
+
+ //{{AFX_VIRTUAL(CBrowsingPage)
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ DECLARE_DYNCREATE(CBrowsingPage)
+
+ //{{AFX_MSG(CBrowsingPage)
+ //}}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:
+
+ static int CALLBACK
+
+ SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
+
+
+
+ CListCtrl m_browseListCtrl;
+
+ bool m_initialized;
+
+ bool m_firstTime;
+
+
+
+public:
+
+
+
+ afx_msg void OnBnClickedAddBrowseDomain();
+
+ afx_msg void OnBnClickedRemoveBrowseDomain();
+
+ afx_msg void OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);
+
+ CButton m_removeButton;
+
+};
+
+
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CAddBrowseDomain
+//---------------------------------------------------------------------------------------------------------------------------
+
+
+class CAddBrowseDomain : public CDialog
+
+{
+
+ DECLARE_DYNAMIC(CAddBrowseDomain)
+
+
+
+public:
+
+ CAddBrowseDomain(CWnd* pParent = NULL); // standard constructor
+
+ virtual ~CAddBrowseDomain();
+
+
+
+// Dialog Data
+
+ enum { IDD = IDR_ADD_BROWSE_DOMAIN };
+
+
+
+protected:
+
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+
+ virtual BOOL OnInitDialog();
+
+ virtual void OnOK();
+
+ DECLARE_MESSAGE_MAP()
+
+public:
+
+ CComboBox m_comboBox;
+
+ CString m_text;
+
+};
+
* 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: ConfigDialog.cpp,v $
-Revision 1.3 2006/08/14 23:25:28 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/03/03 19:55:21 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#include "ConfigDialog.h"
* 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: ConfigDialog.h,v $
-Revision 1.3 2006/08/14 23:25:28 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/03/03 19:55:21 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#pragma once
* 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: 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
-
-Revision 1.4 2005/10/05 20:46:50 herscher
-<rdar://problem/4192011> Move Wide-Area preferences to another part of the registry so they don't removed during an update-install.
-
-Revision 1.3 2005/03/03 19:55:22 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#include "ConfigPropertySheet.h"
#include <WinServices.h>
+extern "C"
+{
+#include <ClientCommon.h>
+}
#include <process.h>
// Custom events
#define WM_DATAREADY ( WM_USER + 0x100 )
-#define WM_REGISTRYCHANGED ( WM_USER + 0x101 )
IMPLEMENT_DYNCREATE(CConfigPropertySheet, CPropertySheet)
:
CPropertySheet(),
m_browseDomainsRef( NULL ),
- m_regDomainsRef( NULL ),
m_thread( NULL ),
m_threadExited( NULL )
{
- AddPage(&m_firstPage);
+ AddPage(&m_firstPage );
AddPage(&m_secondPage);
AddPage(&m_thirdPage);
- AddPage(&m_fourthPage );
InitializeCriticalSection( &m_lock );
}
//{{AFX_MSG_MAP(CConfigPropertySheet)
//}}AFX_MSG_MAP
ON_MESSAGE( WM_DATAREADY, OnDataReady )
- ON_MESSAGE( WM_REGISTRYCHANGED, OnRegistryChanged )
END_MESSAGE_MAP()
err = SetupBrowsing();
require_noerr( err, exit );
- err = SetupRegistryNotifications();
- require_noerr( err, exit );
-
exit:
return b;
{
DNSServiceProcessResult( m_browseDomainsRef );
}
- else if ( m_regDomainsRef && DNSServiceRefSockFD( m_regDomainsRef ) == (int) sock )
- {
- DNSServiceProcessResult( m_regDomainsRef );
- }
- }
-
- return 0;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CConfigPropertySheet::OnRegistryChanged
-//---------------------------------------------------------------------------------------------------------------------------
-
-afx_msg LRESULT
-CConfigPropertySheet::OnRegistryChanged( WPARAM inWParam, LPARAM inLParam )
-{
- DEBUG_UNUSED( inWParam );
- DEBUG_UNUSED( inLParam );
-
- if ( GetActivePage() == &m_firstPage )
- {
- m_firstPage.OnRegistryChanged();
}
return 0;
{
OSStatus err;
- err = TearDownRegistryNotifications();
- check_noerr( err );
-
err = TearDownBrowsing();
check_noerr( err );
}
err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, WM_DATAREADY, FD_READ|FD_CLOSE );
require_noerr( err, exit );
- // Start browsing for registration domains
-
- err = DNSServiceEnumerateDomains( &m_regDomainsRef, kDNSServiceFlagsRegistrationDomains, 0, RegDomainsReply, this );
- require_noerr( err, exit );
-
- err = WSAAsyncSelect( DNSServiceRefSockFD( m_regDomainsRef ), m_hWnd, WM_DATAREADY, FD_READ|FD_CLOSE );
- require_noerr( err, exit );
-
exit:
if ( err )
m_browseDomainsRef = NULL;
}
- if ( m_regDomainsRef )
- {
- err = WSAAsyncSelect( DNSServiceRefSockFD( m_regDomainsRef ), m_hWnd, 0, 0 );
- check_noerr( err );
-
- DNSServiceRefDeallocate( m_regDomainsRef );
-
- m_regDomainsRef = NULL;
- }
-
- return err;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CConfigPropertySheet::SetupRegistryNotifications
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CConfigPropertySheet::SetupRegistryNotifications()
-{
- unsigned int threadId;
- OSStatus err;
-
- check( m_threadExited == NULL );
- check( m_thread == NULL );
-
- err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\State\\Hostnames", &m_statusKey );
- require_noerr( err, exit );
-
- m_threadExited = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( m_threadExited, (OSStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- // Create thread with _beginthreadex() instead of CreateThread() to avoid memory leaks when using static run-time
- // libraries. See <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createthread.asp>.
-
- m_thread = (HANDLE) _beginthreadex_compat( NULL, 0, WatchRegistry, this, 0, &threadId );
- err = translate_errno( m_thread, (OSStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
-exit:
-
- if ( err )
- {
- TearDownRegistryNotifications();
- }
-
- return err;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CConfigPropertySheet::TearDownRegistryNotifications
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CConfigPropertySheet::TearDownRegistryNotifications()
-{
- OSStatus err = kNoErr;
-
- if ( m_statusKey )
- {
- EnterCriticalSection( &m_lock );
-
- RegCloseKey( m_statusKey );
- m_statusKey = NULL;
-
- LeaveCriticalSection( &m_lock );
- }
-
- if ( m_threadExited )
- {
- err = WaitForSingleObject( m_threadExited, 5 * 1000 );
- require_noerr( err, exit );
- }
-
-exit:
-
- if ( m_threadExited )
- {
- CloseHandle( m_threadExited );
- m_threadExited = NULL;
- }
-
- if ( m_thread )
- {
- CloseHandle( m_thread );
- m_thread = NULL;
- }
-
return err;
}
}
-//---------------------------------------------------------------------------------------------------------------------------
-// CConfigPropertySheet::GetNextLabel
-//---------------------------------------------------------------------------------------------------------------------------
-
-const char*
-CConfigPropertySheet::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);
-}
-
-
//---------------------------------------------------------------------------------------------------------------------------
// CConfigPropertySheet::BrowseDomainsReply
//---------------------------------------------------------------------------------------------------------------------------
goto exit;
}
-
-
err = self->DecodeDomainName( replyDomain, decoded );
require_noerr( err, exit );
return;
}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CConfigPropertySheet::RegDomainsReply
-//---------------------------------------------------------------------------------------------------------------------------
-
-void DNSSD_API
-CConfigPropertySheet::RegDomainsReply
- (
- DNSServiceRef sdRef,
- DNSServiceFlags flags,
- uint32_t interfaceIndex,
- DNSServiceErrorType errorCode,
- const char * replyDomain,
- void * context
- )
-{
- CConfigPropertySheet * self = reinterpret_cast<CConfigPropertySheet*>(context);
- CString decoded;
- OSStatus err;
-
- DEBUG_UNUSED( sdRef );
- DEBUG_UNUSED( interfaceIndex );
-
- if ( errorCode )
- {
- goto exit;
- }
-
- check( replyDomain );
-
- // Ignore local domains
-
- if ( strcmp( replyDomain, "local." ) == 0 )
- {
- goto exit;
- }
-
- err = self->DecodeDomainName( replyDomain, decoded );
- require_noerr( err, exit );
-
- // Remove trailing '.'
-
- decoded.TrimRight( '.' );
-
- if ( flags & kDNSServiceFlagsAdd )
- {
- if ( self->GetActivePage() == &self->m_secondPage )
- {
- self->m_secondPage.OnAddRegistrationDomain( decoded );
- }
-
- self->m_regDomains.push_back( decoded );
- }
- else
- {
- if ( self->GetActivePage() == &self->m_secondPage )
- {
- self->m_secondPage.OnRemoveRegistrationDomain( decoded );
- }
-
- self->m_regDomains.remove( decoded );
- }
-
-exit:
-
- return;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CConfigPropertySheet::WatchRegistry
-//---------------------------------------------------------------------------------------------------------------------------
-
-unsigned WINAPI
-CConfigPropertySheet::WatchRegistry ( LPVOID inParam )
-{
- bool done = false;
-
- CConfigPropertySheet * self = reinterpret_cast<CConfigPropertySheet*>(inParam);
- check( self );
-
- while ( !done )
- {
- RegNotifyChangeKeyValue( self->m_statusKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, NULL, FALSE );
-
- EnterCriticalSection( &self->m_lock );
-
- done = ( self->m_statusKey == NULL ) ? true : false;
-
- if ( !done )
- {
- self->PostMessage( WM_REGISTRYCHANGED, 0, 0 );
- }
-
- LeaveCriticalSection( &self->m_lock );
- }
-
- SetEvent( self->m_threadExited );
-
- return 0;
-}
* 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: 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
-
-Revision 1.4 2005/03/03 19:55:21 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#ifndef _ConfigPropertySheet_h
#define _ConfigPropertySheet_h
#include "stdafx.h"
-#include "FirstPage.h"
-#include "SecondPage.h"
-#include "ThirdPage.h"
-#include "FourthPage.h"
+#include "ServicesPage.h"
+#include "RegistrationPage.h"
+#include "BrowsingPage.h"
#include <RegNames.h>
#include <dns_sd.h>
typedef std::list<CString> StringList;
StringList m_browseDomains;
- StringList m_regDomains;
protected:
- CFirstPage m_firstPage;
- CSecondPage m_secondPage;
- CThirdPage m_thirdPage;
- CFourthPage m_fourthPage;
+ CServicesPage m_firstPage;
+ CRegistrationPage m_secondPage;
+ CBrowsingPage m_thirdPage;
//{{AFX_VIRTUAL(CConfigPropertySheet)
//}}AFX_VIRTUAL
OSStatus
TearDownBrowsing();
- OSStatus
- SetupRegistryNotifications();
-
- OSStatus
- TearDownRegistryNotifications();
-
OSStatus
DecodeDomainName( const char * raw, CString & decoded );
- const char*
- GetNextLabel( const char * cstr, char label[64] );
-
static void DNSSD_API
BrowseDomainsReply
(
void * context
);
- static void DNSSD_API
- RegDomainsReply
- (
- DNSServiceRef sdRef,
- DNSServiceFlags flags,
- uint32_t interfaceIndex,
- DNSServiceErrorType errorCode,
- const char * replyDomain,
- void * context
- );
-
// This thread will watch for registry changes
static unsigned WINAPI
HANDLE m_thread;
HANDLE m_threadExited;
DNSServiceRef m_browseDomainsRef;
- DNSServiceRef m_regDomainsRef;
CRITICAL_SECTION m_lock;
};
* 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: 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
-
-Revision 1.3 2006/08/14 23:25:28 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/03/03 19:55:22 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#include "ControlPanel.h"
; 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: ControlPanel.def,v $
-; Revision 1.4 2006/08/14 23:25:28 cheshire
-; Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-;
-; Revision 1.3 2005/03/03 19:55:22 shersche
-; <rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-;
-;
-;
LIBRARY "Bonjour"
* 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: ControlPanel.h,v $
-Revision 1.3 2006/08/14 23:25:28 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/03/03 19:55:21 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#pragma once
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-#include "WinVersRes.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
- "#define _AFX_NO_OLE_RESOURCES\r\n"
- "#define _AFX_NO_TRACKER_RESOURCES\r\n"
- "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
- "\r\n"
- "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
- "#ifdef _WIN32\r\n"
- "LANGUAGE 9, 1\r\n"
- "#pragma code_page(1252)\r\n"
- "#endif\r\n"
- "#include ""res\\ControlPanel.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
- "#include ""afxres.rc"" // Standard components\r\n"
- "#endif\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDR_APPLET ICON "res\\controlpanel.ico"
-IDI_FAILURE ICON "res\\failure.ico"
-IDI_SUCCESS ICON "res\\success.ico"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Dialog
-//
-
-IDR_APPLET_PAGE1 DIALOGEX 0, 0, 262, 140
-STYLE DS_SETFONT | WS_CHILD | WS_CAPTION
-CAPTION "Hostname"
-FONT 8, "MS Sans Serif", 0, 0, 0x0
-BEGIN
- LTEXT "Enter a hostname for this computer. Other computers on the Internet will be able to reach your computer using this hostname.",
- IDC_STATIC,10,19,245,28
- LTEXT "Hostname:",IDC_STATIC,13,55,35,8
- EDITTEXT IDC_EDIT1,55,53,184,14,ES_AUTOHSCROLL
- PUSHBUTTON "Password...",IDC_BUTTON1,55,72,65,14
- ICON IDI_FAILURE,IDC_FAILURE,240,50,20,20,SS_CENTERIMAGE |
- SS_REALSIZEIMAGE
- ICON IDI_SUCCESS,IDC_SUCCESS,240,50,20,20,SS_CENTERIMAGE |
- SS_REALSIZEIMAGE | NOT WS_VISIBLE
-END
-
-IDR_APPLET_PAGE2 DIALOGEX 0, 0, 262, 140
-STYLE DS_SETFONT | WS_CHILD | WS_CAPTION
-CAPTION "Registration"
-FONT 8, "MS Sans Serif", 0, 0, 0x0
-BEGIN
- CONTROL "Domain:",IDC_CHECK1,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,13,54,41,10
- COMBOBOX IDC_COMBO2,55,53,193,46,CBS_DROPDOWN | CBS_SORT |
- WS_DISABLED | WS_VSCROLL | WS_TABSTOP
- PUSHBUTTON "Password...",IDC_BUTTON1,55,72,65,14
- LTEXT "Check the box and enter a registration domain to enable Bonjour advertising beyond the local subnet. ",
- IDC_STATIC,10,19,233,23
-END
-
-IDR_SECRET DIALOGEX 0, 0, 251, 90
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
- WS_SYSMENU
-CAPTION "Password"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- DEFPUSHBUTTON "OK",IDOK,139,69,50,14
- PUSHBUTTON "Cancel",IDCANCEL,194,69,50,14
- LTEXT "Name:",IDC_STATIC,9,28,22,8
- EDITTEXT IDC_KEY,49,26,195,14,ES_AUTOHSCROLL
- LTEXT "Password:",IDC_STATIC,9,44,32,8
- EDITTEXT IDC_SECRET,49,42,195,14,ES_PASSWORD | ES_AUTOHSCROLL
- LTEXT "Enter a Password if your DNS server requires authentication.",
- IDC_STATIC,7,7,237,15
-END
-
-IDR_APPLET_PAGE3 DIALOGEX 0, 0, 262, 140
-STYLE DS_SETFONT | WS_CHILD | WS_CAPTION
-CAPTION "Browsing"
-FONT 8, "MS Sans Serif", 0, 0, 0x0
-BEGIN
- LTEXT "Choose which domains to browse using Wide-Area Bonjour",
- -1,7,16,248,12
- CONTROL "",IDC_BROWSE_LIST,"SysListView32",LVS_REPORT |
- LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER |
- WS_TABSTOP,7,37,248,57
- PUSHBUTTON "Add",IDC_ADD_BROWSE_DOMAIN,152,100,50,14
- 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
-CAPTION "Add Browse Domain"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- DEFPUSHBUTTON "OK",IDOK,117,74,50,14
- PUSHBUTTON "Cancel",IDCANCEL,173,74,50,14
- COMBOBOX IDC_COMBO1,35,42,188,100,CBS_DROPDOWN | CBS_SORT |
- WS_VSCROLL | WS_TABSTOP
- LTEXT "Domain:",IDC_STATIC,7,43,27,8
- LTEXT "The following domain will be added to your list of Bonjour browse domains.",
- IDC_STATIC,7,15,216,16
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// DESIGNINFO
-//
-
-#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO
-BEGIN
- IDR_APPLET_PAGE1, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 255
- TOPMARGIN, 7
- BOTTOMMARGIN, 133
- END
-
- IDR_APPLET_PAGE2, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 255
- TOPMARGIN, 7
- BOTTOMMARGIN, 133
- END
-
- IDR_SECRET, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 244
- TOPMARGIN, 7
- BOTTOMMARGIN, 83
- END
-
- IDR_APPLET_PAGE3, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 255
- TOPMARGIN, 7
- BOTTOMMARGIN, 133
- END
-
- IDR_ADD_BROWSE_DOMAIN, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 223
- TOPMARGIN, 7
- BOTTOMMARGIN, 88
- END
-END
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// String Table
-//
-
-STRINGTABLE
-BEGIN
- IDR_APPLET "Bonjour"
- IDS_APPLET_DESCRIPTION "Wide-Area Bonjour Control Panel"
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-#define _AFX_NO_SPLITTER_RESOURCES
-#define _AFX_NO_OLE_RESOURCES
-#define _AFX_NO_TRACKER_RESOURCES
-#define _AFX_NO_PROPERTY_RESOURCES
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE 9, 1
-#pragma code_page(1252)
-#endif
-#include "res\ControlPanel.rc2" // non-Microsoft Visual C++ edited resources
-#include "afxres.rc" // Standard components
-#endif
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
+// 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 "afxres.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 ""afxres.h""\r\n"\r
+ "#include ""WinVersRes.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"\r
+ "#define _AFX_NO_OLE_RESOURCES\r\n"\r
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"\r
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"\r
+ "\r\n"\r
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"\r
+ "LANGUAGE 9, 1\r\n"\r
+ "#pragma code_page(1252)\r\n"\r
+ "#include ""afxres.rc"" // Standard components\r\n"\r
+ "#endif\r\n"\r
+ "\0"\r
+END\r
+\r
+#endif // APSTUDIO_INVOKED\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Icon\r
+//\r
+\r
+// Icon with lowest ID value placed first to ensure application icon\r
+// remains consistent on all systems.\r
+IDR_APPLET ICON "res\\controlpanel.ico"\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 "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", MASTER_COMPANY_NAME\r
+ VALUE "FileDescription", "Bonjour Control Panel"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "ControlPanel.cpl"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "ControlPanel.cpl"\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, 1200\r
+ END\r
+END\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// String Table\r
+//\r
+\r
+STRINGTABLE\r
+BEGIN\r
+ IDS_REINSTALL "Bonjour Control Panel cannot run because some of its required files are missing. Please reinstall Bonjour Control Panel."\r
+ IDS_REINSTALL_CAPTION "Bonjour"\r
+END\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
+#define _AFX_NO_SPLITTER_RESOURCES\r
+#define _AFX_NO_OLE_RESOURCES\r
+#define _AFX_NO_TRACKER_RESOURCES\r
+#define _AFX_NO_PROPERTY_RESOURCES\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#include "afxres.rc" // Standard components\r
+#endif\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
ProjectType="Visual C++"\r
Version="8.00"\r
Name="ControlPanel"\r
- ProjectGUID="{F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}"\r
+ ProjectGUID="{0DF09484-B4C2-4AB4-9FC0-7B091ADEAFEB}"\r
+ RootNamespace="ControlPanel"\r
Keyword="MFCProj"\r
>\r
<Platforms>\r
<Configurations>\r
<Configuration\r
Name="Debug|Win32"\r
- OutputDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
- IntermediateDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
- ConfigurationType="2"\r
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ ConfigurationType="1"\r
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
UseOfMFC="1"\r
ATLMinimizesCRunTimeLibraryUsage="false"\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
+ MkTypLibCompatible="false"\r
/>\r
<Tool\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
+ AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared;../../Clients"\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
SuppressStartupBanner="true"\r
Detect64BitPortabilityProblems="true"\r
DebugInformationFormat="3"\r
+ CallingConvention="0"\r
DisableSpecificWarnings="4311;4312"\r
/>\r
<Tool\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
- AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
- OutputFile="$(OutDir)/Bonjour.cpl"\r
+ AdditionalDependencies="../DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib"\r
+ OutputFile="$(OutDir)/ControlPanel.exe"\r
LinkIncremental="2"\r
SuppressStartupBanner="true"\r
- ModuleDefinitionFile=".\ControlPanel.def"\r
GenerateDebugInformation="true"\r
- ProgramDatabaseFile=".\$(IntDir)\ControlPanel.pdb"\r
+ ProgramDatabaseFile="$(OutDir)\ControlPanel.pdb"\r
SubSystem="2"\r
- ImportLibrary=".\$(OutDir)\Bonjour.lib"\r
+ EntryPointSymbol="wWinMainCRTStartup"\r
TargetMachine="1"\r
/>\r
<Tool\r
</Configuration>\r
<Configuration\r
Name="Debug|x64"\r
- OutputDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
- IntermediateDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
- ConfigurationType="2"\r
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ ConfigurationType="1"\r
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
UseOfMFC="1"\r
ATLMinimizesCRunTimeLibraryUsage="false"\r
<Tool\r
Name="VCMIDLTool"\r
PreprocessorDefinitions="_DEBUG"\r
- MkTypLibCompatible="true"\r
- SuppressStartupBanner="true"\r
+ MkTypLibCompatible="false"\r
TargetEnvironment="3"\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;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+ AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared;../../Clients"\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
SuppressStartupBanner="true"\r
Detect64BitPortabilityProblems="true"\r
DebugInformationFormat="3"\r
+ CallingConvention="0"\r
DisableSpecificWarnings="4311;4312"\r
/>\r
<Tool\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
+ AdditionalDependencies="../DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib"\r
+ OutputFile="$(OutDir)/ControlPanel.exe"\r
LinkIncremental="2"\r
SuppressStartupBanner="true"\r
- ModuleDefinitionFile=".\ControlPanel.def"\r
GenerateDebugInformation="true"\r
- ProgramDatabaseFile=".\$(IntDir)\ControlPanel.pdb"\r
+ ProgramDatabaseFile="$(OutDir)\ControlPanel.pdb"\r
SubSystem="2"\r
- ImportLibrary=".\$(OutDir)\Bonjour.lib"\r
+ EntryPointSymbol="wWinMainCRTStartup"\r
TargetMachine="17"\r
/>\r
<Tool\r
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
- IntermediateDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
- ConfigurationType="2"\r
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ ConfigurationType="1"\r
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
UseOfMFC="1"\r
- ATLMinimizesCRunTimeLibraryUsage="false"\r
+ CharacterSet="2"\r
>\r
<Tool\r
Name="VCPreBuildEventTool"\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
+ MkTypLibCompatible="false"\r
/>\r
<Tool\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
+ AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared;../../Clients"\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
<Tool\r
Name="VCLinkerTool"\r
AdditionalOptions="/NXCOMPAT /DYNAMICBASE /SAFESEH"\r
- AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
- OutputFile="$(OutDir)/Bonjour.cpl"\r
+ AdditionalDependencies="../DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib"\r
+ OutputFile="$(OutDir)/ControlPanel.exe"\r
LinkIncremental="1"\r
SuppressStartupBanner="true"\r
- ModuleDefinitionFile=".\ControlPanel.def"\r
- ProgramDatabaseFile=".\$(IntDir)\ControlPanel.pdb"\r
+ ProgramDatabaseFile="$(OutDir)\ControlPanel.pdb"\r
SubSystem="2"\r
- ImportLibrary=".\$(OutDir)\Bonjour.lib"\r
+ OptimizeReferences="0"\r
+ EnableCOMDATFolding="0"\r
+ EntryPointSymbol="wWinMainCRTStartup"\r
TargetMachine="1"\r
/>\r
<Tool\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
Name="Release|x64"\r
- OutputDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
- IntermediateDirectory="DLLBuild\$(PlatformName)\$(ConfigurationName)"\r
- ConfigurationType="2"\r
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ ConfigurationType="1"\r
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
UseOfMFC="1"\r
- ATLMinimizesCRunTimeLibraryUsage="false"\r
+ CharacterSet="2"\r
>\r
<Tool\r
Name="VCPreBuildEventTool"\r
<Tool\r
Name="VCMIDLTool"\r
PreprocessorDefinitions="NDEBUG"\r
- MkTypLibCompatible="true"\r
- SuppressStartupBanner="true"\r
+ MkTypLibCompatible="false"\r
TargetEnvironment="3"\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;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1"\r
+ AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared;../../Clients"\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
<Tool\r
Name="VCLinkerTool"\r
AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
- AdditionalDependencies="../DLL/$(PlatformName)/$(ConfigurationName)/dnssd.lib ws2_32.lib"\r
- OutputFile="$(OutDir)/Bonjour.cpl"\r
+ AdditionalDependencies="../DLLStub/$(PlatformName)/$(ConfigurationName)/dnssdStatic.lib ws2_32.lib"\r
+ OutputFile="$(OutDir)/ControlPanel.exe"\r
LinkIncremental="1"\r
SuppressStartupBanner="true"\r
- ModuleDefinitionFile=".\ControlPanel.def"\r
- ProgramDatabaseFile=".\$(IntDir)\ControlPanel.pdb"\r
+ ProgramDatabaseFile="$(OutDir)\ControlPanel.pdb"\r
SubSystem="2"\r
- ImportLibrary=".\$(OutDir)\Bonjour.lib"\r
+ OptimizeReferences="0"\r
+ EnableCOMDATFolding="0"\r
+ EntryPointSymbol="wWinMainCRTStartup"\r
TargetMachine="17"\r
/>\r
<Tool\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\r
</FileConfiguration>\r
</File>\r
<File\r
- RelativePath="ControlPanel.cpp"\r
+ RelativePath=".\ControlPanelExe.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|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
- />\r
- </FileConfiguration>\r
</File>\r
<File\r
- RelativePath="ControlPanel.def"\r
+ RelativePath=".\ServicesPage.cpp"\r
>\r
</File>\r
<File\r
- RelativePath="FirstPage.cpp"\r
+ RelativePath="RegistrationPage.cpp"\r
>\r
<FileConfiguration\r
Name="Debug|Win32"\r
</FileConfiguration>\r
</File>\r
<File\r
- RelativePath=".\FourthPage.cpp"\r
- >\r
- </File>\r
- <File\r
- RelativePath="SecondPage.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|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
- />\r
- </FileConfiguration>\r
- </File>\r
- <File\r
- RelativePath="SharedSecret.cpp"\r
+ RelativePath="..\loclibrary.c"\r
>\r
</File>\r
<File\r
</FileConfiguration>\r
</File>\r
<File\r
- RelativePath="ThirdPage.cpp"\r
+ RelativePath="BrowsingPage.cpp"\r
>\r
</File>\r
</Filter>\r
>\r
</File>\r
<File\r
- RelativePath="ControlPanel.h"\r
+ RelativePath=".\ControlPanelExe.h"\r
>\r
</File>\r
<File\r
- RelativePath="FirstPage.h"\r
+ RelativePath=".\ServicesPage.h"\r
>\r
</File>\r
<File\r
- RelativePath=".\FourthPage.h"\r
+ RelativePath="RegistrationPage.h"\r
>\r
</File>\r
<File\r
- RelativePath="Resource.h"\r
+ RelativePath="..\loclibrary.h"\r
>\r
</File>\r
<File\r
- RelativePath="SecondPage.h"\r
- >\r
- </File>\r
- <File\r
- RelativePath="SharedSecret.h"\r
+ RelativePath="Resource.h"\r
>\r
</File>\r
<File\r
>\r
</File>\r
<File\r
- RelativePath="ThirdPage.h"\r
+ RelativePath="BrowsingPage.h"\r
>\r
</File>\r
</Filter>\r
RelativePath="res\controlpanel.ico"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\ControlPanel.rc"\r
+ >\r
+ </File>\r
<File\r
RelativePath=".\res\ControlPanel.rc2"\r
>\r
</File>\r
<File\r
- RelativePath=".\ControlPanelDll.rc"\r
+ RelativePath=".\res\EnergySaver.ico"\r
>\r
</File>\r
<File\r
<Filter\r
Name="Support"\r
>\r
+ <File\r
+ RelativePath="..\..\Clients\ClientCommon.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\Clients\ClientCommon.h"\r
+ >\r
+ </File>\r
<File\r
RelativePath="..\..\mDNSShared\CommonServices.h"\r
>\r
</Filter>\r
</Files>\r
<Globals>\r
- <Global\r
- Name="RESOURCE_FILE"\r
- Value="ControlPanelDll.rc"\r
- />\r
</Globals>\r
</VisualStudioProject>\r
* 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: ControlPanelExe.cpp,v $
-Revision 1.3 2007/04/27 21:43:00 herscher
-Update license info to Apache License, Version 2.0
-
-Revision 1.2 2007/04/27 20:42:12 herscher
-<rdar://problem/5078828> mDNS: Bonjour Control Panel for Windows doesn't work on Vista
-
-Revision 1.1.2.1 2007/04/27 18:13:55 herscher
-<rdar://problem/5078828> mDNS: Bonjour Control Panel for Windows doesn't work on Vista
-
-
-
-*/
+ */
#include "ControlPanelExe.h"
#include "resource.h"
#include <DebugServices.h>
+#include "loclibrary.h"
#ifdef _DEBUG
static char THIS_FILE[] = __FILE__;
#endif
+#ifndef HeapEnableTerminationOnCorruption
+# define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS) 1
+#endif
+
+
+// Stash away pointers to our resource DLLs
+
+static HINSTANCE g_nonLocalizedResources = NULL;
+static HINSTANCE g_localizedResources = NULL;
+
+
+HINSTANCE GetNonLocalizedResources()
+{
+ return g_nonLocalizedResources;
+}
+
+
+HINSTANCE GetLocalizedResources()
+{
+ return g_localizedResources;
+}
+
+
//---------------------------------------------------------------------------------------------------------------------------
// Static Declarations
//---------------------------------------------------------------------------------------------------------------------------
-DEFINE_GUID(CLSID_ControlPanel, \r
-0x1207552c, 0xe59, 0x4d9f, 0x85, 0x54, 0xf1, 0xf8, 0x6, 0xcd, 0x7f, 0xa9);\r
-\r
+DEFINE_GUID(CLSID_ControlPanel,
+
+0x1207552c, 0xe59, 0x4d9f, 0x85, 0x54, 0xf1, 0xf8, 0x6, 0xcd, 0x7f, 0xa9);
+
static LPCTSTR g_controlPanelGUID = TEXT( "{1207552C-0E59-4d9f-8554-F1F806CD7FA9}" );
-static LPCTSTR g_controlPanelName = TEXT( "Bonjour Control Panel" );
+static LPCTSTR g_controlPanelName = TEXT( "Bonjour" );
+static LPCTSTR g_controlPanelCanonicalName = TEXT( "Apple.Bonjour" );
static LPCTSTR g_controlPanelCategory = TEXT( "3,8" );
-static LPCTSTR g_controlPanelLocalizedName = g_controlPanelName;
-static LPCTSTR g_controlPanelInfoTip = TEXT( "Configures Wide-Area Bonjour" );
static CCPApp theApp;
void
-CCPApp::Register( LPCTSTR inClsidString, LPCTSTR inName, LPCTSTR inCategory, LPCTSTR inLocalizedName, LPCTSTR inInfoTip, LPCTSTR inIconPath, LPCTSTR inExePath )
+CCPApp::Register( LPCTSTR inClsidString, LPCTSTR inName, LPCTSTR inCanonicalName, LPCTSTR inCategory, LPCTSTR inLocalizedName, LPCTSTR inInfoTip, LPCTSTR inIconPath, LPCTSTR inExePath )
{
typedef struct RegistryBuilder RegistryBuilder;
{
{ HKEY_LOCAL_MACHINE, TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace\\%s" ), NULL, REG_SZ, inName },
{ HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s" ), NULL, NULL, NULL },
- { HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s" ), TEXT( "System.ApplicationName" ), REG_SZ, inName },
+ { HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s" ), TEXT( "System.ApplicationName" ), REG_SZ, inCanonicalName },
{ HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s" ), TEXT( "System.ControlPanel.Category" ), REG_SZ, inCategory },
{ HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s" ), TEXT( "LocalizedString" ), REG_SZ, inLocalizedName },
{ HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s" ), TEXT( "InfoTip" ), REG_SZ, inInfoTip },
CCPApp::InitInstance()
{
CCommandLineInfo commandLine;
+ wchar_t resource[MAX_PATH];
+ CString errorMessage;
+ CString errorCaption;
+ int res;
OSStatus err = kNoErr;
+ HeapSetInformation( NULL, HeapEnableTerminationOnCorruption, NULL, 0 );
+
+ //
+ // initialize the debugging framework
+ //
+ debug_initialize( kDebugOutputTypeWindowsDebugger, "ControlPanel", NULL );
+ debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
+
+ // Before we load the resources, let's load the error string
+
+ errorMessage.LoadString( IDS_REINSTALL );
+ errorCaption.LoadString( IDS_REINSTALL_CAPTION );
+
+ res = PathForResource( NULL, L"ControlPanelResources.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 );
+
+ res = PathForResource( NULL, L"ControlPanelLocalized.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 );
+
// InitCommonControls() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
if ( commandLine.m_nShellCommand == CCommandLineInfo::AppRegister )
{
+ CString localizedName;
+ CString toolTip;
TCHAR iconPath[ MAX_PATH + 12 ] = TEXT( "" );
TCHAR exePath[ MAX_PATH ] = TEXT( "" );
DWORD nChars;
OSStatus err;
- nChars = GetModuleFileName( NULL, exePath, sizeof_array( exePath ) );\r
- err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );\r
+ nChars = GetModuleFileName( NULL, exePath, sizeof_array( exePath ) );
+
+ err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
+
require_noerr( err, exit );
wsprintf( iconPath, L"%s,-%d", exePath, IDR_APPLET );
- Register( g_controlPanelGUID, g_controlPanelName, g_controlPanelCategory, g_controlPanelName, g_controlPanelInfoTip, iconPath, exePath );
+ localizedName.LoadString( IDS_APPLET_NAME );
+ toolTip.LoadString( IDS_APPLET_TOOLTIP );
+
+ Register( g_controlPanelGUID, g_controlPanelName, g_controlPanelCanonicalName, g_controlPanelCategory, localizedName, toolTip, iconPath, exePath );
}
else if ( commandLine.m_nShellCommand == CCommandLineInfo::AppUnregister )
{
exit:
+ if ( err )
+ {
+ MessageBox( NULL, errorMessage, errorCaption, MB_ICONERROR | MB_OK );
+ }
+
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
* 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: ControlPanelExe.h,v $
-Revision 1.3 2007/04/27 21:43:00 herscher
-Update license info to Apache License, Version 2.0
-
-Revision 1.2 2007/04/27 20:42:12 herscher
-<rdar://problem/5078828> mDNS: Bonjour Control Panel for Windows doesn't work on Vista
-
-Revision 1.1.2.1 2007/04/27 18:13:55 herscher
-<rdar://problem/5078828> mDNS: Bonjour Control Panel for Windows doesn't work on Vista
-
-
-*/
+ */
#pragma once
-#include "stdafx.h"
+#include "stdafx.h"\r
+extern HINSTANCE GetNonLocalizedResources();
+extern HINSTANCE GetLocalizedResources();
//-------------------------------------------------
// CCPApp
virtual BOOL InitInstance();
void
- Register( LPCTSTR inClsidString, LPCTSTR inName, LPCTSTR inCategory, LPCTSTR inLocalizedName, LPCTSTR inInfoTip, LPCTSTR inIconPath, LPCTSTR inExePath );
+ Register( LPCTSTR inClsidString, LPCTSTR inName, LPCTSTR inCanonicalName, LPCTSTR inCategory, LPCTSTR inLocalizedName, LPCTSTR inInfoTip, LPCTSTR inIconPath, LPCTSTR inExePath );
void
Unregister( LPCTSTR clsidString );
RelativePath=".\ControlPanelExe.cpp"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\FifthPage.cpp"\r
+ >\r
+ </File>\r
<File\r
RelativePath="FirstPage.cpp"\r
>\r
RelativePath=".\ControlPanelExe.h"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\FifthPage.h"\r
+ >\r
+ </File>\r
<File\r
RelativePath="FirstPage.h"\r
>\r
--- /dev/null
+// 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 "afxres.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 ""afxres.h""\r\n"\r
+ "#include ""WinVersRes.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"\r
+ "#define _AFX_NO_OLE_RESOURCES\r\n"\r
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"\r
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"\r
+ "\r\n"\r
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"\r
+ "LANGUAGE 9, 1\r\n"\r
+ "#pragma code_page(1252)\r\n"\r
+ "#include ""afxres.rc"" // Standard components\r\n"\r
+ "#endif\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 "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", MASTER_COMPANY_NAME\r
+ VALUE "FileDescription", "Bonjour Resource Module"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "ControlPanelLocalized.dll"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "ControlPanelLocalized.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, 1200\r
+ END\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Dialog\r
+//\r
+\r
+IDR_APPLET_PAGE1 DIALOGEX 0, 0, 262, 140\r
+STYLE DS_SETFONT | WS_CHILD | WS_CAPTION\r
+CAPTION "Registration"\r
+FONT 8, "MS Sans Serif", 0, 0, 0x0\r
+BEGIN\r
+ LTEXT "Hostname:",IDC_STATIC,13,22,35,8\r
+ EDITTEXT IDC_HOSTNAME,55,20,184,12,ES_AUTOHSCROLL\r
+ LTEXT "User:",IDC_STATIC,13,38,35,8\r
+ EDITTEXT IDC_USERNAME,55,36,184,12,ES_AUTOHSCROLL\r
+ LTEXT "Password:",IDC_STATIC,13,54,35,8\r
+ EDITTEXT IDC_PASSWORD,55,52,184,12,ES_PASSWORD | ES_AUTOHSCROLL\r
+ CONTROL "Advertise services in this domain using Bonjour",IDC_ADVERTISE_SERVICES,\r
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,55,80,199,8\r
+END\r
+\r
+IDR_APPLET_PAGE3 DIALOGEX 0, 0, 262, 140\r
+STYLE DS_SETFONT | WS_CHILD | WS_CAPTION\r
+CAPTION "Browsing"\r
+FONT 8, "MS Sans Serif", 0, 0, 0x0\r
+BEGIN\r
+ LTEXT "Choose which domains to browse using wide-area Bonjour",\r
+ -1,7,16,248,12\r
+ CONTROL "",IDC_BROWSE_LIST,"SysListView32",LVS_REPORT | \r
+ LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | \r
+ WS_TABSTOP,7,37,248,57\r
+ PUSHBUTTON "Add",IDC_ADD_BROWSE_DOMAIN,152,100,50,14\r
+ PUSHBUTTON "Remove",IDC_REMOVE_BROWSE_DOMAIN,205,100,50,14\r
+END\r
+\r
+IDR_APPLET_PAGE5 DIALOGEX 0, 0, 262, 140\r
+STYLE DS_SETFONT | WS_CHILD | WS_CAPTION\r
+CAPTION "Services"\r
+FONT 8, "MS Sans Serif", 0, 0, 0x0\r
+BEGIN\r
+ CONTROL "Advertise shared folders using Bonjour",IDC_ADVERTISE_SMB,\r
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,19,199,8\r
+ CONTROL "Enable Wake on Demand",IDC_POWER_MANAGEMENT,\r
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,34,199,8\r
+END\r
+\r
+IDR_POWER_MANAGEMENT_WARNING DIALOGEX 0, 0, 230, 95\r
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
+ WS_SYSMENU\r
+CAPTION "Power Management"\r
+FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
+BEGIN\r
+ DEFPUSHBUTTON "OK",IDOK,173,74,50,14\r
+ LTEXT "When 'Wake On Demand' is enabled, you may hear your computer wake up occasionally.",\r
+ IDC_STATIC,50,12,175,26\r
+ LTEXT "This informs other devices that your computer is still available on the network.",\r
+ IDC_STATIC,50,38,175,26\r
+ ICON IDI_ENERGY_SAVER,IDC_ENERGY_SAVER,2,10,64,64,SS_REALSIZEIMAGE\r
+END\r
+\r
+IDR_ADD_BROWSE_DOMAIN DIALOGEX 0, 0, 230, 95\r
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
+ WS_SYSMENU\r
+CAPTION "Add Browse Domain"\r
+FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
+BEGIN\r
+ DEFPUSHBUTTON "OK",IDOK,117,74,50,14\r
+ PUSHBUTTON "Cancel",IDCANCEL,173,74,50,14\r
+ COMBOBOX IDC_COMBO1,35,42,188,100,CBS_DROPDOWN | CBS_SORT | \r
+ WS_VSCROLL | WS_TABSTOP\r
+ LTEXT "Domain:",IDC_STATIC,7,43,27,8\r
+ LTEXT "The following domain will be added to your list of Bonjour browse domains.",\r
+ IDC_STATIC,7,15,216,16\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// DESIGNINFO\r
+//\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+GUIDELINES DESIGNINFO \r
+BEGIN\r
+ IDR_APPLET_PAGE1, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 255\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 133\r
+ END\r
+\r
+ IDR_APPLET_PAGE2, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 255\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 133\r
+ END\r
+\r
+ IDR_SECRET, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 244\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 83\r
+ END\r
+\r
+ IDR_APPLET_PAGE3, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 255\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 133\r
+ END\r
+\r
+ IDR_POWER_MANAGEMENT_WARNING, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 223\r
+ TOPMARGIN, 7,\r
+ BOTTOMMARGIN, 88\r
+ END\r
+\r
+ IDR_ADD_BROWSE_DOMAIN, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 223\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 88\r
+ END\r
+END\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// String Table\r
+//\r
+\r
+STRINGTABLE \r
+BEGIN\r
+ IDR_APPLET "Bonjour"\r
+ IDS_APPLET_NAME "Bonjour"\r
+ IDS_APPLET_DESCRIPTION "Bonjour"\r
+ IDS_APPLET_TOOLTIP "Change Bonjour settings for this computer."\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
+#define _AFX_NO_SPLITTER_RESOURCES\r
+#define _AFX_NO_OLE_RESOURCES\r
+#define _AFX_NO_TRACKER_RESOURCES\r
+#define _AFX_NO_PROPERTY_RESOURCES\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#include "afxres.rc" // Standard components\r
+#endif\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="8.00"\r
+ Name="ControlPanelLocRes"\r
+ ProjectGUID="{4490229E-025A-478F-A2CF-51154DA83E39}"\r
+ RootNamespace="ControlPanelLocRes"\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
+ 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
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories=".."\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="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories=".."\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist $(OutDir)\ControlPanel.Resources mkdir $(OutDir)\ControlPanel.Resources
if not exist $(OutDir)\ControlPanel.Resources\en.lproj mkdir $(OutDir)\ControlPanel.Resources\en.lproj
"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ AdditionalDependencies=""\r
+ OutputFile="$(OutDir)\ControlPanel.Resources\en.lproj\ControlPanelLocalized.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
+ />\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="3"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories=".."\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="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories=".."\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist $(OutDir)\ControlPanel.Resources mkdir $(OutDir)\ControlPanel.Resources
if not exist $(OutDir)\ControlPanel.Resources\en.lproj mkdir $(OutDir)\ControlPanel.Resources\en.lproj
"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ AdditionalDependencies=""\r
+ OutputFile="$(OutDir)\ControlPanel.Resources\en.lproj\ControlPanelLocalized.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="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
+ 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
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="2"\r
+ FavorSizeOrSpeed="2"\r
+ OmitFramePointers="true"\r
+ AdditionalIncludeDirectories=".."\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="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories=".."\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist $(OutDir)\ControlPanel.Resources mkdir $(OutDir)\ControlPanel.Resources
if not exist $(OutDir)\ControlPanel.Resources\en.lproj mkdir $(OutDir)\ControlPanel.Resources\en.lproj
"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ AdditionalDependencies=""\r
+ OutputFile="$(OutDir)\ControlPanel.Resources\en.lproj\ControlPanelLocalized.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
+ />\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 "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources\en.lproj"
: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="3"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="2"\r
+ FavorSizeOrSpeed="2"\r
+ OmitFramePointers="true"\r
+ AdditionalIncludeDirectories=".."\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="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories=".."\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist $(OutDir)\ControlPanel.Resources mkdir $(OutDir)\ControlPanel.Resources
if not exist $(OutDir)\ControlPanel.Resources\en.lproj mkdir $(OutDir)\ControlPanel.Resources\en.lproj
"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ AdditionalDependencies=""\r
+ OutputFile="$(OutDir)\ControlPanel.Resources\en.lproj\ControlPanelLocalized.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="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 "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources\en.lproj" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources\en.lproj"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources\en.lproj"
:END
"\r
+ />\r
+ </Configuration>\r
+ </Configurations>\r
+ <References>\r
+ </References>\r
+ <Files>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc"\r
+ >\r
+ <File\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
+ >\r
+ <File\r
+ RelativePath="ControlPanelLocRes.rc"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ <Global\r
+ Name="RESOURCE_FILE"\r
+ Value="ControlPanelLocRes.rc"\r
+ />\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+// 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 "afxres.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 ""afxres.h""\r\n"\r
+ "#include ""WinVersRes.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"\r
+ "#define _AFX_NO_OLE_RESOURCES\r\n"\r
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"\r
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"\r
+ "\r\n"\r
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"\r
+ "LANGUAGE 9, 1\r\n"\r
+ "#pragma code_page(1252)\r\n"\r
+ "#include ""afxres.rc"" // Standard components\r\n"\r
+ "#endif\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 "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", MASTER_COMPANY_NAME\r
+ VALUE "FileDescription", "Bonjour Resource Module"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "ControlPanelResources.dll"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "ControlPanelResources.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, 1200\r
+ END\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Icon\r
+//\r
+\r
+// Icon with lowest ID value placed first to ensure application icon\r
+// remains consistent on all systems.\r
+IDR_APPLET ICON "res\\controlpanel.ico"\r
+IDI_FAILURE ICON "res\\failure.ico"\r
+IDI_SUCCESS ICON "res\\success.ico"\r
+IDI_ENERGY_SAVER ICON "res\\EnergySaver.ico"\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
+#define _AFX_NO_SPLITTER_RESOURCES\r
+#define _AFX_NO_OLE_RESOURCES\r
+#define _AFX_NO_TRACKER_RESOURCES\r
+#define _AFX_NO_PROPERTY_RESOURCES\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#include "afxres.rc" // Standard components\r
+#endif\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="8.00"\r
+ Name="ControlPanelRes"\r
+ ProjectGUID="{5254AA9C-3D2E-4539-86D9-5EB0F4151215}"\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
+ 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
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories=".."\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="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories=".."\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist $(OutDir)\ControlPanel.Resources mkdir $(OutDir)\ControlPanel.Resources
"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ OutputFile="$(OutDir)\ControlPanel.Resources\ControlPanelResources.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
+ />\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="3"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories=".."\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="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories=".."\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist $(OutDir)\ControlPanel.Resources mkdir $(OutDir)\ControlPanel.Resources
"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ OutputFile="$(OutDir)\ControlPanel.Resources\ControlPanelResources.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="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
+ 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
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="2"\r
+ FavorSizeOrSpeed="2"\r
+ OmitFramePointers="true"\r
+ AdditionalIncludeDirectories="..\..\mDNSShared;.."\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="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories=".."\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist $(OutDir)\ControlPanel.Resources mkdir $(OutDir)\ControlPanel.Resources
"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ OutputFile="$(OutDir)\ControlPanel.Resources\ControlPanelResources.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
+ />\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 "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources"
: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="3"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="2"\r
+ FavorSizeOrSpeed="2"\r
+ OmitFramePointers="true"\r
+ AdditionalIncludeDirectories="..\..\mDNSShared;.."\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="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories=".."\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist $(OutDir)\ControlPanel.Resources mkdir $(OutDir)\ControlPanel.Resources
"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ OutputFile="$(OutDir)\ControlPanel.Resources\ControlPanelResources.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="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 "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour SDK\bin\$(PlatformName)\ControlPanel.Resources"
:END
"\r
+ />\r
+ </Configuration>\r
+ </Configurations>\r
+ <References>\r
+ </References>\r
+ <Files>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc"\r
+ >\r
+ <File\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
+ >\r
+ <File\r
+ RelativePath="res\about.bmp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\about.bmp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="res\button-2k.ico"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="res\button-xp.ico"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\res\cold.ico"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="ControlPanelRes.rc"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\hot.ico"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="res\logo.bmp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\logo.bmp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="Web.ico"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ <Global\r
+ Name="RESOURCE_FILE"\r
+ Value="ControlPanelRes.rc"\r
+ />\r
+ </Globals>\r
+</VisualStudioProject>\r
+++ /dev/null
-/* -*- 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: 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
-
-Revision 1.5 2005/10/05 20:46:50 herscher
-<rdar://problem/4192011> Move Wide-Area preferences to another part of the registry so they don't removed during an update-install.
-
-Revision 1.4 2005/04/05 03:52:14 shersche
-<rdar://problem/4066485> Registering with shared secret key doesn't work. Additionally, mDNSResponder wasn't dynamically re-reading it's DynDNS setup after setting a shared secret key.
-
-Revision 1.3 2005/03/07 18:27:42 shersche
-<rdar://problem/4037940> Fix problem when ControlPanel commits changes to the browse domain list
-
-Revision 1.2 2005/03/03 19:55:22 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
-
-#include "FirstPage.h"
-#include "resource.h"
-
-#include "ConfigPropertySheet.h"
-#include "SharedSecret.h"
-
-#define MAX_KEY_LENGTH 255
-
-
-IMPLEMENT_DYNCREATE(CFirstPage, CPropertyPage)
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::CFirstPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CFirstPage::CFirstPage()
-:
- CPropertyPage(CFirstPage::IDD),
- m_ignoreHostnameChange( false ),
- m_statusKey( NULL ),
- m_setupKey( NULL )
-{
- //{{AFX_DATA_INIT(CFirstPage)
- //}}AFX_DATA_INIT
-
- OSStatus err;
-
- err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\State\\Hostnames", &m_statusKey );
- check_noerr( err );
-
- err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\Hostnames", &m_setupKey );
- check_noerr( err );
-}
-
-CFirstPage::~CFirstPage()
-{
- if ( m_statusKey )
- {
- RegCloseKey( m_statusKey );
- m_statusKey = NULL;
- }
-
- if ( m_setupKey )
- {
- RegCloseKey( m_setupKey );
- m_setupKey = NULL;
- }
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::DoDataExchange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CFirstPage::DoDataExchange(CDataExchange* pDX)
-{
- CPropertyPage::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CFirstPage)
- //}}AFX_DATA_MAP
- DDX_Control(pDX, IDC_EDIT1, m_hostnameControl);
- DDX_Control(pDX, IDC_FAILURE, m_failureIcon);
- DDX_Control(pDX, IDC_SUCCESS, m_successIcon);
-}
-
-BEGIN_MESSAGE_MAP(CFirstPage, CPropertyPage)
- //{{AFX_MSG_MAP(CFirstPage)
- //}}AFX_MSG_MAP
- ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedSharedSecret)
- ON_EN_CHANGE(IDC_EDIT1, OnEnChangeHostname)
-END_MESSAGE_MAP()
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::OnEnChangedHostname
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CFirstPage::OnEnChangeHostname()
-{
- if ( !m_ignoreHostnameChange )
- {
- SetModified( TRUE );
- }
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::OnBnClickedSharedSecret
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CFirstPage::OnBnClickedSharedSecret()
-{
- CString name;
-
- m_hostnameControl.GetWindowText( name );
-
- CSharedSecret dlg;
-
- dlg.Load( name );
-
- if ( dlg.DoModal() == IDOK )
- {
- DWORD wakeup = 0;
- DWORD dwSize = sizeof( DWORD );
- OSStatus err;
-
- dlg.Commit( name );
-
- // We have now updated the secret, however the system service
- // doesn't know about it yet. So we're going to update the
- // registry with a dummy value which will cause the system
- // service to re-initialize it's DynDNS setup
- //
-
- RegQueryValueEx( m_setupKey, L"Wakeup", NULL, NULL, (LPBYTE) &wakeup, &dwSize );
-
- wakeup++;
-
- err = RegSetValueEx( m_setupKey, L"Wakeup", 0, REG_DWORD, (LPBYTE) &wakeup, sizeof( DWORD ) );
- require_noerr( err, exit );
- }
-
-exit:
-
- return;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::SetModified
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CFirstPage::SetModified( BOOL bChanged )
-{
- m_modified = bChanged ? true : false;
-
- CPropertyPage::SetModified( bChanged );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::OnSetActive
-//---------------------------------------------------------------------------------------------------------------------------
-
-BOOL
-CFirstPage::OnSetActive()
-{
- TCHAR name[kDNSServiceMaxDomainName + 1];
- DWORD nameLen = ( kDNSServiceMaxDomainName + 1 ) * sizeof( TCHAR );
- DWORD err;
-
- BOOL b = CPropertyPage::OnSetActive();
-
- m_modified = FALSE;
-
- if ( m_setupKey )
- {
- err = RegQueryValueEx( m_setupKey, L"", NULL, NULL, (LPBYTE) name, &nameLen );
-
- if ( !err )
- {
- m_ignoreHostnameChange = true;
- m_hostnameControl.SetWindowText( name );
- m_ignoreHostnameChange = false;
- }
- }
-
- // Check the status of this hostname
-
- err = CheckStatus();
- check_noerr( err );
-
- return b;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::OnOK
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CFirstPage::OnOK()
-{
- if ( m_modified )
- {
- Commit();
- }
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::Commit
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CFirstPage::Commit()
-{
- DWORD enabled = 1;
- CString name;
- DWORD err;
-
- m_hostnameControl.GetWindowText( name );
-
- // Convert to lower case
-
- name.MakeLower();
-
- // Remove trailing dot
-
- name.TrimRight( '.' );
-
- err = RegSetValueEx( m_setupKey, L"", 0, REG_SZ, (LPBYTE) (LPCTSTR) name, ( name.GetLength() + 1 ) * sizeof( TCHAR ) );
- require_noerr( err, exit );
-
- err = RegSetValueEx( m_setupKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
- require_noerr( err, exit );
-
-exit:
-
- return;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::CheckStatus
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CFirstPage::CheckStatus()
-{
- DWORD status = 0;
- DWORD dwSize = sizeof( DWORD );
- OSStatus err;
-
- // Get the status field
-
- err = RegQueryValueEx( m_statusKey, L"Status", NULL, NULL, (LPBYTE) &status, &dwSize );
- require_noerr( err, exit );
-
- ShowStatus( status );
-
-exit:
-
- return kNoErr;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::ShowStatus
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CFirstPage::ShowStatus( DWORD status )
-{
- if ( status )
- {
- m_failureIcon.ShowWindow( SW_HIDE );
- m_successIcon.ShowWindow( SW_SHOW );
- }
- else
- {
- m_failureIcon.ShowWindow( SW_SHOW );
- m_successIcon.ShowWindow( SW_HIDE );
- }
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage::OnRegistryChanged
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CFirstPage::OnRegistryChanged()
-{
- CheckStatus();
-}
+++ /dev/null
-/* -*- 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: FirstPage.h,v $
-Revision 1.4 2006/08/14 23:25:28 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2005/03/07 18:27:42 shersche
-<rdar://problem/4037940> Fix problem when ControlPanel commits changes to the browse domain list
-
-Revision 1.2 2005/03/03 19:55:21 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
-
-#pragma once
-
-#include "stdafx.h"
-#include "resource.h"
-
-#include <DebugServices.h>
-#include "afxwin.h"
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CFirstPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CFirstPage : public CPropertyPage
-{
-public:
- CFirstPage();
- ~CFirstPage();
-
-protected:
- //{{AFX_DATA(CFirstPage)
- enum { IDD = IDR_APPLET_PAGE1 };
- //}}AFX_DATA
-
- //{{AFX_VIRTUAL(CFirstPage)
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
- DECLARE_DYNCREATE(CFirstPage)
-
- //{{AFX_MSG(CFirstPage)
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-public:
- afx_msg void OnBnClickedSharedSecret();
- void OnRegistryChanged();
-private:
-
- afx_msg BOOL OnSetActive();
- afx_msg void OnOK();
-
- void SetModified( BOOL bChanged = TRUE );
- void Commit();
-
- OSStatus CheckStatus();
- void ShowStatus( DWORD status );
-
- CEdit m_hostnameControl;
- bool m_ignoreHostnameChange;
- bool m_modified;
- HKEY m_statusKey;
- HKEY m_setupKey;
-
-public:
-
- afx_msg void OnEnChangeHostname();
- CStatic m_failureIcon;
- CStatic m_successIcon;
-};
* 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"
BEGIN_MESSAGE_MAP(CFourthPage, CPropertyPage)
//{{AFX_MSG_MAP(CFourthPage)
- //}}AFX_MSG_MAP\r
- ON_BN_CLICKED(IDC_POWER_MANAGEMENT, &CFourthPage::OnBnClickedPowerManagement)\r
+ //}}AFX_MSG_MAP
+
+ ON_BN_CLICKED(IDC_POWER_MANAGEMENT, &CFourthPage::OnBnClickedPowerManagement)
+
END_MESSAGE_MAP()
// Now populate the browse domain box
- err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", &key );
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
require_noerr( err, exit );
dwSize = sizeof( DWORD );
DWORD enabled;
DWORD err;
- err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", &key );
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
require_noerr( err, exit );
enabled = m_checkBox.GetCheck();
// 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
+
+
+void CFourthPage::OnBnClickedPowerManagement()
+
+{
+
+ char buf[ 256 ];
+
+
+
+ sprintf( buf, "check box: %d", m_checkBox.GetCheck() );
+
+ OutputDebugStringA( buf );
+
+ // TODO: Add your control notification handler code here
+
+
+
+ SetModified( TRUE );
+
+}
+
* 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
CButton m_checkBox;
public:
-\r
- afx_msg void OnBnClickedPowerManagement();\r
+
+
+ afx_msg void OnBnClickedPowerManagement();
+
};
--- /dev/null
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Secret.h>
+#include "RegistrationPage.h"
+#include "resource.h"
+
+#include "ConfigPropertySheet.h"
+extern "C"
+{
+#include <ClientCommon.h>
+}
+#include <WinServices.h>
+
+#define MAX_KEY_LENGTH 255
+
+
+IMPLEMENT_DYNCREATE(CRegistrationPage, CPropertyPage)
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::CRegistrationPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CRegistrationPage::CRegistrationPage()
+:
+ CPropertyPage(CRegistrationPage::IDD),
+ m_ignoreChanges( false ),
+ m_hostnameSetupKey( NULL ),
+ m_registrationSetupKey( NULL ),
+ m_statusKey( NULL )
+{
+ //{{AFX_DATA_INIT(CRegistrationPage)
+ //}}AFX_DATA_INIT
+
+ OSStatus err;
+
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\Hostnames", 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &m_hostnameSetupKey, NULL );
+ check_noerr( err );
+
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &m_registrationSetupKey, NULL );
+ check_noerr( err );
+
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\State\\Hostnames", 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &m_statusKey, NULL );
+ check_noerr( err );
+
+
+}
+
+CRegistrationPage::~CRegistrationPage()
+{
+ if ( m_hostnameSetupKey )
+ {
+ RegCloseKey( m_hostnameSetupKey );
+ m_hostnameSetupKey = NULL;
+ }
+
+ if ( m_registrationSetupKey )
+ {
+ RegCloseKey( m_registrationSetupKey );
+ m_registrationSetupKey = NULL;
+ }
+
+ if ( m_statusKey )
+ {
+ RegCloseKey( m_statusKey );
+ m_statusKey = NULL;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::DoDataExchange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CRegistrationPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CRegistrationPage)
+ //}}AFX_DATA_MAP
+ DDX_Control(pDX, IDC_HOSTNAME, m_hostnameControl);
+ DDX_Control(pDX, IDC_USERNAME, m_usernameControl);
+ DDX_Control(pDX, IDC_PASSWORD, m_passwordControl);
+ DDX_Control(pDX, IDC_ADVERTISE_SERVICES, m_advertiseServices);
+}
+
+BEGIN_MESSAGE_MAP(CRegistrationPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CRegistrationPage)
+ //}}AFX_MSG_MAP
+ ON_EN_CHANGE(IDC_HOSTNAME, OnEnChangeHostname)
+ ON_EN_CHANGE(IDC_USERNAME, OnEnChangeUsername)
+ ON_EN_CHANGE(IDC_PASSWORD, OnEnChangePassword)
+ ON_BN_CLICKED(IDC_ADVERTISE_SERVICES, OnBnClickedAdvertiseServices)
+END_MESSAGE_MAP()
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::OnEnChangedHostname
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CRegistrationPage::OnEnChangeHostname()
+{
+ if ( !m_ignoreChanges )
+ {
+ SetModified( TRUE );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::OnEnChangedUsername
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CRegistrationPage::OnEnChangeUsername()
+{
+ if ( !m_ignoreChanges )
+ {
+ SetModified( TRUE );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::OnEnChangedPassword
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CRegistrationPage::OnEnChangePassword()
+{
+ if ( !m_ignoreChanges )
+ {
+ SetModified( TRUE );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::OnBnClickedAdvertiseServices
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CRegistrationPage::OnBnClickedAdvertiseServices()
+{
+ if ( !m_ignoreChanges )
+ {
+ SetModified( TRUE );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::SetModified
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CRegistrationPage::SetModified( BOOL bChanged )
+{
+ m_modified = bChanged ? true : false;
+
+ CPropertyPage::SetModified( bChanged );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::OnSetActive
+//---------------------------------------------------------------------------------------------------------------------------
+
+BOOL
+CRegistrationPage::OnSetActive()
+{
+ TCHAR name[kDNSServiceMaxDomainName + 1];
+ DWORD nameLen = ( kDNSServiceMaxDomainName + 1 ) * sizeof( TCHAR );
+ DWORD err;
+
+ BOOL b = CPropertyPage::OnSetActive();
+
+ m_ignoreChanges = true;
+ m_modified = FALSE;
+
+ if ( m_hostnameSetupKey )
+ {
+ err = RegQueryValueEx( m_hostnameSetupKey, L"", NULL, NULL, (LPBYTE) name, &nameLen );
+
+ if ( !err )
+ {
+ char hostnameUTF8[ 256 ];
+ char outDomain[ 256 ];
+ char outUsername[ 256 ];
+ char outPassword[ 256 ];
+ CString hostname = name;
+ CString username;
+ CString password;
+
+ m_hostnameControl.SetWindowText( hostname );
+
+ StringObjectToUTF8String( hostname, hostnameUTF8, sizeof( hostnameUTF8 ) );
+
+ if ( LsaGetSecret( hostnameUTF8, outDomain, sizeof( outDomain ) / sizeof( TCHAR ), outUsername, sizeof( outUsername ) / sizeof( TCHAR ), outPassword, sizeof( outPassword ) / sizeof( TCHAR ) ) )
+ {
+ username = outUsername;
+ m_usernameControl.SetWindowText( username );
+
+ password = outPassword;
+ m_passwordControl.SetWindowText( password );
+ }
+ }
+ }
+
+ m_advertiseServices.SetCheck( 0 );
+
+ if ( m_registrationSetupKey )
+ {
+ HKEY subKey = NULL;
+ DWORD dwSize;
+ DWORD enabled = 0;
+ TCHAR subKeyName[MAX_KEY_LENGTH];
+ DWORD cSubKeys = 0;
+ DWORD cbMaxSubKey;
+ DWORD cchMaxClass;
+ OSStatus err;
+
+ err = RegQueryInfoKey( m_registrationSetupKey, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
+ if ( !err )
+ {
+ if ( cSubKeys > 0 )
+ {
+ dwSize = MAX_KEY_LENGTH;
+
+ err = RegEnumKeyEx( m_registrationSetupKey, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
+ if ( !err )
+ {
+ err = RegOpenKey( m_registrationSetupKey, subKeyName, &subKey );
+ if ( !err )
+ {
+ dwSize = sizeof( DWORD );
+ err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+ if ( !err && enabled )
+ {
+ m_advertiseServices.SetCheck( enabled );
+ }
+
+ RegCloseKey( subKey );
+ subKey = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ m_ignoreChanges = false;
+
+ return b;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::OnOK
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CRegistrationPage::OnOK()
+{
+ if ( m_modified )
+ {
+ Commit();
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage::Commit
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CRegistrationPage::Commit()
+{
+ CString hostname;
+ char hostnameUTF8[ 256 ];
+ CString username;
+ char usernameUTF8[ 256 ];
+ CString password;
+ char passwordUTF8[ 256 ];
+ DWORD enabled = 1;
+ BOOL secret = FALSE;
+ DWORD err;
+
+ m_hostnameControl.GetWindowText( hostname );
+ hostname.MakeLower();
+ hostname.TrimRight( '.' );
+ StringObjectToUTF8String( hostname, hostnameUTF8, sizeof( hostnameUTF8 ) );
+
+ m_usernameControl.GetWindowText( username );
+ m_passwordControl.GetWindowText( password );
+
+ if ( username.GetLength() && password.GetLength() )
+ {
+ StringObjectToUTF8String( username, usernameUTF8, sizeof( usernameUTF8 ) );
+ StringObjectToUTF8String( password, passwordUTF8, sizeof( passwordUTF8 ) );
+ secret = TRUE;
+ }
+
+ if ( m_hostnameSetupKey != NULL )
+ {
+ err = RegSetValueEx( m_hostnameSetupKey, L"", 0, REG_SZ, (LPBYTE) (LPCTSTR) hostname, ( hostname.GetLength() + 1 ) * sizeof( TCHAR ) );
+ require_noerr( err, exit );
+
+ err = RegSetValueEx( m_hostnameSetupKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
+ require_noerr( err, exit );
+
+ if ( secret )
+ {
+ LsaSetSecret( hostnameUTF8, usernameUTF8, passwordUTF8 );
+ }
+ }
+
+ if ( m_registrationSetupKey != NULL )
+ {
+ TCHAR subKeyName[MAX_KEY_LENGTH];
+ DWORD cSubKeys = 0;
+ DWORD cbMaxSubKey;
+ DWORD cchMaxClass;
+ DWORD dwSize;
+ int i;
+ OSStatus err = kNoErr;
+
+ // First, remove all the entries that are there
+
+ err = RegQueryInfoKey( m_registrationSetupKey, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
+ if ( !err )
+ {
+ for ( i = 0; i < (int) cSubKeys; i++ )
+ {
+ dwSize = MAX_KEY_LENGTH;
+
+ err = RegEnumKeyEx( m_registrationSetupKey, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
+
+ err = RegDeleteKey( m_registrationSetupKey, subKeyName );
+ require_noerr( err, exit );
+ }
+ }
+
+ if ( m_advertiseServices.GetCheck() )
+ {
+ const char * domainUTF8;
+ CString domain;
+ char label[ 64 ];
+ HKEY subKey = NULL;
+
+ domainUTF8 = GetNextLabel( hostnameUTF8, label );
+ domain = domainUTF8;
+
+ err = RegCreateKeyEx( m_registrationSetupKey, domain, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &subKey, NULL );
+ if ( !err )
+ {
+ err = RegSetValueEx( subKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
+ check_noerr( err );
+
+ RegCloseKey( subKey );
+ subKey = NULL;
+ }
+
+ if ( secret )
+ {
+ LsaSetSecret( domainUTF8, usernameUTF8, passwordUTF8 );
+ }
+ }
+ }
+
+exit:
+
+ return;
+}
--- /dev/null
+/* -*- 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.
+ */
+
+#pragma once
+
+#include "stdafx.h"
+#include "resource.h"
+#include <DebugServices.h>
+#include "afxwin.h"
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CRegistrationPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+class CRegistrationPage : public CPropertyPage
+{
+public:
+ CRegistrationPage();
+ ~CRegistrationPage();
+
+protected:
+ //{{AFX_DATA(CRegistrationPage)
+ enum { IDD = IDR_APPLET_PAGE1 };
+ //}}AFX_DATA
+
+ //{{AFX_VIRTUAL(CRegistrationPage)
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ DECLARE_DYNCREATE(CRegistrationPage)
+
+ //{{AFX_MSG(CRegistrationPage)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+private:
+
+ afx_msg BOOL OnSetActive();
+ afx_msg void OnOK();
+
+ void SetModified( BOOL bChanged = TRUE );
+ void Commit();
+
+ CEdit m_hostnameControl;
+ CEdit m_usernameControl;
+ CEdit m_passwordControl;
+ CButton m_advertiseServices;
+ bool m_ignoreChanges;
+ bool m_modified;
+ HKEY m_hostnameSetupKey;
+ HKEY m_registrationSetupKey;
+ HKEY m_statusKey;
+
+public:
+
+ afx_msg void OnEnChangeHostname();
+ afx_msg void OnEnChangeUsername();
+ afx_msg void OnEnChangePassword();
+ afx_msg void OnBnClickedAdvertiseServices();
+};
* 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: SecondPage.cpp,v $
-Revision 1.7 2006/08/14 23:25:28 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.6 2005/10/05 20:46:50 herscher
-<rdar://problem/4192011> Move Wide-Area preferences to another part of the registry so they don't removed during an update-install.
-
-Revision 1.5 2005/04/05 04:15:46 shersche
-RegQueryString was returning uninitialized strings if the registry key couldn't be found, so always initialize strings before checking the registry key.
-
-Revision 1.4 2005/04/05 03:52:14 shersche
-<rdar://problem/4066485> Registering with shared secret key doesn't work. Additionally, mDNSResponder wasn't dynamically re-reading it's DynDNS setup after setting a shared secret key.
-
-Revision 1.3 2005/03/03 19:55:22 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#include "SecondPage.h"
#include "resource.h"
#include <WinServices.h>
+#define MAX_KEY_LENGTH 255
+
IMPLEMENT_DYNCREATE(CSecondPage, CPropertyPage)
OSStatus err;
- err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &m_setupKey );
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &m_setupKey, NULL );
check_noerr( err );
}
CSecondPage::OnSetActive()
{
CConfigPropertySheet * psheet;
- DWORD dwSize;
- DWORD enabled;
DWORD err;
BOOL b = CPropertyPage::OnSetActive();
err = Populate( m_regDomainsBox, m_setupKey, psheet->m_regDomains );
check_noerr( err );
- dwSize = sizeof( DWORD );
- err = RegQueryValueEx( m_setupKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
- m_advertiseServicesButton.SetCheck( ( !err && enabled ) ? BST_CHECKED : BST_UNCHECKED );
- m_regDomainsBox.EnableWindow( ( !err && enabled ) );
- m_sharedSecretButton.EnableWindow( (!err && enabled ) );
-
exit:
return b;
CSecondPage::Commit( CComboBox & box, HKEY key, DWORD enabled )
{
CString selected;
+ HKEY subKey = NULL;
+ TCHAR subKeyName[MAX_KEY_LENGTH];
+ DWORD cSubKeys = 0;
+ DWORD cbMaxSubKey;
+ DWORD cchMaxClass;
+ DWORD dwSize;
+ int i;
OSStatus err = kNoErr;
+ // First, remove all the entries that are there
+
+ err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
+
+ for ( i = 0; i < (int) cSubKeys; i++ )
+ {
+ dwSize = MAX_KEY_LENGTH;
+
+ err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
+
+ err = RegDeleteKey( key, subKeyName );
+ require_noerr( err, exit );
+ }
+
// Get selected text
box.GetWindowText( selected );
// Save selected text in registry. This will trigger mDNSResponder to setup
// DynDNS config again
- err = RegSetValueEx( key, L"", 0, REG_SZ, (LPBYTE) (LPCTSTR) selected, ( selected.GetLength() + 1 ) * sizeof( TCHAR ) );
- check_noerr( err );
+ err = RegCreateKeyEx( key, selected, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &subKey, NULL );
+ require_noerr( err, exit );
- err = RegSetValueEx( key, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
+ err = RegSetValueEx( subKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
check_noerr( err );
+exit:
+
+ if ( subKey )
+ {
+ RegCloseKey( subKey );
+ subKey = NULL;
+ }
+
return err;
}
CSharedSecret dlg;
- dlg.m_key = name;
+ dlg.Load( name );
if ( dlg.DoModal() == IDOK )
{
OSStatus
CSecondPage::Populate( CComboBox & box, HKEY key, StringList & l )
{
- TCHAR rawString[kDNSServiceMaxDomainName + 1];
- DWORD rawStringLen;
CString string;
+ HKEY subKey = NULL;
+ DWORD dwSize;
+ DWORD enabled = 0;
+ TCHAR subKeyName[MAX_KEY_LENGTH];
+ DWORD cSubKeys = 0;
+ DWORD cbMaxSubKey;
+ DWORD cchMaxClass;
OSStatus err;
err = RegQueryString( key, L"UserDefined", string );
}
}
- // Now look to see if there is a selected string, and if so,
- // select it
+ err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
- rawString[0] = '\0';
+ if ( cSubKeys > 0 )
+ {
+ dwSize = MAX_KEY_LENGTH;
+
+ err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
- rawStringLen = sizeof( rawString );
+ err = RegOpenKey( key, subKeyName, &subKey );
+ require_noerr( err, exit );
- err = RegQueryValueEx( key, L"", 0, NULL, (LPBYTE) rawString, &rawStringLen );
+ dwSize = sizeof( DWORD );
+ err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+ require_noerr( err, exit );
- string = rawString;
-
- if ( !err && ( string.GetLength() != 0 ) )
- {
// See if it's there
- if ( box.SelectString( -1, string ) == CB_ERR )
+ if ( box.SelectString( -1, subKeyName ) == CB_ERR )
{
// If not, add it
- box.AddString( string );
+ box.AddString( subKeyName );
}
- box.SelectString( -1, string );
+ box.SelectString( -1, subKeyName );
+
+ RegCloseKey( subKey );
+ subKey = NULL;
}
+exit:
+
+ m_advertiseServicesButton.SetCheck( ( !err && enabled ) ? BST_CHECKED : BST_UNCHECKED );
+ m_regDomainsBox.EnableWindow( ( !err && enabled ) );
+ m_sharedSecretButton.EnableWindow( (!err && enabled ) );
+
return err;
}
HKEY key = NULL;
OSStatus err;
- err = RegCreateKey( HKEY_LOCAL_MACHINE, (LPCTSTR) name, &key );
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, (LPCTSTR) name, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
require_noerr( err, exit );
err = RegSetValueEx( key, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
* 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: SecondPage.h,v $
-Revision 1.5 2006/08/14 23:25:28 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.4 2005/04/05 03:52:14 shersche
-<rdar://problem/4066485> Registering with shared secret key doesn't work. Additionally, mDNSResponder wasn't dynamically re-reading it's DynDNS setup after setting a shared secret key.
-
-Revision 1.3 2005/03/03 19:55:21 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#pragma once
--- /dev/null
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ServicesPage.h"
+#include "resource.h"
+
+#include "ControlPanelExe.h"
+#include "ConfigPropertySheet.h"
+
+#include <WinServices.h>
+
+#define MAX_KEY_LENGTH 255
+
+
+IMPLEMENT_DYNCREATE(CServicesPage, CPropertyPage)
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage::CServicesPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CServicesPage::CServicesPage()
+:
+ CPropertyPage(CServicesPage::IDD)
+{
+ //{{AFX_DATA_INIT(CServicesPage)
+ //}}AFX_DATA_INIT
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage::~CServicesPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CServicesPage::~CServicesPage()
+{
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage::DoDataExchange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CServicesPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CServicesPage)
+ //}}AFX_DATA_MAP
+ DDX_Control(pDX, IDC_ADVERTISE_SMB, m_SMBCheckBox);
+ DDX_Control(pDX, IDC_POWER_MANAGEMENT, m_powerManagementCheckBox);
+}
+
+BEGIN_MESSAGE_MAP(CServicesPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CServicesPage)
+ //}}AFX_MSG_MAP
+
+ ON_BN_CLICKED(IDC_ADVERTISE_SMB, &CServicesPage::OnBnClickedAdvertiseSMB)
+ ON_BN_CLICKED(IDC_POWER_MANAGEMENT, &CServicesPage::OnBnClickedPowerManagement)
+
+END_MESSAGE_MAP()
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage::SetModified
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CServicesPage::SetModified( BOOL bChanged )
+{
+ m_modified = bChanged;
+
+ CPropertyPage::SetModified( bChanged );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage::OnSetActive
+//---------------------------------------------------------------------------------------------------------------------------
+
+BOOL
+CServicesPage::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_SMBCheckBox.SetCheck( 0 );
+
+ // Now populate the browse domain box
+
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Services\\SMB", 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
+ require_noerr( err, exit );
+
+ dwSize = sizeof( DWORD );
+ err = RegQueryValueEx( key, L"Advertise", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+ require_noerr( err, exit );
+
+ m_SMBCheckBox.SetCheck( enabled );
+
+ RegCloseKey( key );
+ key = NULL;
+
+ m_powerManagementCheckBox.SetCheck( 0 );
+
+ // Now populate the browse domain box
+
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
+ require_noerr( err, exit );
+
+ dwSize = sizeof( DWORD );
+ err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+ require_noerr( err, exit );
+
+ m_powerManagementCheckBox.SetCheck( enabled );
+
+exit:
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+
+ return b;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage::OnOK
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CServicesPage::OnOK()
+{
+ if ( m_modified )
+ {
+ Commit();
+ }
+}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage::Commit
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CServicesPage::Commit()
+{
+ HKEY key = NULL;
+ DWORD enabled;
+ DWORD err;
+
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Services\\SMB", 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
+ require_noerr( err, exit );
+
+ enabled = m_SMBCheckBox.GetCheck();
+ err = RegSetValueEx( key, L"Advertise", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
+ require_noerr( err, exit );
+
+ RegCloseKey( key );
+ key = NULL;
+
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
+ require_noerr( err, exit );
+
+ enabled = m_powerManagementCheckBox.GetCheck();
+ err = RegSetValueEx( key, L"Enabled", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
+ require_noerr( err, exit );
+
+exit:
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage::OnBnClickedAdvertiseSMB
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CServicesPage::OnBnClickedAdvertiseSMB()
+{
+ SetModified( TRUE );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage::OnBnClickedPowerManagement
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CServicesPage::OnBnClickedPowerManagement()
+{
+ SetModified( TRUE );
+
+ if ( m_powerManagementCheckBox.GetCheck() )
+ {
+ CPowerManagementWarning dlg( GetParent() );
+
+ dlg.DoModal();
+ }
+}
+
+
+// CPowerManagementWarning dialog
+
+IMPLEMENT_DYNAMIC(CPowerManagementWarning, CDialog)
+CPowerManagementWarning::CPowerManagementWarning(CWnd* pParent /*=NULL*/)
+ : CDialog(CPowerManagementWarning::IDD, pParent)
+{
+}
+
+CPowerManagementWarning::~CPowerManagementWarning()
+{
+}
+
+void CPowerManagementWarning::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_ENERGY_SAVER, m_energySaverIcon);
+}
+
+
+BOOL
+CPowerManagementWarning::OnInitDialog()
+{
+ BOOL b = CDialog::OnInitDialog();
+
+ const HICON hIcon = ( HICON ) ::LoadImage( GetNonLocalizedResources(), MAKEINTRESOURCE( IDI_ENERGY_SAVER ), IMAGE_ICON, 0, 0, 0);
+
+ if ( hIcon )
+ {
+ m_energySaverIcon.SetIcon( hIcon );
+ }
+
+ return b;
+}
+
+
+void
+CPowerManagementWarning::OnOK()
+{
+ CDialog::OnOK();
+}
+
+
+BEGIN_MESSAGE_MAP(CPowerManagementWarning, CDialog)
+END_MESSAGE_MAP()
+
--- /dev/null
+/* -*- 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.
+ */
+
+#pragma once
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include <DebugServices.h>
+#include <list>
+#include "afxcmn.h"
+
+#include "afxwin.h"
+
+
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CServicesPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+class CServicesPage : public CPropertyPage
+{
+public:
+ CServicesPage();
+ ~CServicesPage();
+
+protected:
+
+ //{{AFX_DATA(CServicesPage)
+ enum { IDD = IDR_APPLET_PAGE5 };
+ //}}AFX_DATA
+
+ //{{AFX_VIRTUAL(CServicesPage)
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ DECLARE_DYNCREATE(CServicesPage)
+
+ //{{AFX_MSG(CServicesPage)
+ //}}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_SMBCheckBox;
+ CButton m_powerManagementCheckBox;
+
+public:
+
+
+ afx_msg void OnBnClickedAdvertiseSMB();
+ afx_msg void OnBnClickedPowerManagement();
+};
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CPowerManagementWarning
+//---------------------------------------------------------------------------------------------------------------------------
+
+class CPowerManagementWarning : public CDialog
+{
+ DECLARE_DYNAMIC(CPowerManagementWarning)
+
+public:
+
+ CPowerManagementWarning(CWnd* pParent = NULL); // standard constructor
+
+ virtual ~CPowerManagementWarning();
+
+// Dialog Data
+
+ enum { IDD = IDR_POWER_MANAGEMENT_WARNING };
+
+protected:
+
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+
+ virtual BOOL OnInitDialog();
+
+ virtual void OnOK();
+
+ DECLARE_MESSAGE_MAP()
+
+public:
+
+ CStatic m_energySaverIcon;
+};
+
* 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: 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.
-
-Revision 1.5 2006/08/14 23:25:28 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.4 2005/10/18 06:13:41 herscher
-<rdar://problem/4192119> Prepend "$" to key name to ensure that secure updates work if the domain name and key name are the same
-
-Revision 1.3 2005/04/06 02:04:49 shersche
-<rdar://problem/4066485> Registering with shared secret doesn't work
-
-Revision 1.2 2005/03/03 19:55:22 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
// SharedSecret.cpp : implementation file
* 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: 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
-
-Revision 1.3 2005/04/06 02:04:49 shersche
-<rdar://problem/4066485> Registering with shared secret doesn't work
-
-Revision 1.2 2005/03/03 19:55:21 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#pragma once
+++ /dev/null
-/* -*- 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: ThirdPage.cpp,v $
-Revision 1.5 2006/08/14 23:25:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.4 2005/10/05 20:46:50 herscher
-<rdar://problem/4192011> Move Wide-Area preferences to another part of the registry so they don't removed during an update-install.
-
-Revision 1.3 2005/03/07 18:27:42 shersche
-<rdar://problem/4037940> Fix problem when ControlPanel commits changes to the browse domain list
-
-Revision 1.2 2005/03/03 19:55:22 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
-
-#include "ThirdPage.h"
-#include "resource.h"
-
-#include "ConfigPropertySheet.h"
-#include "SharedSecret.h"
-
-#include <WinServices.h>
-
-#define MAX_KEY_LENGTH 255
-
-
-IMPLEMENT_DYNCREATE(CThirdPage, CPropertyPage)
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage::CThirdPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CThirdPage::CThirdPage()
-:
- CPropertyPage(CThirdPage::IDD)
-{
- //{{AFX_DATA_INIT(CThirdPage)
- //}}AFX_DATA_INIT
-
- m_firstTime = true;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage::~CThirdPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CThirdPage::~CThirdPage()
-{
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage::DoDataExchange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CThirdPage::DoDataExchange(CDataExchange* pDX)
-{
- CPropertyPage::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CThirdPage)
- //}}AFX_DATA_MAP
- DDX_Control(pDX, IDC_BROWSE_LIST, m_browseListCtrl);
- DDX_Control(pDX, IDC_REMOVE_BROWSE_DOMAIN, m_removeButton);
-}
-
-BEGIN_MESSAGE_MAP(CThirdPage, CPropertyPage)
- //{{AFX_MSG_MAP(CThirdPage)
- //}}AFX_MSG_MAP
- ON_BN_CLICKED(IDC_ADD_BROWSE_DOMAIN, OnBnClickedAddBrowseDomain)
- ON_BN_CLICKED(IDC_REMOVE_BROWSE_DOMAIN, OnBnClickedRemoveBrowseDomain)
- ON_NOTIFY(LVN_ITEMCHANGED, IDC_BROWSE_LIST, OnLvnItemchangedBrowseList)
-END_MESSAGE_MAP()
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage::SetModified
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CThirdPage::SetModified( BOOL bChanged )
-{
- m_modified = bChanged;
-
- CPropertyPage::SetModified( bChanged );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage::OnSetActive
-//---------------------------------------------------------------------------------------------------------------------------
-
-BOOL
-CThirdPage::OnSetActive()
-{
- CConfigPropertySheet * psheet;
- HKEY key = NULL;
- HKEY subKey = NULL;
- DWORD dwSize;
- DWORD enabled;
- DWORD err;
- TCHAR subKeyName[MAX_KEY_LENGTH];
- DWORD cSubKeys = 0;
- DWORD cbMaxSubKey;
- DWORD cchMaxClass;
- int nIndex;
- DWORD i;
- BOOL b = CPropertyPage::OnSetActive();
-
- psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
- require_quiet( psheet, exit );
-
- m_modified = FALSE;
-
- if ( m_firstTime )
- {
- m_browseListCtrl.SetExtendedStyle((m_browseListCtrl.GetStyle() & (~LVS_EX_GRIDLINES))|LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
-
- m_browseListCtrl.InsertColumn(0, L"", LVCFMT_LEFT, 20 );
- m_browseListCtrl.InsertColumn(1, L"", LVCFMT_LEFT, 345);
-
- m_firstTime = false;
- }
-
- m_initialized = false;
-
- // Clear out what's there
-
- m_browseListCtrl.DeleteAllItems();
-
- // Now populate the browse domain box
-
- err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\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 );
-
- for ( i = 0; i < cSubKeys; i++)
- {
- dwSize = MAX_KEY_LENGTH;
-
- err = RegEnumKeyEx( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
- require_noerr( err, exit );
-
- err = RegOpenKey( key, subKeyName, &subKey );
- require_noerr( err, exit );
-
- dwSize = sizeof( DWORD );
- err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
- require_noerr( err, exit );
-
- nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L"");
- m_browseListCtrl.SetItemText( nIndex, 1, subKeyName );
- m_browseListCtrl.SetCheck( nIndex, enabled );
-
- RegCloseKey( subKey );
- subKey = NULL;
- }
-
- m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );
-
- m_removeButton.EnableWindow( FALSE );
-
-exit:
-
- if ( subKey )
- {
- RegCloseKey( subKey );
- }
-
- if ( key )
- {
- RegCloseKey( key );
- }
-
- m_initialized = true;
-
- return b;
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage::OnOK
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CThirdPage::OnOK()
-{
- if ( m_modified )
- {
- Commit();
- }
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage::Commit
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CThirdPage::Commit()
-{
- HKEY key = NULL;
- HKEY subKey = NULL;
- TCHAR subKeyName[MAX_KEY_LENGTH];
- DWORD cSubKeys = 0;
- DWORD cbMaxSubKey;
- DWORD cchMaxClass;
- DWORD dwSize;
- int i;
- DWORD err;
-
- err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key );
- require_noerr( err, exit );
-
- // First, remove all the entries that are there
-
- err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
- require_noerr( err, exit );
-
- for ( i = 0; i < (int) cSubKeys; i++ )
- {
- dwSize = MAX_KEY_LENGTH;
-
- err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
- require_noerr( err, exit );
-
- err = RegDeleteKey( key, subKeyName );
- require_noerr( err, exit );
- }
-
- // Now re-populate
-
- for ( i = 0; i < m_browseListCtrl.GetItemCount(); i++ )
- {
- DWORD enabled = (DWORD) m_browseListCtrl.GetCheck( i );
-
- err = RegCreateKey( key, m_browseListCtrl.GetItemText( i, 1 ), &subKey );
- require_noerr( err, exit );
-
- err = RegSetValueEx( subKey, L"Enabled", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
- require_noerr( err, exit );
-
- RegCloseKey( subKey );
- subKey = NULL;
- }
-
-exit:
-
- if ( subKey )
- {
- RegCloseKey( subKey );
- }
-
- if ( key )
- {
- RegCloseKey( key );
- }
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage::OnBnClickedAddBrowseDomain
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CThirdPage::OnBnClickedAddBrowseDomain()
-{
- CAddBrowseDomain dlg( GetParent() );
-
- if ( ( dlg.DoModal() == IDOK ) && ( dlg.m_text.GetLength() > 0 ) )
- {
- int nIndex;
-
- nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L"");
- m_browseListCtrl.SetItemText( nIndex, 1, dlg.m_text );
- m_browseListCtrl.SetCheck( nIndex, 1 );
-
- m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );
-
- m_browseListCtrl.Invalidate();
-
- SetModified( TRUE );
- }
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage::OnBnClickedRemoveBrowseDomain
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CThirdPage::OnBnClickedRemoveBrowseDomain()
-{
- UINT selectedCount = m_browseListCtrl.GetSelectedCount();
- int nItem = -1;
- UINT i;
-
- // Update all of the selected items.
-
- for ( i = 0; i < selectedCount; i++ )
- {
- nItem = m_browseListCtrl.GetNextItem( -1, LVNI_SELECTED );
- check( nItem != -1 );
-
- m_browseListCtrl.DeleteItem( nItem );
-
- SetModified( TRUE );
- }
-
- m_removeButton.EnableWindow( FALSE );
-}
-
-
-void
-CThirdPage::OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
-{
- if ( m_browseListCtrl.GetSelectedCount() )
- {
- m_removeButton.EnableWindow( TRUE );
- }
-
- if ( m_initialized )
- {
- NM_LISTVIEW * pNMListView = (NM_LISTVIEW*)pNMHDR;
-
- BOOL bPrevState = (BOOL) ( ( ( pNMListView->uOldState & LVIS_STATEIMAGEMASK ) >> 12 ) - 1 );
-
- if ( bPrevState < 0 )
- {
- bPrevState = 0;
- }
-
-
- BOOL bChecked = ( BOOL ) ( ( ( pNMListView->uNewState & LVIS_STATEIMAGEMASK ) >> 12) - 1 );
-
- if ( bChecked < 0 )
- {
- bChecked = 0;
- }
-
- if ( bPrevState != bChecked )
- {
- SetModified( TRUE );
- }
- }
-
- *pResult = 0;
-}
-
-
-
-int CALLBACK
-CThirdPage::SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
-{
- CString str1;
- CString str2;
- int ret = 0;
-
- CThirdPage * self = reinterpret_cast<CThirdPage*>( lParamSort );
- require_quiet( self, exit );
-
- str1 = self->m_browseListCtrl.GetItemText( (int) lParam1, 1 );
- str2 = self->m_browseListCtrl.GetItemText( (int) lParam2, 1 );
-
- ret = str1.Compare( str2 );
-
-exit:
-
- return ret;
-}
-
-
-// CAddBrowseDomain dialog
-
-IMPLEMENT_DYNAMIC(CAddBrowseDomain, CDialog)
-CAddBrowseDomain::CAddBrowseDomain(CWnd* pParent /*=NULL*/)
- : CDialog(CAddBrowseDomain::IDD, pParent)
-{
-}
-
-CAddBrowseDomain::~CAddBrowseDomain()
-{
-}
-
-void CAddBrowseDomain::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- DDX_Control(pDX, IDC_COMBO1, m_comboBox);
-}
-
-
-BOOL
-CAddBrowseDomain::OnInitDialog()
-{
- CConfigPropertySheet * psheet;
- CConfigPropertySheet::StringList::iterator it;
-
- BOOL b = CDialog::OnInitDialog();
-
- psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
- require_quiet( psheet, exit );
-
- for ( it = psheet->m_browseDomains.begin(); it != psheet->m_browseDomains.end(); it++ )
- {
- CString text = *it;
-
- if ( m_comboBox.FindStringExact( -1, *it ) == CB_ERR )
- {
- m_comboBox.AddString( *it );
- }
- }
-
-exit:
-
- return b;
-}
-
-
-void
-CAddBrowseDomain::OnOK()
-{
- m_comboBox.GetWindowText( m_text );
-
- CDialog::OnOK();
-}
-
-
-
-BEGIN_MESSAGE_MAP(CAddBrowseDomain, CDialog)
-END_MESSAGE_MAP()
-
+++ /dev/null
-/* -*- 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: ThirdPage.h,v $
-Revision 1.3 2006/08/14 23:25:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/03/03 19:55:21 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
-
-#pragma once
-
-#include "stdafx.h"
-#include "resource.h"
-
-#include <DebugServices.h>
-#include <list>
-#include "afxcmn.h"
-
-#include "afxwin.h"
-
-
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CThirdPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CThirdPage : public CPropertyPage
-{
-public:
- CThirdPage();
- ~CThirdPage();
-
-protected:
-
- //{{AFX_DATA(CThirdPage)
- enum { IDD = IDR_APPLET_PAGE3 };
- //}}AFX_DATA
-
- //{{AFX_VIRTUAL(CThirdPage)
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
- DECLARE_DYNCREATE(CThirdPage)
-
- //{{AFX_MSG(CThirdPage)
- //}}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:
-
- static int CALLBACK
-
- SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
-
-
-
- CListCtrl m_browseListCtrl;
-
- bool m_initialized;
-
- bool m_firstTime;
-
-
-
-public:
-
-
-
- afx_msg void OnBnClickedAddBrowseDomain();
-
- afx_msg void OnBnClickedRemoveBrowseDomain();
-
- afx_msg void OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);
-
- CButton m_removeButton;
-
-};
-
-
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-// CAddBrowseDomain
-//---------------------------------------------------------------------------------------------------------------------------
-
-
-class CAddBrowseDomain : public CDialog
-
-{
-
- DECLARE_DYNAMIC(CAddBrowseDomain)
-
-
-
-public:
-
- CAddBrowseDomain(CWnd* pParent = NULL); // standard constructor
-
- virtual ~CAddBrowseDomain();
-
-
-
-// Dialog Data
-
- enum { IDD = IDR_ADD_BROWSE_DOMAIN };
-
-
-
-protected:
-
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
-
- virtual BOOL OnInitDialog();
-
- virtual void OnOK();
-
- DECLARE_MESSAGE_MAP()
-
-public:
-
- CComboBox m_comboBox;
-
- CString m_text;
-
-};
-
#define IDR_SECRET 133
#define IDR_APPLET_PAGE3 134
#define IDR_APPLET_PAGE4 135
+#define IDR_APPLET_PAGE5 136
#define IDI_FAILURE 140
#define IDI_SUCCESS 141
-#define IDD_ADD_BROWSE_DOMAIN 142
-#define IDR_ADD_BROWSE_DOMAIN 142
-#define IDC_EDIT1 1000
-#define IDC_BUTTON1 1001
-#define IDC_COMBO1 1002
-#define IDC_CHECK1 1003
-#define IDC_COMBO2 1004
-#define IDC_EDIT2 1005
-#define IDC_SECRET 1005
-#define IDC_COMBO3 1007
-#define IDC_FAILURE 1008
-#define IDC_SUCCESS 1009
-#define IDC_SECRET_NAME 1010
-#define IDC_NAME 1010
-#define IDC_KEY 1010
-#define IDC_LIST1 1011
-#define IDC_BROWSE_LIST 1011
-#define IDC_BUTTON2 1012
-#define IDC_REMOVE_BROWSE_DOMAIN 1012
-#define IDC_ADD_BROWSE_DOMAIN 1013
-#define IDC_POWER_MANAGEMENT 1014
+#define IDI_ENERGY_SAVER 142
+#define IDR_ADD_BROWSE_DOMAIN 143
+#define IDR_POWER_MANAGEMENT_WARNING 144
+#define IDS_REINSTALL 145
+#define IDS_REINSTALL_CAPTION 146
+#define IDS_APPLET_NAME 147
+#define IDS_APPLET_TOOLTIP 148
+#define IDC_HOSTNAME 1000
+#define IDC_USERNAME 1001
+#define IDC_PASSWORD 1002
+#define IDC_ADVERTISE_SERVICES 1003
+#define IDC_BUTTON1 1004
+#define IDC_COMBO1 1005
+#define IDC_CHECK1 1006
+#define IDC_COMBO2 1007
+#define IDC_EDIT2 1008
+#define IDC_SECRET 1009
+#define IDC_COMBO3 1010
+#define IDC_FAILURE 1011
+#define IDC_SUCCESS 1012
+#define IDC_SECRET_NAME 1013
+#define IDC_NAME 1014
+#define IDC_KEY 1015
+#define IDC_LIST1 1016
+#define IDC_BROWSE_LIST 1017
+#define IDC_BUTTON2 1018
+#define IDC_REMOVE_BROWSE_DOMAIN 1019
+#define IDC_ADD_BROWSE_DOMAIN 1020
+#define IDC_POWER_MANAGEMENT 1021
+#define IDC_ADVERTISE_SMB 1022
+#define IDC_ENERGY_SAVER 1023
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 143
+#define _APS_NEXT_RESOURCE_VALUE 149
#define _APS_NEXT_COMMAND_VALUE 32771
-#define _APS_NEXT_CONTROL_VALUE 1015
+#define _APS_NEXT_CONTROL_VALUE 1024
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
* 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.cpp,v $
-Revision 1.3 2006/08/14 23:25:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/03/03 19:55:22 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#include "stdafx.h"
* 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.4 2006/08/14 23:25:29 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2005/10/19 19:50:35 herscher
-Workaround a bug in the latest Microsoft Platform SDK when compiling C++ files that include (directly or indirectly) <WspiApi.h>
-
-Revision 1.2 2005/03/03 19:55:21 shersche
-<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
-
-
-*/
+ */
#pragma once
* 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: 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
-
-Revision 1.4 2004/07/26 21:03:00 shersche
-enable strong naming for dnssd.NET assembly
-
-Revision 1.3 2004/07/14 19:54:57 shersche
-use version file to get version numbers
-
-Revision 1.2 2004/07/14 15:42:47 shersche
-remove entries for strong authentication
-
-Revision 1.1 2004/06/26 04:01:22 shersche
-Initial revision
-
-
*/
#include "stdafx.h"
* 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: PString.h,v $
-Revision 1.3 2006/08/14 23:25:43 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/19 16:08:56 shersche
-fix problems in UTF8/Unicode string translations
-
-Revision 1.1 2004/06/26 04:01:22 shersche
-Initial revision
-
-
*/
#pragma once
* 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.cpp,v $
-Revision 1.3 2006/08/14 23:25:43 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2005/02/05 02:37:01 cheshire
-Convert newlines to Unix-style (ASCII 10)
-
-Revision 1.1 2004/06/26 04:01:22 shersche
-Initial revision
-
*/
// stdafx.cpp : source file that includes just the standard includes
* 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.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
-
-Revision 1.4 2005/10/19 19:50:35 herscher
-Workaround a bug in the latest Microsoft Platform SDK when compiling C++ files that include (directly or indirectly) <WspiApi.h>
-
-Revision 1.3 2005/02/05 02:40:59 cheshire
-Convert newlines to Unix-style (ASCII 10)
-
-Revision 1.2 2005/02/05 02:37:01 cheshire
-Convert newlines to Unix-style (ASCII 10)
-
-Revision 1.1 2004/06/26 04:01:22 shersche
-Initial revision
-
*/
// stdafx.h : include file for standard system include files,
* 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: 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
-
-Revision 1.9 2004/09/16 18:17:13 shersche
-Use background threads, cleanup to parameter names.
-Submitted by: prepin@gmail.com
-
-Revision 1.8 2004/09/13 19:35:58 shersche
-<rdar://problem/3798941> Add Apple.DNSSD namespace to MC++ wrapper class
-<rdar://problem/3798950> Change all instances of unsigned short to int
-Bug #: 3798941, 3798950
-
-Revision 1.7 2004/09/11 00:36:40 shersche
-<rdar://problem/3786226> Modified .NET shim code to use host byte order for ports in APIs and callbacks
-Bug #: 3786226
-
-Revision 1.6 2004/09/02 21:20:56 cheshire
-<rdar://problem/3774871> DLL.NET crashes on null record
-
-Revision 1.5 2004/07/27 07:12:56 shersche
-make TextRecord an instantiable class object
-
-Revision 1.4 2004/07/26 06:19:05 shersche
-Treat byte arrays of zero-length as null arrays
-
-Revision 1.3 2004/07/19 16:08:56 shersche
-fix problems in UTF8/Unicode string translations
-
-Revision 1.2 2004/07/19 07:48:34 shersche
-fix bug in DNSService.Register when passing in NULL text record, add TextRecord APIs
-
-Revision 1.1 2004/06/26 04:01:22 shersche
-Initial revision
-
-
*/
// This is the main DLL file.
*
* <http://lists.apple.com/bonjour-dev/>
*
-
- Change History (most recent first):
-
-$Log: dnssd_NET.h,v $
-Revision 1.9 2006/08/14 23:25:43 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.8 2005/02/10 22:35:33 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.7 2004/12/16 19:56:12 cheshire
-Update comments
-
-Revision 1.6 2004/09/20 22:47:06 cheshire
-Add cautionary comment
-
-Revision 1.5 2004/09/16 18:16:27 shersche
-Cleanup to parameter names
-Submitted by: prepin@gmail.com
-
-Revision 1.4 2004/09/13 19:35:57 shersche
-<rdar://problem/3798941> Add Apple.DNSSD namespace to MC++ wrapper class
-<rdar://problem/3798950> Change all instances of unsigned short to int
-Bug #: 3798941, 3798950
-
-Revision 1.3 2004/07/27 07:12:10 shersche
-make TextRecord an instantiable class object
-
-Revision 1.2 2004/07/19 07:48:34 shersche
-fix bug in DNSService.Register when passing in NULL text record, add TextRecord APIs
-
-Revision 1.1 2004/06/26 04:01:22 shersche
-Initial revision
-
-
*/
#pragma once
* 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: dllmain.c,v $
-Revision 1.4 2006/08/14 23:25:41 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2005/07/07 19:18:29 shersche
-Fix error in previous checkin, change SystemServiceIsDisabled() to IsSystemServiceDisabled()
-
-Revision 1.2 2005/06/30 17:55:35 shersche
-<rdar://problem/4096913> Implement ISSystemServiceDisabled(). This is used to determine how long we should wait to connect to the system service.
-
-Revision 1.1 2004/06/18 03:55:11 rpantos
-Move DLL up to main level; additional integration from Scott.
-
-Revision 1.1 2004/02/21 04:16:50 bradley
-DLL wrapper for DNS-SD API.
-
-*/
+ */
#include <windows.h>
#include <DebugServices.h>
; See the License for the specific language governing permissions and
; limitations under the License.
;
-; 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()
-;
-; Revision 1.3 2006/08/14 23:25:41 cheshire
-; Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-;
-; Revision 1.2 2004/07/19 07:43:59 shersche
-; export TXTRecord APIs
-;
-; Revision 1.1 2004/06/18 03:55:11 rpantos
-; Move DLL up to main level; additional integration from Scott.
-;
-; Revision 1.2 2004/03/19 10:07:14 bradley
-; Export all DNS-SD API symbols from the DLL so they can be used by clients.
-;
-; Revision 1.1 2004/02/21 04:16:50 bradley
-; DLL wrapper for DNS-SD API.
-;
-;
-;
LIBRARY dnssd
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\WINDOWS\system32\$(PlatformName)" mkdir "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\include" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\include"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
xcopy /I/Y "$(OutDir)\dnssd.lib" "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)"
xcopy /I/Y "$(ProjectDir)..\..\mDNSShared\dns_sd.h" "$(DSTROOT)\Program Files\Bonjour SDK\include"
:END
"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\WINDOWS\system32\$(PlatformName)" mkdir "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\include" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\include"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
xcopy /I/Y "$(ProjectDir)..\..\mDNSShared\dns_sd.h" "$(DSTROOT)\Program Files\Bonjour SDK\include"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\WINDOWS\system32\$(PlatformName)" mkdir "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\include" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\include"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
xcopy /I/Y "$(OutDir)\dnssd.lib" "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)"
:END
"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\WINDOWS\system32\$(PlatformName)" mkdir "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\include" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\include"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\WINDOWS\system32\$(PlatformName)"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)"
echo F | xcopy /Y "$(OutDir)\dnssdStatic.lib" "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)\dnssd.lib"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)"
echo F | xcopy /I/Y "$(OutDir)\dnssdStatic.lib" "$(DSTROOT)\Program Files\Bonjour SDK\lib\$(PlatformName)\dnssd.lib"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\r
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ */
+
+
+
+
+
+#include "stdafx.h"
+
+#include "resource.h"
+
+#include "DLLX.h"
+
+#include "dlldatax.h"
+
+#include <DebugServices.h>
+
+
+
+
+
+class CDLLComponentModule : public CAtlDllModuleT< CDLLComponentModule >
+
+{
+
+public :
+
+ DECLARE_LIBID(LIBID_Bonjour)
+
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_DLLX, "{56608F9C-223B-4CB6-813D-85EDCCADFB4B}")
+
+};
+
+
+
+CDLLComponentModule _AtlModule;
+
+
+
+
+
+#ifdef _MANAGED
+
+#pragma managed(push, off)
+
+#endif
+
+
+
+// DLL Entry Point
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+
+{
- 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
+ debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
+
+
+
+#ifdef _MERGE_PROXYSTUB
+
+ if (!PrxDllMain(hInstance, dwReason, lpReserved))
+
+ return FALSE;
+
+#endif
+
+ hInstance;
+
+ return _AtlModule.DllMain(dwReason, lpReserved);
+
+}
+
+
+
+#ifdef _MANAGED
+
+#pragma managed(pop)
+
+#endif
+
+
+
+
+
+
+
+
+
+// Used to determine whether the DLL can be unloaded by OLE
+
+STDAPI DllCanUnloadNow(void)
+
+{
+
+#ifdef _MERGE_PROXYSTUB
+
+ HRESULT hr = PrxDllCanUnloadNow();
+
+ if (hr != S_OK)
+
+ return hr;
+
+#endif
+
+ return _AtlModule.DllCanUnloadNow();
+
+}
+
+
+
+
+
+// Returns a class factory to create an object of the requested type
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+
+{
+
+#ifdef _MERGE_PROXYSTUB
+
+ if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
+
+ return S_OK;
+
+#endif
+
+ return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+
+}
+
+
+
+
+
+// DllRegisterServer - Adds entries to the system registry
+
+STDAPI DllRegisterServer(void)
+
+{
+
+ // registers object, typelib and all interfaces in typelib
+
+ HRESULT hr = _AtlModule.DllRegisterServer();
+
+#ifdef _MERGE_PROXYSTUB
+
+ if (FAILED(hr))
+
+ return hr;
+
+ hr = PrxDllRegisterServer();
+
+#endif
+
+ return hr;
+
+}
+
+
+
+
+
+// DllUnregisterServer - Removes entries from the system registry
+
+STDAPI DllUnregisterServer(void)
+
+{
+
+ HRESULT hr = _AtlModule.DllUnregisterServer();
+
+#ifdef _MERGE_PROXYSTUB
+
+ if (FAILED(hr))
+
+ return hr;
+
+ hr = PrxDllRegisterServer();
+
+ if (FAILED(hr))
+
+ return hr;
+
+ hr = PrxDllUnregisterServer();
+
+#endif
+
+ return hr;
+
+}
+
+
+
; 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
+
+
+
+
+
+LIBRARY "dnssdX.DLL"
+
+
+
+EXPORTS
+
+ DllCanUnloadNow PRIVATE
+
+ DllGetClassObject PRIVATE
+
+ DllRegisterServer PRIVATE
+
+ DllUnregisterServer PRIVATE
+
* 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.
+ */
+
+
+
+// This file will be processed by the MIDL tool to
+
+// produce the type library (DLLComponent.tlb) and marshalling code.
+
+
+
+typedef [ uuid(4085DD59-D0E1-4efe-B6EE-DDBF7631B9C0) ]
+
+enum DNSSDFlags
+
+{
+
+ kDNSSDFlagsMoreComing = 0x0001,
+
+ kDNSSDFlagsDefault = 0x0004,
+
+ kDNSSDFlagsNoAutoRename = 0x0008,
+
+ kDNSSDFlagsShared = 0x0010,
+
+ kDNSSDFlagsUnique = 0x0020,
+
+ kDNSSDFlagsBrowseDomains = 0x0040,
+
+ kDNSSDFlagsRegistrationDomains = 0x0080,
+
+ kDNSSDFlagsLongLivedQuery = 0x0100,
+
+ kDNSSDFlagsAllowRemoteQuery = 0x0200,
+
+ kDNSSDFlagsForceMulticast = 0x0400,
+
+ kDNSSDFlagsForce = 0x0800,
+
+ kDNSSDFlagsReturnIntermediates = 0x1000,
+
+ kDNSSDFlagsNonBrowsable = 0x2000
+
+} DNSSDFlags;
+
+
+
+
+
+typedef [ uuid(30CDF335-CA52-4b17-AFF2-E83C64C450D4) ]
+
+enum DNSSDAddressFamily
+
+{
+
+ kDNSSDAddressFamily_IPv4 = 0x1,
+
+ kDNSSDAddressFamily_IPv6 = 0x2
+
+} DNSSDAddressFamily;
+
+
+
+
+
+typedef [ uuid(98FB4702-7374-4b16-A8DB-AD35BFB8364D) ]
+
+enum DNSSDProtocol
+
+{
+
+ kDNSSDProtocol_UDP = 0x10,
+
+ kDNSSDProtocol_TCP = 0x20
+
+} DNSSDProtocol;
+
+
+
+
+
+typedef [ uuid(72BF3EC3-19BC-47e5-8D95-3B73FF37D893) ]
+
+enum DNSSDRRClass
+
+{
+
+ kDNSSDClass_IN = 1
+
+} DNSSDRRClass;
+
+
+
+
+
+typedef [ uuid(08E362DF-5468-4c9a-AC66-FD4747B917BD) ]
+
+enum DNSSDRRType
+
+{
- 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_AXFR = 252,
kDNSSDType_MAILB = 253,
kDNSSDType_MAILA = 254,
- kDNSSDType_ANY = 255\r
-} DNSSDRRType;\r
-\r
-\r
-typedef [ uuid(3B0059E7-5297-4301-9AAB-1522F31EC8A7) ]\r
+ kDNSSDType_ANY = 255
+
+} DNSSDRRType;
+
+
+
+
+
+typedef [ uuid(3B0059E7-5297-4301-9AAB-1522F31EC8A7) ]
+
enum DNSSDError
{
kDNSSDError_NoError = 0,
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
+} DNSSDError;
+
+
+
+import "oaidl.idl";
+
+import "ocidl.idl";
+
+
+
+
+
+[
+
+ object,
+
+ uuid(8FA0889C-5973-4FC9-970B-EC15C925D0CE),
+
+ dual,
+
+ nonextensible,
+
+ helpstring("ITXTRecord Interface"),
+
+ pointer_default(unique)
+
+]
+
+interface ITXTRecord : IDispatch{
+
+ [id(1), helpstring("method SetValue")] HRESULT SetValue([in] BSTR key, [in] VARIANT value);
+
+ [id(2), helpstring("method RemoveValue")] HRESULT RemoveValue([in] BSTR key);
+
+ [id(3), helpstring("method ContainsKey")] HRESULT ContainsKey([in] BSTR key, [out,retval] VARIANT_BOOL* retval);
+
+ [id(4), helpstring("method GetValueForKey")] HRESULT GetValueForKey([in] BSTR key, [out,retval] VARIANT* value);
+
+ [id(5), helpstring("method GetCount")] HRESULT GetCount([out,retval] ULONG* count);
+
+ [id(6), helpstring("method GetKeyAtIndex")] HRESULT GetKeyAtIndex([in] ULONG index, [out,retval] BSTR* retval);
+
+ [id(7), helpstring("method GetValueAtIndex")] HRESULT GetValueAtIndex([in] ULONG index, [out,retval] VARIANT* retval);
+
+};
+
+[
+
+ object,
+
+ uuid(9CE603A0-3365-4DA0-86D1-3F780ECBA110),
+
+ dual,
+
+ nonextensible,
+
+ helpstring("IDNSSDRecord Interface"),
+
+ pointer_default(unique)
+
+]
+
+interface IDNSSDRecord : IDispatch{
+
+ [id(1), helpstring("method Update")] HRESULT Update([in] DNSSDFlags flags, [in] VARIANT rdata, [in] ULONG ttl);
+
+ [id(2), helpstring("method Remove")] HRESULT Remove([in] DNSSDFlags flags);
+
+};
+
+[
+
+ object,
+
+ uuid(7FD72324-63E1-45AD-B337-4D525BD98DAD),
+
+ dual,
+
+ nonextensible,
+
+ helpstring("IDNSSDEventManager Interface"),
+
+ pointer_default(unique)
+
+]
+
+interface IDNSSDEventManager : IDispatch{
+
+};
+
+[
+
+ object,
+
+ uuid(29DE265F-8402-474F-833A-D4653B23458F),
+
+ dual,
+
+ nonextensible,
+
+ helpstring("IDNSSDService Interface"),
+
+ pointer_default(unique)
+
+]
+
+interface IDNSSDService : IDispatch{
+
+ [id(1), helpstring("method EnumerateDomains")] HRESULT EnumerateDomains([in] DNSSDFlags flags, [in] ULONG ifIndex, [in] IDNSSDEventManager* eventManager, [out,retval] IDNSSDService** service);
+
+ [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);
+
+ [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);
+
+ [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);
+
+ [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);
+
+ [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);
+
+ [id(7), helpstring("method AddRecord")] HRESULT AddRecord([in] DNSSDFlags flags, [in] DNSSDRRType rrtype, [in] VARIANT rdata, [in] ULONG ttl, [out,retval] IDNSSDRecord** record);
+
+ [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);
+
+ [id(9), helpstring("method GetProperty")] HRESULT GetProperty([in] BSTR prop, [in,out] VARIANT * value );
+
+ [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);
+
+ [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);
+
+ [id(12), helpstring("method Stop"), local] HRESULT Stop(void);
+
+};
+
+[
+
+ uuid(18FBED6D-F2B7-4EC8-A4A4-46282E635308),
+
+ version(1.0),
+
+ helpstring("Apple Bonjour Library 1.0")
+
+]
+
+library Bonjour
+
+{
+
+ importlib("stdole2.tlb");
+
+ [
+
+ uuid(21AE8D7F-D5FE-45cf-B632-CFA2C2C6B498),
+
+ helpstring("_IDNSSDEvents Interface")
+
+ ]
+
+ dispinterface _IDNSSDEvents
+
+ {
+
+ properties:
+
+ methods:
+
+ [id(1), helpstring("method DomainFound")] void DomainFound([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR domain);
+
+ [id(2), helpstring("method DomainLost")] void DomainLost([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] ULONG ifIndex, [in] BSTR domain);
+
+ [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);
+
+ [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);
+
+ [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);
+
+ [id(6), helpstring("method ServiceRegistered")] void ServiceRegistered([in] IDNSSDService* service, [in] DNSSDFlags flags, [in] BSTR name, [in] BSTR regType, [in] BSTR domain);
+
+ [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);
+
+ [id(8), helpstring("method RecordRegistered")] void RecordRegistered([in] IDNSSDRecord* record, [in] DNSSDFlags flags);
+
+ [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);
+
+ [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);
+
+ [id(11), helpstring("method OperationFailed")] void OperationFailed([in] IDNSSDService* service, [in] DNSSDError error);
+
+ };
+
+ [
+
+ uuid(24CD4DE9-FF84-4701-9DC1-9B69E0D1090A),
+
+ helpstring("DNSSDService Class")
+
+ ]
+
+ coclass DNSSDService
+
+ {
+
+ [default] interface IDNSSDService;
+
+ };
+
+ [
+
+ uuid(AFEE063C-05BA-4248-A26E-168477F49734),
+
+ helpstring("TXTRecord Class")
+
+ ]
+
+ coclass TXTRecord
+
+ {
+
+ [default] interface ITXTRecord;
+
+ };
+
+ [
+
+ uuid(5E93C5A9-7516-4259-A67B-41A656F6E01C),
+
+ helpstring("DNSSDRecord Class")
+
+ ]
+
+ coclass DNSSDRecord
+
+ {
+
+ [default] interface IDNSSDRecord;
+
+ };
+
+ [
+
+ uuid(BEEB932A-8D4A-4619-AEFE-A836F988B221),
+
+ helpstring("DNSSDEventManager Class")
+
+ ]
+
+ coclass DNSSDEventManager
+
+ {
+
+ [default] interface IDNSSDEventManager;
+
+ [default, source] dispinterface _IDNSSDEvents;
+
+ };
+
+ enum DNSSDFlags;
+
+ enum DNSSDAddressFamily;
+
+ enum DNSSDProtocol;
+
+ enum DNSSDRRClass;
+
+ enum DNSSDRRType;
+
+ enum DNSSDError;
+
+};
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ */
+
+
+
+#include "stdafx.h"
+
+#include "DNSSDEventManager.h"
+
+
+
+
+
+// CDNSSDEventManager
+
+
- 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
* 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.
+ */
+
+
+
+#pragma once
+
+#include "resource.h" // main symbols
+
+
+
+#include "DLLX.h"
+
+#include "_IDNSSDEvents_CP.H"
+
+
+
+
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+
+#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."
+
+#endif
+
+
+
+
+
+
+
+// CDNSSDEventManager
+
+
+
+class ATL_NO_VTABLE CDNSSDEventManager :
+
+ public CComObjectRootEx<CComSingleThreadModel>,
+
+ public CComCoClass<CDNSSDEventManager, &CLSID_DNSSDEventManager>,
+
+ public IConnectionPointContainerImpl<CDNSSDEventManager>,
+
+ public CProxy_IDNSSDEvents<CDNSSDEventManager>,
+
+ public IDispatchImpl<IDNSSDEventManager, &IID_IDNSSDEventManager, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>
+
+{
+
+public:
+
+ CDNSSDEventManager()
+
+ {
+
+ }
+
+
+
+DECLARE_REGISTRY_RESOURCEID(IDR_DNSSDEVENTMANAGER)
+
+
+
+
+
+BEGIN_COM_MAP(CDNSSDEventManager)
+
+ COM_INTERFACE_ENTRY(IDNSSDEventManager)
+
+ COM_INTERFACE_ENTRY(IDispatch)
+
+ COM_INTERFACE_ENTRY(IConnectionPointContainer)
+
+END_COM_MAP()
+
+
+
+BEGIN_CONNECTION_POINT_MAP(CDNSSDEventManager)
+
+ CONNECTION_POINT_ENTRY(__uuidof(_IDNSSDEvents))
+
+END_CONNECTION_POINT_MAP()
+
+
+
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+
+
+ HRESULT FinalConstruct()
+
+ {
+
+ return S_OK;
+
+ }
+
+
+
+ void FinalRelease()
+
+ {
+
+ }
+
+
+
+public:
+
+
+
+};
+
+
+
+OBJECT_ENTRY_AUTO(__uuidof(DNSSDEventManager), CDNSSDEventManager)
- 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
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ */
+
+
+
+#include "stdafx.h"
+
+#include "DNSSDRecord.h"
+
+#include "StringServices.h"
+
+#include <DebugServices.h>
+
+
+
+
+
+// CDNSSDRecord
+
+
+
+STDMETHODIMP CDNSSDRecord::Update(DNSSDFlags flags, VARIANT rdata, ULONG ttl)
+
+{
+
+ std::vector< BYTE > byteArray;
+
+ const void * byteArrayPtr = NULL;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+ BOOL ok;
+
+
+
+ // Convert the VARIANT
+
+ ok = VariantToByteArray( &rdata, byteArray );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ err = DNSServiceUpdateRecord( m_serviceObject->GetSubordRef(), m_rref, flags, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl );
+
+ require_noerr( err, exit );
+
+
+
+exit:
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDRecord::Remove(DNSSDFlags flags)
+
+{
+
+ DNSServiceErrorType err = 0;
+
+
+
+ err = DNSServiceRemoveRecord( m_serviceObject->GetSubordRef(), m_rref, flags );
+
+ require_noerr( err, exit );
+
+
+
+exit:
+
+
+
+ return err;
+
+}
+
+
- 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
* 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.
+ */
+
+
+
+#pragma once
+
+#include "resource.h" // main symbols
+
+
+
+#include "DLLX.h"
+
+#include "DNSSDService.h"
+
+#include <dns_sd.h>
+
+
+
+
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+
+#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."
+
+#endif
+
+
+
+
+
+
+
+// CDNSSDRecord
+
+
+
+class ATL_NO_VTABLE CDNSSDRecord :
+
+ public CComObjectRootEx<CComSingleThreadModel>,
+
+ public CComCoClass<CDNSSDRecord, &CLSID_DNSSDRecord>,
+
+ public IDispatchImpl<IDNSSDRecord, &IID_IDNSSDRecord, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>
+
+{
+
+public:
+
+ CDNSSDRecord()
+
+ {
+
+ }
+
+
+
+DECLARE_REGISTRY_RESOURCEID(IDR_DNSSDRECORD)
+
+
+
+
+
+BEGIN_COM_MAP(CDNSSDRecord)
+
+ COM_INTERFACE_ENTRY(IDNSSDRecord)
+
+ COM_INTERFACE_ENTRY(IDispatch)
+
+END_COM_MAP()
+
+
+
+
+
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+
+
+ HRESULT FinalConstruct()
+
+ {
+
+ return S_OK;
+
+ }
+
+
+
+ void FinalRelease()
+
+ {
+
+ }
+
+
+
+ inline CDNSSDService*
+
+ GetServiceObject()
+
+ {
+
+ return m_serviceObject;
+
+ }
+
+
+
+ inline void
+
+ SetServiceObject( CDNSSDService * serviceObject )
+
+ {
+
+ m_serviceObject = serviceObject;
+
+ }
+
+
+
+ inline DNSRecordRef
+
+ GetRecordRef()
+
+ {
+
+ return m_rref;
+
+ }
+
+
+
+ inline void
+
+ SetRecordRef( DNSRecordRef rref )
+
+ {
+
+ m_rref = rref;
+
+ }
+
+
+
+public:
+
+
+
+ STDMETHOD(Update)(DNSSDFlags flags, VARIANT rdata, ULONG ttl);
+
+ STDMETHOD(Remove)(DNSSDFlags flags);
+
+
+
+private:
+
+
+
+ CDNSSDService * m_serviceObject;
+
+ DNSRecordRef m_rref;
+
+};
+
+
+
+OBJECT_ENTRY_AUTO(__uuidof(DNSSDRecord), CDNSSDRecord)
- 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
* 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.
+ */
+
+
+
+#pragma warning(disable:4995)
+
+
+
+#include "stdafx.h"
+
+#include <strsafe.h>
+
+#include "DNSSDService.h"
+
+#include "DNSSDEventManager.h"
+
+#include "DNSSDRecord.h"
+
+#include "TXTRecord.h"
+
+#include "StringServices.h"
+
+#include <DebugServices.h>
+
+
+
+
+
+#define WM_SOCKET (WM_APP + 100)
+
+
+
+
+
+// CDNSSDService
+
+
+
+BOOL CDNSSDService::m_registeredWindowClass = FALSE;
+
+HWND CDNSSDService::m_hiddenWindow = NULL;
+
+CDNSSDService::SocketMap CDNSSDService::m_socketMap;
+
+
+
+
+
+HRESULT CDNSSDService::FinalConstruct()
+
+{
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = S_OK;
+
+
+
+ m_isPrimary = TRUE;
+
+ err = DNSServiceCreateConnection( &m_primary );
+
+ require_action( !err, exit, hr = E_FAIL );
+
+
+
+ if ( !m_hiddenWindow )
+
+ {
+
+ TCHAR windowClassName[ 256 ];
+
+
+
+ StringCchPrintf( windowClassName, sizeof( windowClassName ) / sizeof( TCHAR ), TEXT( "Bonjour Hidden Window %d" ), GetProcessId( NULL ) );
+
+
+
+ if ( !m_registeredWindowClass )
+
+ {
+
+ WNDCLASS wc;
+
+ ATOM atom;
+
+
+
+ wc.style = 0;
+
+ wc.lpfnWndProc = WndProc;
+
+ wc.cbClsExtra = 0;
+
+ wc.cbWndExtra = 0;
+
+ wc.hInstance = NULL;
+
+ wc.hIcon = NULL;
+
+ wc.hCursor = NULL;
+
+ wc.hbrBackground = NULL;
+
+ wc.lpszMenuName = NULL;
+
+ wc.lpszClassName = windowClassName;
+
+
+
+ atom = RegisterClass(&wc);
+
+ require_action( atom != NULL, exit, hr = E_FAIL );
+
+
+
+ m_registeredWindowClass = TRUE;
+
+ }
+
+
+
+ m_hiddenWindow = CreateWindow( windowClassName, windowClassName, WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandle( NULL ), NULL );
+
+ require_action( m_hiddenWindow != NULL, exit, hr = E_FAIL );
+
+ }
+
+
+
+ err = WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, WM_SOCKET, FD_READ );
+
+ require_action( !err, exit, hr = E_FAIL );
+
+
+
+ m_socketMap[ DNSServiceRefSockFD( m_primary ) ] = this;
+
+
+
+exit:
+
+
+
+ return hr;
+
+}
+
+
+
+
+
+void CDNSSDService::FinalRelease()
+
+{
+
+ dlog( kDebugLevelTrace, "FinalRelease()\n" );
+
+ Stop();
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service)
+
+{
+
+ CComObject<CDNSSDService> * object = NULL;
+
+ DNSServiceRef subord = NULL;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+
+
+ check( m_primary );
+
+
+
+ // Initialize
+
+ *service = NULL;
+
+
+
+ try
+
+ {
+
+ object = new CComObject<CDNSSDService>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ object = NULL;
+
+ }
+
+
+
+ require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
+
+ object->AddRef();
+
+
+
+ subord = m_primary;
+
+ err = DNSServiceEnumerateDomains( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );
+
+ require_noerr( err, exit );
+
+
+
+ object->SetPrimaryRef( m_primary );
+
+ object->SetSubordRef( subord );
+
+ object->SetEventManager( eventManager );
+
+
+
+ *service = object;
+
+
+
+exit:
+
+
+
+ if ( err && object )
+
+ {
+
+ object->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service )
+
+{
+
+ CComObject<CDNSSDService> * object = NULL;
+
+ std::string regtypeUTF8;
+
+ std::string domainUTF8;
+
+ DNSServiceRef subord = NULL;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+ BOOL ok;
+
+
+
+ check( m_primary );
+
+
+
+ // Initialize
+
+ *service = NULL;
+
+
+
+ // Convert BSTR params to utf8
+
+ ok = BSTRToUTF8( regtype, regtypeUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+ ok = BSTRToUTF8( domain, domainUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+
+
+ try
+
+ {
+
+ object = new CComObject<CDNSSDService>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ object = NULL;
+
+ }
+
+
+
+ require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
+
+ object->AddRef();
+
+
+
+ subord = m_primary;
+
+ err = DNSServiceBrowse( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, regtypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, ( DNSServiceBrowseReply ) &BrowseReply, object );
+
+ require_noerr( err, exit );
+
+
+
+ object->SetPrimaryRef( m_primary );
+
+ object->SetSubordRef( subord );
+
+ object->SetEventManager( eventManager );
+
+
+
+ *service = object;
+
+
+
+exit:
+
+
+
+ if ( err && object )
+
+ {
+
+ object->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service)
+
+{
+
+ CComObject<CDNSSDService> * object = NULL;
+
+ std::string serviceNameUTF8;
+
+ std::string regTypeUTF8;
+
+ std::string domainUTF8;
+
+ DNSServiceRef subord = NULL;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+ BOOL ok;
+
+
+
+ check( m_primary );
+
+
+
+ // Initialize
+
+ *service = NULL;
+
+
+
+ // Convert BSTR params to utf8
+
+ ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+ ok = BSTRToUTF8( regType, regTypeUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+ ok = BSTRToUTF8( domain, domainUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+
+
+ try
+
+ {
+
+ object = new CComObject<CDNSSDService>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ object = NULL;
+
+ }
+
+
+
+ require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
+
+ object->AddRef();
+
+
+
+ subord = m_primary;
+
+ err = DNSServiceResolve( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );
+
+ require_noerr( err, exit );
+
+
+
+ object->SetPrimaryRef( m_primary );
+
+ object->SetSubordRef( subord );
+
+ object->SetEventManager( eventManager );
+
+
+
+ *service = object;
+
+
+
+exit:
+
+
+
+ if ( err && object )
+
+ {
+
+ object->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service)
+
+{
+
+ CComObject<CDNSSDService> * object = NULL;
+
+ std::string serviceNameUTF8;
+
+ std::string regTypeUTF8;
+
+ std::string domainUTF8;
+
+ std::string hostUTF8;
+
+ const void * txtRecord = NULL;
+
+ uint16_t txtLen = 0;
+
+ DNSServiceRef subord = NULL;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+ BOOL ok;
+
+
+
+ check( m_primary );
+
+
+
+ // Initialize
+
+ *service = NULL;
+
+
+
+ // Convert BSTR params to utf8
+
+ ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+ ok = BSTRToUTF8( regType, regTypeUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+ ok = BSTRToUTF8( domain, domainUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+ ok = BSTRToUTF8( host, hostUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+
+
+ try
+
+ {
+
+ object = new CComObject<CDNSSDService>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ object = NULL;
+
+ }
+
+
+
+ require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
+
+ object->AddRef();
+
+
+
+ if ( record )
+
+ {
+
+ CComObject< CTXTRecord > * realTXTRecord;
+
+
+
+ realTXTRecord = ( CComObject< CTXTRecord >* ) record;
+
+
+
+ txtRecord = realTXTRecord->GetBytes();
+
+ txtLen = realTXTRecord->GetLen();
+
+ }
+
+
+
+ subord = m_primary;
+
+ 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 );
+
+ require_noerr( err, exit );
+
+
+
+ object->SetPrimaryRef( m_primary );
+
+ object->SetSubordRef( subord );
+
+ object->SetEventManager( eventManager );
+
+
+
+ *service = object;
+
+
+
+exit:
+
+
+
+ if ( err && object )
+
+ {
+
+ object->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service)
+
+{
+
+ CComObject<CDNSSDService> * object = NULL;
+
+ DNSServiceRef subord = NULL;
+
+ std::string fullNameUTF8;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+ BOOL ok;
+
+
+
+ check( m_primary );
+
+
+
+ // Initialize
+
+ *service = NULL;
+
+
+
+ // Convert BSTR params to utf8
+
+ ok = BSTRToUTF8( fullname, fullNameUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+
+
+ try
+
+ {
+
+ object = new CComObject<CDNSSDService>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ object = NULL;
+
+ }
+
+
+
+ require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
+
+ object->AddRef();
+
+
+
+ subord = m_primary;
+
+ err = DNSServiceQueryRecord( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );
+
+ require_noerr( err, exit );
+
+
+
+ object->SetPrimaryRef( m_primary );
+
+ object->SetSubordRef( subord );
+
+ object->SetEventManager( eventManager );
+
+
+
+ *service = object;
+
+
+
+exit:
+
+
+
+ if ( err && object )
+
+ {
+
+ object->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::RegisterRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record)
+
+{
+
+ CComObject<CDNSSDRecord> * object = NULL;
+
+ DNSRecordRef rref = NULL;
+
+ std::string fullNameUTF8;
+
+ std::vector< BYTE > byteArray;
+
+ const void * byteArrayPtr = NULL;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+ BOOL ok;
+
+
+
+ check( m_primary );
+
+
+
+ // Initialize
+
+ *object = NULL;
+
+
+
+ // Convert BSTR params to utf8
+
+ ok = BSTRToUTF8( fullName, fullNameUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+
+
+ // Convert the VARIANT
+
+ ok = VariantToByteArray( &rdata, byteArray );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ try
+
+ {
+
+ object = new CComObject<CDNSSDRecord>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ object = NULL;
+
+ }
+
+
+
+ require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
+
+ object->AddRef();
+
+
+
+ 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 );
+
+ require_noerr( err, exit );
+
+
+
+ object->SetServiceObject( this );
+
+ object->SetRecordRef( rref );
+
+ this->SetEventManager( eventManager );
+
+
+
+ *record = object;
+
+
+
+exit:
+
+
+
+ if ( err && object )
+
+ {
+
+ object->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::AddRecord(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record)
+
+{
+
+ CComObject<CDNSSDRecord> * object = NULL;
+
+ DNSRecordRef rref = NULL;
+
+ std::vector< BYTE > byteArray;
+
+ const void * byteArrayPtr = NULL;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+ BOOL ok;
+
+
+
+ check( m_primary );
+
+
+
+ // Initialize
+
+ *object = NULL;
+
+
+
+ // Convert the VARIANT
+
+ ok = VariantToByteArray( &rdata, byteArray );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ try
+
+ {
+
+ object = new CComObject<CDNSSDRecord>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ object = NULL;
+
+ }
+
+
+
+ require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
+
+ object->AddRef();
+
+
+
+ err = DNSServiceAddRecord( m_primary, &rref, flags, rrtype, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl );
+
+ require_noerr( err, exit );
+
+
+
+ object->SetServiceObject( this );
+
+ object->SetRecordRef( rref );
+
+
+
+ *record = object;
+
+
+
+exit:
+
+
+
+ if ( err && object )
+
+ {
+
+ object->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+STDMETHODIMP CDNSSDService::ReconfirmRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata)
+
+{
+
+ std::string fullNameUTF8;
+
+ std::vector< BYTE > byteArray;
+
+ const void * byteArrayPtr = NULL;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+ BOOL ok;
+
+
+
+ // Convert BSTR params to utf8
+
+ ok = BSTRToUTF8( fullName, fullNameUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+
+
+ // Convert the VARIANT
+
+ ok = VariantToByteArray( &rdata, byteArray );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ err = DNSServiceReconfirmRecord( flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL );
+
+ require_noerr( err, exit );
+
+
+
+exit:
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::GetProperty(BSTR prop, VARIANT * value )
+
+{
+
+ std::string propUTF8;
+
+ std::vector< BYTE > byteArray;
+
+ SAFEARRAY * psa = NULL;
+
+ BYTE * pData = NULL;
+
+ uint32_t elems = 0;
+
+ DNSServiceErrorType err = 0;
+
+ BOOL ok = TRUE;
+
+
+
+ // Convert BSTR params to utf8
+
+ ok = BSTRToUTF8( prop, propUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+
+
+ // Setup the byte array
+
+ require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );
+
+ psa = V_ARRAY( value );
+
+ require_action( psa, exit, err = kDNSServiceErr_Unknown );
+
+ require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );
+
+ byteArray.reserve( psa->rgsabound[0].cElements );
+
+ byteArray.assign( byteArray.capacity(), 0 );
+
+ elems = ( uint32_t ) byteArray.capacity();
+
+
+
+ // Call the function and package the return value in the Variant
+
+ err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );
+
+ require_noerr( err, exit );
+
+ ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );
+
+ require_action( ok, exit, err = kDNSSDError_Unknown );
+
+
+
+exit:
+
+
+
+ if ( psa )
+
+ {
+
+ SafeArrayUnaccessData( psa );
+
+ psa = NULL;
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+STDMETHODIMP CDNSSDService::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IDNSSDEventManager *eventManager, IDNSSDService **service)
+
+{
+
+ CComObject<CDNSSDService> * object = NULL;
+
+ DNSServiceRef subord = NULL;
+
+ std::string hostNameUTF8;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+ BOOL ok;
+
+
+
+ check( m_primary );
+
+
+
+ // Initialize
+
+ *service = NULL;
+
+
+
+ // Convert BSTR params to utf8
+
+ ok = BSTRToUTF8( hostName, hostNameUTF8 );
+
+ require_action( ok, exit, err = kDNSServiceErr_BadParam );
+
+
+
+ try
+
+ {
+
+ object = new CComObject<CDNSSDService>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ object = NULL;
+
+ }
+
+
+
+ require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
+
+ object->AddRef();
+
+
+
+ subord = m_primary;
+
+ err = DNSServiceGetAddrInfo( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );
+
+ require_noerr( err, exit );
+
+
+
+ object->SetPrimaryRef( m_primary );
+
+ object->SetSubordRef( subord );
+
+ object->SetEventManager( eventManager );
+
+
+
+ *service = object;
+
+
+
+exit:
+
+
+
+ if ( err && object )
+
+ {
+
+ object->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service)
+
+{
+
+ CComObject<CDNSSDService> * object = NULL;
+
+ DNSServiceRef subord = NULL;
+
+ DNSServiceProtocol prot = 0;
+
+ DNSServiceErrorType err = 0;
+
+ HRESULT hr = 0;
+
+
+
+ check( m_primary );
+
+
+
+ // Initialize
+
+ *service = NULL;
+
+
+
+ try
+
+ {
+
+ object = new CComObject<CDNSSDService>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ object = NULL;
+
+ }
+
+
+
+ require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
+
+ object->AddRef();
+
+
+
+ prot = ( addressFamily | protocol );
+
+
+
+ subord = m_primary;
+
+ err = DNSServiceNATPortMappingCreate( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, prot, htons( internalPort ), htons( externalPort ), ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );
+
+ require_noerr( err, exit );
+
+
+
+ object->SetPrimaryRef( m_primary );
+
+ object->SetSubordRef( subord );
+
+ object->SetEventManager( eventManager );
+
+
+
+ *service = object;
+
+
+
+exit:
+
+
+
+ if ( err && object )
+
+ {
+
+ object->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+
+
+
+STDMETHODIMP CDNSSDService::Stop(void)
+
+{
+
+ if ( !m_stopped )
+
+ {
+
+ m_stopped = TRUE;
+
+
+
+ dlog( kDebugLevelTrace, "Stop()\n" );
+
+
+
+ if ( m_isPrimary && m_primary )
+
+ {
+
+ SocketMap::iterator it;
+
+
+
+ if ( m_hiddenWindow )
+
+ {
+
+ WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, 0, 0 );
+
+ }
+
+
+
+ it = m_socketMap.find( DNSServiceRefSockFD( m_primary ) );
+
+
+
+ if ( it != m_socketMap.end() )
+
+ {
+
+ m_socketMap.erase( it );
+
+ }
+
+
+
+ DNSServiceRefDeallocate( m_primary );
+
+ m_primary = NULL;
+
+ }
+
+ else if ( m_subord )
+
+ {
+
+ DNSServiceRefDeallocate( m_subord );
+
+ m_subord = NULL;
+
+ }
+
+
+
+ if ( m_eventManager != NULL )
+
+ {
+
+ m_eventManager->Release();
+
+ m_eventManager = NULL;
+
+ }
+
+ }
+
+
+
+ return S_OK;
+
+}
+
+
+
+
- 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
(
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
+ )
+
+{
+
+ CComObject<CDNSSDService> * service = NULL;
+
+ CDNSSDEventManager * eventManager = NULL;
+
+ int err = 0;
+
+
+
+ service = ( CComObject< CDNSSDService>* ) context;
+
+ require_action( service, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ if ( service->ShouldHandleReply( errorCode, eventManager ) )
+
+ {
+
+ CComBSTR replyDomain;
+
+ BOOL ok;
+
+
+
+ ok = UTF8ToBSTR( replyDomainUTF8, replyDomain );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ if ( flags & kDNSServiceFlagsAdd )
+
+ {
+
+ eventManager->Fire_DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
+
+ }
+
+ else
+
+ {
+
+ eventManager->Fire_DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
+
+ }
+
+ }
+
+
+
+exit:
+
+
+
+ return;
+
+}
+
+
+
+
+
void DNSSD_API
CDNSSDService::BrowseReply
(
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
+ )
+
+{
+
+ CComObject<CDNSSDService> * service = NULL;
+
+ CDNSSDEventManager * eventManager = NULL;
+
+ int err = 0;
+
+
+
+ service = ( CComObject< CDNSSDService>* ) context;
+
+ require_action( service, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ if ( service->ShouldHandleReply( errorCode, eventManager ) )
+
+ {
+
+ CComBSTR serviceName;
+
+ CComBSTR regType;
+
+ CComBSTR replyDomain;
+
+
+
+ UTF8ToBSTR( serviceNameUTF8, serviceName );
+
+ UTF8ToBSTR( regTypeUTF8, regType );
+
+ UTF8ToBSTR( replyDomainUTF8, replyDomain );
+
+
+
+ if ( flags & kDNSServiceFlagsAdd )
+
+ {
+
+ eventManager->Fire_ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
+
+ }
+
+ else
+
+ {
+
+ eventManager->Fire_ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
+
+ }
+
+ }
+
+
+
+exit:
+
+
+
+ return;
+
+}
+
+
+
+
+
+void DNSSD_API
+
+CDNSSDService::ResolveReply
+
(
DNSServiceRef sdRef,
DNSServiceFlags flags,
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 *context
+
+ )
+
+{
+
+ CComObject<CDNSSDService> * service = NULL;
+
+ CDNSSDEventManager * eventManager = NULL;
+
+ int err = 0;
+
+
+
+ service = ( CComObject< CDNSSDService>* ) context;
+
+ require_action( service, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ if ( service->ShouldHandleReply( errorCode, eventManager ) )
+
+ {
+
+ CComBSTR fullName;
+
+ CComBSTR hostName;
+
+ CComBSTR regType;
+
+ CComBSTR replyDomain;
+
+ CComObject< CTXTRecord >* record;
+
+ BOOL ok;
+
+
+
+ ok = UTF8ToBSTR( fullNameUTF8, fullName );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+ ok = UTF8ToBSTR( hostNameUTF8, hostName );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ try
+
+ {
+
+ record = new CComObject<CTXTRecord>();
+
+ }
+
+ catch ( ... )
+
+ {
+
+ record = NULL;
+
+ }
+
+
+
+ require_action( record, exit, err = kDNSServiceErr_NoMemory );
+
+ record->AddRef();
+
+
+
+ if ( txtLen > 0 )
+
+ {
+
+ record->SetBytes( txtRecord, txtLen );
+
+ }
+
+
+
+ eventManager->Fire_ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, ntohs( port ), record );
+
+ }
+
+
+
+exit:
+
+
+
+ return;
+
+}
+
+
+
+
+
void DNSSD_API
CDNSSDService::RegisterReply
(
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
+ )
+
+{
+
+ CComObject<CDNSSDService> * service = NULL;
+
+ CDNSSDEventManager * eventManager = NULL;
+
+ int err = 0;
+
+
+
+ service = ( CComObject< CDNSSDService>* ) context;
+
+ require_action( service, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ if ( service->ShouldHandleReply( errorCode, eventManager ) )
+
+ {
+
+ CComBSTR serviceName;
+
+ CComBSTR regType;
+
+ CComBSTR domain;
+
+ BOOL ok;
+
+
+
+ ok = UTF8ToBSTR( serviceNameUTF8, serviceName );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+ ok = UTF8ToBSTR( regTypeUTF8, regType );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+ ok = UTF8ToBSTR( domainUTF8, domain );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ eventManager->Fire_ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );
+
+ }
+
+
+
+exit:
+
+
+
+ return;
+
+}
+
+
+
+
+
void DNSSD_API
CDNSSDService::QueryRecordReply
(
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
+ )
+
+{
+
+ CComObject<CDNSSDService> * service = NULL;
+
+ CDNSSDEventManager * eventManager = NULL;
+
+ int err = 0;
+
+
+
+ service = ( CComObject< CDNSSDService>* ) context;
+
+ require_action( service, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ if ( service->ShouldHandleReply( errorCode, eventManager ) )
+
+ {
+
+ CComBSTR fullName;
+
+ VARIANT var;
+
+ BOOL ok;
+
+
+
+ ok = UTF8ToBSTR( fullNameUTF8, fullName );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+ ok = ByteArrayToVariant( rdata, rdlen, &var );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ eventManager->Fire_QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );
+
+ }
+
+
+
+exit:
+
+
+
+ return;
+
+}
+
+
+
+
+
void DNSSD_API
CDNSSDService::GetAddrInfoReply
(
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
+ )
+
+{
+
+ CComObject<CDNSSDService> * service = NULL;
+
+ CDNSSDEventManager * eventManager = NULL;
+
+ int err = 0;
+
+
+
+ service = ( CComObject< CDNSSDService>* ) context;
+
+ require_action( service, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ if ( service->ShouldHandleReply( errorCode, eventManager ) )
+
+ {
+
+ CComBSTR hostName;
+
+ DWORD sockaddrLen;
+
+ DNSSDAddressFamily addressFamily;
+
+ char addressUTF8[INET6_ADDRSTRLEN];
+
+ DWORD addressLen = sizeof( addressUTF8 );
+
+ CComBSTR address;
+
+ BOOL ok;
+
+
+
+ ok = UTF8ToBSTR( hostNameUTF8, hostName );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ switch ( rawAddress->sa_family )
+
+ {
+
+ case AF_INET:
+
+ {
+
+ addressFamily = kDNSSDAddressFamily_IPv4;
+
+ sockaddrLen = sizeof( sockaddr_in );
+
+ }
+
+ break;
+
+
+
+ case AF_INET6:
+
+ {
+
+ addressFamily = kDNSSDAddressFamily_IPv6;
+
+ sockaddrLen = sizeof( sockaddr_in6 );
+
+ }
+
+ break;
+
+ }
+
+
+
+ err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );
+
+ require_noerr( err, exit );
+
+ ok = UTF8ToBSTR( addressUTF8, address );
+
+ require_action( ok, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ eventManager->Fire_AddressFound( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );
+
+ }
+
+
+
+exit:
+
+
+
+ return;
+
+}
+
+
+
+
+
void DNSSD_API
CDNSSDService::NATPortMappingReply
(
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
+ )
+
+{
+
+ CComObject<CDNSSDService> * service = NULL;
+
+ CDNSSDEventManager * eventManager = NULL;
+
+ int err = 0;
+
+
+
+ service = ( CComObject< CDNSSDService>* ) context;
+
+ require_action( service, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ if ( service->ShouldHandleReply( errorCode, eventManager ) )
+
+ {
+
+ eventManager->Fire_MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), ntohs( internalPort ), ntohs( externalPort ), ttl );
+
+ }
+
+
+
+exit:
+
+
+
+ return;
+
+}
+
+
+
+
+
void DNSSD_API
CDNSSDService::RegisterRecordReply
(
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
+ )
+
+{
+
+ CComObject<CDNSSDRecord> * record = NULL;
+
+ CDNSSDService * service = NULL;
+
+ CDNSSDEventManager * eventManager = NULL;
+
+ int err = 0;
+
+
+
+ record = ( CComObject< CDNSSDRecord >* ) context;
+
+ require_action( record, exit, err = kDNSServiceErr_Unknown );
+
+ service = record->GetServiceObject();
+
+ require_action( service, exit, err = kDNSServiceErr_Unknown );
+
+
+
+ if ( service->ShouldHandleReply( errorCode, eventManager ) )
+
+ {
+
+ eventManager->Fire_RecordRegistered( record, ( DNSSDFlags ) flags );
+
+ }
+
+
+
+exit:
+
+
+
+ return;
+
+}
+
+
+
+
+
+BOOL
+
+CDNSSDService::ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager )
+
+{
+
+ BOOL ok = FALSE;
+
+
+
+ if ( !this->Stopped() )
+
+ {
+
+ eventManager = this->GetEventManager();
+
+ require_action( eventManager, exit, ok = FALSE );
+
+
+
+ if ( !errorCode )
+
+ {
+
+ ok = TRUE;
+
+ }
+
+ else
+
+ {
+
+ eventManager->Fire_OperationFailed( this, ( DNSSDError ) errorCode );
+
+ }
+
+ }
+
+
+
+exit:
+
+
+
+ return ok;
+
+}
+
+
+
+
+
+LRESULT CALLBACK
+
+CDNSSDService::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
+
+{
+
+ if ( msg == WM_SOCKET )
+
+ {
+
+ SocketMap::iterator it;
+
+
+
+ it = m_socketMap.find( ( SOCKET ) wParam );
+
+ check( it != m_socketMap.end() );
+
+
+
+ if ( it != m_socketMap.end() )
+
+ {
+
+ DNSServiceProcessResult( it->second->m_primary );
+
+ }
+
+ }
+
+
+
+ return DefWindowProc(hWnd, msg, wParam, lParam);;
+
+}
+
* 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.
+ */
+
+
+
+#pragma once
+
+#include "resource.h" // main symbols
+
+
+
+#include "DLLX.h"
+
+#include "DNSSDEventManager.h"
+
+#include <CommonServices.h>
+
+#include <DebugServices.h>
+
+#include <dns_sd.h>
+
+#include <map>
+
+
+
+
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+
+#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."
+
+#endif
+
+
+
+
+
+
+
+// CDNSSDService
+
+
+
+class ATL_NO_VTABLE CDNSSDService :
+
+ public CComObjectRootEx<CComSingleThreadModel>,
+
+ public CComCoClass<CDNSSDService, &CLSID_DNSSDService>,
+
+ public IDispatchImpl<IDNSSDService, &IID_IDNSSDService, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>
+
+{
+
+public:
+
+
+
+ typedef CComObjectRootEx<CComSingleThreadModel> Super;
+
+
+
+ CDNSSDService()
+
+ :
+
+ m_isPrimary( FALSE ),
+
+ m_eventManager( NULL ),
+
+ m_stopped( FALSE ),
+
+ m_primary( NULL ),
+
+ m_subord( NULL )
+
+ {
+
+ }
+
+
+
+DECLARE_REGISTRY_RESOURCEID(IDR_DNSSDSERVICE)
+
+
+
+
+
+BEGIN_COM_MAP(CDNSSDService)
+
+ COM_INTERFACE_ENTRY(IDNSSDService)
+
+ COM_INTERFACE_ENTRY(IDispatch)
+
+END_COM_MAP()
+
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+
+
+ HRESULT
+
+ FinalConstruct();
+
+
+
+ void
+
+ FinalRelease();
+
+
+
+public:
+
+
+
+ inline DNSServiceRef
+
+ GetPrimaryRef()
+
+ {
+
+ return m_primary;
+
+ }
+
+
+
+ inline void
+
+ SetPrimaryRef( DNSServiceRef primary )
+
+ {
+
+ m_primary = primary;
+
+ }
+
+
+
+ inline DNSServiceRef
+
+ GetSubordRef()
+
+ {
+
+ return m_subord;
+
+ }
+
+
+
+ inline void
+
+ SetSubordRef( DNSServiceRef subord )
+
+ {
+
+ m_subord = subord;
+
+ }
+
+
+
+ inline CDNSSDEventManager*
+
+ GetEventManager()
+
+ {
+
+ return m_eventManager;
+
+ }
+
+
+
+ inline void
+
+ SetEventManager( IDNSSDEventManager * eventManager )
+
+ {
+
+ if ( m_eventManager )
+
+ {
+
+ m_eventManager->Release();
+
+ m_eventManager = NULL;
+
+ }
+
+
+
+ if ( eventManager )
+
+ {
+
+ m_eventManager = dynamic_cast< CDNSSDEventManager* >( eventManager );
+
+ check( m_eventManager );
+
+ m_eventManager->AddRef();
+
+ }
+
+ }
+
+
+
+ inline BOOL
+
+ Stopped()
+
+ {
+
+ return m_stopped;
+
+ }
+
+
+
+private:
+
+
- 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
(
DNSServiceErrorType errorCode,
const char *replyDomain,
void *context
- );\r
-\r
+ );
+
+
+
static void DNSSD_API
BrowseReply
(
const char *regtype,
const char *replyDomain,
void *context
- );\r
-\r
- static void DNSSD_API\r
- ResolveReply\r
+ );
+
+
+
+ static void DNSSD_API
+
+ ResolveReply
+
(
DNSServiceRef sdRef,
DNSServiceFlags flags,
uint16_t port,
uint16_t txtLen,
const unsigned char *txtRecord,
- void *context\r
- );\r
-\r
+ void *context
+
+ );
+
+
+
static void DNSSD_API
RegisterReply
(
const char *regtype,
const char *domain,
void *context
- );\r
-\r
+ );
+
+
+
static void DNSSD_API
QueryRecordReply
(
const void *rdata,
uint32_t ttl,
void *context
- );\r
-\r
+ );
+
+
+
static void DNSSD_API
GetAddrInfoReply
(
const struct sockaddr *address,
uint32_t ttl,
void *context
- );\r
-\r
+ );
+
+
+
static void DNSSD_API
NATPortMappingReply
(
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
(
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
+ );
+
+
+
+ inline BOOL
+
+ ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager );
+
+
+
+ static LRESULT CALLBACK
+
+ WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
+
+
+
+ typedef std::map< SOCKET, CDNSSDService* > SocketMap;
+
+
+
+ static BOOL m_registeredWindowClass;
+
+ static HWND m_hiddenWindow;
+
+ static SocketMap m_socketMap;
+
+ CDNSSDEventManager * m_eventManager;
+
+ BOOL m_stopped;
+
+ BOOL m_isPrimary;
+
+ DNSServiceRef m_primary;
+
+ DNSServiceRef m_subord;
+
+public:
+
+ STDMETHOD(EnumerateDomains)(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service);
+
+ STDMETHOD(Browse)(DNSSDFlags flags, ULONG interfaceIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** sdref);
+
+ STDMETHOD(Resolve)(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service);
+
+ STDMETHOD(Register)(DNSSDFlags flags, ULONG ifIndex, BSTR name, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service);
+
+ STDMETHOD(QueryRecord)(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service);
+
+ STDMETHOD(RegisterRecord)(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record);
+
+ STDMETHOD(AddRecord)(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record);
+
+ STDMETHOD(ReconfirmRecord)(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata);
+
+ STDMETHOD(GetProperty)(BSTR prop, VARIANT * value);
+
+ STDMETHOD(GetAddrInfo)(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostname, IDNSSDEventManager *eventManager, IDNSSDService **service);
+
+ STDMETHOD(NATPortMappingCreate)(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service);
+
+ STDMETHOD(Stop)(void);
+
+};
+
+
+
+OBJECT_ENTRY_AUTO(__uuidof(DNSSDService), CDNSSDService)
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ */
+
+
+
+#include "StringServices.h"
+
+#include <DebugServices.h>
+
+
+
+
+
+extern BOOL
+
+BSTRToUTF8
+
+ (
+
+ BSTR inString,
+
+ std::string & outString
+
+ )
+
+{
+
+ USES_CONVERSION;
+
+
+
+ char * utf8String = NULL;
+
+ OSStatus err = kNoErr;
+
+
- 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
+ if ( inString )
+
{
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
+
+
+ utf16String = OLE2T( inString );
+
+ require_action( utf16String != NULL, exit, err = kUnknownErr );
+
+
+
+ if ( wcslen( utf16String ) > 0 )
+
+ {
+
+ size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), NULL, 0, NULL, NULL );
+
+ err = translate_errno( size != 0, GetLastError(), kUnknownErr );
+
+ require_noerr( err, exit );
+
+
+
+ try
+
+ {
+
+ utf8String = new char[ size + 1 ];
+
+ }
+
+ catch ( ... )
+
+ {
+
+ utf8String = NULL;
+
+ }
+
+
+
+ require_action( utf8String != NULL, exit, err = kNoMemoryErr );
+
+ size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), utf8String, (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
+
+
+
+ utf8String[size] = '\0';
+
+ outString = utf8String;
+
}
- }\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
+ }
+
+
+
+exit:
+
+
+
+ if ( utf8String != NULL )
+
+ {
+
+ delete [] utf8String;
+
+ }
+
+
+
+ return ( !err ) ? TRUE : FALSE;
+
+}
+
+
+
+
+
+extern BOOL
+
+UTF8ToBSTR
+
+ (
+
+ const char * inString,
+
+ CComBSTR & outString
+
+ )
+
+{
+
+ wchar_t * unicode = NULL;
+
+ OSStatus err = 0;
+
+
+
+ if ( inString )
+
{
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
+ n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, NULL, 0 );
+
+
+
+ if ( n > 0 )
+
+ {
+
+ try
+
+ {
+
+ unicode = new wchar_t[ n ];
+
+ }
+
+ catch ( ... )
+
+ {
+
+ unicode = NULL;
+
+ }
+
+
+
+ require_action( unicode, exit, err = ERROR_INSUFFICIENT_BUFFER );
+
+
+
+ n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, unicode, n );
+
+ }
+
+
+
+ outString = unicode;
+
+ }
+
+
+exit:
+
+
+
+ if ( unicode != NULL )
+
+ {
+
+ delete [] unicode;
+
}
-\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
+
+
+
+ return ( !err ) ? TRUE : FALSE;
+
+}
+
+
+
+
+
+BOOL
+
+ByteArrayToVariant
+
+ (
+
+ const void * inArray,
+
+ size_t inArrayLen,
+
+ VARIANT * outVariant
+
+ )
+
+{
+
+ LPBYTE buf = NULL;
+
+ HRESULT hr = 0;
+
+ BOOL ok = TRUE;
+
+
+
+ VariantClear( outVariant );
+
+ outVariant->vt = VT_ARRAY|VT_UI1;
+
+ outVariant->parray = SafeArrayCreateVector( VT_UI1, 0, ( ULONG ) inArrayLen );
+
+ require_action( outVariant->parray, exit, ok = FALSE );
+
+ hr = SafeArrayAccessData( outVariant->parray, (LPVOID *)&buf );
+
+ require_action( hr == S_OK, exit, ok = FALSE );
+
+ memcpy( buf, inArray, inArrayLen );
+
+ hr = SafeArrayUnaccessData( outVariant->parray );
+
+ require_action( hr == S_OK, exit, ok = FALSE );
+
+
+
+exit:
+
+
+
+ return ok;
+
+}
+
+
+
+
+
+extern BOOL
+
+VariantToByteArray
+
+ (
+
+ VARIANT * inVariant,
+
+ std::vector< BYTE > & outArray
+
+ )
+
+{
+
+ SAFEARRAY * psa = NULL;
+
+ BYTE * pData = NULL;
+
+ ULONG cElements = 0;
+
+ HRESULT hr;
+
+ BOOL ok = TRUE;
+
+
+
+ require_action( V_VT( inVariant ) == ( VT_ARRAY|VT_UI1 ), exit, ok = FALSE );
+
+ psa = V_ARRAY( inVariant );
+
+ require_action( psa, exit, ok = FALSE );
+
+ require_action( SafeArrayGetDim( psa ) == 1, exit, ok = FALSE );
+
+ hr = SafeArrayAccessData( psa, ( LPVOID* )&pData );
+
+ require_action( hr == S_OK, exit, ok = FALSE );
+
+ cElements = psa->rgsabound[0].cElements;
+
+ outArray.reserve( cElements );
+
+ outArray.assign( cElements, 0 );
+
+ memcpy( &outArray[ 0 ], pData, cElements );
+
+ SafeArrayUnaccessData( psa );
+
+
+
+exit:
+
+
+
+ return ok;
+
}
\ No newline at end of file
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ */
+
+
+
+#ifndef _StringServices_h
+
+#define _StringServices_h
+
+
+
+#include <atlbase.h>
+
+#include <vector>
+
+#include <string>
+
+
+
+
+
+extern BOOL
+
+BSTRToUTF8
+
+ (
+
+ BSTR inString,
+
+ std::string & outString
+
+ );
+
+
+
+
+
+extern BOOL
+
+UTF8ToBSTR
+
+ (
+
+ const char * inString,
+
+ CComBSTR & outString
+
+ );
+
+
+
+
+
+extern BOOL
+
+ByteArrayToVariant
+
+ (
+
+ const void * inArray,
+
+ size_t inArrayLen,
+
+ VARIANT * outVariant
+
+ );
+
+
+
+
+
+extern BOOL
+
+VariantToByteArray
+
+ (
+
+ VARIANT * inVariant,
+
+ std::vector< BYTE > & outArray
+
+ );
+
+
+
+
- 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
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ */
+
+
+
+#include "stdafx.h"
+
+#include "TXTRecord.h"
+
+#include "StringServices.h"
+
+#include <DebugServices.h>
+
+
+
+
+
+// CTXTRecord
+
+
+
+
+
+STDMETHODIMP CTXTRecord::SetValue(BSTR key, VARIANT value)
+
+{
+
+ std::string keyUTF8;
+
+ ByteArray valueArray;
+
+ BOOL ok;
+
+ DNSServiceErrorType err;
+
+ HRESULT hr = S_OK;
+
+
+
+ if ( !m_allocated )
+
+ {
+
+ TXTRecordCreate( &m_tref, 0, NULL );
+
+ m_allocated = TRUE;
+
+ }
+
+
+
+ ok = BSTRToUTF8( key, keyUTF8 );
+
+ require_action( ok, exit, hr = S_FALSE );
+
+
+
+ ok = VariantToByteArray( &value, valueArray );
+
+ require_action( ok, exit, hr = S_FALSE );
+
+
+
+ err = TXTRecordSetValue( &m_tref, keyUTF8.c_str(), ( uint8_t ) valueArray.size(), &valueArray[ 0 ] );
+
+ require_action( !err, exit, hr = S_FALSE );
+
+
+
+exit:
+
+
+
+ return hr;
+
+}
+
+
+
+STDMETHODIMP CTXTRecord::RemoveValue(BSTR key)
+
+{
+
+ HRESULT hr = S_OK;
+
+
+
+ if ( m_allocated )
+
+ {
+
+ std::string keyUTF8;
+
+ BOOL ok;
+
+ DNSServiceErrorType err;
+
+
+
+ ok = BSTRToUTF8( key, keyUTF8 );
+
+ require_action( ok, exit, hr = S_FALSE );
+
+
+
+ err = TXTRecordRemoveValue( &m_tref, keyUTF8.c_str() );
+
+ require_action( !err, exit, hr = S_FALSE );
+
+ }
+
+
+
+exit:
+
+
+
+ return hr;
+
+}
+
+
+
+STDMETHODIMP CTXTRecord::ContainsKey(BSTR key, VARIANT_BOOL* retval)
+
+{
+
+ std::string keyUTF8;
+
+ int ret = 0;
+
+ HRESULT err = S_OK;
+
+
+
+ if ( m_byteArray.size() > 0 )
+
+ {
+
+ BOOL ok;
+
+
+
+ ok = BSTRToUTF8( key, keyUTF8 );
+
+ require_action( ok, exit, err = S_FALSE );
+
+
+
+ ret = TXTRecordContainsKey( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], keyUTF8.c_str() );
+
+ }
+
+
+
+ *retval = ( ret ) ? VARIANT_TRUE : VARIANT_FALSE;
+
+
+
+exit:
+
+
+
+ return err;
+
+}
+
+
+
+STDMETHODIMP CTXTRecord::GetValueForKey(BSTR key, VARIANT* value)
+
+{
+
+ std::string keyUTF8;
+
+ const void * rawValue;
+
+ uint8_t rawValueLen;
+
+ BOOL ok = TRUE;
+
+ HRESULT hr = S_OK;
+
+
+
+ VariantClear( value );
+
+
+
+ if ( m_byteArray.size() > 0 )
+
+ {
+
+ ok = BSTRToUTF8( key, keyUTF8 );
+
+ require_action( ok, exit, hr = S_FALSE );
+
+
+
+ rawValue = TXTRecordGetValuePtr( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], keyUTF8.c_str(), &rawValueLen );
+
+
+
+ if ( rawValue )
+
+ {
+
+ ok = ByteArrayToVariant( rawValue, rawValueLen, value );
+
+ require_action( ok, exit, hr = S_FALSE );
+
+ }
+
+ }
+
+
+
+exit:
+
+
+
+ return hr;
+
+}
+
+
+
+STDMETHODIMP CTXTRecord::GetCount(ULONG* count)
+
+{
+
+ *count = 0;
+
+
+
+ if ( m_byteArray.size() > 0 )
+
+ {
+
+ *count = TXTRecordGetCount( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ] );
+
+ }
+
+
+
+ return S_OK;
+
+}
+
+
+
+STDMETHODIMP CTXTRecord::GetKeyAtIndex(ULONG index, BSTR* retval)
+
+{
+
+ char keyBuf[ 64 ];
+
+ uint8_t rawValueLen;
+
+ const void * rawValue;
+
+ CComBSTR temp;
+
+ DNSServiceErrorType err;
+
+ BOOL ok;
+
+ HRESULT hr = S_OK;
+
+
+
+ err = TXTRecordGetItemAtIndex( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], ( uint16_t ) index, sizeof( keyBuf ), keyBuf, &rawValueLen, &rawValue );
+
+ require_action( !err, exit, hr = S_FALSE );
+
+
+
+ ok = UTF8ToBSTR( keyBuf, temp );
+
+ require_action( ok, exit, hr = S_FALSE );
+
+
+
+ *retval = temp;
+
+
+
+exit:
+
+
+
+ return hr;
+
+}
+
+
+
+STDMETHODIMP CTXTRecord::GetValueAtIndex(ULONG index, VARIANT* retval)
+
+{
+
+ char keyBuf[ 64 ];
+
+ uint8_t rawValueLen;
+
+ const void * rawValue;
+
+ CComBSTR temp;
+
+ DNSServiceErrorType err;
+
+ BOOL ok;
+
+ HRESULT hr = S_OK;
+
+
+
+ err = TXTRecordGetItemAtIndex( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], ( uint16_t ) index, sizeof( keyBuf ), keyBuf, &rawValueLen, &rawValue );
+
+ require_action( !err, exit, hr = S_FALSE );
+
+
+
+ ok = ByteArrayToVariant( rawValue, rawValueLen, retval );
+
+ require_action( ok, exit, hr = S_FALSE );
+
+
+
+exit:
+
+
+
+ return hr;
+
+}
+
+
+
+
+
+void
+
+CTXTRecord::SetBytes
+
+ (
+
+ const unsigned char * bytes,
+
+ uint16_t len
+
+ )
+
+{
+
+ check ( bytes != NULL );
+
+ check( len );
+
+
+
+ m_byteArray.reserve( len );
+
+ m_byteArray.assign( bytes, bytes + len );
+
+}
- 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
* 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.
+ */
+
+
+
+#pragma once
+
+#include "resource.h" // main symbols
+
+#include "DLLX.h"
+
+#include <vector>
+
+#include <dns_sd.h>
+
+
+
+
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+
+#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."
+
+#endif
+
+
+
+
+
+
+
+// CTXTRecord
+
+
+
+class ATL_NO_VTABLE CTXTRecord :
+
+ public CComObjectRootEx<CComSingleThreadModel>,
+
+ public CComCoClass<CTXTRecord, &CLSID_TXTRecord>,
+
+ public IDispatchImpl<ITXTRecord, &IID_ITXTRecord, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>
+
+{
+
+public:
+
+ CTXTRecord()
+
+ :
+
+ m_allocated( FALSE )
+
+ {
+
+ }
+
+
+
+DECLARE_REGISTRY_RESOURCEID(IDR_TXTRECORD)
+
+
+
+
+
+BEGIN_COM_MAP(CTXTRecord)
+
+ COM_INTERFACE_ENTRY(ITXTRecord)
+
+ COM_INTERFACE_ENTRY(IDispatch)
+
+END_COM_MAP()
+
+
+
+
+
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+
+
+ HRESULT FinalConstruct()
+
+ {
+
+ return S_OK;
+
+ }
+
+
+
+ void FinalRelease()
+
+ {
+
+ if ( m_allocated )
+
+ {
+
+ TXTRecordDeallocate( &m_tref );
+
+ }
+
+ }
+
+
+
+public:
+
+
+
+ STDMETHOD(SetValue)(BSTR key, VARIANT value);
+
+ STDMETHOD(RemoveValue)(BSTR key);
+
+ STDMETHOD(ContainsKey)(BSTR key, VARIANT_BOOL* retval);
+
+ STDMETHOD(GetValueForKey)(BSTR key, VARIANT* value);
+
+ STDMETHOD(GetCount)(ULONG* count);
+
+ STDMETHOD(GetKeyAtIndex)(ULONG index, BSTR* retval);
+
+ STDMETHOD(GetValueAtIndex)(ULONG index, VARIANT* retval);
+
+
+
+private:
+
+
+
+ typedef std::vector< BYTE > ByteArray;
+
+ ByteArray m_byteArray;
+
+ BOOL m_allocated;
+
+ TXTRecordRef m_tref;
+
+
+
+public:
+
+
+
+ uint16_t
+
+ GetLen()
+
+ {
+
+ return TXTRecordGetLength( &m_tref );
+
+ }
+
+
+
+ const void*
+
+ GetBytes()
+
+ {
+
+ return TXTRecordGetBytesPtr( &m_tref );
+
+ }
+
+
+
+ void
+
+ SetBytes
+
+ (
+
+ const unsigned char * bytes,
+
+ uint16_t len
+
+ );
+
+};
+
+
+
+OBJECT_ENTRY_AUTO(__uuidof(TXTRecord), CTXTRecord)
- 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
* 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.
+ */
+
+
+
+#ifdef _MERGE_PROXYSTUB // merge proxy stub DLL
+
+
+
+#define REGISTER_PROXY_DLL //DllRegisterServer, etc.
+
+
+
+#define _WIN32_WINNT 0x0500 //for WinNT 4.0 or Win95 with DCOM
+
+#define USE_STUBLESS_PROXY //defined only with MIDL switch /Oicf
+
+
+
+#pragma comment(lib, "rpcns4.lib")
+
+#pragma comment(lib, "rpcrt4.lib")
+
+
+
+#define ENTRY_PREFIX Prx
+
+
+
+#include "dlldata.c"
+
+#include "DLLX_p.c"
+
+
+
+#endif //_MERGE_PROXYSTUB
- 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
* 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.
+ */
+
+
+
+#pragma once
+
+
+
+#ifdef _MERGE_PROXYSTUB
+
+
+
+extern "C"
+
+{
+
+BOOL WINAPI PrxDllMain(HINSTANCE hInstance, DWORD dwReason,
+
+ LPVOID lpReserved);
+
+STDAPI PrxDllCanUnloadNow(void);
+
+STDAPI PrxDllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
+
+STDAPI PrxDllRegisterServer(void);
+
+STDAPI PrxDllUnregisterServer(void);
+
+}
+
+
+
+#endif
- 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
* 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.
+ */
+
+
+
+#pragma once
+
+
+
+#ifndef STRICT
+
+#define STRICT
+
+#endif
+
+
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+
+#ifndef WINVER // Allow use of features specific to Windows XP or later.
+
+#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
+
+#endif
+
+
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+
+#endif
+
+
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+
+#endif
+
+
+
+#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
+
+#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
+
+#endif
+
+
+
+#define _ATL_APARTMENT_THREADED
+
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+
+
+
+
+#include "resource.h"
+
+#include <atlbase.h>
+
+#include <atlcom.h>
+
+
- 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
* 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: Application.rc2,v $
-Revision 1.3 2006/08/14 23:25:48 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:26 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:35 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:33 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:06:46 bradley
-Moved DNSServiceBrowser for non-Windows CE into Windows sub-folder.
-
-Revision 1.2 2003/08/20 07:06:34 bradley
-Update to APSL 2.0. Updated change history to match other mDNSResponder files.
-
-Revision 1.1 2002/09/20 06:12:48 bradley
-DNSServiceBrowser for Windows
-
-*/
+ */
#ifdef APSTUDIO_INVOKED
#error this file is not editable by Microsoft Visual C++
* 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: 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
-
-Revision 1.2 2004/07/13 21:24:26 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:06:47 bradley
-Moved DNSServiceBrowser for non-Windows CE into Windows sub-folder.
-
-Revision 1.4 2003/08/12 19:56:28 cheshire
-Update to APSL 2.0
-
-Revision 1.3 2003/07/02 21:20:06 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.2 2002/09/21 20:44:55 zarzycki
-Added APSL info
-
-Revision 1.1 2002/09/20 06:12:49 bradley
-DNSServiceBrowser for Windows
-
-*/
+ */
#include <stdlib.h>
* 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: 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
-
-Revision 1.2 2004/07/13 21:24:26 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:06:47 bradley
-Moved DNSServiceBrowser for non-Windows CE into Windows sub-folder.
-
-Revision 1.4 2003/08/12 19:56:28 cheshire
-Update to APSL 2.0
-
-Revision 1.3 2003/07/02 21:20:06 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.2 2002/09/21 20:44:55 zarzycki
-Added APSL info
-
-Revision 1.1 2002/09/20 06:12:50 bradley
-DNSServiceBrowser for Windows
-
-*/
+ */
#if !defined(AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_)
#define AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_
* 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: Application.cpp,v $
-Revision 1.3 2006/08/14 23:25:49 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:26 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:06:47 bradley
-Moved DNSServiceBrowser for non-Windows CE into Windows sub-folder.
-
-Revision 1.5 2003/08/12 19:56:28 cheshire
-Update to APSL 2.0
-
-Revision 1.4 2003/07/02 21:20:06 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.3 2002/09/21 20:44:55 zarzycki
-Added APSL info
-
-Revision 1.2 2002/09/20 08:37:34 bradley
-Increased the DNS record cache from the default of 64 to 512 entries for larger networks.
-
-Revision 1.1 2002/09/20 06:12:51 bradley
-DNSServiceBrowser for Windows
-
-*/
+ */
#include <assert.h>
* 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: Application.h,v $
-Revision 1.3 2006/08/14 23:25:49 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:26 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:06:47 bradley
-Moved DNSServiceBrowser for non-Windows CE into Windows sub-folder.
-
-Revision 1.4 2003/08/12 19:56:28 cheshire
-Update to APSL 2.0
-
-Revision 1.3 2003/07/02 21:20:06 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.2 2002/09/21 20:44:55 zarzycki
-Added APSL info
-
-Revision 1.1 2002/09/20 06:12:51 bradley
-DNSServiceBrowser for Windows
-
-*/
+ */
#if !defined(AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_)
#define AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_
* 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: 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
-
-Revision 1.3 2005/02/10 22:35:35 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.2 2004/07/13 21:24:26 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.10 2004/04/23 01:19:41 bradley
-Changed TXT record new line delimiter from \n to \r\n so it works now that it is an edit text.
-
-Revision 1.9 2004/03/07 05:51:04 bradley
-Updated service type list table to include all service types from dns-sd.org as of 2004-03-06.
-Added separate Service Type and Service Description columns so both are show in the window.
-
-Revision 1.8 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.7 2003/12/25 03:42:04 bradley
-Added login dialog to get username/password when going to FTP sites. Added more services.
-
-Revision 1.6 2003/10/31 12:18:30 bradley
-Added display of the resolved host name. Show separate TXT record entries on separate lines.
-
-Revision 1.5 2003/10/16 09:21:56 bradley
-Ignore non-IPv4 resolves until mDNS on Windows supports IPv6.
-
-Revision 1.4 2003/10/10 03:41:29 bradley
-Changed HTTP double-click handling to work with or without the path= prefix in the TXT record.
-
-Revision 1.3 2003/10/09 19:50:40 bradley
-Sort service type list by description.
-
-Revision 1.2 2003/10/09 19:41:29 bradley
-Changed quit handling to go through normal close path so dialog is freed on quit. Integrated changes
-from Andrew van der Stock for the addition of an _rfb._tcp service type for a VNC Remote Framebuffer
-Server for KDE support. Widened service type list to handle larger service type descriptions.
-
-Revision 1.1 2003/08/21 02:06:47 bradley
-Moved DNSServiceBrowser for non-Windows CE into Windows sub-folder.
-
-Revision 1.7 2003/08/20 06:45:56 bradley
-Updated for IP address changes in DNSServices. Added support for browsing for Xserve RAID.
-
-Revision 1.6 2003/08/12 19:56:28 cheshire
-Update to APSL 2.0
-
-Revision 1.5 2003/07/13 01:03:55 cheshire
-Diffs provided by Bob Bradley to provide provide proper display of Unicode names
-
-Revision 1.4 2003/07/02 21:20:06 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.3 2002/09/21 20:44:55 zarzycki
-Added APSL info
-
-Revision 1.2 2002/09/20 08:39:21 bradley
-Make sure each resolved item matches the selected service type to handle resolved that may have
-been queued up on the Windows Message Loop. Reduce column to fit when scrollbar is present.
-
-Revision 1.1 2002/09/20 06:12:52 bradley
-DNSServiceBrowser for Windows
-
-*/
+ */
#include <assert.h>
#include <stdio.h>
* 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: ChooserDialog.h,v $
-Revision 1.3 2006/08/14 23:25:49 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:26 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.3 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.2 2003/10/31 12:18:30 bradley
-Added display of the resolved host name. Show separate TXT record entries on separate lines.
-
-Revision 1.1 2003/08/21 02:06:47 bradley
-Moved DNSServiceBrowser for non-Windows CE into Windows sub-folder.
-
-Revision 1.4 2003/08/12 19:56:28 cheshire
-Update to APSL 2.0
-
-Revision 1.3 2003/07/02 21:20:06 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.2 2002/09/21 20:44:55 zarzycki
-Added APSL info
-
-Revision 1.1 2002/09/20 06:12:52 bradley
-DNSServiceBrowser for Windows
-
-*/
+ */
#if !defined(AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_)
#define AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_
* 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: LoginDialog.cpp,v $
-Revision 1.2 2006/08/14 23:25:49 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/12/25 03:47:28 bradley
-Login dialog to get the username/password from the user.
-
-*/
+ */
#include <assert.h>
#include <stdlib.h>
* 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: LoginDialog.h,v $
-Revision 1.2 2006/08/14 23:25:49 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/12/25 03:47:28 bradley
-Login dialog to get the username/password from the user.
-
-*/
+ */
#ifndef __LOGIN_DIALOG__
#define __LOGIN_DIALOG__
* 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.cpp,v $
-Revision 1.3 2006/08/14 23:25:49 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:26 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:06:47 bradley
-Moved DNSServiceBrowser for non-Windows CE into Windows sub-folder.
-
-Revision 1.4 2003/08/12 19:56:28 cheshire
-Update to APSL 2.0
-
-Revision 1.3 2003/07/02 21:20:06 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.2 2002/09/21 20:44:55 zarzycki
-Added APSL info
-
-Revision 1.1 2002/09/20 06:12:53 bradley
-DNSServiceBrowser for Windows
-
-*/
+ */
#include "stdafx.h"
* 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.3 2006/08/14 23:25:49 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:26 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:36 rpantos
-Move up one level
-
-Revision 1.3 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.2 2003/10/09 02:31:55 bradley
-Define WINVER if not already defined to avoid warning with Visual Studio .NET 2003.
-
-Revision 1.1 2003/08/21 02:06:47 bradley
-Moved DNSServiceBrowser for non-Windows CE into Windows sub-folder.
-
-Revision 1.4 2003/08/12 19:56:28 cheshire
-Update to APSL 2.0
-
-Revision 1.3 2003/07/02 21:20:06 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.2 2002/09/21 20:44:56 zarzycki
-Added APSL info
-
-Revision 1.1 2002/09/20 06:12:53 bradley
-DNSServiceBrowser for Windows
-
-*/
+ */
#if !defined(AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_)
#define AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_
* 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: Application.cpp,v $
-Revision 1.3 2006/08/14 23:25:55 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:27 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:37 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:33 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:16:10 bradley
-DNSServiceBrowser for HTTP services for Windows CE/PocketPC.
-
-*/
+ */
#include "stdafx.h"
* 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: Application.h,v $
-Revision 1.3 2006/08/14 23:25:55 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:27 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:37 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:33 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:16:10 bradley
-DNSServiceBrowser for HTTP services for Windows CE/PocketPC.
-
-*/
+ */
#if !defined(AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_)
#define AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_
* 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: 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
-
-Revision 1.2 2004/07/13 21:24:27 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:37 rpantos
-Move up one level
-
-Revision 1.5 2004/01/30 02:56:33 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.4 2003/10/16 09:21:56 bradley
-Ignore non-IPv4 resolves until mDNS on Windows supports IPv6.
-
-Revision 1.3 2003/10/14 03:28:50 bradley
-Insert services in sorted order to make them easier to find. Defer service adds/removes to the main
-thread to avoid potential problems with multi-threaded MFC message map access. Added some asserts.
-
-Revision 1.2 2003/10/10 03:43:34 bradley
-Added support for launching a web browser to go to the browsed web site on a single-tap.
-
-Revision 1.1 2003/08/21 02:16:10 bradley
-DNSServiceBrowser for HTTP services for Windows CE/PocketPC.
-
-*/
+ */
#include "stdafx.h"
* 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: BrowserDialog.h,v $
-Revision 1.3 2006/08/14 23:25:55 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:27 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:37 rpantos
-Move up one level
-
-Revision 1.4 2004/01/30 02:56:33 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.3 2003/10/14 03:28:50 bradley
-Insert services in sorted order to make them easier to find. Defer service adds/removes to the main
-thread to avoid potential problems with multi-threaded MFC message map access. Added some asserts.
-
-Revision 1.2 2003/10/10 03:43:34 bradley
-Added support for launching a web browser to go to the browsed web site on a single-tap.
-
-Revision 1.1 2003/08/21 02:16:10 bradley
-DNSServiceBrowser for HTTP services for Windows CE/PocketPC.
-
-*/
+ */
#if !defined(AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_)
#define AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_
* 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.cpp,v $
-Revision 1.3 2006/08/14 23:25:55 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:27 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:37 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:33 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:16:10 bradley
-DNSServiceBrowser for HTTP services for Windows CE/PocketPC.
-
-*/
+ */
#include "stdafx.h"
* 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.3 2006/08/14 23:25:55 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2004/07/13 21:24:27 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1 2004/06/18 04:04:37 rpantos
-Move up one level
-
-Revision 1.2 2004/01/30 02:56:33 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.1 2003/08/21 02:16:10 bradley
-DNSServiceBrowser for HTTP services for Windows CE/PocketPC.
-
-*/
+ */
#if !defined(AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_)
#define AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_
/>\r
</Configuration>\r
<Configuration\r
- Name="Release|Win32"\r
- OutputDirectory="Release"\r
- IntermediateDirectory="Release"\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"\r
- ReBuildCommandLine="nmake /f makefile"\r
- CleanCommandLine="nmake /f makefile clean"\r
+ BuildCommandLine="nmake /f makefile64 DEBUG=1"\r
+ ReBuildCommandLine="nmake /f makefile64 DEBUG=1"\r
+ CleanCommandLine="nmake /f makefile64 DEBUG=1 clean"\r
Output=""\r
PreprocessorDefinitions=""\r
IncludeSearchPath=""\r
/>\r
</Configuration>\r
<Configuration\r
- Name="Debug|x64"\r
- OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
- IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ Name="Release|Win32"\r
+ OutputDirectory="Release"\r
+ IntermediateDirectory="Release"\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
+ BuildCommandLine="nmake /f makefile"\r
+ ReBuildCommandLine="nmake /f makefile"\r
+ CleanCommandLine="nmake /f makefile clean"\r
Output=""\r
PreprocessorDefinitions=""\r
IncludeSearchPath=""\r
>\r
<Tool\r
Name="VCNMakeTool"\r
- BuildCommandLine="nmake /f makefile"\r
- ReBuildCommandLine="nmake /f makefile"\r
- CleanCommandLine="nmake /f makefile clean"\r
+ BuildCommandLine="nmake /f makefile64"\r
+ ReBuildCommandLine="nmake /f makefile64"\r
+ CleanCommandLine="nmake /f makefile64 clean"\r
Output=""\r
PreprocessorDefinitions=""\r
IncludeSearchPath=""\r
* 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: jdns_sd.rc,v $
-Revision 1.5 2007/04/27 20:34:31 herscher
-<rdar://problem/5159673> mDNS: Company name needs to be changed to Apple Inc.
-
-Revision 1.4 2006/08/14 23:26:04 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2004/10/19 03:41:42 shersche
-<rdar://problem/3843396> Include "afxres.h" to resource script so it gets compiled correctly
-Bug #: 3843396
-
-Revision 1.2 2004/06/26 21:27:38 rpantos
-Update to use WinVersRes.h
-
-Revision 1.1 2004/06/26 20:06:51 rpantos
-Update to use WinVersRes.h
-
-
-*/
+ */
#ifndef JDNS_SD_RC
#define JDNS_SD_RC
# See the License for the specific language governing permissions and
# 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
-#
-# Revision 1.8 2006/07/05 20:57:22 cheshire
-# <rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
-#
-# Revision 1.7 2005/10/19 17:19:56 herscher
-# Change JDK to use JAVA_HOME environment variable
-#
-# Revision 1.6 2005/02/10 22:35:36 cheshire
-# <rdar://problem/3727944> Update name
-#
-# Revision 1.5 2005/02/08 23:47:51 shersche
-# Build into proper directories for installer
-#
-# Revision 1.4 2004/12/16 22:38:00 shersche
-# Compile DNSSDException.java first to avoid build errors, copy output to appropriate "buildroot" folder
-#
-# Revision 1.3 2004/11/23 08:13:07 shersche
-# Link to the iphlpapi.lib for GetAdaptersInfo
-#
-# Revision 1.2 2004/06/26 20:07:06 rpantos
-# Update to use WinVersRes.h
-#
-# Revision 1.1 2004/06/18 04:12:05 rpantos
-# Move up one level. Integration changes for Scott.
-#
-# Revision 1.2 2004/05/01 00:31:41 rpantos
-# Change line endings for CVS.
-#
-# Revision 1.1 2004/04/30 16:32:34 rpantos
-# First checked in.
-#
# This Makefile builds a .jar file and accompanying JNI support library
# containing the DNSSD implementation for Java and support classes.
#
$(BUILDDIR)\jdns_sd.dll: $(JAVASRC)\JNISupport.c $(OBJDIR)\DNSSD.java.h $(OBJDIR)\jdns_sd.RES
$(CC) -Fe$@ $(JAVASRC)\JNISupport.c $(CFLAGS) -I$(OBJDIR) \
- $(LIBDIR)\DNSSD.lib $(JDK)\lib\jvm.lib ws2_32.lib iphlpapi.lib $(OBJDIR)\jdns_sd.RES
+ $(LIBDIR)\DNSSD.lib $(JDK)\lib\jvm.lib ws2_32.lib iphlpapi.lib $(OBJDIR)\jdns_sd.RES /link /NXCOMPAT /DYNAMICBASE /SAFESEH
.SUFFIXES : .java
{$(JAVASRC)}.java{$(OBJDIR)\com\apple\dnssd}.class:
--- /dev/null
+# -*- 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.
+#
+# This Makefile builds a .jar file and accompanying JNI support library
+# containing the DNSSD implementation for Java and support classes.
+#
+# Prior to building Java support, you must build DNSSD.dll.
+#
+# nmake with no arguments builds all production targets.
+# 'nmake DEBUG=1' to build debugging targets.
+# 'nmake clean' or 'nmake clean DEBUG=1' to delete prod/debug objects & targets
+#
+# To run nmake, you may need to set up your PATH correctly, using a script
+# such as: "\Program Files\Microsoft Visual Studio .NET\Vc7\bin\vcvars32.bat"
+#
+# The default location of the JDK is \javasdk. You can override this on the
+# command line (e.g. 'nmake JDK=\j2dk1.4.2_03').
+
+############################################################################
+
+COREDIR = ..\..\mDNSCore
+SHAREDDIR = ..\..\mDNSShared
+
+JDK = $(JAVA_HOME)
+
+CC = cl
+RC = rc
+LD = ld
+CP = copy
+RM = del /Q
+RMDIR = rmdir /S /Q
+JAVAC = $(JDK)\bin\javac
+JAVAH = $(JDK)\bin\javah
+JAR = $(JDK)\bin\jar
+CFLAGS_COMMON = -LD -DAUTO_CALLBACKS=0 -I. -I..\.. \
+ -I$(COREDIR) -I$(SHAREDDIR) -I$(JDK)\include -I$(JDK)\include\win32
+
+# Set up diverging paths for debug vs. prod builds
+DEBUG=0
+!if $(DEBUG) == 1
+CFLAGS_DEBUG = -Zi -DMDNS_DEBUGMSGS=2
+OBJDIR = objects\debug\x64
+BUILDDIR = build\debug\x64
+INSTALLDIR = root\"Program Files"\Bonjour
+LIBDIR = ..\DLL\x64\Debug
+!else
+CFLAGS_DEBUG = -Os -DMDNS_DEBUGMSGS=0
+OBJDIR = objects\prod\x64
+BUILDDIR = build\prod\x64
+INSTALLDIR = root\"Program Files"\Bonjour
+LIBDIR = ..\DLL\x64\Release
+!endif
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_DEBUG)
+JAVACFLAGS = $(CFLAGS) $(JAVACFLAGS_OS)
+
+#############################################################################
+
+all: setup Java postbuild
+
+# 'setup' sets up the build directory structure the way we want
+setup:
+ @if not exist objects mkdir objects
+ @if not exist build mkdir build
+ @if not exist $(OBJDIR) mkdir $(OBJDIR)
+ @if not exist $(BUILDDIR) mkdir $(BUILDDIR)
+
+postbuild:
+ @if not "%RC_XBS%"=="YES" GOTO CONT
+ @if not exist "$(DSTROOT)\WINDOWS\system32\x64" mkdir "$(DSTROOT)\WINDOWS\system32\x64"
+ @if not exist "$(DSTROOT)\Program Files\Bonjour\x64" mkdir "$(DSTROOT)\Program Files\Bonjour\x64"
+ @copy $(BUILDDIR)\jdns_sd.dll "$(DSTROOT)\WINDOWS\system32\x64"
+ @copy $(BUILDDIR)\dns_sd.jar "$(DSTROOT)\Program Files\Bonjour\x64"
+ @: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)
+ copy $(BUILDDIR)\jdns_sd.dll $(INSTALLDIR)
+
+# clean removes targets and objects
+clean:
+ @if exist $(OBJDIR) $(RMDIR) $(OBJDIR)
+ @if exist $(BUILDDIR) $(RMDIR) $(BUILDDIR)
+
+#############################################################################
+
+# The following targets build Java wrappers for the dns-sd.h API.
+
+Java: setup $(BUILDDIR)\dns_sd.jar $(BUILDDIR)\jdns_sd.dll postbuild
+ @echo "Java wrappers done"
+
+JAVASRC = $(SHAREDDIR)\Java
+JARCONTENTS = $(OBJDIR)\com\apple\dnssd\DNSSDService.class \
+ $(OBJDIR)\com\apple\dnssd\DNSSDException.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\DNSSD.class
+
+$(BUILDDIR)\dns_sd.jar: $(JARCONTENTS)
+ $(JAR) -cf $@ -C $(OBJDIR) com
+
+$(BUILDDIR)\jdns_sd.dll: $(JAVASRC)\JNISupport.c $(OBJDIR)\DNSSD.java.h $(OBJDIR)\jdns_sd.RES
+ $(CC) -Fe$@ $(JAVASRC)\JNISupport.c $(CFLAGS) -I$(OBJDIR) \
+ $(LIBDIR)\DNSSD.lib $(JDK)\lib\jvm.lib ws2_32.lib iphlpapi.lib $(OBJDIR)\jdns_sd.RES /link /NXCOMPAT /DYNAMICBASE
+
+.SUFFIXES : .java
+{$(JAVASRC)}.java{$(OBJDIR)\com\apple\dnssd}.class:
+ $(JAVAC) -d $(OBJDIR) -classpath $(OBJDIR) $<
+
+$(OBJDIR)\DNSSD.java.h: $(OBJDIR)\com\apple\dnssd\DNSSD.class
+ $(JAVAH) -classpath $(OBJDIR) -o $@ \
+ com.apple.dnssd.AppleBrowser \
+ com.apple.dnssd.AppleResolver \
+ com.apple.dnssd.AppleRegistration \
+ com.apple.dnssd.AppleQuery \
+ com.apple.dnssd.AppleService
+
+$(OBJDIR)\jdns_sd.RES: jdns_sd.rc
+ $(RC) /fo $@ $?
+
* 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: NSPTool.c,v $
-Revision 1.4 2006/08/14 23:26:06 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.3 2004/08/26 04:46:49 shersche
-Add -q switch for silent operation
-
-Revision 1.2 2004/06/23 16:39:14 shersche
-Fix extraneous warnings regarding implict casts
-
-Submitted by: Scott Herscher (sherscher@apple.com)
-
-Revision 1.1 2004/06/18 04:14:26 rpantos
-Move up one level.
-
-Revision 1.1 2004/01/30 03:02:58 bradley
-NameSpace Provider Tool for installing, removing, list, etc. NameSpace Providers.
-
-*/
+ */
#include <stdio.h>
#include <stdlib.h>
* 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: Prefix.h,v $
-Revision 1.2 2006/08/14 23:26:06 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2004/06/18 04:14:26 rpantos
-Move up one level.
-
-Revision 1.1 2004/01/30 03:02:58 bradley
-NameSpace Provider Tool for installing, removing, list, etc. NameSpace Providers.
-
-*/
+ */
#ifndef __PREFIX__
#define __PREFIX__
* 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: PosixCompat.c,v $
-Revision 1.1 2009/07/09 21:40:32 herscher
-<rdar://problem/3775717> SDK: Port mDNSNetMonitor to Windows. Add a small Posix compatibility layer to the mDNSWindows platform layer. This makes it possible to centralize the implementations to functions such as if_indextoname() and inet_pton() that are made in several projects in B4W.
-
-
-*/
+ */
#include "PosixCompat.h"
#include <DebugServices.h>
}
else return 0;
}
-
+\r
int
gettimeofday( struct timeval * tv, struct timezone * tz )
-{
-#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
-# define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
-#else
-# define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
-#endif
-
- FILETIME ft;
- unsigned __int64 tmpres = 0;
-
- if ( tv != NULL )
- {
- GetSystemTimeAsFileTime(&ft);
-
- tmpres |= ft.dwHighDateTime;
- tmpres <<= 32;
- tmpres |= ft.dwLowDateTime;
-
- tmpres -= DELTA_EPOCH_IN_MICROSECS;
- tmpres /= 10; /*convert into microseconds*/
- tv->tv_sec = (long)(tmpres / 1000000UL);
- tv->tv_usec = (long)(tmpres % 1000000UL);
- }
-
+{\r
+#define EPOCHFILETIME (116444736000000000i64)\r
+\r
+ if ( tv != NULL )\r
+ {\r
+ FILETIME ft;\r
+ LARGE_INTEGER li;\r
+ __int64 t;\r
+\r
+ GetSystemTimeAsFileTime(&ft);\r
+ li.LowPart = ft.dwLowDateTime;\r
+ li.HighPart = ft.dwHighDateTime;\r
+ t = li.QuadPart; /* In 100-nanosecond intervals */\r
+ t -= EPOCHFILETIME; /* Offset to the Epoch time */\r
+ t /= 10; /* In microseconds */\r
+ tv->tv_sec = ( long )( t / 1000000 );\r
+ tv->tv_usec = ( long )( t % 1000000 );\r
+ }\r
+\r
return 0;
}
extern struct tm*
localtime_r( const time_t * clock, struct tm * result )
{
- result = localtime( clock );
+ localtime_s( result, clock );
return result;
}
* 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: PosixCompat.h,v $
-Revision 1.1 2009/07/09 21:40:32 herscher
-<rdar://problem/3775717> SDK: Port mDNSNetMonitor to Windows. Add a small Posix compatibility layer to the mDNSWindows platform layer. This makes it possible to centralize the implementations to functions such as if_indextoname() and inet_pton() that are made in several projects in B4W.
-
-
-*/
+ */
#pragma once
* 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: 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
-
-Revision 1.2 2005/10/05 18:05:28 herscher
-<rdar://problem/4192011> Save Wide-Area preferences in a different spot in the registry so they don't get removed when doing an update install.
-
-Revision 1.1 2005/03/03 02:31:37 shersche
-Consolidates all registry key names and can safely be included in any component that needs it
-
-
-*/
+ */
//----------------------------------------------------------------------------------------
// Registry Constants
# define kServiceManageLLRouting L"ManageLLRouting"
# define kServiceCacheEntryCount L"CacheEntryCount"
# define kServiceManageFirewall L"ManageFirewall"
+# define kServiceAdvertisedServices L"Services"
# else
* 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.3 2009/07/17 19:50:25 herscher
-<rdar://problem/5265747> ControlPanel doesn't display key and password in dialog box
-
-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>
* 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
--- /dev/null
+MessageIdTypedef=WORD
+LanguageNames=(English=0x409:MSG00409)
+
+MessageId=100
+SymbolicName=MDNSRESPONDER_LOG
+Severity=Success
+Facility=Application
+Language=English
+%1
+.
+
* 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: 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
-
-Revision 1.3 2005/09/29 06:33:54 herscher
-<rdar://problem/4278931> Fix compilation error when using latest Microsoft Platform SDK.
-
-Revision 1.2 2004/09/15 09:39:53 shersche
-Retry the method INetFwPolicy::get_CurrentProfile on error
-
-Revision 1.1 2004/09/13 07:32:31 shersche
-Wrapper for Windows Firewall API code
-
-
-*/
+ */
// <rdar://problem/4278931> Doesn't compile correctly with latest Platform SDK
}
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
+}
+
+
+
+
+
+static OSStatus
+
+mDNSFirewallIsFileAndPrintSharingEnabled
+
+ (
+
+ IN INetFwProfile * fwProfile,
+
+ OUT BOOL * fwServiceEnabled
+
+ )
+
+{
+
+ VARIANT_BOOL fwEnabled;
+
+ INetFwService* fwService = NULL;
+
+ INetFwServices* fwServices = NULL;
+
+ OSStatus err = S_OK;
+
+
+
+ _ASSERT(fwProfile != NULL);
+
+ _ASSERT(fwServiceEnabled != NULL);
+
+
+
+ *fwServiceEnabled = FALSE;
+
+
+
+ // Retrieve the globally open ports collection.
+
+ err = fwProfile->get_Services(&fwServices);
+
+ require( SUCCEEDED( err ), exit );
+
+
+
+ // Attempt to retrieve the globally open port.
+
+ err = fwServices->Item(NET_FW_SERVICE_FILE_AND_PRINT, &fwService);
+
+ require( SUCCEEDED( err ), exit );
+
+
+
+ // Find out if the globally open port is enabled.
+
+ err = fwService->get_Enabled(&fwEnabled);
+
+ require( SUCCEEDED( err ), exit );
+
+ if (fwEnabled != VARIANT_FALSE)
+
+ {
+
+ *fwServiceEnabled = TRUE;
+
+ }
+
+
+
+exit:
+
+
+
+ // Release the globally open port.
+
+ if (fwService != NULL)
+
+ {
+
+ fwService->Release();
+
+ }
+
+
+
+ // Release the globally open ports collection.
+
+ if (fwServices != NULL)
+
+ {
+
+ fwServices->Release();
+
+ }
+
+
+
+ return err;
+
}
BOOL
-mDNSIsFileAndPrintSharingEnabled()
+mDNSIsFileAndPrintSharingEnabled( BOOL * retry )
{
INetFwProfile * fwProfile = NULL;
HRESULT comInit = E_FAIL;
// Initialize COM.
+ *retry = FALSE;
comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
// Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
if (comInit != RPC_E_CHANGED_MODE)
{
+ *retry = TRUE;
err = comInit;
require(SUCCEEDED(err), exit);
}
* 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: 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
-
-Revision 1.1 2004/09/13 07:32:31 shersche
-Wrapper for Windows Firewall API code
-
-
-
-
-*/
+ */
BOOL
-mDNSIsFileAndPrintSharingEnabled();
+mDNSIsFileAndPrintSharingEnabled( BOOL * retry );
* 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: Prefix.h,v $
-Revision 1.2 2006/08/14 23:26:07 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.1 2004/06/18 04:16:41 rpantos
-Move up one level.
-
-Revision 1.2 2004/04/30 02:40:23 bradley
-Define DNS_SD_CLIENT_ENABLED=0 so DNSSD.c can be included without linking the client IPC code.
-
-Revision 1.1 2004/01/30 02:58:39 bradley
-mDNSResponder Windows Service. Provides global Bonjour support with an IPC interface.
-
-*/
+ */
#ifndef __PREFIX__
#define __PREFIX__
* 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: Service.c,v $
-Revision 1.49 2009/07/17 19:59:46 herscher
-<rdar://problem/7062660> Update the womp settings for each network adapter immediately preceding the call to mDNSCoreMachineSleep().
-
-Revision 1.48 2009/07/09 21:34:14 herscher
-<rdar://problem/3775717> SDK: Port mDNSNetMonitor to Windows. Refactor the system service slightly by removing the main() function from Service.c so that mDNSNetMonitor can link to functions defined in Service.c
-
-Revision 1.47 2009/07/07 21:35:06 herscher
-<rdar://problem/6713286> windows platform changes to support use as sleep proxy client
-
-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
-
-Revision 1.41 2007/02/06 19:06:49 cheshire
-<rdar://problem/3956518> Need to go native with launchd
-
-Revision 1.40 2007/01/05 05:46:08 cheshire
-Add mDNS *const m parameter to udsserver_handle_configchange()
-
-Revision 1.39 2006/08/14 23:26:07 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.38 2005/10/05 20:55:15 herscher
-<rdar://problem/4096464> Don't call SetLLRoute on loopback interface
-
-Revision 1.37 2005/10/05 18:05:28 herscher
-<rdar://problem/4192011> Save Wide-Area preferences in a different spot in the registry so they don't get removed when doing an update install.
-
-Revision 1.36 2005/09/11 22:12:42 herscher
-<rdar://problem/4247793> Remove dependency on WMI. Ensure that the Windows firewall is turned on before trying to configure it.
-
-Revision 1.35 2005/06/30 18:29:49 shersche
-<rdar://problem/4090059> Don't overwrite the localized service description text
-
-Revision 1.34 2005/04/22 07:34:23 shersche
-Check an interface's address and make sure it's valid before using it to set link-local routes.
-
-Revision 1.33 2005/04/13 17:48:23 shersche
-<rdar://problem/4079667> Make sure there is only one default route for link-local addresses.
-
-Revision 1.32 2005/04/06 01:32:05 shersche
-Remove default route for link-local addressing when another interface comes up with a routable IPv4 address
-
-Revision 1.31 2005/04/06 01:00:11 shersche
-<rdar://problem/4080127> GetFullPathName() should be passed the number of TCHARs in the path buffer, not the size in bytes of the path buffer.
-
-Revision 1.30 2005/04/06 00:52:43 shersche
-<rdar://problem/4079667> Only add default route if there are no other routable IPv4 addresses on any of the other interfaces. More work needs to be done to correctly configure the routing table when multiple interfaces are extant and none of them have routable IPv4 addresses.
-
-Revision 1.29 2005/03/06 05:21:56 shersche
-<rdar://problem/4037635> Fix corrupt UTF-8 name when non-ASCII system name used, enabled unicode support
-
-Revision 1.28 2005/03/03 02:27:24 shersche
-Include the RegNames.h header file for names of registry keys
-
-Revision 1.27 2005/03/02 20:12:59 shersche
-Update name
-
-Revision 1.26 2005/02/15 08:00:27 shersche
-<rdar://problem/4007151> Update name
-
-Revision 1.25 2005/02/10 22:35:36 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.24 2005/01/27 20:02:43 cheshire
-udsSupportRemoveFDFromEventLoop() needs to close the SocketRef as well
-
-Revision 1.23 2005/01/25 08:14:15 shersche
-Change CacheRecord to CacheEntity
-
-Revision 1.22 2004/12/10 13:18:40 cheshire
-Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
-
-Revision 1.21 2004/11/10 04:03:41 shersche
-Remove SharedAccess dependency. This causes problems on XP SP1, and isn't necessary for XP SP2 because we already are dependent on WMI, which itself is dependent on SharedAccess.
-
-Revision 1.20 2004/10/14 21:44:05 shersche
-<rdar://problem/3838237> Fix a race condition between the socket thread and the main processing thread that resulted in the socket thread accessing a previously deleted Win32EventSource object.
-Bug #: 3838237
-
-Revision 1.19 2004/10/12 17:59:55 shersche
-<rdar://problem/3718122> Disable routing table modifications when Nortel VPN adapter is active
-Bug #: 3718122
-
-Revision 1.18 2004/10/11 21:57:50 shersche
-<rdar://problem/3832450> The SharedAccess service dependency causes a circular dependency on Windows Server 2003. Only add the SharedAccess service dependency if running on XP. All other platforms do not manipulate the firewall and thus are not dependent on it.
-Bug #: 3832450
-
-Revision 1.17 2004/09/17 01:08:58 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.16 2004/09/16 18:49:34 shersche
-Remove the XP SP2 check before attempting to manage the firewall. There is a race condition in the SP2 updater such that upon first reboot after the upgrade, mDNSResponder might not know that it is running under SP2 yet. This necessitates a second reboot before the firewall is managed. Removing the check will cause mDNSResponder to try and manage the firewall everytime it boots up, if and only if it hasn't managed the firewall a previous time.
-
-Revision 1.15 2004/09/15 17:13:33 shersche
-Change Firewall name
-
-Revision 1.14 2004/09/15 09:37:25 shersche
-Add SharedAccess to dependency list, call CheckFirewall after sending status back to SCM
-
-Revision 1.13 2004/09/13 07:35:10 shersche
-<rdar://problem/3762235> Add mDNSResponder to Windows Firewall application list if SP2 is detected and app hasn't been added before
-Bug #: 3762235
-
-Revision 1.12 2004/09/11 21:18:32 shersche
-<rdar://problem/3779502> Add route to ARP everything when a 169.254.x.x address is selected
-Bug #: 3779502
-
-Revision 1.11 2004/09/11 05:39:19 shersche
-<rdar://problem/3780203> Detect power managment state changes, calling mDNSCoreMachineSleep(m, true) on sleep, and mDNSCoreMachineSleep(m, false) on resume
-Bug #: 3780203
-
-Revision 1.10 2004/08/16 21:45:24 shersche
-Use the full pathname of executable when calling CreateService()
-Submitted by: prepin@zetron.com
-
-Revision 1.9 2004/08/11 01:59:41 cheshire
-Remove "mDNS *globalInstance" parameter from udsserver_init()
-
-Revision 1.8 2004/08/05 05:40:05 shersche
-<rdar://problem/3751566> Only invoke SetConsoleCtrlHandler when running directly from command line.
-<rdar://problem/3751481> Invoke udsserver_handle_configchange() when the computer description changes
-Bug #: 3751481, 3751566
-
-Revision 1.7 2004/07/26 05:35:07 shersche
-ignore non-enet interfaces when setting up link-local routing
-
-Revision 1.6 2004/07/20 06:48:26 shersche
-<rdar://problem/3718122> Allow registry entries to dictate whether to manage link local routing
-Bug #: 3718122
-
-Revision 1.5 2004/07/09 19:08:07 shersche
-<rdar://problem/3713762> ServiceSetupEventLogging() errors are handled gracefully
-Bug #: 3713762
-
-Revision 1.4 2004/06/24 20:58:15 shersche
-Fix compiler error in Release build
-Submitted by: herscher
-
-Revision 1.3 2004/06/24 15:28:53 shersche
-Automatically setup routes to link-local addresses upon interface list change events.
-Submitted by: herscher
-
-Revision 1.2 2004/06/23 16:56:00 shersche
-<rdar://problem/3697326> locked call to udsserver_idle().
-Bug #: 3697326
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:16:41 rpantos
-Move up one level.
-
-Revision 1.1 2004/01/30 02:58:39 bradley
-mDNSResponder Windows Service. Provides global Bonjour support with an IPC interface.
-
-*/
+ */
#include <stdio.h>
#include <stdlib.h>
+#include <crtdbg.h>
#include <stdarg.h>
#include <stddef.h>
#include "uds_daemon.h"
#include "GenLinkedList.h"
#include "Service.h"
+#include "EventLog.h"
#include "Resource.h"
#include "mDNSEmbeddedAPI.h"
+#include "uDNS.h"
#include "mDNSWin32.h"
#include "Firewall.h"
// Constants
//===========================================================================================================================
-#define DEBUG_NAME "[Server] "
+#define DEBUG_NAME "[mDNSWin32] "
#define kServiceFirewallName L"Bonjour"
#define kServiceDependencies TEXT("Tcpip\0\0")
#define kDNSServiceCacheEntryCountDefault 512
#define kDefValueSize MAX_PATH + 1
#define kZeroIndex 0
#define kDefaultRouteMetric 399
+#define kSecondsTo100NSUnits ( 10 * 1000 * 1000 )
+#define kSPSMaintenanceWakePeriod -30
#define RR_CACHE_SIZE 500
static CacheEntity gRRCache[RR_CACHE_SIZE];
//===========================================================================================================================
// Structures
//===========================================================================================================================
-//---------------------------------------------------------------------------------------------------------------------------
-/*! @typedef EventSourceFlags
-
- @abstract Session flags.
-
- @constant EventSourceFlagsNone No flags.
- @constant EventSourceFlagsThreadDone Thread is no longer active.
- @constant EventSourceFlagsNoClose Do not close the session when the thread exits.
- @constant EventSourceFinalized Finalize has been called for this session
-*/
-
-typedef uint32_t EventSourceFlags;
-
-#define EventSourceFlagsNone 0
-#define EventSourceFlagsThreadDone ( 1 << 2 )
-#define EventSourceFlagsNoClose ( 1 << 3 )
-#define EventSourceFinalized ( 1 << 4 )
-
-typedef struct Win32EventSource
+typedef struct EventSource
{
- EventSourceFlags flags;
- HANDLE threadHandle;
- unsigned threadID;
- HANDLE socketEvent;
- HANDLE closeEvent;
- udsEventCallback callback;
- void * context;
- DWORD waitCount;
- HANDLE waitList[2];
- SOCKET sock;
- struct Win32EventSource * next;
-} Win32EventSource;
+ HANDLE event;
+ void * context;
+ RegisterWaitableEventHandler handler;
+ struct EventSource * next;
+} EventSource;
+
+static BOOL gEventSourceListChanged = FALSE;
+static EventSource * gEventSourceList = NULL;
+static EventSource * gCurrentSource = NULL;
+static int gEventSources = 0;
+
+#define kWaitListStopEvent ( WAIT_OBJECT_0 + 0 )
+#define kWaitListInterfaceListChangedEvent ( WAIT_OBJECT_0 + 1 )
+#define kWaitListComputerDescriptionEvent ( WAIT_OBJECT_0 + 2 )
+#define kWaitListTCPIPEvent ( WAIT_OBJECT_0 + 3 )
+#define kWaitListDynDNSEvent ( WAIT_OBJECT_0 + 4 )
+#define kWaitListFileShareEvent ( WAIT_OBJECT_0 + 5 )
+#define kWaitListFirewallEvent ( WAIT_OBJECT_0 + 6 )
+#define kWaitListAdvertisedServicesEvent ( WAIT_OBJECT_0 + 7 )
+#define kWaitListSPSWakeupEvent ( WAIT_OBJECT_0 + 8 )
+#define kWaitListSPSSleepEvent ( WAIT_OBJECT_0 + 9 )
+#define kWaitListFixedItemCount 10
#if 0
static OSStatus ServiceSpecificRun( int argc, LPTSTR argv[] );
static OSStatus ServiceSpecificStop( void );
static void ServiceSpecificFinalize( int argc, LPTSTR argv[] );
-static mStatus EventSourceFinalize(Win32EventSource * source);
-static void EventSourceLock();
-static void EventSourceUnlock();
-static mDNSs32 udsIdle(mDNS * const inMDNS, mDNSs32 interval);
+static mStatus SetupNotifications();
+static mStatus TearDownNotifications();
+static mStatus RegisterWaitableEvent( mDNS * const inMDNS, HANDLE event, void * context, RegisterWaitableEventHandler handler );
+static void UnregisterWaitableEvent( mDNS * const inMDNS, HANDLE event );
+static mStatus SetupWaitList( mDNS * const inMDNS, HANDLE **outWaitList, int *outWaitListCount );
+static void UDSCanAccept( mDNS * const inMDNS, HANDLE event, void * context );
+static void UDSCanRead( TCPSocket * sock );
+static void HandlePowerSuspend( void * v );
+static void HandlePowerResumeSuspend( void * v );
static void CoreCallback(mDNS * const inMDNS, mStatus result);
-static void HostDescriptionChanged(mDNS * const inMDNS);
static mDNSu8 SystemWakeForNetworkAccess( LARGE_INTEGER * timeout );
static OSStatus GetRouteDestination(DWORD * ifIndex, DWORD * address);
static OSStatus SetLLRoute( mDNS * const inMDNS );
{ kServiceName, ServiceMain },
{ NULL, NULL }
};
+DEBUG_LOCAL SOCKET gInterfaceListChangedSocket = INVALID_SOCKET;
+DEBUG_LOCAL HANDLE gInterfaceListChangedEvent = NULL;
+DEBUG_LOCAL HKEY gDescKey = NULL;
+DEBUG_LOCAL HANDLE gDescChangedEvent = NULL; // Computer description changed event
+DEBUG_LOCAL HKEY gTcpipKey = NULL;
+DEBUG_LOCAL HANDLE gTcpipChangedEvent = NULL; // TCP/IP config changed
+DEBUG_LOCAL HKEY gDdnsKey = NULL;
+DEBUG_LOCAL HANDLE gDdnsChangedEvent = NULL; // DynDNS config changed
+DEBUG_LOCAL HKEY gFileSharingKey = NULL;
+DEBUG_LOCAL HANDLE gFileSharingChangedEvent = NULL; // File Sharing changed
+DEBUG_LOCAL HKEY gFirewallKey = NULL;
+DEBUG_LOCAL HANDLE gFirewallChangedEvent = NULL; // Firewall changed
+DEBUG_LOCAL HKEY gAdvertisedServicesKey = NULL;
+DEBUG_LOCAL HANDLE gAdvertisedServicesChangedEvent = NULL; // Advertised services changed
DEBUG_LOCAL SERVICE_STATUS gServiceStatus;
DEBUG_LOCAL SERVICE_STATUS_HANDLE gServiceStatusHandle = NULL;
DEBUG_LOCAL HANDLE gServiceEventSource = NULL;
DEBUG_LOCAL HANDLE gStopEvent = NULL;
DEBUG_LOCAL HANDLE gSPSWakeupEvent = NULL;
DEBUG_LOCAL HANDLE gSPSSleepEvent = NULL;
-DEBUG_LOCAL CRITICAL_SECTION gEventSourceLock;
-DEBUG_LOCAL GenLinkedList gEventSources;
+DEBUG_LOCAL HANDLE gUDSEvent = NULL;
+DEBUG_LOCAL SocketRef gUDSSocket = 0;
+DEBUG_LOCAL udsEventCallback gUDSCallback = NULL;
DEBUG_LOCAL BOOL gRetryFirewall = FALSE;
DEBUG_LOCAL DWORD gOSMajorVersion;
DEBUG_LOCAL DWORD gOSMinorVersion;
int i;
HeapSetInformation( NULL, HeapEnableTerminationOnCorruption, NULL, 0 );
-
+
debug_initialize( kDebugOutputTypeMetaConsole );
debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
exit:
dlog( kDebugLevelTrace, DEBUG_NAME "exited (%d %m)\n", err, err );
+ _CrtDumpMemoryLeaks();
return( (int) err );
}
err = translate_errno( ok, (OSStatus) GetLastError(), kInUseErr );
require_noerr( err, exit );
- ReportStatus( EVENTLOG_SUCCESS, "installed service \"%s\"/\"%s\" at \"%s\"\n", inName, inDisplayName, inPath );
+ ReportStatus( EVENTLOG_SUCCESS, "installed service\n" );
err = kNoErr;
exit:
err = translate_errno( ok, (OSStatus) GetLastError(), kDeletedErr );
require_noerr( err, exit );
- ReportStatus( EVENTLOG_SUCCESS, "Removed service \"%s\"\n", inName );
+ ReportStatus( EVENTLOG_SUCCESS, "Removed service\n" );
err = ERROR_SUCCESS;
exit:
vsprintf( s, inFormat, args );
array[ 0 ] = s;
- ok = ReportEventA( gServiceEventSource, (WORD) inType, 0, 0x20000001L, NULL, 1, 0, array, NULL );
+ ok = ReportEventA( gServiceEventSource, (WORD) inType, 0, MDNSRESPONDER_LOG, NULL, 1, 0, array, NULL );
check_translated_errno( ok, GetLastError(), kUnknownErr );
}
else
// Run the service. This does not return until the service quits or is stopped.
- ReportStatus( EVENTLOG_SUCCESS, "Running \"%s\" service directly\n", kServiceName );
+ ReportStatus( EVENTLOG_INFORMATION_TYPE, "Running service directly\n" );
err = ServiceSpecificRun( argc, argv );
require_noerr( err, exit );
gServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
gServiceStatus.dwCurrentState = 0;
- gServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_POWEREVENT;
+ gServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_POWEREVENT;
gServiceStatus.dwWin32ExitCode = NO_ERROR;
gServiceStatus.dwServiceSpecificExitCode = NO_ERROR;
gServiceStatus.dwCheckPoint = 0;
return( err );
}
+//===========================================================================================================================
+// HandlePowerSuspend
+//===========================================================================================================================
+
+static void HandlePowerSuspend( void * v )
+{
+ LARGE_INTEGER timeout;
+ BOOL ok;
+
+ ( void ) v;
+
+ dlog( kDebugLevelInfo, DEBUG_NAME "HandlePowerSuspend\n" );
+
+ gMDNSRecord.SystemWakeOnLANEnabled = SystemWakeForNetworkAccess( &timeout );
+
+ if ( gMDNSRecord.SystemWakeOnLANEnabled )
+ {
+ ok = SetWaitableTimer( gSPSWakeupEvent, &timeout, 0, NULL, NULL, TRUE );
+ check( ok );
+ }
+
+ mDNSCoreMachineSleep(&gMDNSRecord, TRUE);
+}
+
+
+//===========================================================================================================================
+// HandlePowerResumeSuspend
+//===========================================================================================================================
+
+static void HandlePowerResumeSuspend( void * v )
+{
+ ( void ) v;
+
+ dlog( kDebugLevelInfo, DEBUG_NAME "HandlePowerResumeSuspend\n" );
+
+ if ( gSPSWakeupEvent )
+ {
+ CancelWaitableTimer( gSPSWakeupEvent );
+ }
+
+ if ( gSPSSleepEvent )
+ {
+ CancelWaitableTimer( gSPSSleepEvent );
+ }
+
+ mDNSCoreMachineSleep(&gMDNSRecord, FALSE);
+}
+
+
//===========================================================================================================================
// ServiceControlHandler
//===========================================================================================================================
switch( inControl )
{
case SERVICE_CONTROL_STOP:
- dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: SERVICE_CONTROL_STOP\n" );
+ case SERVICE_CONTROL_SHUTDOWN:
+ dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: SERVICE_CONTROL_STOP|SERVICE_CONTROL_SHUTDOWN\n" );
ServiceStop();
setStatus = FALSE;
if (inEventType == PBT_APMSUSPEND)
{
- LARGE_INTEGER timeout;
-
dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: PBT_APMSUSPEND\n" );
- mDNSPlatformLock( &gMDNSRecord );
-
- gMDNSRecord.SystemWakeOnLANEnabled = SystemWakeForNetworkAccess( &timeout );
-
- if ( gMDNSRecord.SystemWakeOnLANEnabled )
- {
- ok = SetWaitableTimer( gSPSWakeupEvent, &timeout, 0, NULL, NULL, TRUE );
- check( ok );
- }
-
- mDNSPlatformUnlock( &gMDNSRecord );
-
- mDNSCoreMachineSleep(&gMDNSRecord, TRUE);
+ QueueUserAPC( ( PAPCFUNC ) HandlePowerSuspend, gMDNSRecord.p->mainThread, ( ULONG_PTR ) NULL );
}
else if (inEventType == PBT_APMRESUMESUSPEND)
{
dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: PBT_APMRESUMESUSPEND\n" );
- mDNSPlatformLock( &gMDNSRecord );
-
- if ( gSPSWakeupEvent )
- {
- CancelWaitableTimer( gSPSWakeupEvent );
- }
-
- if ( gSPSSleepEvent )
- {
- CancelWaitableTimer( gSPSSleepEvent );
- }
-
- mDNSPlatformUnlock( &gMDNSRecord );
-
- mDNSCoreMachineSleep(&gMDNSRecord, FALSE);
+ QueueUserAPC( ( PAPCFUNC ) HandlePowerResumeSuspend, gMDNSRecord.p->mainThread, ( ULONG_PTR ) NULL );
}
break;
// Run the service-specific stuff. This does not return until the service quits or is stopped.
- ReportStatus( EVENTLOG_INFORMATION_TYPE, "mDNSResponder started\n" );
+ ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service started\n" );
err = ServiceSpecificRun( argc, argv );
- ReportStatus( EVENTLOG_INFORMATION_TYPE, "mDNSResponder stopped (%d)\n", err );
+ ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service stopped (%d)\n", err );
require_noerr( err, exit );
// Service stopped. Clean up and we're done.
mDNSPlatformMemZero( &gMDNSRecord, sizeof gMDNSRecord);
mDNSPlatformMemZero( &gPlatformStorage, sizeof gPlatformStorage);
- gPlatformStorage.idleThreadCallback = udsIdle;
- gPlatformStorage.hostDescriptionChangedCallback = HostDescriptionChanged;
-
- InitializeCriticalSection(&gEventSourceLock);
-
- gStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- err = translate_errno( gStopEvent, errno_compat(), kNoResourcesErr );
- require_noerr( err, exit );
-
- gSPSWakeupEvent = CreateWaitableTimer( NULL, FALSE, NULL );
- err = translate_errno( gSPSWakeupEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- gSPSSleepEvent = CreateWaitableTimer( NULL, FALSE, NULL );
- err = translate_errno( gSPSSleepEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
+ gPlatformStorage.registerWaitableEventFunc = RegisterWaitableEvent;
+ gPlatformStorage.unregisterWaitableEventFunc = UnregisterWaitableEvent;
err = mDNS_Init( &gMDNSRecord, &gPlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses, CoreCallback, mDNS_Init_NoInitCallbackContext);
require_noerr( err, exit);
+ err = SetupNotifications();
+ check_noerr( err );
+
err = udsserver_init(mDNSNULL, 0);
require_noerr( err, exit);
static OSStatus ServiceSpecificRun( int argc, LPTSTR argv[] )
{
- DWORD timeout;
- DWORD result;
+ HANDLE * waitList;
+ int waitListCount;
+ DWORD timeout;
+ DWORD result;
+ BOOL done;
+ mStatus err;
DEBUG_UNUSED( argc );
DEBUG_UNUSED( argv );
- // Main event loop. Process connection requests and state changes (i.e. quit).
-
timeout = ( gRetryFirewall ) ? kRetryFirewallPeriod : INFINITE;
- for ( ;; )
+ err = SetupInterfaceList( &gMDNSRecord );
+ check( !err );
+
+ err = uDNS_SetupDNSConfig( &gMDNSRecord );
+ check( !err );
+
+ done = FALSE;
+
+ // Main event loop.
+
+ while( !done )
{
- HANDLE waitList[ 3 ];
+ waitList = NULL;
+ waitListCount = 0;
- waitList[ 0 ] = gStopEvent;
- waitList[ 1 ] = gSPSWakeupEvent;
- waitList[ 2 ] = gSPSSleepEvent;
+ err = SetupWaitList( &gMDNSRecord, &waitList, &waitListCount );
+ require_noerr( err, exit );
- result = WaitForMultipleObjects( 3, waitList, FALSE, timeout );
+ gEventSourceListChanged = FALSE;
- if ( result == WAIT_OBJECT_0 )
+ while ( !gEventSourceListChanged )
{
- break;
- }
- else if ( result == WAIT_OBJECT_0 + 1 )
- {
- __int64 temp;
- LARGE_INTEGER timeout;
+ static mDNSs32 RepeatedBusy = 0;
+ mDNSs32 nextTimerEvent;
- dlog( kDebugLevelInfo, DEBUG_NAME "setting suspend event\n" );
+ // Give the mDNS core a chance to do its work and determine next event time.
- // Stay awake for 60 seconds
+ nextTimerEvent = udsserver_idle( mDNS_Execute( &gMDNSRecord ) - mDNS_TimeNow( &gMDNSRecord ) );
- temp = -60 * 10000000;
- timeout.LowPart = (DWORD) ( temp & 0xFFFFFFFF );
- timeout.HighPart = (LONG) ( temp >> 32 );
+ if ( nextTimerEvent < 0) nextTimerEvent = 0;
+ else if ( nextTimerEvent > (0x7FFFFFFF / 1000)) nextTimerEvent = 0x7FFFFFFF / mDNSPlatformOneSecond;
+ else nextTimerEvent = ( nextTimerEvent * 1000) / mDNSPlatformOneSecond;
- SetWaitableTimer( gSPSSleepEvent, &timeout, 0, NULL, NULL, TRUE );
- }
- else if ( result == WAIT_OBJECT_0 + 2 )
- {
- dlog( kDebugLevelInfo, DEBUG_NAME "suspending machine\n" );
- SetSuspendState( FALSE, FALSE, FALSE );
- }
- else if ( result == WAIT_TIMEOUT )
- {
- OSStatus err;
+ // Debugging sanity check, to guard against CPU spins
+
+ if ( nextTimerEvent > 0 )
+ {
+ RepeatedBusy = 0;
+ }
+ else
+ {
+ nextTimerEvent = 1;
- err = CheckFirewall();
- check_noerr( err );
+ if ( ++RepeatedBusy >= mDNSPlatformOneSecond )
+ {
+ ShowTaskSchedulingError( &gMDNSRecord );
+ RepeatedBusy = 0;
+ }
+ }
+
+ if ( gMDNSRecord.ShutdownTime )
+ {
+ mDNSs32 now = mDNS_TimeNow( &gMDNSRecord );
+
+ if ( mDNS_ExitNow( &gMDNSRecord, now ) )
+ {
+ mDNS_FinalExit( &gMDNSRecord );
+ done = TRUE;
+ break;
+ }
+
+ if ( nextTimerEvent - gMDNSRecord.ShutdownTime >= 0 )
+ {
+ nextTimerEvent = gMDNSRecord.ShutdownTime;
+ }
+ }
+
+ // Wait until something occurs (e.g. cancel, incoming packet, or timeout).
+
+ SetSocketEventsEnabled( &gMDNSRecord, TRUE );
+ result = WaitForMultipleObjectsEx( ( DWORD ) waitListCount, waitList, FALSE, (DWORD) nextTimerEvent, TRUE );
+ SetSocketEventsEnabled( &gMDNSRecord, FALSE );
+ check( result != WAIT_FAILED );
+
+ if ( result != WAIT_FAILED )
+ {
+ if ( result == WAIT_TIMEOUT )
+ {
+ // Next task timeout occurred. Loop back up to give mDNS core a chance to work.
+
+ dlog( kDebugLevelChatty - 1, DEBUG_NAME "timeout\n" );
+ continue;
+ }
+ else if ( result == WAIT_IO_COMPLETION )
+ {
+ dlog( kDebugLevelChatty - 1, DEBUG_NAME "i/o completion\n" );
+ continue;
+ }
+ else if ( result == kWaitListStopEvent )
+ {
+ // Stop event. Set the done flag and break to exit.
+
+ dlog( kDebugLevelVerbose, DEBUG_NAME "stopping...\n" );
+ udsserver_exit();
+ mDNS_StartExit( &gMDNSRecord );
+ break;
+ }
+ else if( result == kWaitListInterfaceListChangedEvent )
+ {
+ int inBuffer;
+ int outBuffer;
+ DWORD outSize;
+
+ // 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.
+
+ InterfaceListDidChange( &gMDNSRecord );
+
+ // reset the event handler
+ inBuffer = 0;
+ outBuffer = 0;
+ err = WSAIoctl( gInterfaceListChangedSocket, SIO_ADDRESS_LIST_CHANGE, &inBuffer, 0, &outBuffer, 0, &outSize, NULL, NULL );
+ if( err < 0 )
+ {
+ check( errno_compat() == WSAEWOULDBLOCK );
+ }
+ }
+ else if ( result == kWaitListComputerDescriptionEvent )
+ {
+ // The computer description might have changed
+
+ ComputerDescriptionDidChange( &gMDNSRecord );
+ udsserver_handle_configchange( &gMDNSRecord );
+
+ // and reset the event handler
+ if ( ( gDescKey != NULL ) && ( gDescChangedEvent != NULL ) )
+ {
+ err = RegNotifyChangeKeyValue( gDescKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, gDescChangedEvent, TRUE);
+ check_noerr( err );
+ }
+ }
+ else if ( result == kWaitListTCPIPEvent )
+ {
+ // The TCP/IP might have changed
+
+ TCPIPConfigDidChange( &gMDNSRecord );
+ udsserver_handle_configchange( &gMDNSRecord );
+
+ // and reset the event handler
+
+ if ( ( gTcpipKey != NULL ) && ( gTcpipChangedEvent ) )
+ {
+ err = RegNotifyChangeKeyValue( gTcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gTcpipChangedEvent, TRUE );
+ check_noerr( err );
+ }
+ }
+ else if ( result == kWaitListDynDNSEvent )
+ {
+ // The DynDNS config might have changed
+
+ DynDNSConfigDidChange( &gMDNSRecord );
+ udsserver_handle_configchange( &gMDNSRecord );
+
+ // and reset the event handler
+
+ if ((gDdnsKey != NULL) && (gDdnsChangedEvent))
+ {
+ err = RegNotifyChangeKeyValue(gDdnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gDdnsChangedEvent, TRUE);
+ check_noerr( err );
+ }
+ }
+ else if ( result == kWaitListFileShareEvent )
+ {
+ // File sharing changed
+
+ FileSharingDidChange( &gMDNSRecord );
+
+ // and reset the event handler
+
+ if ((gFileSharingKey != NULL) && (gFileSharingChangedEvent))
+ {
+ err = RegNotifyChangeKeyValue(gFileSharingKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFileSharingChangedEvent, TRUE);
+ check_noerr( err );
+ }
+ }
+ else if ( result == kWaitListFirewallEvent )
+ {
+ // Firewall configuration changed
+
+ FirewallDidChange( &gMDNSRecord );
+
+ // and reset the event handler
+
+ if ((gFirewallKey != NULL) && (gFirewallChangedEvent))
+ {
+ err = RegNotifyChangeKeyValue(gFirewallKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFirewallChangedEvent, TRUE);
+ check_noerr( err );
+ }
+ }
+ else if ( result == kWaitListAdvertisedServicesEvent )
+ {
+ // Ultimately we'll want to manage multiple services, but right now the only service
+ // we'll be managing is SMB.
+
+ FileSharingDidChange( &gMDNSRecord );
+
+ // and reset the event handler
+
+ if ( ( gAdvertisedServicesKey != NULL ) && ( gAdvertisedServicesChangedEvent ) )
+ {
+ err = RegNotifyChangeKeyValue(gAdvertisedServicesKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gAdvertisedServicesChangedEvent, TRUE);
+ check_noerr( err );
+ }
+ }
+ else if ( result == kWaitListSPSWakeupEvent )
+ {
+ LARGE_INTEGER timeout;
- timeout = INFINITE;
+ ReportStatus( EVENTLOG_INFORMATION_TYPE, "Maintenance wake" );
+
+ timeout.QuadPart = kSPSMaintenanceWakePeriod;
+ timeout.QuadPart *= kSecondsTo100NSUnits;
+
+ SetWaitableTimer( gSPSSleepEvent, &timeout, 0, NULL, NULL, TRUE );
+ }
+ else if ( result == kWaitListSPSSleepEvent )
+ {
+ ReportStatus( EVENTLOG_INFORMATION_TYPE, "Returning to sleep after maintenance wake" );
+
+ // Calling SetSuspendState() doesn't invoke our sleep handlers, so we'll
+ // call HandlePowerSuspend() explicity. This will reset the
+ // maintenance wake timers.
+
+ HandlePowerSuspend( NULL );
+ SetSuspendState( FALSE, FALSE, FALSE );
+ }
+ else
+ {
+ int waitItemIndex;
+
+ waitItemIndex = (int)( ( (int) result ) - WAIT_OBJECT_0 );
+ dlog( kDebugLevelChatty, DEBUG_NAME "waitable event on %d\n", waitItemIndex );
+ check( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) );
+
+ if ( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) )
+ {
+ HANDLE signaledEvent;
+ int n = 0;
+
+ signaledEvent = waitList[ waitItemIndex ];
+
+ // If gCurrentSource is not NULL, then this routine has been called
+ // re-entrantly which should never happen.
+
+ check( !gCurrentSource );
+
+ for ( gCurrentSource = gEventSourceList; gCurrentSource; )
+ {
+ EventSource * current = gCurrentSource;
+
+ if ( gCurrentSource->event == signaledEvent )
+ {
+ gCurrentSource->handler( &gMDNSRecord, gCurrentSource->event, gCurrentSource->context );
+ ++n;
+ break;
+ }
+
+ // If the current node was removed as a result of calling
+ // the handler, then gCurrentSource was already incremented to
+ // the next node. If it wasn't removed, then increment it
+ // ourselves
+
+ if ( gCurrentSource == current )
+ {
+ gCurrentSource = gCurrentSource->next;
+ }
+ }
+
+ gCurrentSource = NULL;
+
+ check( n > 0 );
+ }
+ else
+ {
+ dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, result );
+ }
+ }
+ }
+ else
+ {
+ Sleep( 3 * 1000 );
+
+ err = SetupInterfaceList( &gMDNSRecord );
+ check( !err );
+
+ err = uDNS_SetupDNSConfig( &gMDNSRecord );
+ check( !err );
+
+ break;
+ }
}
- else
+
+ if ( waitList )
{
- // Unexpected wait result.
- dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, result );
+ free( waitList );
+ waitList = NULL;
+ waitListCount = 0;
}
}
- return kNoErr;
+exit:
+
+ return( 0 );
}
//===========================================================================================================================
//
// clean up any open sessions
//
- while (gEventSources.Head)
+ while ( gEventSourceList )
{
- EventSourceFinalize((Win32EventSource*) gEventSources.Head);
+ UnregisterWaitableEvent( &gMDNSRecord, gEventSourceList->event );
}
- //
- // give a chance for the udsserver code to clean up
- //
- udsserver_exit();
-
- //
- // and finally close down the mDNSCore
- //
- mDNS_Close(&gMDNSRecord);
//
- // clean up the event sources mutex...no one should be using it now
+ // clean up the notifications
//
- DeleteCriticalSection(&gEventSourceLock);
-
- if ( gSPSWakeupEvent )
- {
- CloseHandle( gSPSWakeupEvent );
- gSPSWakeupEvent = NULL;
- }
-
- if ( gSPSSleepEvent )
- {
- CloseHandle( gSPSSleepEvent );
- gSPSSleepEvent = NULL;
- }
-
- if ( gStopEvent )
- {
- CloseHandle( gStopEvent );
- gStopEvent = NULL;
- }
+ TearDownNotifications();
//
// clean up loaded library
}
-static void
-CoreCallback(mDNS * const inMDNS, mStatus status)
-{
- if (status == mStatus_ConfigChanged)
- {
- SetLLRoute( inMDNS );
- }
-}
-
+//===========================================================================================================================
+// SetupNotifications
+//===========================================================================================================================
-static mDNSs32
-udsIdle(mDNS * const inMDNS, mDNSs32 interval)
+mDNSlocal mStatus SetupNotifications()
{
- DEBUG_UNUSED( inMDNS );
+ mStatus err;
+ SocketRef sock;
+ unsigned long param;
+ int inBuffer;
+ int outBuffer;
+ DWORD outSize;
+
+ gStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ err = translate_errno( gStopEvent, errno_compat(), kNoResourcesErr );
+ require_noerr( err, exit );
- //
- // rdar://problem/3697326
- //
- // udsserver_idle wasn't being locked. This resulted
- // in multiple threads contesting for the all_requests
- // data structure in uds_daemon.c
- //
- mDNSPlatformLock(&gMDNSRecord);
+ // Register to listen for address list changes.
+
+ gInterfaceListChangedEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( gInterfaceListChangedEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
- interval = udsserver_idle(interval);
+ sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
+ err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+ gInterfaceListChangedSocket = sock;
+
+ // Make the socket non-blocking so the WSAIoctl returns immediately with WSAEWOULDBLOCK. It will set the event
+ // when a change to the interface list is detected.
+
+ param = 1;
+ err = ioctlsocket( sock, FIONBIO, ¶m );
+ err = translate_errno( err == 0, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+ inBuffer = 0;
+ outBuffer = 0;
+ err = WSAIoctl( sock, SIO_ADDRESS_LIST_CHANGE, &inBuffer, 0, &outBuffer, 0, &outSize, NULL, NULL );
+ if( err < 0 )
+ {
+ check( errno_compat() == WSAEWOULDBLOCK );
+ }
+
+ err = WSAEventSelect( sock, gInterfaceListChangedEvent, FD_ADDRESS_LIST_CHANGE );
+ err = translate_errno( err == 0, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
- mDNSPlatformUnlock(&gMDNSRecord);
+ gDescChangedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ err = translate_errno( gDescChangedEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
- return interval;
-}
+ err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters"), 0, KEY_READ, &gDescKey);
+ check_translated_errno( err == 0, errno_compat(), kNameErr );
+ if ( gDescKey != NULL )
+ {
+ err = RegNotifyChangeKeyValue( gDescKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, gDescChangedEvent, TRUE);
+ require_noerr( err, exit );
+ }
-static void
-HostDescriptionChanged(mDNS * const inMDNS)
-{
- DEBUG_UNUSED( inMDNS );
+ // This will catch all changes to tcp/ip networking, including changes to the domain search list
- udsserver_handle_configchange(inMDNS);
-}
+ gTcpipChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ err = translate_errno( gTcpipChangedEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &gTcpipKey );
+ require_noerr( err, exit );
-mDNSlocal unsigned WINAPI
-udsSocketThread(LPVOID inParam)
-{
- Win32EventSource * source = (Win32EventSource*) inParam;
- DWORD threadID = GetCurrentThreadId();
- DWORD waitCount;
- HANDLE waitList[2];
- bool safeToClose;
- bool done;
- bool locked = false;
- mStatus err = 0;
+ err = RegNotifyChangeKeyValue( gTcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gTcpipChangedEvent, TRUE);
+ require_noerr( err, exit );
- waitCount = source->waitCount;
- waitList[0] = source->waitList[0];
- waitList[1] = source->waitList[1];
- done = (bool) (source->flags & EventSourceFinalized);
+ // This will catch all changes to ddns configuration
- while (!done)
- {
- DWORD result;
+ gDdnsChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ err = translate_errno( gDdnsChangedEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
- result = WaitForMultipleObjects(waitCount, waitList, FALSE, INFINITE);
-
- mDNSPlatformLock(&gMDNSRecord);
- locked = true;
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup"), &gDdnsKey );
+ require_noerr( err, exit );
- // <rdar://problem/3838237>
- //
- // Look up the source by the thread id. This will ensure that the
- // source is still extant. It could already have been deleted
- // by the processing thread.
- //
+ err = RegNotifyChangeKeyValue( gDdnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gDdnsChangedEvent, TRUE);
+ require_noerr( err, exit );
- EventSourceLock();
+ // This will catch all changes to file sharing
- for (source = gEventSources.Head; source; source = source->next)
- {
- if (source->threadID == threadID)
- {
- break;
- }
- }
+ gFileSharingChangedEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( gFileSharingChangedEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
- EventSourceUnlock();
-
- if (source == NULL)
- {
- goto exit;
- }
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\Shares"), &gFileSharingKey );
+
+ // 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.
- //
- // socket event
- //
- if (result == WAIT_OBJECT_0)
- {
- source->callback( (int) source->sock, 0, source->context);
- }
- //
- // close event
- //
- else if (result == WAIT_OBJECT_0 + 1)
- {
- //
- // this is a bit of a hack. we want to clean up the internal data structures
- // so we'll go in here and it will clean up for us
- //
- shutdown(source->sock, 2);
- source->callback( (int) source->sock, 0, source->context);
+ if ( !err )
+ {
+ err = RegNotifyChangeKeyValue( gFileSharingKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFileSharingChangedEvent, TRUE);
+ require_noerr( err, exit );
+ }
+ else
+ {
+ err = mStatus_NoError;
+ }
- break;
- }
- else
- {
- // Unexpected wait result.
- dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, result );
- goto exit;
- }
+ // This will catch changes to the Windows firewall
- done = (bool) (source->flags & EventSourceFinalized);
-
- mDNSPlatformUnlock(&gMDNSRecord);
- locked = false;
- }
+ gFirewallChangedEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( gFirewallChangedEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
- EventSourceLock();
- source->flags |= EventSourceFlagsThreadDone;
- safeToClose = !( source->flags & EventSourceFlagsNoClose );
- EventSourceUnlock();
+ // 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.
- if( safeToClose )
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\FirewallRules"), &gFirewallKey );
+
+ if ( !err )
{
- EventSourceFinalize( source );
+ err = RegNotifyChangeKeyValue( gFirewallKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFirewallChangedEvent, TRUE);
+ require_noerr( err, exit );
}
-
-exit:
-
- if ( locked )
+ else
{
- mDNSPlatformUnlock(&gMDNSRecord);
+ err = mStatus_NoError;
}
- _endthreadex_compat( (unsigned) err );
- return( (unsigned) err );
-}
-
+ // This will catch all changes to advertised services configuration
-mStatus
-udsSupportAddFDToEventLoop( SocketRef fd, udsEventCallback callback, void *context)
-{
- Win32EventSource * newSource;
- DWORD result;
- mStatus err;
+ gAdvertisedServicesChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ err = translate_errno( gAdvertisedServicesChangedEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
- newSource = malloc(sizeof(Win32EventSource));
- require_action( newSource, exit, err = mStatus_NoMemoryErr );
- mDNSPlatformMemZero(newSource, sizeof(Win32EventSource));
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\Services"), &gAdvertisedServicesKey );
+ require_noerr( err, exit );
- newSource->flags = 0;
- newSource->sock = (SOCKET) fd;
- newSource->callback = callback;
- newSource->context = context;
+ err = RegNotifyChangeKeyValue( gAdvertisedServicesKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gAdvertisedServicesChangedEvent, TRUE);
+ require_noerr( err, exit );
- newSource->socketEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- err = translate_errno( newSource->socketEvent, (mStatus) GetLastError(), kUnknownErr );
+ gSPSWakeupEvent = CreateWaitableTimer( NULL, FALSE, NULL );
+ err = translate_errno( gSPSWakeupEvent, (mStatus) GetLastError(), kUnknownErr );
require_noerr( err, exit );
- newSource->closeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- err = translate_errno( newSource->closeEvent, (mStatus) GetLastError(), kUnknownErr );
+ gSPSSleepEvent = CreateWaitableTimer( NULL, FALSE, NULL );
+ err = translate_errno( gSPSSleepEvent, (mStatus) GetLastError(), kUnknownErr );
require_noerr( err, exit );
- err = WSAEventSelect(newSource->sock, newSource->socketEvent, FD_ACCEPT|FD_READ|FD_CLOSE);
- err = translate_errno( err == 0, errno_compat(), kNoResourcesErr );
+ gUDSEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( gUDSEvent, ( mStatus ) GetLastError(), kUnknownErr );
require_noerr( err, exit );
- newSource->waitCount = 0;
- newSource->waitList[ newSource->waitCount++ ] = newSource->socketEvent;
- newSource->waitList[ newSource->waitCount++ ] = newSource->closeEvent;
+exit:
+ if( err )
+ {
+ TearDownNotifications();
+ }
+ return( err );
+}
- //
- // lock the list
- //
- EventSourceLock();
-
- // add the event source to the end of the list, while checking
- // to see if the list needs to be initialized
- //
- if ( gEventSources.LinkOffset == 0)
+//===========================================================================================================================
+// TearDownNotifications
+//===========================================================================================================================
+
+mDNSlocal mStatus TearDownNotifications()
+{
+ if ( gStopEvent )
{
- InitLinkedList( &gEventSources, offsetof( Win32EventSource, next));
+ CloseHandle( gStopEvent );
+ gStopEvent = NULL;
}
- AddToTail( &gEventSources, newSource);
+ if( IsValidSocket( gInterfaceListChangedSocket ) )
+ {
+ close_compat( gInterfaceListChangedSocket );
+ gInterfaceListChangedSocket = kInvalidSocketRef;
+ }
- //
- // no longer using the list
- //
- EventSourceUnlock();
+ if( gInterfaceListChangedEvent )
+ {
+ CloseHandle( gInterfaceListChangedEvent );
+ gInterfaceListChangedEvent = 0;
+ }
- // Create thread with _beginthreadex() instead of CreateThread() to avoid memory leaks when using static run-time
- // libraries. See <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createthread.asp>.
- // Create the thread suspended then resume it so the thread handle and ID are valid before the thread starts running.
- newSource->threadHandle = (HANDLE) _beginthreadex_compat( NULL, 0, udsSocketThread, newSource, CREATE_SUSPENDED, &newSource->threadID );
- err = translate_errno( newSource->threadHandle, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
+ if ( gDescChangedEvent != NULL )
+ {
+ CloseHandle( gDescChangedEvent );
+ gDescChangedEvent = NULL;
+ }
- result = ResumeThread( newSource->threadHandle );
- err = translate_errno( result != (DWORD) -1, errno_compat(), kNoResourcesErr );
- require_noerr( err, exit );
+ if ( gDescKey != NULL )
+ {
+ RegCloseKey( gDescKey );
+ gDescKey = NULL;
+ }
-exit:
+ if ( gTcpipChangedEvent != NULL )
+ {
+ CloseHandle( gTcpipChangedEvent );
+ gTcpipChangedEvent = NULL;
+ }
- if (err && newSource)
+ if ( gDdnsChangedEvent != NULL )
{
- EventSourceFinalize(newSource);
+ CloseHandle( gDdnsChangedEvent );
+ gDdnsChangedEvent = NULL;
}
- return err;
-}
+ if ( gDdnsKey != NULL )
+ {
+ RegCloseKey( gDdnsKey );
+ gDdnsKey = NULL;
+ }
+ if ( gFileSharingChangedEvent != NULL )
+ {
+ CloseHandle( gFileSharingChangedEvent );
+ gFileSharingChangedEvent = NULL;
+ }
-mStatus
-udsSupportRemoveFDFromEventLoop( SocketRef fd) // Note: This also CLOSES the socket
-{
- Win32EventSource * source;
- mStatus err = mStatus_NoError;
-
- //
- // find the event source
- //
- EventSourceLock();
+ if ( gFileSharingKey != NULL )
+ {
+ RegCloseKey( gFileSharingKey );
+ gFileSharingKey = NULL;
+ }
- for (source = gEventSources.Head; source; source = source->next)
+ if ( gFirewallChangedEvent != NULL )
{
- if (source->sock == (SOCKET) fd)
- {
- break;
- }
+ CloseHandle( gFirewallChangedEvent );
+ gFirewallChangedEvent = NULL;
}
- //
- // if we found him, finalize him
- //
- if (source != NULL)
+ if ( gFirewallKey != NULL )
{
- EventSourceFinalize(source);
+ RegCloseKey( gFirewallKey );
+ gFirewallKey = NULL;
}
- //
- // done with the list
- //
- EventSourceUnlock();
-
- closesocket(fd);
+ if ( gAdvertisedServicesChangedEvent != NULL )
+ {
+ CloseHandle( gAdvertisedServicesChangedEvent );
+ gAdvertisedServicesChangedEvent = NULL;
+ }
- return err;
-}
+ if ( gAdvertisedServicesKey != NULL )
+ {
+ RegCloseKey( gAdvertisedServicesKey );
+ gAdvertisedServicesKey = NULL;
+ }
+ if ( gSPSWakeupEvent )
+ {
+ CloseHandle( gSPSWakeupEvent );
+ gSPSWakeupEvent = NULL;
+ }
-mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
+ if ( gSPSSleepEvent )
{
- (void)m;
- (void)delay;
- // No-op, for now
+ CloseHandle( gSPSSleepEvent );
+ gSPSSleepEvent = NULL;
}
+ return( mStatus_NoError );
+}
+
+
+//===========================================================================================================================
+// RegisterWaitableEvent
+//===========================================================================================================================
-static mStatus
-EventSourceFinalize(Win32EventSource * source)
+static mStatus RegisterWaitableEvent( mDNS * const inMDNS, HANDLE event, void * context, RegisterWaitableEventHandler handler )
{
- OSStatus err;
- bool locked;
- Win32EventSource * inserted;
- bool sameThread;
- bool deferClose;
- BOOL ok;
- DWORD threadID;
- DWORD result;
-
- check( source );
-
- // Find the session in the list.
-
- EventSourceLock();
- locked = true;
-
- for( inserted = (Win32EventSource*) gEventSources.Head; inserted; inserted = inserted->next )
+ EventSource * source;
+ mStatus err = mStatus_NoError;
+
+ ( void ) inMDNS;
+ check( event );
+ check( handler );
+
+ source = ( EventSource* ) malloc( sizeof( EventSource ) );
+ require_action( source, exit, err = mStatus_NoMemoryErr );
+ mDNSPlatformMemZero( source, sizeof( EventSource ) );
+ source->event = event;
+ source->context = context;
+ source->handler = handler;
+
+ source->next = gEventSourceList;
+ gEventSourceList = source;
+ gEventSourceListChanged = TRUE;
+ gEventSources++;
+
+exit:
+
+ return err;
+}
+
+
+//===========================================================================================================================
+// UnregisterWaitableEvent
+//===========================================================================================================================
+
+static void UnregisterWaitableEvent( mDNS * const inMDNS, HANDLE event )
+{
+ EventSource * current = gEventSourceList;
+ EventSource * last = NULL;
+
+ ( void ) inMDNS;
+ check( event );
+
+ while ( current )
{
- if( inserted == source )
+ if ( current->event == event )
{
+ if ( last == NULL )
+ {
+ gEventSourceList = current->next;
+ }
+ else
+ {
+ last->next = current->next;
+ }
+
+ gEventSourceListChanged = TRUE;
+
+ // Protect against removing the node that we happen
+ // to be looking at as we iterate through the event
+ // source list in ServiceSpecificRun()
+
+ if ( current == gCurrentSource )
+ {
+ gCurrentSource = current->next;
+ }
+
+ gEventSources--;
+ free( current );
+
break;
}
+
+ last = current;
+ current = current->next;
}
- require_action( inserted, exit, err = kNotFoundErr );
+}
- //
- // note that we've had finalize called
- //
- source->flags |= EventSourceFinalized;
+
+//===========================================================================================================================
+// SetupWaitList
+//===========================================================================================================================
+
+mDNSlocal mStatus SetupWaitList( mDNS * const inMDNS, HANDLE **outWaitList, int *outWaitListCount )
+{
+ int waitListCount;
+ HANDLE * waitList;
+ HANDLE * waitItemPtr;
+ EventSource * source;
+ mStatus err;
- // If we're being called from the same thread as the session (e.g. message callback is closing the session) then
- // we must defer the close until the thread is done because the thread is still using the session object.
+ dlog( kDebugLevelTrace, DEBUG_NAME "setting up wait list\n" );
- deferClose = false;
- threadID = GetCurrentThreadId();
- sameThread = source->threadHandle && ( threadID == source->threadID );
- if( sameThread && !( source->flags & EventSourceFlagsThreadDone ) )
- {
- source->flags &= ~EventSourceFlagsNoClose;
- deferClose = true;
- }
+ ( void ) inMDNS;
+ check( inMDNS->p );
+ check( outWaitList );
+ check( outWaitListCount );
- // If the thread we're not being called from the session thread, but the thread has already marked itself as
- // as done (e.g. session closed from something like a peer disconnect and at the same time the client also
- // tried to close) then we only want to continue with the close if the thread is not going to close itself.
+ // Allocate an array to hold all the objects to wait on.
- if( !sameThread && ( source->flags & EventSourceFlagsThreadDone ) && !( source->flags & EventSourceFlagsNoClose ) )
- {
- deferClose = true;
- }
+ waitListCount = kWaitListFixedItemCount + gEventSources;
+ waitList = ( HANDLE* ) malloc( waitListCount * sizeof( *waitList ) );
+ require_action( waitList, exit, err = mStatus_NoMemoryErr );
+ waitItemPtr = waitList;
- // Signal a close so the thread exits.
+ // Add the fixed wait items to the beginning of the list.
- if( source->closeEvent )
- {
- ok = SetEvent( source->closeEvent );
- check_translated_errno( ok, errno_compat(), kUnknownErr );
- }
- if( deferClose )
+ *waitItemPtr++ = gStopEvent;
+ *waitItemPtr++ = gInterfaceListChangedEvent;
+ *waitItemPtr++ = gDescChangedEvent;
+ *waitItemPtr++ = gTcpipChangedEvent;
+ *waitItemPtr++ = gDdnsChangedEvent;
+ *waitItemPtr++ = gFileSharingChangedEvent;
+ *waitItemPtr++ = gFirewallChangedEvent;
+ *waitItemPtr++ = gAdvertisedServicesChangedEvent;
+ *waitItemPtr++ = gSPSWakeupEvent;
+ *waitItemPtr++ = gSPSSleepEvent;
+
+ for ( source = gEventSourceList; source; source = source->next )
{
- err = kNoErr;
- goto exit;
+ *waitItemPtr++ = source->event;
}
+
+ check( ( int )( waitItemPtr - waitList ) == waitListCount );
- source->flags |= EventSourceFlagsNoClose;
-
- // Remove the session from the list.
- RemoveFromList(&gEventSources, source);
-
- EventSourceUnlock();
- locked = false;
-
- // Wait for the thread to exit. Give up after 3 seconds to handle a hung thread.
+ *outWaitList = waitList;
+ *outWaitListCount = waitListCount;
+ waitList = NULL;
+ err = mStatus_NoError;
- if( source->threadHandle && ( threadID != source->threadID ) )
+exit:
+
+ if( waitList )
{
- result = WaitForSingleObject( source->threadHandle, 3 * 1000 );
- check_translated_errno( result == WAIT_OBJECT_0, (OSStatus) GetLastError(), result );
+ free( waitList );
}
-
- // Release the thread.
-
- if( source->threadHandle )
+
+ dlog( kDebugLevelTrace, DEBUG_NAME "setting up wait list done (err=%d %m)\n", err, err );
+ return( err );
+}
+
+
+//===========================================================================================================================
+// CoreCallback
+//===========================================================================================================================
+
+static void
+CoreCallback(mDNS * const inMDNS, mStatus status)
+{
+ if (status == mStatus_ConfigChanged)
{
- ok = CloseHandle( source->threadHandle );
- check_translated_errno( ok, errno_compat(), kUnknownErr );
- source->threadHandle = NULL;
+ SetLLRoute( inMDNS );
}
+}
+
+
+//===========================================================================================================================
+// UDSCanAccept
+//===========================================================================================================================
+
+mDNSlocal void UDSCanAccept( mDNS * const inMDNS, HANDLE event, void * context )
+{
+ ( void ) inMDNS;
+ ( void ) event;
- // Release the socket event.
-
- if( source->socketEvent )
+ if ( gUDSCallback )
{
- ok = CloseHandle( source->socketEvent );
- check_translated_errno( ok, errno_compat(), kUnknownErr );
- source->socketEvent = NULL;
+ gUDSCallback( ( int ) gUDSSocket, 0, context );
}
-
- // Release the close event.
-
- if( source->closeEvent )
+}
+
+
+//===========================================================================================================================
+// UDSCanRead
+//===========================================================================================================================
+
+mDNSlocal void UDSCanRead( TCPSocket * sock )
+{
+ udsEventCallback callback = ( udsEventCallback ) sock->userCallback;
+
+ if ( callback )
{
- ok = CloseHandle( source->closeEvent );
- check_translated_errno( ok, errno_compat(), kUnknownErr );
- source->closeEvent = NULL;
+ callback( (int) sock->fd, 0, sock->userContext );
}
-
- // Release the memory used by the object.
- free ( source );
+}
- err = kNoErr;
-
- dlog( kDebugLevelNotice, DEBUG_NAME "session closed\n" );
-
-exit:
- if( locked )
+//===========================================================================================================================
+// udsSupportAddFDToEventLoop
+//===========================================================================================================================
+
+mStatus
+udsSupportAddFDToEventLoop( SocketRef fd, udsEventCallback callback, void *context, void **platform_data)
+{
+ mStatus err = mStatus_NoError;
+
+ // We are using some knowledge of what is being passed to us here. If the fd is a listen socket,
+ // then the "callback" parameter is NULL. If it is an actual read/write socket, then the "callback"
+ // parameter is not null. This is important because we use waitable events for the listen socket
+ // and alertable I/O for the read/write sockets.
+
+ if ( context )
{
- EventSourceUnlock();
+ TCPSocket * sock;
+
+ sock = malloc( sizeof( TCPSocket ) );
+ require_action( sock, exit, err = mStatus_NoMemoryErr );
+ mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
+
+ sock->fd = (SOCKET) fd;
+ sock->readEventHandler = UDSCanRead;
+ sock->userCallback = callback;
+ sock->userContext = context;
+ sock->m = &gMDNSRecord;
+
+ err = TCPAddSocket( sock->m, sock );
+ require_noerr( err, exit );
+
+ *platform_data = sock;
+ }
+ else
+ {
+ gUDSSocket = fd;
+ gUDSCallback = callback;
+ gUDSEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( gUDSEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+ err = WSAEventSelect( fd, gUDSEvent, FD_ACCEPT | FD_CLOSE );
+ err = translate_errno( err == 0, WSAGetLastError(), kNoResourcesErr );
+ require_noerr( err, exit );
+ err = RegisterWaitableEvent( &gMDNSRecord, gUDSEvent, context, UDSCanAccept );
+ require_noerr( err, exit );
}
- return( err );
+exit:
+
+ return err;
}
-static void
-EventSourceLock()
+int
+udsSupportReadFD( SocketRef fd, char *buf, int len, int flags, void *platform_data )
{
- EnterCriticalSection(&gEventSourceLock);
+ TCPSocket * sock;
+ mDNSBool closed;
+ int ret;
+
+ ( void ) flags;
+
+ sock = ( TCPSocket* ) platform_data;
+ require_action( sock, exit, ret = -1 );
+ require_action( sock->fd == fd, exit, ret = -1 );
+
+ ret = mDNSPlatformReadTCP( sock, buf, len, &closed );
+
+ if ( closed )
+ {
+ ret = 0;
+ }
+
+exit:
+
+ return ret;
}
-static void
-EventSourceUnlock()
+mStatus
+udsSupportRemoveFDFromEventLoop( SocketRef fd, void *platform_data) // Note: This also CLOSES the socket
{
- LeaveCriticalSection(&gEventSourceLock);
+ mStatus err = kNoErr;
+
+ if ( platform_data != NULL )
+ {
+ TCPSocket * sock;
+
+ dlog( kDebugLevelInfo, DEBUG_NAME "session closed\n" );
+ sock = ( TCPSocket* ) platform_data;
+ check( sock->fd == fd );
+ mDNSPlatformTCPCloseConnection( sock );
+ }
+ else if ( gUDSEvent != NULL )
+ {
+ UnregisterWaitableEvent( &gMDNSRecord, gUDSEvent );
+ WSAEventSelect( fd, gUDSEvent, 0 );
+ CloseHandle( gUDSEvent );
+ gUDSEvent = NULL;
+ }
+
+ return err;
}
+mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
+ {
+ (void)m;
+ (void)delay;
+ // No-op, for now
+ }
+
+
//===========================================================================================================================
// SystemWakeForNetworkAccess
//===========================================================================================================================
SYSTEM_POWER_STATUS powerStatus;
time_t startTime;
time_t nextWakeupTime;
- time_t delta;
- __int64 delta64;
+ int delta;
DWORD err;
dlog( kDebugLevelInfo, DEBUG_NAME "SystemWakeForNetworkAccess\n" );
// Now make sure we have a network interface that does wake-on-lan
- UpdateWOMPConfig( &gMDNSRecord );
- require_action( gMDNSRecord.p->womp, exit, ok = FALSE );
+ ok = ( mDNSu8 ) IsWOMPEnabled( &gMDNSRecord );
+ require_action( ok, exit, ok = FALSE );
+
+ // Now make sure we have advertised services. Doesn't make sense to
+ // enable sleep proxy if we have no multicast services that could
+ // potentially wake us up.
+
+ ok = ( mDNSu8 ) mDNSCoreHaveAdvertisedMulticastServices( &gMDNSRecord );
+ require_action( ok, exit, ok = FALSE );
// Calculate next wake up time
- startTime = time( NULL );
- nextWakeupTime = startTime + ( 120 * 60 );
+ startTime = time( NULL ); // Seconds since midnight January 1, 1970
+ nextWakeupTime = startTime + ( 120 * 60 ); // 2 hours later
if ( gMDNSRecord.p->nextDHCPLeaseExpires < nextWakeupTime )
{
// Finally calculate the next relative wakeup time
- delta = ( time_t ) ( ( ( double )( nextWakeupTime - startTime ) ) * 0.9 );
- delta64 = -delta * 10000000;
- timeout->LowPart = (DWORD) ( delta64 & 0xFFFFFFFF );
- timeout->HighPart = (LONG) ( delta64 >> 32 );
+ delta = ( int )( ( ( double )( nextWakeupTime - startTime ) ) * 0.9 );
+ ReportStatus( EVENTLOG_INFORMATION_TYPE, "enabling sleep proxy client with next maintenance wake in %d seconds", delta );
+
+ // Convert seconds to 100 nanosecond units expected by SetWaitableTimer
- dlog( kDebugLevelInfo, DEBUG_NAME "enabling sleep proxy client with next wakeup time %d seconds from now\n", delta );
+ timeout->QuadPart = -delta;
+ timeout->QuadPart *= kSecondsTo100NSUnits;
ok = TRUE;
* 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: Service.h,v $
-Revision 1.1 2009/07/09 21:34:15 herscher
-<rdar://problem/3775717> SDK: Port mDNSNetMonitor to Windows. Refactor the system service slightly by removing the main() function from Service.c so that mDNSNetMonitor can link to functions defined in Service.c
-
-
*/
#ifndef __MDNS_SERVICE_H__
//
#include "winres.h"
#include "WinVersRes.h"
+#include "EventLog.rc"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
Version="8.00"\r
Name="mDNSResponder"\r
ProjectGUID="{C1D98254-BA27-4427-A3BE-A68CA2CC5F69}"\r
+ RootNamespace="mDNSResponder"\r
Keyword="Win32Proj"\r
>\r
<Platforms>\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalOptions="/NXCOMPAT /DYNAMICBASE"\r
- AdditionalDependencies="ws2_32.lib iphlpapi.lib crypt32.lib netapi32.lib"\r
+ AdditionalDependencies="ws2_32.lib iphlpapi.lib crypt32.lib netapi32.lib powrprof.lib"\r
OutputFile="$(OutDir)/mDNSResponder.exe"\r
LinkIncremental="2"\r
IgnoreAllDefaultLibraries="false"\r
WarningLevel="4"\r
Detect64BitPortabilityProblems="true"\r
DebugInformationFormat="3"\r
+ CallingConvention="2"\r
DisableSpecificWarnings="4127;4201"\r
/>\r
<Tool\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
:END
"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
if not exist "$(DSTROOT)\AppleInternal" mkdir "$(DSTROOT)\AppleInternal"
if not exist "$(DSTROOT)\AppleInternal\bin" mkdir "$(DSTROOT)\AppleInternal\bin"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
xcopy /I/Y "$(TargetDir)$(TargetName).pdb" "$(DSTROOT)\AppleInternal\bin"
:END
"\r
/>\r
</Configuration>\r
<Configuration\r
/>\r
<Tool\r
Name="VCPostBuildEventTool"\r
- CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
:END
"\r
+ CommandLine="if not "%RC_XBS%" == "YES" goto END
if not exist "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)" mkdir "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
if not exist "$(DSTROOT)\AppleInternal" mkdir "$(DSTROOT)\AppleInternal"
if not exist "$(DSTROOT)\AppleInternal\bin" mkdir "$(DSTROOT)\AppleInternal\bin"
xcopy /I/Y "$(TargetPath)" "$(DSTROOT)\Program Files\Bonjour\$(PlatformName)"
xcopy /I/Y "$(TargetDir)$(TargetName).pdb" "$(DSTROOT)\AppleInternal\bin"
:END
"\r
/>\r
</Configuration>\r
</Configurations>\r
RelativePath="..\..\mDNSShared\dnssd_ipc.c"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\EventLog.mc"\r
+ >\r
+ <FileConfiguration\r
+ Name="Debug|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ Description="Compiling Message Resource"\r
+ CommandLine="mc.exe EventLog.mc"\r
+ Outputs="EventLog.rc EventLog.h"\r
+ />\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Debug|x64"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ Description="Compiling Message Resource"\r
+ CommandLine="mc.exe EventLog.mc"\r
+ Outputs="EventLog.rc EventLog.h"\r
+ />\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ Description="Compiling Message Resource"\r
+ CommandLine="mc.exe EventLog.mc"\r
+ Outputs="EventLog.rc EventLog.h"\r
+ />\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|x64"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ Description="Compiling Message Resource"\r
+ CommandLine="mc.exe EventLog.mc"\r
+ Outputs="EventLog.rc EventLog.h"\r
+ />\r
+ </FileConfiguration>\r
+ </File>\r
<File\r
RelativePath="Firewall.cpp"\r
>\r
* 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: main.c,v $
-Revision 1.1 2009/07/09 21:34:15 herscher
-<rdar://problem/3775717> SDK: Port mDNSNetMonitor to Windows. Refactor the system service slightly by removing the main() function from Service.c so that mDNSNetMonitor can link to functions defined in Service.c
-
-
*/
#include "Service.h"
* 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: VPCDetect.cpp,v $
-Revision 1.3 2006/08/14 23:25:20 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2006/02/26 19:31:05 herscher
-<rdar://problem/4455038> Bonjour For Windows takes 90 seconds to start. This was caused by a bad interaction between the VirtualPC check, and the removal of the WMI dependency. The problem was fixed by: 1) checking to see if WMI is running before trying to talk to it. 2) Retrying the VirtualPC check every 10 seconds upon failure, stopping after 10 unsuccessful tries.
-
-Revision 1.1 2005/11/27 20:21:16 herscher
-<rdar://problem/4210580> Workaround Virtual PC bug that incorrectly modifies incoming mDNS packets
-
-*/
+ */
#define _WIN32_DCOM
#include "VPCDetect.h"
* 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: VPCDetect.h,v $
-Revision 1.3 2006/08/14 23:25:20 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.2 2006/02/26 19:31:05 herscher
-<rdar://problem/4455038> Bonjour For Windows takes 90 seconds to start. This was caused by a bad interaction between the VirtualPC check, and the removal of the WMI dependency. The problem was fixed by: 1) checking to see if WMI is running before trying to talk to it. 2) Retrying the VirtualPC check every 10 seconds upon failure, stopping after 10 unsuccessful tries.
-
-Revision 1.1 2005/11/27 20:21:16 herscher
-<rdar://problem/4210580> Workaround Virtual PC bug that incorrectly modifies incoming mDNS packets
-
-*/
+ */
#pragma once
* 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: 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
-
-Revision 1.1 2004/06/18 05:23:33 rpantos
-First checked in
-
-
-*/
+ */
#include "WinServices.h"
#include <DebugServices.h>
* 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: 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
-
-Revision 1.1 2004/06/18 05:23:33 rpantos
-First checked in
-
-
-*/
+ */
#pragma once
* 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: WinVersRes.h,v $
-Revision 1.63 2009/07/21 05:10:55 herscher
-Bump version to 2.0.0.7
-
-Revision 1.62 2009/07/13 18:47:58 herscher
-Bump to version 2.0.0.6
-
-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.
-
-Revision 1.54 2006/08/14 23:25:21 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.53 2006/02/28 20:07:53 herscher
-Bump to 1.0.3.1
-
-Revision 1.52 2006/01/09 20:45:29 cheshire
-Update copyright date to 2006
-
-Revision 1.51 2005/11/28 19:49:56 herscher
-Bump to 1.0.2.9
-
-Revision 1.50 2005/10/28 18:48:04 herscher
-Bump to version 1.0.2.8
-
-Revision 1.49 2005/10/25 05:24:27 herscher
-Bump to 1.0.2.7
-
-Revision 1.48 2005/10/18 06:17:05 herscher
-Bump to 1.0.2.6
-
-Revision 1.47 2005/10/05 22:16:57 herscher
-Bump version number to 1.0.2.5
-
-Revision 1.46 2005/09/29 06:43:07 herscher
-Bump to version 1.0.2.4
-
-Revision 1.45 2005/09/22 07:11:35 herscher
-Bump version to 1.0.2.3
-
-Revision 1.44 2005/09/13 01:07:40 herscher
-Bump to 1.0.2.2
-
-Revision 1.43 2005/09/12 06:13:32 herscher
-Bump version 1.0.2.1
-
-Revision 1.42 2005/07/22 19:41:44 ksekar
-Update version
-
-Revision 1.41 2005/07/15 15:22:20 shersche
-Bump to 1.0.1.1
-
-Revision 1.40 2005/07/11 20:42:03 shersche
-Bump version to 1.0.0.68
-
-Revision 1.39 2005/07/07 19:12:47 shersche
-Bump to 1.0.0.67
-
-Revision 1.38 2005/04/25 21:59:42 shersche
-Bump to 1.0.0.66
-
-Revision 1.37 2005/04/22 07:39:48 shersche
-Bump to 1.0.0.65
-
-Revision 1.36 2005/04/19 07:25:56 shersche
-Bump version to 1.0.0.64
-
-Revision 1.35 2005/04/13 17:48:58 shersche
-Bump to 1.0.0.63
-
-Revision 1.34 2005/04/06 01:00:55 shersche
-Bump to 1.0.0.62
-
-Revision 1.33 2005/03/30 07:37:41 shersche
-Bump to 1.0.0.61
-
-Revision 1.32 2005/03/23 00:39:46 shersche
-Bump to version 1.0.0.60
-
-Revision 1.31 2005/03/16 03:52:06 shersche
-Bump to 1.0.0.59
-
-Revision 1.30 2005/03/07 19:18:18 shersche
-<rdar://problem/4039831> Update Windows build to 1.0.0.58
-
-Revision 1.29 2005/03/02 20:11:45 shersche
-Update name
-
-Revision 1.28 2005/03/02 03:57:51 shersche
-Bump to 1.0.0.57
-
-Revision 1.27 2005/02/23 03:12:27 shersche
-Bump to 1.0.0.56
-
-Revision 1.26 2005/02/15 23:20:18 shersche
-Bump to 1.0.0.55 and update name
-
-Revision 1.25 2005/02/10 22:35:29 cheshire
-<rdar://problem/3727944> Update name
-
-Revision 1.24 2005/02/08 23:32:24 shersche
-Bump to 1.0.0.54
-
-Revision 1.23 2005/02/02 02:08:28 shersche
-Bump to version 1.0.0.53
-
-Revision 1.22 2005/01/25 17:15:52 shersche
-Bump to 1.0.0.51. Add legal copyright string.
-
-Revision 1.21 2005/01/11 07:09:32 shersche
-Bump to version 1.0.0.51
-
-Revision 1.20 2004/12/17 01:23:24 shersche
-Bump version to 1.0.0.50
-
-Revision 1.19 2004/12/16 08:09:47 shersche
-Revert version number back to 1.0.0.22
-
-Revision 1.18 2004/12/16 02:48:10 shersche
-Bump version number to 1.1.0.0
-
-Revision 1.17 2004/10/20 15:37:46 shersche
-Bump to Windows-trial-21
-
-Revision 1.16 2004/10/12 23:51:36 cheshire
-Bump version to 1.0.0.20
-
-Revision 1.15 2004/09/21 01:15:56 shersche
-bump version to 1.0.19
-
-Revision 1.14 2004/09/16 21:27:46 shersche
-Bump to version 18
-
-Revision 1.13 2004/09/13 21:28:41 shersche
-Bump version to 17
-
-Revision 1.12 2004/08/28 00:18:01 rpantos
-no message
-
-Revision 1.11 2004/08/26 17:37:15 shersche
-bump version to 1.0.0.14
-
-Revision 1.10 2004/08/05 18:00:04 rpantos
-bump to 1.0.0.13
-
-Revision 1.9 2004/07/27 07:31:46 shersche
-bump to 1.0.0.12
-
-Revision 1.8 2004/07/22 23:28:54 shersche
-bump to Version 1.0.0.11
-
-Revision 1.7 2004/07/20 23:36:24 shersche
-bump to version 1.0.0.10
-
-Revision 1.6 2004/07/14 19:53:26 shersche
-bump version to 1.0.0.9
-
-Revision 1.5 2004/07/13 22:20:02 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.4 2004/07/09 18:04:17 shersche
-bump version to 1.0.0.8
-
-Revision 1.3 2004/06/27 17:00:15 rpantos
-Cleanup.
-
-Revision 1.2 2004/06/26 22:24:08 rpantos
-Cleanup.
-
-Revision 1.1 2004/06/26 19:17:41 rpantos
-First checked in.
-
*/
#ifndef WINRESVERS_H
#define MASTER_COMPANY_NAME "Apple Inc."
// Define the product version for mDNSResponder on Windows
-#define MASTER_PROD_VERS 2,0,0,7
-#define MASTER_PROD_VERS_STR "2,0,0,7"
-#define MASTER_PROD_VERS_STR2 "2.0.0.7"
-#define MASTER_PROD_VERS_STR3 "Explorer Plugin 2.0.0.7"
+#define MASTER_PROD_VERS 2,0,0,19
+#define MASTER_PROD_VERS_STR "2,0,0,19"
+#define MASTER_PROD_VERS_STR2 "2.0.0.19"
+#define MASTER_PROD_VERS_STR3 "Explorer Plugin 2.0.0.19"
// Define the legal copyright
-#define MASTER_LEGAL_COPYRIGHT "Copyright (C) 2003-2009 Apple Inc."
+#define MASTER_LEGAL_COPYRIGHT "Copyright (C) 2003-2010 Apple Inc."
#endif // WINRESVERS_H
* 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):
-
-*/
+ */
/* isocode.h */
/* ----------------------------------------------------------------------*/
8, 22, 'p','t','_','P','T', 0 ,
4, 24, 'r','o', 0 , 0 , 0 , 0 ,
8, 24, 'r','o', 0 , 0 , 0 , 0 ,
-4, 15, 'r','u', 0 , 0 , 0 , 0 ,
+4, 25, 'r','u', 0 , 0 , 0 , 0 ,
8, 25, 'r','u', 0 , 0 , 0 , 0 ,
4, 30, 't','h', 0 , 0 , 0 , 0 ,
4, 31, 't','r', 0 , 0 , 0 , 0 ,
* 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):
-
*/
/* loclibrary.c
* 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):
-
*/
/* loclibrary.h
* See the License for the specific language governing permissions and
* limitations under the License.
- Change History (most recent first):
-
-$Log: mDNSWin32.c,v $
-Revision 1.145 2009/07/20 04:07:41 herscher
-<rdar://problem/6145339> Bonjour does not list IPv6 loopback address when all network adapters are disabled
-
-Revision 1.144 2009/07/17 19:59:46 herscher
-<rdar://problem/7062660> Update the womp settings for each network adapter immediately preceding the call to mDNSCoreMachineSleep().
-
-Revision 1.143 2009/07/07 21:34:58 herscher
-<rdar://problem/6713286> windows platform changes to support use as sleep proxy client
-
-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
-
-Revision 1.129 2007/10/17 22:52:26 cheshire
-Get rid of unused mDNS_UpdateLLQs()
-
-Revision 1.128 2007/09/12 19:23:17 cheshire
-Get rid of unnecessary mDNSPlatformTCPIsConnected() routine
-
-Revision 1.127 2007/07/20 00:54:22 cheshire
-<rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
-
-Revision 1.126 2007/07/11 02:56:20 cheshire
-<rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
-Remove unused mDNSPlatformDefaultRegDomainChanged
-
-Revision 1.125 2007/06/20 01:10:13 cheshire
-<rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
-
-Revision 1.124 2007/04/26 00:35:16 cheshire
-<rdar://problem/5140339> uDNS: Domain discovery not working over VPN
-Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server
-inside the firewall may give answers where a public one gives none, and vice versa.)
-
-Revision 1.123 2007/04/18 21:00:40 cheshire
-Use mDNS_AddSearchDomain_CString() instead of MakeDomainNameFromDNSNameString ... mDNS_AddSearchDomain
-
-Revision 1.122 2007/04/17 19:21:29 cheshire
-<rdar://problem/5140339> Domain discovery not working over VPN
-
-Revision 1.121 2007/04/05 20:40:37 cheshire
-Remove unused mDNSPlatformTCPGetFlags()
-
-Revision 1.120 2007/03/28 20:59:27 cheshire
-<rdar://problem/4743285> Remove inappropriate use of IsPrivateV4Addr()
-
-Revision 1.119 2007/03/28 15:56:38 cheshire
-<rdar://problem/5085774> Add listing of NAT port mapping and GetAddrInfo requests in SIGINFO output
-
-Revision 1.118 2007/03/22 18:31:49 cheshire
-Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
-
-Revision 1.117 2007/03/21 00:30:07 cheshire
-<rdar://problem/4789455> Multiple errors in DNameList-related code
-
-Revision 1.116 2007/03/20 17:07:16 cheshire
-Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
-
-Revision 1.115 2007/02/08 21:12:28 cheshire
-<rdar://problem/4386497> Stop reading /etc/mDNSResponder.conf on every sleep/wake
-
-Revision 1.114 2007/01/05 08:31:01 cheshire
-Trim excessive "$Log" checkin history from before 2006
-(checkin history still available via "cvs log ..." of course)
-
-Revision 1.113 2007/01/04 23:12:20 cheshire
-Remove unused mDNSPlatformDefaultBrowseDomainChanged
-
-Revision 1.112 2006/12/22 20:59:51 cheshire
-<rdar://problem/4742742> Read *all* DNS keys from keychain,
- not just key for the system-wide default registration domain
-
-Revision 1.111 2006/12/19 22:43:56 cheshire
-Fix compiler warnings
-
-Revision 1.110 2006/09/27 00:47:40 herscher
-Fix compile error caused by changes to the tcp callback api.
-
-Revision 1.109 2006/08/14 23:25:21 cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-Revision 1.108 2006/07/06 00:06:21 cheshire
-<rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
-
-Revision 1.107 2006/03/19 02:00:13 cheshire
-<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
-
-Revision 1.106 2006/02/26 19:31:05 herscher
-<rdar://problem/4455038> Bonjour For Windows takes 90 seconds to start. This was caused by a bad interaction between the VirtualPC check, and the removal of the WMI dependency. The problem was fixed by: 1) checking to see if WMI is running before trying to talk to it. 2) Retrying the VirtualPC check every 10 seconds upon failure, stopping after 10 unsuccessful tries.
-
To Do:
- Get unicode name of machine for nice name instead of just the host name.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <crtdbg.h>
#include <string.h>
#include "CommonServices.h"
#include <dns_sd.h>
#include <Iphlpapi.h>
-#if( !TARGET_OS_WINDOWS_CE )
- #include <mswsock.h>
- #include <process.h>
- #include <ntsecapi.h>
- #include <lm.h>
- #include <winioctl.h>
- #include <ntddndis.h> // This defines the IOCTL constants.
-#endif
+#include <mswsock.h>
+#include <process.h>
+#include <ntsecapi.h>
+#include <lm.h>
+#include <winioctl.h>
+#include <ntddndis.h> // This defines the IOCTL constants.
#include "mDNSEmbeddedAPI.h"
+#include "GenLinkedList.h"
#include "DNSCommon.h"
#include "mDNSWin32.h"
#define kWinSockMajorMin 2
#define kWinSockMinorMin 2
-#define kWaitListCancelEvent ( WAIT_OBJECT_0 + 0 )
-#define kWaitListInterfaceListChangedEvent ( WAIT_OBJECT_0 + 1 )
-#define kWaitListWakeupEvent ( WAIT_OBJECT_0 + 2 )
-#define kWaitListComputerDescriptionEvent ( WAIT_OBJECT_0 + 3 )
-#define kWaitListTCPIPEvent ( WAIT_OBJECT_0 + 4 )
-#define kWaitListDynDNSEvent ( WAIT_OBJECT_0 + 5 )
-#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
+static GUID kWSARecvMsgGUID = WSAID_WSARECVMSG;
#define kIPv6IfIndexBase (10000000L)
#define SMBPortAsNumber 445
#define DEVICE_PREFIX "\\\\.\\"
-
#if 0
#pragma mark == Prototypes ==
#endif
// Prototypes
//===========================================================================================================================
-mDNSlocal mStatus SetupSynchronizationObjects( mDNS * const inMDNS );
-mDNSlocal mStatus TearDownSynchronizationObjects( mDNS * const inMDNS );
mDNSlocal mStatus SetupNiceName( mDNS * const inMDNS );
mDNSlocal mStatus SetupHostName( mDNS * const inMDNS );
mDNSlocal mStatus SetupName( mDNS * const inMDNS );
-mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS );
-mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS );
mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD );
mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD );
+mDNSlocal void CALLBACK FreeInterface( mDNSInterfaceData *inIFD );
mDNSlocal mStatus SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef );
mDNSlocal mStatus SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort );
-mDNSlocal mStatus SetupNotifications( mDNS * const inMDNS );
-mDNSlocal mStatus TearDownNotifications( 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, 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 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 );
mDNSAddr ip;
};
-struct TCPSocket_struct
-{
- TCPSocketFlags flags; // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with TCPSocketFlags flags
- SocketRef fd;
- BOOL connected;
- TCPConnectionCallback callback;
- void * context;
- HANDLE pendingEvent;
- 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 );
mDNSlocal int getifaddrs_ipv6( struct ifaddrs **outAddrs );
#endif
-#if( !TARGET_OS_WINDOWS_CE )
- mDNSlocal int getifaddrs_ipv4( struct ifaddrs **outAddrs );
-#endif
+mDNSlocal int getifaddrs_ipv4( struct ifaddrs **outAddrs );
-#if( TARGET_OS_WINDOWS_CE )
- mDNSlocal int getifaddrs_ce( struct ifaddrs **outAddrs );
-#endif
mDNSlocal DWORD GetPrimaryInterface();
mDNSlocal mStatus AddressToIndexAndMask( struct sockaddr * address, uint32_t * index, struct sockaddr * mask );
mDNSlocal struct ifaddrs* myGetIfAddrs(int refresh);
mDNSlocal OSStatus TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize );
mDNSlocal OSStatus WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize );
-mDNSlocal void FreeTCPSocket( TCPSocket *sock );
-mDNSlocal void FreeUDPSocket( UDPSocket * sock );
+mDNSlocal void TCPDidConnect( mDNS * const inMDNS, HANDLE event, void * context );
+mDNSlocal void TCPCanRead( TCPSocket * sock );
+mDNSlocal mStatus TCPBeginRecv( TCPSocket * sock );
+mDNSlocal void CALLBACK TCPEndRecv( DWORD error, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags );
+mDNSlocal void CALLBACK TCPFreeSocket( TCPSocket *sock );
+mDNSlocal OSStatus UDPBeginRecv( UDPSocket * socket );
+mDNSlocal void CALLBACK UDPEndRecv( DWORD err, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags );
+mDNSlocal void CALLBACK UDPFreeSocket( UDPSocket * sock );
mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa);
mDNSlocal void GetDDNSFQDN( domainname *const fqdn );
#ifdef UNICODE
#else
mDNSlocal void GetDDNSDomains( DNameListElem ** domains, LPCSTR lpSubKey );
#endif
-mDNSlocal void SetDomainSecrets( mDNS * const m );
+mDNSlocal void SetDomainSecrets( mDNS * const inMDNS );
mDNSlocal void SetDomainSecret( mDNS * const m, const domainname * inDomain );
-mDNSlocal void CheckFileShares( mDNS * const m );
-mDNSlocal mDNSu8 IsWOMPEnabled( const char * adapterName );
+mDNSlocal VOID CALLBACK CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue );
+mDNSlocal void CheckFileShares( mDNS * const inMDNS );
+mDNSlocal void SMBCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
+mDNSlocal mDNSu8 IsWOMPEnabledForAdapter( const char * adapterName );
+mDNSlocal void FreeSocketEventsForSocket( mDNS * const inMDNS, void * sock );
+mDNSlocal void FreeSocketEvents( mDNS * const inMDNS );
+mDNSlocal void TCPSocketEventHandler( mDNS * const inMDNS, void * v );
+mDNSlocal void UDPSocketEventHandler( mDNS * const inMDNS, void * v );
#ifdef __cplusplus
}
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;
+mDNSlocal UDPSocket * gUDPSocketList = NULL;
+mDNSlocal int gUDPSockets = 0;
+mDNSlocal BOOL gSocketEventsEnabled = FALSE;
+mDNSlocal GenLinkedList gSocketEvents;
#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
static HCRYPTPROV g_hProvider = ( ULONG_PTR ) NULL;
+typedef DNSServiceErrorType ( DNSSD_API *DNSServiceRegisterFunc )
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *name, /* may be NULL */
+ const char *regtype,
+ const char *domain, /* may be NULL */
+ const char *host, /* may be NULL */
+ uint16_t port,
+ uint16_t txtLen,
+ const void *txtRecord, /* may be NULL */
+ DNSServiceRegisterReply callBack, /* may be NULL */
+ void *context /* may be NULL */
+ );
+
+
+typedef void ( DNSSD_API *DNSServiceRefDeallocateFunc )( DNSServiceRef sdRef );
+
+mDNSlocal HMODULE gDNSSDLibrary = NULL;
+mDNSlocal DNSServiceRegisterFunc gDNSServiceRegister = NULL;
+mDNSlocal DNSServiceRefDeallocateFunc gDNSServiceRefDeallocate = NULL;
+mDNSlocal HANDLE gSMBThread = NULL;
+mDNSlocal HANDLE gSMBThreadRegisterEvent = NULL;
+mDNSlocal HANDLE gSMBThreadDeregisterEvent = NULL;
+mDNSlocal HANDLE gSMBThreadStopEvent = NULL;
+mDNSlocal HANDLE gSMBThreadQuitEvent = NULL;
+
+#define kSMBStopEvent ( WAIT_OBJECT_0 + 0 )
+#define kSMBRegisterEvent ( WAIT_OBJECT_0 + 1 )
+#define kSMBDeregisterEvent ( WAIT_OBJECT_0 + 2 )
+
+
#if 0
#pragma mark -
#pragma mark == Platform Support ==
struct sockaddr_in6 sa6;
int sa4len;
int sa6len;
+ DWORD size;
+ DWORD val;
dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" );
mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) );
if( !inMDNS->p ) inMDNS->p = &gMDNSPlatformSupport;
- inMDNS->p->interfaceListChangedSocket = kInvalidSocketRef;
+ inMDNS->p->mainThread = OpenThread( THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId() );
+ require_action( inMDNS->p->mainThread, exit, err = mStatus_UnknownErr );
+ inMDNS->p->checkFileSharesTimer = CreateWaitableTimer( NULL, FALSE, NULL );
+ require_action( inMDNS->p->checkFileSharesTimer, exit, err = mStatus_UnknownErr );
+ inMDNS->p->checkFileSharesTimeout = 10; // Retry time for CheckFileShares() in seconds
mDNSPlatformOneSecond = 1000; // Use milliseconds as the quantum of time
+ InitLinkedList( &gSocketEvents, offsetof( SocketEvent, next));
// Startup WinSock 2.2 or later.
inMDNS->CanReceiveUnicastOn5353 = CanReceiveUnicast();
- // Setup the HINFO HW/SW strings.
-
-#if ( MDNS_SET_HINFO_STRINGS )
- err = GetWindowsVersionString( (char *) &inMDNS->HIHardware.c[ 1 ], sizeof( inMDNS->HIHardware.c ) - 2 );
- check_noerr( err );
- // Note that GetWindowsVersionString guarantees that the resulting string is always null-terminated,
- // so the following strlen call is safe
- inMDNS->HIHardware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HIHardware.c[ 1 ] );
+ // Setup the HINFO HW strings.
+ //<rdar://problem/7245119> device-info should have model=Windows
+
+ strcpy_s( ( char* ) &inMDNS->HIHardware.c[ 1 ], sizeof( inMDNS->HIHardware.c ) - 2, "Windows" );
+ inMDNS->HIHardware.c[ 0 ] = ( mDNSu8 ) mDNSPlatformStrLen( &inMDNS->HIHardware.c[ 1 ] );
dlog( kDebugLevelInfo, DEBUG_NAME "HIHardware: %#s\n", inMDNS->HIHardware.c );
-
+
+ // Setup the HINFO SW strings.
+#if ( MDNS_SET_HINFO_STRINGS )
mDNS_snprintf( (char *) &inMDNS->HISoftware.c[ 1 ], sizeof( inMDNS->HISoftware.c ) - 2,
"mDNSResponder (%s %s)", __DATE__, __TIME__ );
inMDNS->HISoftware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HISoftware.c[ 1 ] );
dlog( kDebugLevelInfo, DEBUG_NAME "HISoftware: %#s\n", inMDNS->HISoftware.c );
#endif
-
+
+ // Set the thread global overlapped flag
+
+ val = 0;
+ err = setsockopt( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, ( char* ) &val, sizeof( val ) );
+ err = translate_errno( err != SOCKET_ERROR, WSAGetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
// Set up the IPv4 unicast socket
- inMDNS->p->unicastSock4 = INVALID_SOCKET;
- inMDNS->p->unicastSock4ReadEvent = NULL;
- inMDNS->p->unicastSock4RecvMsgPtr = NULL;
+ inMDNS->p->unicastSock4.fd = INVALID_SOCKET;
+ inMDNS->p->unicastSock4.recvMsgPtr = NULL;
+ inMDNS->p->unicastSock4.ifd = NULL;
+ inMDNS->p->unicastSock4.next = NULL;
+ inMDNS->p->unicastSock4.m = inMDNS;
#if ( MDNS_WINDOWS_ENABLE_IPV4 )
sa4.sin_family = AF_INET;
sa4.sin_addr.s_addr = INADDR_ANY;
- err = SetupSocket( inMDNS, (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4 );
+ err = SetupSocket( inMDNS, (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4.fd );
check_noerr( err );
sa4len = sizeof( sa4 );
- err = getsockname( inMDNS->p->unicastSock4, (struct sockaddr*) &sa4, &sa4len );
- require_noerr( err, exit );
- inMDNS->UnicastPort4.NotAnInteger = sa4.sin_port;
- inMDNS->p->unicastSock4ReadEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( inMDNS->p->unicastSock4ReadEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
- err = WSAEventSelect( inMDNS->p->unicastSock4, inMDNS->p->unicastSock4ReadEvent, FD_READ );
+ err = getsockname( inMDNS->p->unicastSock4.fd, (struct sockaddr*) &sa4, &sa4len );
require_noerr( err, exit );
-#if( !TARGET_OS_WINDOWS_CE )
- {
- DWORD size;
-
- err = WSAIoctl( inMDNS->p->unicastSock4, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID,
- sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock4RecvMsgPtr, sizeof( inMDNS->p->unicastSock4RecvMsgPtr ), &size, NULL, NULL );
+ inMDNS->p->unicastSock4.port.NotAnInteger = sa4.sin_port;
+ inMDNS->UnicastPort4 = inMDNS->p->unicastSock4.port;
+ err = WSAIoctl( inMDNS->p->unicastSock4.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock4.recvMsgPtr, sizeof( inMDNS->p->unicastSock4.recvMsgPtr ), &size, NULL, NULL );
- if ( err )
- {
- inMDNS->p->unicastSock4RecvMsgPtr = NULL;
- }
+ if ( err )
+ {
+ inMDNS->p->unicastSock4.recvMsgPtr = NULL;
}
-#endif
+
+ err = UDPBeginRecv( &inMDNS->p->unicastSock4 );
+ require_noerr( err, exit );
#endif
// Set up the IPv6 unicast socket
- inMDNS->p->unicastSock6 = INVALID_SOCKET;
- inMDNS->p->unicastSock6ReadEvent = NULL;
- inMDNS->p->unicastSock6RecvMsgPtr = NULL;
+ inMDNS->p->unicastSock6.fd = INVALID_SOCKET;
+ inMDNS->p->unicastSock6.recvMsgPtr = NULL;
+ inMDNS->p->unicastSock6.ifd = NULL;
+ inMDNS->p->unicastSock6.next = NULL;
+ inMDNS->p->unicastSock6.m = inMDNS;
#if ( MDNS_WINDOWS_ENABLE_IPV6 )
// This call will fail if the machine hasn't installed IPv6. In that case,
// the error will be WSAEAFNOSUPPORT.
- err = SetupSocket( inMDNS, (const struct sockaddr*) &sa6, zeroIPPort, &inMDNS->p->unicastSock6 );
+ err = SetupSocket( inMDNS, (const struct sockaddr*) &sa6, zeroIPPort, &inMDNS->p->unicastSock6.fd );
require_action( !err || ( err == WSAEAFNOSUPPORT ), exit, err = (mStatus) WSAGetLastError() );
- inMDNS->p->unicastSock6ReadEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( inMDNS->p->unicastSock6ReadEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
+ err = kNoErr;
// If we weren't able to create the socket (because IPv6 hasn't been installed) don't do this
- if ( inMDNS->p->unicastSock6 != INVALID_SOCKET )
+ if ( inMDNS->p->unicastSock6.fd != INVALID_SOCKET )
{
sa6len = sizeof( sa6 );
- err = getsockname( inMDNS->p->unicastSock6, (struct sockaddr*) &sa6, &sa6len );
- require_noerr( err, exit );
- inMDNS->UnicastPort6.NotAnInteger = sa6.sin6_port;
-
- err = WSAEventSelect( inMDNS->p->unicastSock6, inMDNS->p->unicastSock6ReadEvent, FD_READ );
+ err = getsockname( inMDNS->p->unicastSock6.fd, (struct sockaddr*) &sa6, &sa6len );
require_noerr( err, exit );
+ inMDNS->p->unicastSock6.port.NotAnInteger = sa6.sin6_port;
+ inMDNS->UnicastPort6 = inMDNS->p->unicastSock6.port;
-#if( !TARGET_OS_WINDOWS_CE )
- {
- DWORD size;
-
- err = WSAIoctl( inMDNS->p->unicastSock6, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID,
- sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock6RecvMsgPtr, sizeof( inMDNS->p->unicastSock6RecvMsgPtr ), &size, NULL, NULL );
+ err = WSAIoctl( inMDNS->p->unicastSock6.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock6.recvMsgPtr, sizeof( inMDNS->p->unicastSock6.recvMsgPtr ), &size, NULL, NULL );
- if ( err != 0 )
- {
- inMDNS->p->unicastSock6RecvMsgPtr = NULL;
- }
+ if ( err != 0 )
+ {
+ inMDNS->p->unicastSock6.recvMsgPtr = NULL;
}
-#endif
- }
-#endif
+ err = UDPBeginRecv( &inMDNS->p->unicastSock6 );
+ require_noerr( err, exit );
+ }
- // Set up the mDNS thread.
-
- err = SetupSynchronizationObjects( inMDNS );
- require_noerr( err, exit );
-
- err = SetupThread( inMDNS );
- require_noerr( err, exit );
+#endif
// Notify core of domain secret keys
mDNSCoreInitComplete( inMDNS, err );
- // See if we need to advertise file sharing
-
- inMDNS->p->smbRegistered = mDNSfalse;
- CheckFileShares( inMDNS );
exit:
- if( err )
+
+ if ( err )
{
mDNSPlatformClose( inMDNS );
}
+
dlog( kDebugLevelTrace, DEBUG_NAME "platform init done (err=%d %m)\n", err, err );
return( err );
}
dlog( kDebugLevelTrace, DEBUG_NAME "platform close\n" );
check( inMDNS );
-
- // Tear everything down in reverse order to how it was set up.
+
+ if ( gSMBThread != NULL )
+ {
+ dlog( kDebugLevelTrace, DEBUG_NAME "tearing down smb registration thread\n" );
+ SetEvent( gSMBThreadStopEvent );
- err = TearDownThread( inMDNS );
- check_noerr( err );
+ if ( WaitForSingleObject( gSMBThreadQuitEvent, 5 * 1000 ) == WAIT_OBJECT_0 )
+ {
+ if ( gSMBThreadQuitEvent )
+ {
+ CloseHandle( gSMBThreadQuitEvent );
+ gSMBThreadQuitEvent = NULL;
+ }
+
+ if ( gSMBThreadStopEvent )
+ {
+ CloseHandle( gSMBThreadStopEvent );
+ gSMBThreadStopEvent = NULL;
+ }
+
+ if ( gSMBThreadDeregisterEvent )
+ {
+ CloseHandle( gSMBThreadDeregisterEvent );
+ gSMBThreadDeregisterEvent = NULL;
+ }
+
+ if ( gSMBThreadRegisterEvent )
+ {
+ CloseHandle( gSMBThreadRegisterEvent );
+ gSMBThreadRegisterEvent = NULL;
+ }
+
+ if ( gDNSSDLibrary )
+ {
+ FreeLibrary( gDNSSDLibrary );
+ gDNSSDLibrary = NULL;
+ }
+ }
+ else
+ {
+ LogMsg( "Unable to stop SMBThread" );
+ }
+
+ inMDNS->p->smbFileSharing = mDNSfalse;
+ inMDNS->p->smbPrintSharing = mDNSfalse;
+ }
+
+ // Tear everything down in reverse order to how it was set up.
err = TearDownInterfaceList( inMDNS );
check_noerr( err );
check( !inMDNS->p->inactiveInterfaceList );
-
- err = TearDownSynchronizationObjects( inMDNS );
- check_noerr( err );
#if ( MDNS_WINDOWS_ENABLE_IPV4 )
- if ( inMDNS->p->unicastSock4ReadEvent )
- {
- CloseHandle( inMDNS->p->unicastSock4ReadEvent );
- inMDNS->p->unicastSock4ReadEvent = 0;
- }
-
- if ( IsValidSocket( inMDNS->p->unicastSock4 ) )
+ if ( inMDNS->p->unicastSock4.fd != INVALID_SOCKET )
{
- close_compat( inMDNS->p->unicastSock4 );
+ closesocket( inMDNS->p->unicastSock4.fd );
+ inMDNS->p->unicastSock4.fd = INVALID_SOCKET;
}
#endif
#if ( MDNS_WINDOWS_ENABLE_IPV6 )
- if ( inMDNS->p->unicastSock6ReadEvent )
- {
- CloseHandle( inMDNS->p->unicastSock6ReadEvent );
- inMDNS->p->unicastSock6ReadEvent = 0;
- }
-
- if ( IsValidSocket( inMDNS->p->unicastSock6 ) )
+ if ( inMDNS->p->unicastSock6.fd != INVALID_SOCKET )
{
- close_compat( inMDNS->p->unicastSock6 );
+ closesocket( inMDNS->p->unicastSock6.fd );
+ inMDNS->p->unicastSock6.fd = INVALID_SOCKET;
}
#endif
g_hAAPI32 = NULL;
}
+ // Clear out the APC queue
+
+ SetSocketEventsEnabled( inMDNS, TRUE );
+ while ( SleepEx( 0, TRUE ) == WAIT_IO_COMPLETION );
+ SetSocketEventsEnabled( inMDNS, FALSE );
+
WSACleanup();
dlog( kDebugLevelTrace, DEBUG_NAME "platform close done\n" );
mDNSexport void mDNSPlatformLock( const mDNS * const inMDNS )
{
- check( inMDNS );
-
- if ( inMDNS->p->lockInitialized )
- {
- EnterCriticalSection( &inMDNS->p->lock );
- }
+ ( void ) inMDNS;
}
//===========================================================================================================================
mDNSexport void mDNSPlatformUnlock( const mDNS * const inMDNS )
{
- check( inMDNS );
- check( inMDNS->p );
-
- if ( inMDNS->p->lockInitialized )
- {
- check( inMDNS->p->threadID );
-
- // Signal a wakeup event if when called from a task other than the mDNS task since if we are called from mDNS task,
- // we'll loop back and call mDNS_Execute anyway. Signaling is needed to re-evaluate the wakeup via mDNS_Execute.
-
- if( GetCurrentThreadId() != inMDNS->p->threadID )
- {
- BOOL wasSet;
-
- wasSet = SetEvent( inMDNS->p->wakeupEvent );
- check_translated_errno( wasSet, GetLastError(), kUnknownErr );
- }
- LeaveCriticalSection( &inMDNS->p->lock );
- }
+ ( void ) inMDNS;
}
//===========================================================================================================================
{
id = mDNSInterface_LocalOnly;
}
+ /* uncomment if Windows ever supports P2P
+ else if( inIndex == kDNSServiceInterfaceIndexP2P )
+ {
+ id = mDNSInterface_P2P;
+ }
+ */
else if( inIndex != 0 )
{
mDNSInterfaceData * ifd;
{
index = (mDNSu32) kDNSServiceInterfaceIndexLocalOnly;
}
+ /* uncomment if Windows ever supports P2P
+ else if( inID == mDNSInterface_P2P )
+ {
+ index = (mDNSu32) kDNSServiceInterfaceIndexP2P;
+ }
+ */
else if( inID )
{
mDNSInterfaceData * ifd;
return( index );
}
+
//===========================================================================================================================
// mDNSPlatformTCPSocket
//===========================================================================================================================
sock = (TCPSocket *) malloc( sizeof( TCPSocket ) );
require_action( sock, exit, err = mStatus_NoMemoryErr );
mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
-
sock->fd = INVALID_SOCKET;
sock->flags = flags;
+ sock->m = m;
mDNSPlatformMemZero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
if ( err && sock )
{
- FreeTCPSocket( sock );
+ TCPFreeSocket( sock );
sock = mDNSNULL;
}
mStatus
mDNSPlatformTCPConnect
(
- TCPSocket * sock,
+ TCPSocket * sock,
const mDNSAddr * inDstIP,
mDNSOpaque16 inDstPort,
+ domainname * hostname,
mDNSInterfaceID inInterfaceID,
TCPConnectionCallback inCallback,
void * inContext
)
{
struct sockaddr_in saddr;
+ ( void ) hostname;
mStatus err = mStatus_NoError;
DEBUG_UNUSED( inInterfaceID );
-
+
if ( inDstIP->type != mDNSAddrType_IPv4 )
{
LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: operation not supported");
// Setup connection data object
- sock->callback = inCallback;
- sock->context = inContext;
+ sock->readEventHandler = TCPCanRead;
+ sock->userCallback = inCallback;
+ sock->userContext = inContext;
mDNSPlatformMemZero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
err = connect( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr ) );
require_action( !err || ( WSAGetLastError() == WSAEWOULDBLOCK ), exit, err = mStatus_ConnFailed );
- sock->connected = !err ? TRUE : FALSE;
- sock->pendingEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( sock->pendingEvent, GetLastError(), mStatus_UnknownErr );
- require_noerr( err, exit );
- err = WSAEventSelect( sock->fd, sock->pendingEvent, FD_CONNECT|FD_READ|FD_CLOSE );
- require_noerr( err, exit );
+ sock->connected = !err ? TRUE : FALSE;
- // Bookkeeping
+ if ( sock->connected )
+ {
+ err = TCPAddSocket( sock->m, sock );
+ require_noerr( err, exit );
+ }
+ else
+ {
+ require_action( sock->m->p->registerWaitableEventFunc != NULL, exit, err = mStatus_ConnFailed );
- sock->next = gTCPConnectionList;
- gTCPConnectionList = sock;
- gTCPConnections++;
- gWaitListChanged = TRUE;
+ sock->connectEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( sock->connectEvent, GetLastError(), mStatus_UnknownErr );
+ require_noerr( err, exit );
+
+ err = WSAEventSelect( sock->fd, sock->connectEvent, FD_CONNECT );
+ require_noerr( err, exit );
+
+ err = sock->m->p->registerWaitableEventFunc( sock->m, sock->connectEvent, sock, TCPDidConnect );
+ require_noerr( err, exit );
+ }
exit:
mDNSexport void mDNSPlatformTCPCloseConnection( TCPSocket *sock )
{
- TCPSocket * inserted = gTCPConnectionList;
- TCPSocket * last = NULL;
+ check( sock );
- while ( inserted )
+ if ( sock->connectEvent && sock->m->p->unregisterWaitableEventFunc )
{
- if ( inserted == sock )
- {
- if ( last == NULL )
- {
- gTCPConnectionList = inserted->next;
- }
- else
- {
- last->next = inserted->next;
- }
-
- gTCPConnections--;
- gWaitListChanged = TRUE;
+ sock->m->p->unregisterWaitableEventFunc( sock->m, sock->connectEvent );
+ }
- break;
- }
+ if ( sock->fd != INVALID_SOCKET )
+ {
+ closesocket( sock->fd );
+ sock->fd = INVALID_SOCKET;
- last = inserted;
- inserted = inserted->next;
+ QueueUserAPC( ( PAPCFUNC ) TCPFreeSocket, sock->m->p->mainThread, ( ULONG_PTR ) sock );
}
- FreeTCPSocket( sock );
+ FreeSocketEventsForSocket( sock->m, sock );
}
//===========================================================================================================================
mDNSexport long mDNSPlatformReadTCP( TCPSocket *sock, void *inBuffer, unsigned long inBufferSize, mDNSBool * closed )
{
- int nread;
+ unsigned long bytesLeft;
+ int wsaError;
+ long ret;
- nread = recv( sock->fd, inBuffer, inBufferSize, 0);
+ *closed = sock->closed;
+ wsaError = sock->lastError;
+ ret = -1;
- if ( nread < 0 )
+ if ( *closed )
+ {
+ ret = 0;
+ }
+ else if ( sock->lastError == 0 )
{
- if ( WSAGetLastError() == WSAEWOULDBLOCK )
+ // First check to see if we have any data left in our buffer
+
+ bytesLeft = ( DWORD ) ( sock->eptr - sock->bptr );
+
+ if ( bytesLeft )
{
- nread = 0;
+ unsigned long bytesToCopy = ( bytesLeft < inBufferSize ) ? bytesLeft : inBufferSize;
+
+ memcpy( inBuffer, sock->bptr, bytesToCopy );
+ sock->bptr += bytesToCopy;
+
+ ret = bytesToCopy;
+
+ if ( bytesLeft == bytesToCopy )
+ {
+ sock->lastError = TCPBeginRecv( sock );
+
+ // If we can't immediately queue up another read, abort the connection
+ // now, even if we successfully wrote bytes to the buffer.
+ // We don't expect this to happen unless something is seriously borked.
+ // If we run into this in the real world, we should consider queuing up
+ // a user APC function to defer an explicit callback to the read event handler
+ // to inform the consumer of the problem.
+
+ if ( sock->lastError )
+ {
+ dlog( kDebugLevelError, DEBUG_NAME "TCPBeginRecv failed with error %d\n", sock->lastError );
+ wsaError = sock->lastError;
+ ret = -1;
+ }
+ }
}
else
{
- nread = -1;
+ wsaError = WSAEWOULDBLOCK;
}
}
- else if ( !nread )
- {
- *closed = mDNStrue;
- }
-
- return nread;
+
+ // Always set the last winsock error, so that we don't inadvertently use a previous one
+
+ WSASetLastError( wsaError );
+
+ return ret;
}
+
//===========================================================================================================================
// mDNSPlatformWriteTCP
//===========================================================================================================================
//===========================================================================================================================
mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock )
- {
- return ( int ) sock->fd;
- }
+{
+ return ( int ) sock->fd;
+}
+
-
//===========================================================================================================================
-// mDNSPlatformUDPSocket
+// TCPAddConnection
//===========================================================================================================================
-mDNSexport UDPSocket* mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
+mStatus TCPAddSocket( mDNS * const inMDNS, TCPSocket *sock )
{
- UDPSocket* sock = NULL;
- mDNSIPPort port = requestedport;
- mStatus err = mStatus_NoError;
- unsigned i;
+ mStatus err;
- // Setup connection data object
+ ( void ) inMDNS;
- sock = (struct UDPSocket_struct*) malloc( sizeof( struct UDPSocket_struct ) );
- require_action( sock, exit, err = mStatus_NoMemoryErr );
- memset( sock, 0, sizeof( struct UDPSocket_struct ) );
+ dlog( kDebugLevelChatty, DEBUG_NAME "adding TCPSocket 0x%x:%d\n", sock, sock->fd );
+ err = TCPBeginRecv( sock );
+ require_noerr( err, exit );
- // Create the socket
+exit:
- sock->recvMsgPtr = m->p->unicastSock4RecvMsgPtr;
- sock->dstAddr = m->p->unicastSock4DestAddr;
- sock->sock = INVALID_SOCKET;
+ return err;
+}
- // Try at most 10000 times to get a unique random port
- for (i=0; i<10000; i++)
+//===========================================================================================================================
+// TCPDidConnect
+//===========================================================================================================================
+
+mDNSlocal void TCPDidConnect( mDNS * const inMDNS, HANDLE event, void * context )
+{
+ TCPSocket * sock = ( TCPSocket* ) context;
+ TCPConnectionCallback callback = NULL;
+ WSANETWORKEVENTS sockEvent;
+ int err = kNoErr;
+
+ if ( inMDNS->p->unregisterWaitableEventFunc )
{
- struct sockaddr_in saddr;
+ inMDNS->p->unregisterWaitableEventFunc( inMDNS, event );
+ }
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = 0;
+ if ( sock )
+ {
+ callback = ( TCPConnectionCallback ) sock->userCallback;
+ err = WSAEnumNetworkEvents( sock->fd, sock->connectEvent, &sockEvent );
+ require_noerr( err, exit );
+ require_action( sockEvent.lNetworkEvents & FD_CONNECT, exit, err = mStatus_UnknownErr );
+ require_action( sockEvent.iErrorCode[ FD_CONNECT_BIT ] == 0, exit, err = sockEvent.iErrorCode[ FD_CONNECT_BIT ] );
- // The kernel doesn't do cryptographically strong random port
- // allocation, so we do it ourselves here
+ sock->connected = mDNStrue;
- if (mDNSIPPortIsZero(requestedport))
+ if ( sock->fd != INVALID_SOCKET )
{
- port = mDNSOpaque16fromIntVal( ( mDNSu16 ) ( 0xC000 + mDNSRandom(0x3FFF) ) );
+ err = TCPAddSocket( sock->m, sock );
+ require_noerr( err, exit );
}
- saddr.sin_port = port.NotAnInteger;
+ if ( callback )
+ {
+ callback( sock, sock->userContext, TRUE, 0 );
+ }
+ }
+
+exit:
+
+ if ( err && callback )
+ {
+ callback( sock, sock->userContext, TRUE, err );
+ }
+}
+
+
+
+//===========================================================================================================================
+// TCPCanRead
+//===========================================================================================================================
+
+mDNSlocal void TCPCanRead( TCPSocket * sock )
+{
+ TCPConnectionCallback callback = ( TCPConnectionCallback ) sock->userCallback;
+
+ if ( callback )
+ {
+ callback( sock, sock->userContext, mDNSfalse, sock->lastError );
+ }
+}
+
+
+//===========================================================================================================================
+// TCPBeginRecv
+//===========================================================================================================================
+
+mDNSlocal mStatus TCPBeginRecv( TCPSocket * sock )
+{
+ DWORD bytesReceived = 0;
+ DWORD flags = 0;
+ mStatus err;
+
+ ZeroMemory( &sock->overlapped, sizeof( sock->overlapped ) );
+ sock->overlapped.hEvent = sock;
+
+ sock->wbuf.buf = ( char* ) sock->buf;
+ sock->wbuf.len = sizeof( sock->buf );
+
+ err = WSARecv( sock->fd, &sock->wbuf, 1, &bytesReceived, &flags, &sock->overlapped, ( LPWSAOVERLAPPED_COMPLETION_ROUTINE ) TCPEndRecv );
+ err = translate_errno( ( err == 0 ) || ( WSAGetLastError() == WSA_IO_PENDING ), WSAGetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+exit:
+
+ return err;
+}
+
+
+//===========================================================================================================================
+// TCPEndRecv
+//===========================================================================================================================
+
+mDNSlocal void CALLBACK TCPEndRecv( DWORD error, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags )
+{
+ TCPSocket * sock;
+
+ ( void ) flags;
+
+ sock = ( overlapped != NULL ) ? overlapped->hEvent : NULL;
+
+ if ( sock && ( sock->fd != INVALID_SOCKET ) )
+ {
+ // <rdar://problem/7532492> mDNSResponder gets locking errors on Windows
+ //
+ // There seems to be a bug in WinSock with respect to Alertable I/O. According
+ // to MSDN <http://msdn.microsoft.com/en-us/library/aa363772(VS.85).aspx>, Alertable I/O
+ // callbacks will only be invoked during the following calls (when the caller sets
+ // the appropriate flag):
+ //
+ // - SleepEx
+ // - WaitForSingleObjectEx
+ // - WaitForMultipleObjectsEx
+ // - SignalObjectAndWait
+ // - MsgWaitForMultipleObjectsEx
+ //
+ // However, we have seen callbacks be invoked during calls to bind() (and maybe others).
+ // To workaround this, we set the gSocketEventsEnabled flag to be TRUE only when it's okay
+ // to directly call the readEventHandler. Otherwise we queue the packet up and
+ // dispatch it later.
+
+ if ( gSocketEventsEnabled && !gSocketEvents.Head )
+ {
+ sock->lastError = error;
+
+ if ( !error )
+ {
+ if ( bytesTransferred )
+ {
+ sock->bptr = sock->buf;
+ sock->eptr = sock->buf + bytesTransferred;
+ }
+ else
+ {
+ sock->closed = TRUE;
+ }
+ }
+
+ if ( sock->readEventHandler != NULL )
+ {
+ // Turn off socket events before calling the readEventHandler.
+ // This will prevent reentrancy problems.
+ //
+ // Don't forget to reenable socket events afterwards.
+
+ SetSocketEventsEnabled( sock->m, FALSE );
+ sock->readEventHandler( sock );
+ SetSocketEventsEnabled( sock->m, TRUE );
+ }
+ }
+ else
+ {
+ TCPSocketEvent * event;
+
+ event = malloc( sizeof( TCPSocketEvent ) );
+ require_action( event, exit, error = ( DWORD ) kNoMemoryErr );
+ event->super.sock = sock;
+ event->super.handler = &TCPSocketEventHandler;
+ event->super.next = NULL;
+ event->error = error;
+ event->bytesTransferred = bytesTransferred;
+
+ if ( bytesTransferred )
+ {
+ memcpy( event->buf, sock->buf, bytesTransferred );
+ }
+
+ AddToTail( &gSocketEvents, event );
+ }
+ }
+
+exit:
+
+ return;
+}
+
+
+//===========================================================================================================================
+// mDNSPlatformUDPSocket
+//===========================================================================================================================
+
+mDNSexport UDPSocket* mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
+{
+ UDPSocket* sock = NULL;
+ mDNSIPPort port = requestedport;
+ mStatus err = mStatus_NoError;
+ unsigned i;
+
+ // Setup connection data object
+
+ sock = ( UDPSocket* ) malloc(sizeof( UDPSocket ) );
+ require_action( sock, exit, err = mStatus_NoMemoryErr );
+ memset( sock, 0, sizeof( UDPSocket ) );
+
+ // Create the socket
+
+ sock->fd = INVALID_SOCKET;
+ sock->recvMsgPtr = m->p->unicastSock4.recvMsgPtr;
+ sock->addr = m->p->unicastSock4.addr;
+ sock->ifd = NULL;
+ sock->m = m;
- err = SetupSocket(m, ( struct sockaddr* ) &saddr, port, &sock->sock );
+ // Try at most 10000 times to get a unique random port
+
+ for (i=0; i<10000; i++)
+ {
+ struct sockaddr_in saddr;
+
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = 0;
+
+ // The kernel doesn't do cryptographically strong random port
+ // allocation, so we do it ourselves here
+
+ if (mDNSIPPortIsZero(requestedport))
+ {
+ port = mDNSOpaque16fromIntVal( ( mDNSu16 ) ( 0xC000 + mDNSRandom(0x3FFF) ) );
+ }
+
+ saddr.sin_port = port.NotAnInteger;
+
+ err = SetupSocket(m, ( struct sockaddr* ) &saddr, port, &sock->fd );
if (!err) break;
}
sock->port = port;
- // Set it up with Windows Eventing
+ // Arm the completion routine
- 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 );
+ err = UDPBeginRecv( sock );
+ require_noerr( err, exit );
// Bookkeeping
sock->next = gUDPSocketList;
gUDPSocketList = sock;
gUDPSockets++;
- gWaitListChanged = TRUE;
exit:
- if ( err )
+ if ( err && sock )
{
- if ( sock )
- {
- FreeUDPSocket( sock );
- sock = NULL;
- }
+ UDPFreeSocket( sock );
+ sock = NULL;
}
return sock;
last->next = sock->next;
}
- FreeUDPSocket( sock );
+ // Alertable I/O is great, except not so much when it comes to closing
+ // the socket. Anything that has been previously queued for this socket
+ // will stay in the queue after you close the socket. This is problematic
+ // for obvious reasons. So we'll attempt to workaround this by closing
+ // the socket which will prevent any further queued packets and then not calling
+ // UDPFreeSocket directly, but by queueing it using QueueUserAPC. The queues
+ // are FIFO, so that will execute *after* any other previous items in the queue
+ //
+ // UDPEndRecv will check if the socket is valid, and if not, it will ignore
+ // the packet
+
+ closesocket( sock->fd );
+ sock->fd = INVALID_SOCKET;
+
+ QueueUserAPC( ( PAPCFUNC ) UDPFreeSocket, sock->m->p->mainThread, ( ULONG_PTR ) sock );
+ FreeSocketEventsForSocket( sock->m, sock );
gUDPSockets--;
- gWaitListChanged = TRUE;
break;
}
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;
+ sendingsocket = ifd ? ifd->sock.fd : inMDNS->p->unicastSock4.fd;
- if (inSrcSocket) { sendingsocket = inSrcSocket->sock; debugf("mDNSPlatformSendUDP using port %d, static port %d, sock %d", mDNSVal16(inSrcSocket->port), inMDNS->p->unicastSock4, sendingsocket); }
+ if (inSrcSocket) { sendingsocket = inSrcSocket->fd; debugf("mDNSPlatformSendUDP using port %d, static port %d, sock %d", mDNSVal16(inSrcSocket->port), inMDNS->p->unicastSock4.fd, sendingsocket); }
}
else if( inDstIP->type == mDNSAddrType_IPv6 )
{
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;
+ sendingsocket = ifd ? ifd->sock.fd : inMDNS->p->unicastSock6.fd;
}
else
{
DEBUG_UNUSED( InterfaceID );
}
-mDNSexport void mDNSPlatformSetLocalARP( const mDNSv4Addr * const tpa, const mDNSEthAddr * const tha, mDNSInterfaceID InterfaceID )
+mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
{
DEBUG_UNUSED( tpa );
DEBUG_UNUSED( tha );
mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
{
- fprintf( stderr, msg );
+ dlog( kDebugLevelInfo, "%s\n", msg );
}
-mDNSexport void mDNSPlatformWriteLogMsg( const char * ident, const char * msg, int flags )
+mDNSexport void mDNSPlatformWriteLogMsg( const char * ident, const char * msg, mDNSLogLevel_t loglevel )
{
+ extern mDNS mDNSStorage;
+ int type;
+
DEBUG_UNUSED( ident );
- DEBUG_UNUSED( msg );
- DEBUG_UNUSED( flags );
+
+ type = EVENTLOG_ERROR_TYPE;
+
+ switch (loglevel)
+ {
+ case MDNS_LOG_MSG: type = EVENTLOG_ERROR_TYPE; break;
+ case MDNS_LOG_OPERATION: type = EVENTLOG_WARNING_TYPE; break;
+ case MDNS_LOG_SPS: type = EVENTLOG_INFORMATION_TYPE; break;
+ case MDNS_LOG_INFO: type = EVENTLOG_INFORMATION_TYPE; break;
+ case MDNS_LOG_DEBUG: type = EVENTLOG_INFORMATION_TYPE; break;
+ default:
+ fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel);
+ fflush(stderr);
+ }
+
+ mDNSStorage.p->reportStatusFunc( type, msg );
+ dlog( kDebugLevelInfo, "%s\n", msg );
}
mDNSexport void mDNSPlatformSourceAddrForDest( mDNSAddr * const src, const mDNSAddr * const dst )
//===========================================================================================================================
// This routine needs to be called whenever the system secrets database changes.
-// We call it from ProcessingThreadDynDNSConfigChanged and mDNSPlatformInit
+// We call it from DynDNSConfigDidChange and mDNSPlatformInit
-mDNSlocal void
+void
SetDomainSecrets( mDNS * const m )
{
DomainAuthInfo *ptr;
{
// Found one that will work
+ if ( pAdapter->AddressLength == sizeof( m->PrimaryMAC ) )
+ {
+ memcpy( &m->PrimaryMAC, pAdapter->Address, pAdapter->AddressLength );
+ }
+
found = TRUE;
break;
}
//===========================================================================================================================
// debugf_
//===========================================================================================================================
-
#if( MDNS_DEBUGMSGS )
mDNSexport void debugf_( const char *inFormat, ... )
{
}
#endif
-//===========================================================================================================================
-// LogMsg
-//===========================================================================================================================
-
-/*
-mDNSexport void LogMsg( const char *inFormat, ... )
-{
- char buffer[ 512 ];
- va_list args;
- mDNSu32 length;
-
- va_start( args, inFormat );
- length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
- va_end( args );
-
- dlog( kDebugLevelWarning, "%s\n", buffer );
-}
-*/
#if 0
#pragma mark -
#pragma mark == Platform Internals ==
#endif
-//===========================================================================================================================
-// SetupSynchronizationObjects
-//===========================================================================================================================
-
-mDNSlocal mStatus SetupSynchronizationObjects( mDNS * const inMDNS )
-{
- mStatus err;
-
- InitializeCriticalSection( &inMDNS->p->lock );
- inMDNS->p->lockInitialized = mDNStrue;
-
- inMDNS->p->cancelEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( inMDNS->p->cancelEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- inMDNS->p->quitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( inMDNS->p->quitEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- inMDNS->p->interfaceListChangedEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( inMDNS->p->interfaceListChangedEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- inMDNS->p->wakeupEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( inMDNS->p->wakeupEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
-exit:
- if( err )
- {
- TearDownSynchronizationObjects( inMDNS );
- }
- return( err );
-}
-
-//===========================================================================================================================
-// TearDownSynchronizationObjects
-//===========================================================================================================================
-
-mDNSlocal mStatus TearDownSynchronizationObjects( mDNS * const inMDNS )
-{
- if( inMDNS->p->quitEvent )
- {
- CloseHandle( inMDNS->p->quitEvent );
- inMDNS->p->quitEvent = 0;
- }
- if( inMDNS->p->cancelEvent )
- {
- CloseHandle( inMDNS->p->cancelEvent );
- inMDNS->p->cancelEvent = 0;
- }
- if( inMDNS->p->interfaceListChangedEvent )
- {
- CloseHandle( inMDNS->p->interfaceListChangedEvent );
- inMDNS->p->interfaceListChangedEvent = 0;
- }
- if( inMDNS->p->wakeupEvent )
- {
- CloseHandle( inMDNS->p->wakeupEvent );
- inMDNS->p->wakeupEvent = 0;
- }
- if( inMDNS->p->lockInitialized )
- {
- DeleteCriticalSection( &inMDNS->p->lock );
- inMDNS->p->lockInitialized = mDNSfalse;
- }
- return( mStatus_NoError );
-}
-
//===========================================================================================================================
// SetupNiceName
//===========================================================================================================================
-mDNSlocal mStatus SetupNiceName( mDNS * const inMDNS )
+mStatus SetupNiceName( mDNS * const inMDNS )
{
- mStatus err = 0;
+ HKEY descKey = NULL;
char utf8[ 256 ];
+ LPCTSTR s;
+ LPWSTR joinName;
+ NETSETUP_JOIN_STATUS joinStatus;
+ mStatus err = 0;
+ DWORD namelen;
+ BOOL ok;
check( inMDNS );
utf8[0] = '\0';
// First try and open the registry key that contains the computer description value
- if (inMDNS->p->descKey == NULL)
- {
- LPCTSTR s = TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters");
- err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &inMDNS->p->descKey);
- check_translated_errno( err == 0, errno_compat(), kNameErr );
-
- if (err)
- {
- inMDNS->p->descKey = NULL;
- }
- }
+ s = TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters");
+ err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &descKey);
+ check_translated_errno( err == 0, errno_compat(), kNameErr );
- // if we opened it...
- if (inMDNS->p->descKey != NULL)
+ if ( !err )
{
TCHAR desc[256];
DWORD descSize = sizeof( desc );
// look for the computer description
- err = RegQueryValueEx(inMDNS->p->descKey, TEXT("srvcomment"), 0, NULL, (LPBYTE) &desc, &descSize);
+ err = RegQueryValueEx( descKey, TEXT("srvcomment"), 0, NULL, (LPBYTE) &desc, &descSize);
if ( !err )
{
if ( err || ( utf8[ 0 ] == '\0' ) )
{
TCHAR hostname[256];
- DWORD hostnameLen = sizeof( hostname ) / sizeof( TCHAR );
- BOOL ok;
+
+ namelen = sizeof( hostname ) / sizeof( TCHAR );
- ok = GetComputerNameExW( ComputerNamePhysicalDnsHostname, hostname, &hostnameLen );
+ ok = GetComputerNameExW( ComputerNamePhysicalDnsHostname, hostname, &namelen );
err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
check_noerr( err );
dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] );
+ if ( descKey )
+ {
+ RegCloseKey( descKey );
+ }
+
+ ZeroMemory( inMDNS->p->nbname, sizeof( inMDNS->p->nbname ) );
+ ZeroMemory( inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
+
+ namelen = sizeof( inMDNS->p->nbname );
+ ok = GetComputerNameExA( ComputerNamePhysicalNetBIOS, inMDNS->p->nbname, &namelen );
+ check( ok );
+ if ( ok ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios name \"%s\"\n", inMDNS->p->nbname );
+
+ err = NetGetJoinInformation( NULL, &joinName, &joinStatus );
+ check ( err == NERR_Success );
+ if ( err == NERR_Success )
+ {
+ if ( ( joinStatus == NetSetupWorkgroupName ) || ( joinStatus == NetSetupDomainName ) )
+ {
+ err = TCHARtoUTF8( joinName, inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
+ check( !err );
+ if ( !err ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios domain/workgroup \"%s\"\n", inMDNS->p->nbdomain );
+ }
+
+ NetApiBufferFree( joinName );
+ joinName = NULL;
+ }
+
+ err = 0;
+
return( err );
}
// SetupInterfaceList
//===========================================================================================================================
-mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS )
+mStatus SetupInterfaceList( mDNS * const inMDNS )
{
mStatus err;
mDNSInterfaceData ** next;
check( inMDNS->p );
inMDNS->p->registeredLoopback4 = mDNSfalse;
- inMDNS->p->nextDHCPLeaseExpires = 0xFFFFFFFF;
- inMDNS->p->womp = mDNSfalse;
+ inMDNS->p->nextDHCPLeaseExpires = 0x7FFFFFFF;
addrs = NULL;
foundv4 = mDNSfalse;
foundv6 = mDNSfalse;
err = SetupName( inMDNS );
check_noerr( err );
-
- // Set up the interface list change notification.
-
- err = SetupNotifications( inMDNS );
- check_noerr( err );
-
+
// Set up IPv4 interface(s). We have to set up IPv4 first so any IPv6 interface with an IPv4-routable address
// can refer to the IPv4 interface when it registers to allow DNS AAAA records over the IPv4 interface.
if ( !foundUnicastSock4DestAddr )
{
- inMDNS->p->unicastSock4DestAddr = ifd->interfaceInfo.ip;
+ inMDNS->p->unicastSock4.addr = ifd->interfaceInfo.ip;
foundUnicastSock4DestAddr = TRUE;
}
if ( !foundUnicastSock6DestAddr )
{
- inMDNS->p->unicastSock6DestAddr = ifd->interfaceInfo.ip;
+ inMDNS->p->unicastSock6.addr = ifd->interfaceInfo.ip;
foundUnicastSock6DestAddr = TRUE;
}
if ( !foundUnicastSock4DestAddr )
{
- inMDNS->p->unicastSock4DestAddr = ifd->defaultAddr;
+ inMDNS->p->unicastSock4.addr = ifd->sock.addr;
foundUnicastSock4DestAddr = TRUE;
}
#endif
if ( !foundUnicastSock6DestAddr )
{
- inMDNS->p->unicastSock6DestAddr = ifd->defaultAddr;
+ inMDNS->p->unicastSock6.addr = ifd->sock.addr;
foundUnicastSock6DestAddr = TRUE;
}
#endif
++inMDNS->p->interfaceCount;
}
+ CheckFileShares( inMDNS );
+
exit:
if( err )
{
// TearDownInterfaceList
//===========================================================================================================================
-mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS )
+mStatus TearDownInterfaceList( mDNS * const inMDNS )
{
- mStatus err;
mDNSInterfaceData ** p;
mDNSInterfaceData * ifd;
dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list\n" );
check( inMDNS );
check( inMDNS->p );
+
+ // Free any pending events received.
+
+ FreeSocketEvents( inMDNS );
// Free any interfaces that were previously marked inactive and are no longer referenced by the mDNS cache.
// Interfaces are marked inactive, but not deleted immediately if they were still referenced by the mDNS cache
dlog( kDebugLevelInfo, DEBUG_NAME "freeing unreferenced, inactive interface %#p %#a\n", ifd, &ifd->interfaceInfo.ip );
*p = ifd->next;
- free( ifd );
+
+ QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) ifd );
}
-
- // Tear down interface list change notifications.
-
- err = TearDownNotifications( inMDNS );
- check_noerr( err );
-
+
// Tear down all the interfaces.
while( inMDNS->p->interfaceList )
{
mDNSInterfaceData * ifd;
mDNSInterfaceData * p;
- SocketRef sock;
mStatus err;
ifd = NULL;
ifd = (mDNSInterfaceData *) calloc( 1, sizeof( *ifd ) );
require_action( ifd, exit, err = mStatus_NoMemoryErr );
- ifd->sock = kInvalidSocketRef;
+ ifd->sock.fd = kInvalidSocketRef;
+ ifd->sock.ifd = ifd;
+ ifd->sock.next = NULL;
+ ifd->sock.m = inMDNS;
ifd->index = inIFA->ifa_extra.index;
ifd->scopeID = inIFA->ifa_extra.index;
check( strlen( inIFA->ifa_name ) < sizeof( ifd->name ) );
if( ifd->interfaceInfo.McastTxRx )
{
- err = SetupSocket( inMDNS, inIFA->ifa_addr, MulticastDNSPort, &sock );
+ DWORD size;
+
+ err = SetupSocket( inMDNS, inIFA->ifa_addr, MulticastDNSPort, &ifd->sock.fd );
require_noerr( err, exit );
- ifd->sock = sock;
- ifd->defaultAddr = ( inIFA->ifa_addr->sa_family == AF_INET6 ) ? AllDNSLinkGroup_v6 : AllDNSLinkGroup_v4;
+ ifd->sock.addr = ( inIFA->ifa_addr->sa_family == AF_INET6 ) ? AllDNSLinkGroup_v6 : AllDNSLinkGroup_v4;
+ ifd->sock.port = MulticastDNSPort;
// Get a ptr to the WSARecvMsg function, if supported. Otherwise, we'll fallback to recvfrom.
- #if( !TARGET_OS_WINDOWS_CE )
- {
- DWORD size;
-
- err = WSAIoctl( sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ),
- &ifd->wsaRecvMsgFunctionPtr, sizeof( ifd->wsaRecvMsgFunctionPtr ), &size, NULL, NULL );
+ err = WSAIoctl( ifd->sock.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &ifd->sock.recvMsgPtr, sizeof( ifd->sock.recvMsgPtr ), &size, NULL, NULL );
- if ( err )
- {
- ifd->wsaRecvMsgFunctionPtr = NULL;
- }
+ if ( err )
+ {
+ ifd->sock.recvMsgPtr = NULL;
}
- #endif
-
- // Set up the read pending event and associate it so we can block until data is available for this socket.
-
- ifd->readPendingEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( ifd->readPendingEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- err = WSAEventSelect( ifd->sock, ifd->readPendingEvent, FD_READ );
- require_noerr( err, exit );
- }
- else
- {
- // Create a placeholder event so WaitForMultipleObjects Handle slot for this interface is valid.
-
- ifd->readPendingEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( ifd->readPendingEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
}
if ( inIFA->ifa_dhcpEnabled && ( inIFA->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
ifd->interfaceInfo.NetWake = inIFA->ifa_womp;
- if ( ifd->interfaceInfo.NetWake )
- {
- inMDNS->p->womp = TRUE;
- }
-
// Register this interface with mDNS.
err = SockAddrToMDNSAddr( inIFA->ifa_addr, &ifd->interfaceInfo.ip, NULL );
err = SockAddrToMDNSAddr( inIFA->ifa_netmask, &ifd->interfaceInfo.mask, NULL );
require_noerr( err, exit );
+
+ memcpy( ifd->interfaceInfo.MAC.b, inIFA->ifa_physaddr, sizeof( ifd->interfaceInfo.MAC.b ) );
ifd->interfaceInfo.Advertise = ( mDNSu8 ) inMDNS->AdvertiseLocalAddresses;
-
- err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, mDNSfalse );
+
+ if ( ifd->sock.fd != kInvalidSocketRef )
+ {
+ err = UDPBeginRecv( &ifd->sock );
+ require_noerr( err, exit );
+ }
+
+ err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, mDNSfalse );
require_noerr( err, exit );
ifd->hostRegistered = mDNStrue;
//===========================================================================================================================
mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD )
-{
- SocketRef sock;
-
+{
check( inMDNS );
check( inIFD );
// Tear down the multicast socket.
- if( inIFD->readPendingEvent )
- {
- CloseHandle( inIFD->readPendingEvent );
- inIFD->readPendingEvent = 0;
- }
-
- sock = inIFD->sock;
- inIFD->sock = kInvalidSocketRef;
- if( IsValidSocket( sock ) )
+ if ( inIFD->sock.fd != INVALID_SOCKET )
{
- close_compat( sock );
+ closesocket( inIFD->sock.fd );
+ inIFD->sock.fd = INVALID_SOCKET;
}
// If the interface is still referenced by items in the mDNS cache then put it on the inactive list. This keeps
else
{
dlog( kDebugLevelInfo, DEBUG_NAME "freeing interface %#p %#a immediately\n", inIFD, &inIFD->interfaceInfo.ip );
- free( inIFD );
+ QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) inIFD );
}
+
return( mStatus_NoError );
}
+mDNSlocal void CALLBACK FreeInterface( mDNSInterfaceData *inIFD )
+{
+ free( inIFD );
+}
+
//===========================================================================================================================
// SetupSocket
//===========================================================================================================================
mStatus err;
SocketRef sock;
int option;
+ DWORD bytesReturned = 0;
+ BOOL behavior = FALSE;
DEBUG_UNUSED( inMDNS );
err = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
check_translated_errno( err == 0, errno_compat(), kOptionErr );
}
-
+
+ // <rdar://problem/7894393> Bonjour for Windows broken on Windows XP
+ //
+ // Not sure why, but the default behavior for sockets is to behave incorrectly
+ // when using them in Overlapped I/O mode on XP. According to MSDN:
+ //
+ // SIO_UDP_CONNRESET (opcode setting: I, T==3)
+ // Windows XP: Controls whether UDP PORT_UNREACHABLE messages are reported. Set to TRUE to enable reporting.
+ // Set to FALSE to disable reporting.
+ //
+ // Packet traces from misbehaving Bonjour installations showed that ICMP port unreachable
+ // messages were being sent to us after we sent out packets to a multicast address. This is clearly
+ // incorrect behavior, but should be harmless. However, after receiving a port unreachable error, WinSock
+ // will no longer receive any packets from that socket, which is not harmless. This behavior is only
+ // seen on XP.
+ //
+ // So we turn off port unreachable reporting to make sure our sockets that are reading
+ // multicast packets function correctly under all circumstances.
+
+ err = WSAIoctl( sock, SIO_UDP_CONNRESET, &behavior, sizeof(behavior), NULL, 0, &bytesReturned, NULL, NULL );
+ check_translated_errno( err == 0, errno_compat(), kOptionErr );
+
if( inAddr->sa_family == AF_INET )
{
mDNSv4Addr ipv4;
return( err );
}
+
+#if 0
+#pragma mark -
+#endif
+
//===========================================================================================================================
-// SetupNotifications
+// UDPBeginRecv
//===========================================================================================================================
-mDNSlocal mStatus SetupNotifications( mDNS * const inMDNS )
+mDNSlocal OSStatus UDPBeginRecv( UDPSocket * sock )
{
- mStatus err;
- SocketRef sock;
- unsigned long param;
- int inBuffer;
- int outBuffer;
- DWORD outSize;
-
- // Register to listen for address list changes.
-
- sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
- err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
- require_noerr( err, exit );
- inMDNS->p->interfaceListChangedSocket = sock;
-
- // Make the socket non-blocking so the WSAIoctl returns immediately with WSAEWOULDBLOCK. It will set the event
- // when a change to the interface list is detected.
-
- param = 1;
- err = ioctlsocket( sock, FIONBIO, ¶m );
- err = translate_errno( err == 0, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
-
- inBuffer = 0;
- outBuffer = 0;
- err = WSAIoctl( sock, SIO_ADDRESS_LIST_CHANGE, &inBuffer, 0, &outBuffer, 0, &outSize, NULL, NULL );
- if( err < 0 )
- {
- check( errno_compat() == WSAEWOULDBLOCK );
- }
-
- err = WSAEventSelect( sock, inMDNS->p->interfaceListChangedEvent, FD_ADDRESS_LIST_CHANGE );
- err = translate_errno( err == 0, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
-
- inMDNS->p->descChangedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- err = translate_errno( inMDNS->p->descChangedEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- if (inMDNS->p->descKey != NULL)
- {
- err = RegNotifyChangeKeyValue(inMDNS->p->descKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->descChangedEvent, TRUE);
- require_noerr( err, exit );
- }
-
- // This will catch all changes to tcp/ip networking, including changes to the domain search list
-
- inMDNS->p->tcpipChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- err = translate_errno( inMDNS->p->tcpipChangedEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &inMDNS->p->tcpipKey );
- require_noerr( err, exit );
-
- err = RegNotifyChangeKeyValue(inMDNS->p->tcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->tcpipChangedEvent, TRUE);
- require_noerr( err, exit );
-
- // This will catch all changes to ddns configuration
+ DWORD size;
+ DWORD numTries;
+ OSStatus err;
- inMDNS->p->ddnsChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- err = translate_errno( inMDNS->p->ddnsChangedEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
+ require_action( socket != NULL, exit, err = kUnknownErr );
- err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup"), &inMDNS->p->ddnsKey );
- require_noerr( err, exit );
+ // Initialize the buffer structure
- err = RegNotifyChangeKeyValue(inMDNS->p->ddnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->ddnsChangedEvent, TRUE);
- require_noerr( err, exit );
+ sock->wbuf.buf = (char *) &sock->packet;
+ sock->wbuf.len = (u_long) sizeof( sock->packet );
+ sock->srcAddrLen = sizeof( sock->srcAddr );
- // This will catch all changes to file sharing
+ // Initialize the overlapped structure
- inMDNS->p->fileShareEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( inMDNS->p->fileShareEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
+ ZeroMemory( &sock->overlapped, sizeof( OVERLAPPED ) );
+ sock->overlapped.hEvent = sock;
- err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\Shares"), &inMDNS->p->fileShareKey );
- require_noerr( err, exit );
+ numTries = 0;
- err = RegNotifyChangeKeyValue(inMDNS->p->fileShareKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->fileShareEvent, TRUE);
- require_noerr( err, exit );
+ do
+ {
+ if ( sock->recvMsgPtr )
+ {
+ sock->wmsg.name = ( LPSOCKADDR ) &sock->srcAddr;
+ sock->wmsg.namelen = sock->srcAddrLen;
+ sock->wmsg.lpBuffers = &sock->wbuf;
+ sock->wmsg.dwBufferCount = 1;
+ sock->wmsg.Control.buf = ( CHAR* ) sock->controlBuffer;
+ sock->wmsg.Control.len = sizeof( sock->controlBuffer );
+ sock->wmsg.dwFlags = 0;
+
+ err = sock->recvMsgPtr( sock->fd, &sock->wmsg, &size, &sock->overlapped, ( LPWSAOVERLAPPED_COMPLETION_ROUTINE ) UDPEndRecv );
+ err = translate_errno( ( err == 0 ) || ( WSAGetLastError() == WSA_IO_PENDING ), (OSStatus) WSAGetLastError(), kUnknownErr );
+
+ // <rdar://problem/7824093> iTunes 9.1 fails to install with Bonjour service on Windows 7 Ultimate
+ //
+ // There seems to be a bug in some network device drivers that involves calling WSARecvMsg() in
+ // overlapped i/o mode. Although all the parameters to WSARecvMsg() are correct, it returns a
+ // WSAEFAULT error code when there is no actual error. We have found experientially that falling
+ // back to using WSARecvFrom() when this happens will work correctly.
- // This will catch changes to the Windows firewall
+ if ( err == WSAEFAULT ) sock->recvMsgPtr = NULL;
+ }
+ else
+ {
+ DWORD flags = 0;
- inMDNS->p->firewallEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( inMDNS->p->firewallEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
+ err = WSARecvFrom( sock->fd, &sock->wbuf, 1, NULL, &flags, ( LPSOCKADDR ) &sock->srcAddr, &sock->srcAddrLen, &sock->overlapped, ( LPWSAOVERLAPPED_COMPLETION_ROUTINE ) UDPEndRecv );
+ err = translate_errno( ( err == 0 ) || ( WSAGetLastError() == WSA_IO_PENDING ), ( OSStatus ) WSAGetLastError(), kUnknownErr );
+ }
- // 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.
+ // According to MSDN <http://msdn.microsoft.com/en-us/library/ms741687(VS.85).aspx>:
+ //
+ // "WSAECONNRESET: For a UDP datagram socket, this error would indicate that a previous
+ // send operation resulted in an ICMP "Port Unreachable" message."
+ //
+ // Because this is the case, we want to ignore this error and try again. Just in case
+ // this is some kind of pathological condition, we'll break out of the retry loop
+ // after 100 iterations
- 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;
+ require_action( !err || ( err == WSAECONNRESET ) || ( err == WSAEFAULT ), exit, err = WSAGetLastError() );
}
+ while ( ( ( err == WSAECONNRESET ) || ( err == WSAEFAULT ) ) && ( numTries++ < 100 ) );
exit:
- if( err )
+
+ if ( err )
{
- TearDownNotifications( inMDNS );
+ LogMsg( "WSARecvMsg failed (%d)\n", err );
}
- return( err );
+
+ return err;
}
+
//===========================================================================================================================
-// TearDownNotifications
+// UDPEndRecv
//===========================================================================================================================
-mDNSlocal mStatus TearDownNotifications( mDNS * const inMDNS )
+mDNSlocal void CALLBACK UDPEndRecv( DWORD err, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags )
{
- if( IsValidSocket( inMDNS->p->interfaceListChangedSocket ) )
- {
- close_compat( inMDNS->p->interfaceListChangedSocket );
- inMDNS->p->interfaceListChangedSocket = kInvalidSocketRef;
- }
-
- if ( inMDNS->p->descChangedEvent != NULL )
- {
- CloseHandle( inMDNS->p->descChangedEvent );
- inMDNS->p->descChangedEvent = NULL;
- }
-
- if ( inMDNS->p->descKey != NULL )
- {
- RegCloseKey( inMDNS->p->descKey );
- inMDNS->p->descKey = NULL;
- }
-
- if ( inMDNS->p->tcpipChangedEvent != NULL )
- {
- CloseHandle( inMDNS->p->tcpipChangedEvent );
- inMDNS->p->tcpipChangedEvent = NULL;
- }
-
- if ( inMDNS->p->ddnsChangedEvent != NULL )
- {
- CloseHandle( inMDNS->p->ddnsChangedEvent );
- inMDNS->p->ddnsChangedEvent = NULL;
- }
-
- if ( inMDNS->p->ddnsKey != NULL )
- {
- RegCloseKey( inMDNS->p->ddnsKey );
- inMDNS->p->ddnsKey = NULL;
- }
+ UDPSocket * sock = NULL;
- if ( inMDNS->p->fileShareEvent != NULL )
- {
- CloseHandle( inMDNS->p->fileShareEvent );
- inMDNS->p->fileShareEvent = NULL;
- }
+ ( void ) flags;
- if ( inMDNS->p->fileShareKey != NULL )
- {
- RegCloseKey( inMDNS->p->fileShareKey );
- inMDNS->p->fileShareKey = NULL;
- }
+ require_action_quiet( err != WSA_OPERATION_ABORTED, exit, err = ( DWORD ) kUnknownErr );
+ require_noerr( err, exit );
+ sock = ( overlapped != NULL ) ? overlapped->hEvent : NULL;
+ require_action( sock != NULL, exit, err = ( DWORD ) kUnknownErr );
- if ( inMDNS->p->firewallEvent != NULL )
- {
- CloseHandle( inMDNS->p->firewallEvent );
- inMDNS->p->firewallEvent = NULL;
- }
+ // If we've closed the socket, then we want to ignore
+ // this read. The packet might have been queued before
+ // the socket was closed.
- if ( inMDNS->p->firewallKey != NULL )
+ if ( sock->fd != INVALID_SOCKET )
{
- RegCloseKey( inMDNS->p->firewallKey );
- inMDNS->p->firewallKey = NULL;
- }
-
- return( mStatus_NoError );
-}
-
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-// SetupThread
-//===========================================================================================================================
-
-mDNSlocal mStatus SetupThread( mDNS * const inMDNS )
-{
- mStatus err;
- HANDLE threadHandle;
- unsigned threadID;
- DWORD result;
+ const mDNSInterfaceID iid = sock->ifd ? sock->ifd->interfaceInfo.InterfaceID : NULL;
+ mDNSAddr srcAddr;
+ mDNSIPPort srcPort;
+ mDNSAddr dstAddr;
+ mDNSIPPort dstPort;
+ mDNSu8 * end;
- dlog( kDebugLevelTrace, DEBUG_NAME "setting up thread\n" );
-
- // To avoid a race condition with the thread ID needed by the unlocking code, we need to make sure the
- // thread has fully initialized. To do this, we create the thread then wait for it to signal it is ready.
-
- inMDNS->p->initEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- err = translate_errno( inMDNS->p->initEvent, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
+ // Translate the source of this packet into mDNS data types
- inMDNS->p->initStatus = mStatus_Invalid;
+ SockAddrToMDNSAddr( (struct sockaddr *) &sock->srcAddr, &srcAddr, &srcPort );
- // Create thread with _beginthreadex() instead of CreateThread() to avoid memory leaks when using static run-time
- // libraries. See <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createthread.asp>.
-
- threadHandle = (HANDLE) _beginthreadex_compat( NULL, 0, ProcessingThread, inMDNS, 0, &threadID );
- err = translate_errno( threadHandle, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- result = WaitForSingleObject( inMDNS->p->initEvent, INFINITE );
- err = translate_errno( result == WAIT_OBJECT_0, (mStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
- err = inMDNS->p->initStatus;
- require_noerr( err, exit );
-
-exit:
- if( inMDNS->p->initEvent )
- {
- CloseHandle( inMDNS->p->initEvent );
- inMDNS->p->initEvent = 0;
- }
- dlog( kDebugLevelTrace, DEBUG_NAME "setting up thread done (err=%d %m)\n", err, err );
- return( err );
-}
+ // Initialize the destination of this packet. Just in case
+ // we can't determine this info because we couldn't call
+ // WSARecvMsg (recvMsgPtr)
-//===========================================================================================================================
-// TearDownThread
-//===========================================================================================================================
+ dstAddr = sock->addr;
+ dstPort = sock->port;
-mDNSlocal mStatus TearDownThread( const mDNS * const inMDNS )
-{
- // Signal the cancel event to cause the thread to exit. Then wait for the quit event to be signal indicating it did
- // exit. If the quit event is not signal in 5 seconds, just give up and close anyway sinec the thread is probably hung.
-
- if( inMDNS->p->cancelEvent )
- {
- BOOL wasSet;
- DWORD result;
-
- wasSet = SetEvent( inMDNS->p->cancelEvent );
- check_translated_errno( wasSet, GetLastError(), kUnknownErr );
-
- if( inMDNS->p->quitEvent )
+ if ( sock->recvMsgPtr )
{
- result = WaitForSingleObject( inMDNS->p->quitEvent, 5 * 1000 );
- check_translated_errno( result == WAIT_OBJECT_0, GetLastError(), kUnknownErr );
- }
- }
- return( mStatus_NoError );
-}
-
-//===========================================================================================================================
-// ProcessingThread
-//===========================================================================================================================
-
-mDNSlocal unsigned WINAPI ProcessingThread( LPVOID inParam )
-{
- mDNS * m;
- int done;
- mStatus err;
- HANDLE * waitList;
- int waitListCount;
- DWORD result;
- BOOL wasSet;
-
- check( inParam );
-
- m = (mDNS *) inParam;
- err = ProcessingThreadInitialize( m );
- check( !err );
-
- done = 0;
- while( !done )
- {
- // Set up the list of objects we'll be waiting on.
-
- waitList = NULL;
- waitListCount = 0;
- err = ProcessingThreadSetupWaitList( m, &waitList, &waitListCount );
- require_noerr( err, exit );
+ LPWSACMSGHDR header;
+ LPWSACMSGHDR last = NULL;
+ int count = 0;
- // Main processing loop.
+ // Parse the control information. Reject packets received on the wrong interface.
- gWaitListChanged = FALSE;
-
- for( ;; )
- {
- // Give the mDNS core a chance to do its work and determine next event time.
-
- mDNSs32 interval = mDNS_Execute(m) - mDNS_TimeNow(m);
-
- if ( gWaitListChanged )
+ // <rdar://problem/7832196> INSTALL: Bonjour 2.0 on Windows can not start / stop
+ //
+ // There seems to be an interaction between Bullguard and this next bit of code.
+ // When a user's machine is running Bullguard, the control information that is
+ // returned is corrupted, and the code would go into an infinite loop. We'll add
+ // two bits of defensive coding here. The first will check that each pointer to
+ // the LPWSACMSGHDR that is returned in the for loop is different than the last.
+ // This fixes the problem with Bullguard. The second will break out of this loop
+ // after 100 iterations, just in case the corruption isn't caught by the first
+ // check.
+
+ for( header = WSA_CMSG_FIRSTHDR( &sock->wmsg ); header; header = WSA_CMSG_NXTHDR( &sock->wmsg, header ) )
{
- break;
- }
-
- if (m->p->idleThreadCallback)
- {
- interval = m->p->idleThreadCallback(m, interval);
- }
- if (interval < 0) interval = 0;
- else if (interval > (0x7FFFFFFF / 1000)) interval = 0x7FFFFFFF / mDNSPlatformOneSecond;
- else interval = (interval * 1000) / mDNSPlatformOneSecond;
-
- // Wait until something occurs (e.g. cancel, incoming packet, or timeout).
-
- result = WaitForMultipleObjects( (DWORD) waitListCount, waitList, FALSE, (DWORD) interval );
- check( result != WAIT_FAILED );
-
- if ( result != WAIT_FAILED )
- {
- if( result == WAIT_TIMEOUT )
- {
- // Next task timeout occurred. Loop back up to give mDNS core a chance to work.
-
- dlog( kDebugLevelChatty - 1, DEBUG_NAME "timeout\n" );
- continue;
- }
- else if( result == kWaitListCancelEvent )
+ if ( ( header != last ) && ( ++count < 100 ) )
{
- // Cancel event. Set the done flag and break to exit.
+ last = header;
- dlog( kDebugLevelVerbose, DEBUG_NAME "canceling...\n" );
- done = 1;
- break;
- }
- 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 );
- break;
- }
- else if( result == kWaitListWakeupEvent )
- {
- // Wakeup event due to an mDNS API call. Loop back to call mDNS_Execute.
-
- dlog( kDebugLevelChatty - 1, DEBUG_NAME "wakeup for mDNS_Execute\n" );
- continue;
- }
- else if ( result == kWaitListComputerDescriptionEvent )
- {
- //
- // The computer description might have changed
- //
- ProcessingThreadComputerDescriptionChanged( m );
- break;
- }
- else if ( result == kWaitListTCPIPEvent )
- {
- //
- // The TCP/IP might have changed
- //
- ProcessingThreadTCPIPConfigChanged( m );
- break;
- }
- else if ( result == kWaitListDynDNSEvent )
- {
- //
- // The DynDNS config might have changed
- //
- 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;
-
- // Socket data available event. Determine which socket and process the packet.
+ if( ( header->cmsg_level == IPPROTO_IP ) && ( header->cmsg_type == IP_PKTINFO ) )
+ {
+ IN_PKTINFO * ipv4PacketInfo;
- 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 ) );
+ ipv4PacketInfo = (IN_PKTINFO *) WSA_CMSG_DATA( header );
- if( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) )
- {
- HANDLE signaledObject;
- int n = 0;
- mDNSInterfaceData * ifd;
- TCPSocket * tcd;
- UDPSocket * sock;
-
- signaledObject = waitList[ waitItemIndex ];
-
-#if ( MDNS_WINDOWS_ENABLE_IPV4 )
- if ( m->p->unicastSock4ReadEvent == signaledObject )
+ if ( sock->ifd != NULL )
{
- ProcessingThreadProcessPacket( m, NULL, NULL, m->p->unicastSock4 );
- ++n;
+ require_action( ipv4PacketInfo->ipi_ifindex == sock->ifd->index, exit, err = ( DWORD ) kMismatchErr );
}
-#endif
+
+ dstAddr.type = mDNSAddrType_IPv4;
+ dstAddr.ip.v4.NotAnInteger = ipv4PacketInfo->ipi_addr.s_addr;
+ }
+ else if( ( header->cmsg_level == IPPROTO_IPV6 ) && ( header->cmsg_type == IPV6_PKTINFO ) )
+ {
+ IN6_PKTINFO * ipv6PacketInfo;
-#if ( MDNS_WINDOWS_ENABLE_IPV6 )
- if ( m->p->unicastSock6ReadEvent == signaledObject )
- {
- ProcessingThreadProcessPacket( m, NULL, NULL, m->p->unicastSock6 );
- ++n;
- }
-#endif
-
- for( ifd = m->p->interfaceList; ifd; ifd = ifd->next )
- {
- if( ifd->readPendingEvent == signaledObject )
- {
- ProcessingThreadProcessPacket( m, ifd, NULL, ifd->sock );
- ++n;
- }
- }
-
- for ( tcd = gTCPConnectionList; tcd; tcd = tcd->next )
- {
- if ( tcd->pendingEvent == signaledObject )
- {
- mDNSBool connect = FALSE;
-
- if ( !tcd->connected )
- {
- tcd->connected = mDNStrue;
- connect = mDNStrue;
- }
-
- tcd->callback( tcd, tcd->context, connect, 0 );
-
- ++n;
-
- break;
- }
- }
-
- for ( sock = gUDPSocketList; sock; sock = sock->next )
+ ipv6PacketInfo = (IN6_PKTINFO *) WSA_CMSG_DATA( header );
+
+ if ( sock->ifd != NULL )
{
- if ( sock->readEvent == signaledObject )
- {
- ProcessingThreadProcessPacket( m, NULL, sock, sock->sock );
-
- ++n;
-
- break;
- }
+ require_action( ipv6PacketInfo->ipi6_ifindex == ( sock->ifd->index - kIPv6IfIndexBase ), exit, err = ( DWORD ) kMismatchErr );
}
- check( n > 0 );
+ dstAddr.type = mDNSAddrType_IPv6;
+ dstAddr.ip.v6 = *( (mDNSv6Addr *) &ipv6PacketInfo->ipi6_addr );
}
- else
+ }
+ else
+ {
+ static BOOL loggedMessage = FALSE;
+
+ if ( !loggedMessage )
{
- // Unexpected wait result.
-
- dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, result );
+ LogMsg( "UDPEndRecv: WSARecvMsg control information error." );
+ loggedMessage = TRUE;
}
+
+ break;
}
}
- else
- {
- Sleep( 3 * 1000 );
- err = ProcessingThreadInitialize( m );
- check( err );
- break;
- }
- }
-
- // Release the wait list.
-
- if( waitList )
- {
- free( waitList );
- waitList = NULL;
- waitListCount = 0;
}
- }
-
- // Signal the quit event to indicate that the thread is finished.
-exit:
- wasSet = SetEvent( m->p->quitEvent );
- check_translated_errno( wasSet, GetLastError(), kUnknownErr );
-
- // Call _endthreadex() explicitly instead of just exiting normally to avoid memory leaks when using static run-time
- // libraries. See <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createthread.asp>.
+ // Dispatch the packet to mDNS.
- _endthreadex_compat( 0 );
- return( 0 );
-}
-
-//===========================================================================================================================
-// ProcessingThreadInitialize
-//===========================================================================================================================
-
-mDNSlocal mStatus ProcessingThreadInitialize( mDNS * const inMDNS )
-{
- mStatus err;
- BOOL wasSet;
+ dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" );
+ dlog( kDebugLevelChatty, DEBUG_NAME " size = %d\n", bytesTransferred );
+ dlog( kDebugLevelChatty, DEBUG_NAME " src = %#a:%u\n", &srcAddr, ntohs( srcPort.NotAnInteger ) );
+ dlog( kDebugLevelChatty, DEBUG_NAME " dst = %#a:%u\n", &dstAddr, ntohs( dstPort.NotAnInteger ) );
- inMDNS->p->threadID = GetCurrentThreadId();
-
- err = SetupInterfaceList( inMDNS );
- require_noerr( err, exit );
-
- err = uDNS_SetupDNSConfig( inMDNS );
- require_noerr( err, exit );
-
-exit:
-
- if( err )
- {
- TearDownInterfaceList( inMDNS );
- }
- inMDNS->p->initStatus = err;
-
- wasSet = SetEvent( inMDNS->p->initEvent );
- check_translated_errno( wasSet, GetLastError(), kUnknownErr );
- return( err );
-}
-
-//===========================================================================================================================
-// ProcessingThreadSetupWaitList
-//===========================================================================================================================
-
-mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **outWaitList, int *outWaitListCount )
-{
- mStatus err;
- int waitListCount;
- HANDLE * waitList;
- HANDLE * waitItemPtr;
- mDNSInterfaceData * ifd;
- TCPSocket * tcd;
- UDPSocket * sock;
-
- dlog( kDebugLevelTrace, DEBUG_NAME "thread setting up wait list\n" );
- check( inMDNS );
- check( inMDNS->p );
- check( outWaitList );
- check( outWaitListCount );
-
- // Allocate an array to hold all the objects to wait on.
-
- waitListCount = kWaitListFixedItemCount + inMDNS->p->interfaceCount + gTCPConnections + gUDPSockets;
- waitList = (HANDLE *) malloc( waitListCount * sizeof( *waitList ) );
- require_action( waitList, exit, err = mStatus_NoMemoryErr );
- waitItemPtr = waitList;
-
- // Add the fixed wait items to the beginning of the list.
-
- *waitItemPtr++ = inMDNS->p->cancelEvent;
- *waitItemPtr++ = inMDNS->p->interfaceListChangedEvent;
- *waitItemPtr++ = inMDNS->p->wakeupEvent;
- *waitItemPtr++ = inMDNS->p->descChangedEvent;
- *waitItemPtr++ = inMDNS->p->tcpipChangedEvent;
- *waitItemPtr++ = inMDNS->p->ddnsChangedEvent;
- *waitItemPtr++ = inMDNS->p->fileShareEvent;
- *waitItemPtr++ = inMDNS->p->firewallEvent;
-
- // Append all the dynamic wait items to the list.
-#if ( MDNS_WINDOWS_ENABLE_IPV4 )
- *waitItemPtr++ = inMDNS->p->unicastSock4ReadEvent;
-#endif
-
-#if ( MDNS_WINDOWS_ENABLE_IPV6 )
- *waitItemPtr++ = inMDNS->p->unicastSock6ReadEvent;
-#endif
-
- for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
- {
- *waitItemPtr++ = ifd->readPendingEvent;
- }
-
- for ( tcd = gTCPConnectionList; tcd; tcd = tcd->next )
- {
- *waitItemPtr++ = tcd->pendingEvent;
- }
-
- for ( sock = gUDPSocketList; sock; sock = sock->next )
- {
- *waitItemPtr++ = sock->readEvent;
- }
+ if ( sock->ifd != NULL )
+ {
+ dlog( kDebugLevelChatty, DEBUG_NAME " interface = %#a (index=0x%08X)\n", &sock->ifd->interfaceInfo.ip, sock->ifd->index );
+ }
- check( (int)( waitItemPtr - waitList ) == waitListCount );
-
- *outWaitList = waitList;
- *outWaitListCount = waitListCount;
- waitList = NULL;
- err = mStatus_NoError;
+ dlog( kDebugLevelChatty, DEBUG_NAME "\n" );
-exit:
- if( waitList )
- {
- free( waitList );
- }
- dlog( kDebugLevelTrace, DEBUG_NAME "thread setting up wait list done (err=%d %m)\n", err, err );
- return( err );
-}
-
-//===========================================================================================================================
-// ProcessingThreadProcessPacket
-//===========================================================================================================================
+ end = ( (mDNSu8 *) &sock->packet ) + bytesTransferred;
-mDNSlocal void ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *inIFD, UDPSocket * inUDPSocket, SocketRef inSock )
-{
- OSStatus err;
- const mDNSInterfaceID iid = inIFD ? inIFD->interfaceInfo.InterfaceID : NULL;
- LPFN_WSARECVMSG recvMsgPtr;
- mDNSAddr srcAddr;
- mDNSIPPort srcPort;
- mDNSAddr dstAddr;
- mDNSIPPort dstPort;
- mDNSu8 ttl;
- struct sockaddr_storage addr;
- DNSMessage packet;
- mDNSu8 * end;
- int n;
-
- check( inMDNS );
- check( IsValidSocket( inSock ) );
-
- // Set up the default in case the packet info options are not supported or reported correctly.
-
- if ( inIFD )
- {
- recvMsgPtr = inIFD->wsaRecvMsgFunctionPtr;
- dstAddr = inIFD->defaultAddr;
- 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 = inMDNS->UnicastPort4;
- ttl = 255;
- }
- else if ( inSock == inMDNS->p->unicastSock6 )
- {
- recvMsgPtr = inMDNS->p->unicastSock6RecvMsgPtr;
- dstAddr = inMDNS->p->unicastSock6DestAddr;
- dstPort = inMDNS->UnicastPort6;
- ttl = 255;
- }
- else
- {
- dlog( kDebugLevelError, DEBUG_NAME "packet received on unknown socket\n" );
- goto exit;
- }
+ // <rdar://problem/7532492> mDNSResponder gets locking errors on Windows
+ //
+ // There seems to be a bug in WinSock with respect to Alertable I/O. According
+ // to MSDN <http://msdn.microsoft.com/en-us/library/aa363772(VS.85).aspx>, Alertable I/O
+ // callbacks will only be invoked during the following calls (when the caller sets
+ // the appropriate flag):
+ //
+ // - SleepEx
+ // - WaitForSingleObjectEx
+ // - WaitForMultipleObjectsEx
+ // - SignalObjectAndWait
+ // - MsgWaitForMultipleObjectsEx
+ //
+ // However, we have seen callbacks be invoked during calls to bind() (and maybe others).
+ // To workaround this, we set the gSocketEventsEnabled flag to be TRUE only when it's okay
+ // to directly call mDNSCoreReceive. Otherwise we queue the packet up and dispatch it later.
-#if( !TARGET_OS_WINDOWS_CE )
- if( recvMsgPtr )
- {
- WSAMSG msg;
- WSABUF buf;
- uint8_t controlBuffer[ 128 ];
- DWORD size;
- LPWSACMSGHDR header;
-
- // Set up the buffer and read the packet.
-
- msg.name = (LPSOCKADDR) &addr;
- msg.namelen = (INT) sizeof( addr );
- buf.buf = (char *) &packet;
- buf.len = (u_long) sizeof( packet );
- msg.lpBuffers = &buf;
- msg.dwBufferCount = 1;
- msg.Control.buf = (char *) controlBuffer;
- msg.Control.len = (u_long) sizeof( controlBuffer );
- msg.dwFlags = 0;
-
- err = recvMsgPtr( inSock, &msg, &size, NULL, NULL );
- err = translate_errno( err == 0, (OSStatus) WSAGetLastError(), kUnknownErr );
- require_noerr( err, exit );
- n = (int) size;
-
- // Parse the control information. Reject packets received on the wrong interface.
-
- for( header = WSA_CMSG_FIRSTHDR( &msg ); header; header = WSA_CMSG_NXTHDR( &msg, header ) )
+ if ( gSocketEventsEnabled && !gSocketEvents.Head )
{
- if( ( header->cmsg_level == IPPROTO_IP ) && ( header->cmsg_type == IP_PKTINFO ) )
- {
- IN_PKTINFO * ipv4PacketInfo;
-
- ipv4PacketInfo = (IN_PKTINFO *) WSA_CMSG_DATA( header );
-
- if ( inIFD )
- {
- require_action( ipv4PacketInfo->ipi_ifindex == inIFD->index, exit, err = kMismatchErr );
- }
-
- dstAddr.type = mDNSAddrType_IPv4;
- dstAddr.ip.v4.NotAnInteger = ipv4PacketInfo->ipi_addr.s_addr;
- }
- else if( ( header->cmsg_level == IPPROTO_IPV6 ) && ( header->cmsg_type == IPV6_PKTINFO ) )
- {
- IN6_PKTINFO * ipv6PacketInfo;
-
- ipv6PacketInfo = (IN6_PKTINFO *) WSA_CMSG_DATA( header );
-
- if ( inIFD )
- {
- require_action( ipv6PacketInfo->ipi6_ifindex == ( inIFD->index - kIPv6IfIndexBase), exit, err = kMismatchErr );
- }
-
- dstAddr.type = mDNSAddrType_IPv6;
- dstAddr.ip.v6 = *( (mDNSv6Addr *) &ipv6PacketInfo->ipi6_addr );
- }
+ // Turn off socket events before calling mDNSCoreReceive().
+ // This will prevent reentrancy problems.
+ //
+ // Don't forget to reenable socket events afterwards.
+
+ SetSocketEventsEnabled( sock->m, FALSE );
+ mDNSCoreReceive( sock->m, &sock->packet, end, &srcAddr, srcPort, &dstAddr, dstPort, iid );
+ SetSocketEventsEnabled( sock->m, TRUE );
+ }
+ else
+ {
+ UDPSocketEvent * event;
+
+ event = malloc( sizeof( UDPSocketEvent ) );
+ require_action( event, exit, err = ( DWORD ) kNoMemoryErr );
+ event->super.sock = sock;
+ event->super.handler = &UDPSocketEventHandler;
+ event->super.next = NULL;
+ event->iid = iid;
+ memcpy( &event->packet, &sock->packet, sizeof( event->packet ) );
+ event->end = ( (mDNSu8 *) &event->packet ) + bytesTransferred;
+ event->srcAddr = srcAddr;
+ event->dstAddr = dstAddr;
+ event->srcPort = srcPort;
+ event->dstPort = dstPort;
+
+ AddToTail( &gSocketEvents, event );
}
}
- else
-#endif
- {
- int addrSize;
-
- addrSize = sizeof( addr );
- n = recvfrom( inSock, (char *) &packet, sizeof( packet ), 0, (struct sockaddr *) &addr, &addrSize );
- err = translate_errno( n > 0, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
- }
- SockAddrToMDNSAddr( (struct sockaddr *) &addr, &srcAddr, &srcPort );
-
- // Dispatch the packet to mDNS.
-
- dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" );
- dlog( kDebugLevelChatty, DEBUG_NAME " size = %d\n", n );
- dlog( kDebugLevelChatty, DEBUG_NAME " src = %#a:%u\n", &srcAddr, ntohs( srcPort.NotAnInteger ) );
- dlog( kDebugLevelChatty, DEBUG_NAME " dst = %#a:%u\n", &dstAddr, ntohs( dstPort.NotAnInteger ) );
- if ( inIFD )
+exit:
+
+ // If the socket is still good, then start up another asynchronous read
+
+ if ( sock && ( sock->fd != INVALID_SOCKET ) )
{
- dlog( kDebugLevelChatty, DEBUG_NAME " interface = %#a (index=0x%08X)\n", &inIFD->interfaceInfo.ip, (int) inIFD->index );
+ err = UDPBeginRecv( sock );
+ check_noerr( err );
}
-
- dlog( kDebugLevelChatty, DEBUG_NAME "\n" );
-
- end = ( (mDNSu8 *) &packet ) + n;
- mDNSCoreReceive( inMDNS, &packet, end, &srcAddr, srcPort, &dstAddr, dstPort, iid );
-
-exit:
- return;
}
+
//===========================================================================================================================
-// ProcessingThreadInterfaceListChanged
+// InterfaceListDidChange
//===========================================================================================================================
-
-mDNSlocal void ProcessingThreadInterfaceListChanged( mDNS *inMDNS )
+void InterfaceListDidChange( mDNS * const inMDNS )
{
- mStatus err;
+ mStatus err;
dlog( kDebugLevelInfo, DEBUG_NAME "interface list changed\n" );
check( inMDNS );
-
- if (inMDNS->p->interfaceListChangedCallback)
- {
- inMDNS->p->interfaceListChangedCallback(inMDNS);
- }
-
- mDNSPlatformLock( inMDNS );
// Tear down the existing interfaces and set up new ones using the new IP info.
err = uDNS_SetupDNSConfig( inMDNS );
check_noerr( err );
-
- mDNSPlatformUnlock( inMDNS );
// Inform clients of the change.
//===========================================================================================================================
-// ProcessingThreadComputerDescriptionChanged
+// ComputerDescriptionDidChange
//===========================================================================================================================
-mDNSlocal void ProcessingThreadComputerDescriptionChanged( mDNS *inMDNS )
-{
- mStatus err;
-
+void ComputerDescriptionDidChange( mDNS * const inMDNS )
+{
dlog( kDebugLevelInfo, DEBUG_NAME "computer description has changed\n" );
check( inMDNS );
- mDNSPlatformLock( inMDNS );
-
// redo the names
SetupNiceName( inMDNS );
-
- if (inMDNS->p->hostDescriptionChangedCallback)
- {
- inMDNS->p->hostDescriptionChangedCallback(inMDNS);
- }
-
- // and reset the event handler
- if ((inMDNS->p->descKey != NULL) && (inMDNS->p->descChangedEvent))
- {
- err = RegNotifyChangeKeyValue(inMDNS->p->descKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->descChangedEvent, TRUE);
- check_noerr( err );
- }
-
- mDNSPlatformUnlock( inMDNS );
}
//===========================================================================================================================
-// ProcessingThreadTCPIPConfigChanged
+// TCPIPConfigDidChange
//===========================================================================================================================
-mDNSlocal void ProcessingThreadTCPIPConfigChanged( mDNS * inMDNS )
+void TCPIPConfigDidChange( mDNS * const inMDNS )
{
mStatus err;
dlog( kDebugLevelInfo, DEBUG_NAME "TCP/IP config has changed\n" );
check( inMDNS );
- mDNSPlatformLock( inMDNS );
-
err = uDNS_SetupDNSConfig( inMDNS );
check_noerr( err );
-
- // and reset the event handler
-
- if ( ( inMDNS->p->tcpipKey != NULL ) && ( inMDNS->p->tcpipChangedEvent ) )
- {
- err = RegNotifyChangeKeyValue( inMDNS->p->tcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->tcpipChangedEvent, TRUE );
- check_noerr( err );
- }
-
- mDNSPlatformUnlock( inMDNS );
}
//===========================================================================================================================
-// ProcessingThreadDynDNSConfigChanged
+// DynDNSConfigDidChange
//===========================================================================================================================
-mDNSlocal void ProcessingThreadDynDNSConfigChanged( mDNS *inMDNS )
+void DynDNSConfigDidChange( mDNS * const inMDNS )
{
mStatus err;
SetDomainSecrets( inMDNS );
- mDNSPlatformLock( inMDNS );
-
err = uDNS_SetupDNSConfig( inMDNS );
check_noerr( err );
-
- // and reset the event handler
-
- if ((inMDNS->p->ddnsKey != NULL) && (inMDNS->p->ddnsChangedEvent))
- {
- err = RegNotifyChangeKeyValue(inMDNS->p->ddnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->ddnsChangedEvent, TRUE);
- check_noerr( err );
- }
-
- mDNSPlatformUnlock( inMDNS );
}
//===========================================================================================================================
-// ProcessingThreadFileShareChanged
+// FileSharingDidChange
//===========================================================================================================================
-mDNSlocal void ProcessingThreadFileShareChanged( mDNS *inMDNS )
-{
- mStatus err;
-
+void FileSharingDidChange( mDNS * const inMDNS )
+{
dlog( kDebugLevelInfo, DEBUG_NAME "File shares has changed\n" );
check( inMDNS );
CheckFileShares( inMDNS );
-
- // and reset the event handler
-
- if ((inMDNS->p->fileShareKey != NULL) && (inMDNS->p->fileShareEvent))
- {
- err = RegNotifyChangeKeyValue(inMDNS->p->fileShareKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->fileShareEvent, TRUE);
- check_noerr( err );
- }
}
//===========================================================================================================================
-// ProcessingThreadFileShareChanged
+// FilewallDidChange
//===========================================================================================================================
-mDNSlocal void ProcessingThreadFirewallChanged( mDNS *inMDNS )
-{
- mStatus err;
-
+void FirewallDidChange( mDNS * const inMDNS )
+{
dlog( kDebugLevelInfo, DEBUG_NAME "Firewall has changed\n" );
check( inMDNS );
CheckFileShares( inMDNS );
-
- // and reset the event handler
-
- if ((inMDNS->p->firewallKey != NULL) && (inMDNS->p->firewallEvent))
- {
- err = RegNotifyChangeKeyValue(inMDNS->p->firewallKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->firewallEvent, TRUE);
- check_noerr( err );
- }
}
-
#if 0
#pragma mark -
#pragma mark == Utilities ==
{
int err;
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS && !TARGET_OS_WINDOWS_CE )
+#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
// Try to the load the GetAdaptersAddresses function from the IP Helpers DLL. This API is only available on Windows
// XP or later. Looking up the symbol at runtime allows the code to still work on older systems without that API.
require_noerr( err, exit );
}
-#elif( !TARGET_OS_WINDOWS_CE )
-
- err = getifaddrs_ipv4( outAddrs );
- require_noerr( err, exit );
-
#else
- err = getifaddrs_ce( outAddrs );
+ err = getifaddrs_ipv4( outAddrs );
require_noerr( err, exit );
#endif
// Get lease lifetime
- if ( ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) && ( addr->LeaseLifetime != 0 ) && ( addr->LeaseLifetime != 0xFFFFFFFF ) )
+ if ( ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) && ( addr->LeaseLifetime != 0 ) && ( addr->ValidLifetime != 0xFFFFFFFF ) )
{
ifa->ifa_dhcpEnabled = TRUE;
- ifa->ifa_dhcpLeaseExpires = time( NULL ) + addr->LeaseLifetime;
+ ifa->ifa_dhcpLeaseExpires = time( NULL ) + addr->ValidLifetime;
}
else
{
ifa->ifa_dhcpLeaseExpires = 0;
}
- // Get WakeOnLAN settings
-
- if ( iaa->IfType == IF_TYPE_ETHERNET_CSMACD )
+ if ( iaa->PhysicalAddressLength == sizeof( ifa->ifa_physaddr ) )
{
- ifa->ifa_womp = IsWOMPEnabled( iaa->AdapterName );
+ memcpy( ifa->ifa_physaddr, iaa->PhysicalAddress, iaa->PhysicalAddressLength );
}
+
+ // Because we don't get notified of womp changes, we're going to just assume
+ // that all wired interfaces have it enabled. Before we go to sleep, we'll check
+ // if the interface actually supports it, and update mDNS->SystemWakeOnLANEnabled
+ // accordingly
+
+ ifa->ifa_womp = ( iaa->IfType == IF_TYPE_ETHERNET_CSMACD ) ? mDNStrue : mDNSfalse;
// Get address.
#endif // MDNS_WINDOWS_USE_IPV6_IF_ADDRS
-#if( !TARGET_OS_WINDOWS_CE )
//===========================================================================================================================
// getifaddrs_ipv4
//===========================================================================================================================
INTERFACE_INFO * buffer;
INTERFACE_INFO * tempBuffer;
INTERFACE_INFO * ifInfo;
- IP_ADAPTER_INFO * pAdapterInfo;
- IP_ADAPTER_INFO * pAdapter;
- ULONG bufLen;
int n;
int i;
struct ifaddrs * head;
struct ifaddrs ** next;
struct ifaddrs * ifa;
-
- sock = INVALID_SOCKET;
- buffer = NULL;
- head = NULL;
- next = &head;
- pAdapterInfo = NULL;
-
- // Get the interface list. WSAIoctl is called with SIO_GET_INTERFACE_LIST, but since this does not provide a
- // way to determine the size of the interface list beforehand, we have to start with an initial size guess and
- // call WSAIoctl repeatedly with increasing buffer sizes until it succeeds. Limit this to 100 tries for safety.
-
- sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
- err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
- require_noerr( err, exit );
-
- n = 0;
- size = 16 * sizeof( INTERFACE_INFO );
- for( ;; )
- {
- tempBuffer = (INTERFACE_INFO *) realloc( buffer, size );
- require_action( tempBuffer, exit, err = WSAENOBUFS );
- buffer = tempBuffer;
-
- err = WSAIoctl( sock, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, size, &actualSize, NULL, NULL );
- if( err == 0 )
- {
- break;
- }
-
- ++n;
- require_action( n < 100, exit, err = WSAEADDRNOTAVAIL );
-
- size += ( 16 * sizeof( INTERFACE_INFO ) );
- }
- check( actualSize <= size );
- check( ( actualSize % sizeof( INTERFACE_INFO ) ) == 0 );
- n = (int)( actualSize / sizeof( INTERFACE_INFO ) );
-
- // Now call GetAdaptersInfo so we can get DHCP information for each interface
-
- pAdapterInfo = NULL;
- bufLen = 0;
-
- for ( i = 0; i < 100; i++ )
- {
- err = GetAdaptersInfo( pAdapterInfo, &bufLen);
-
- if ( err != ERROR_BUFFER_OVERFLOW )
- {
- break;
- }
-
- pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
-
- if ( !pAdapterInfo )
- {
- break;
- }
- }
-
- // Process the raw interface list and build a linked list of IPv4 interfaces.
-
- for( i = 0; i < n; ++i )
- {
- uint32_t ifIndex;
- struct sockaddr_in netmask;
-
- ifInfo = &buffer[ i ];
- if( ifInfo->iiAddress.Address.sa_family != AF_INET )
- {
- continue;
- }
-
- // <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
- // See comment in getifaddrs_ipv6
-
- ifIndex = 0;
- memset( &netmask, 0, sizeof( netmask ) );
- err = AddressToIndexAndMask( ( struct sockaddr* ) &ifInfo->iiAddress.AddressIn, &ifIndex, ( struct sockaddr* ) &netmask );
-
- if ( err )
- {
- continue;
- }
-
- ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
- require_action( ifa, exit, err = WSAENOBUFS );
-
- *next = ifa;
- next = &ifa->ifa_next;
-
- // Get the name.
-
- ifa->ifa_name = (char *) malloc( 16 );
- require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
- sprintf( ifa->ifa_name, "%d", i + 1 );
-
- // Get interface flags.
-
- ifa->ifa_flags = (u_int) ifInfo->iiFlags;
-
- // Get addresses.
-
- if ( ifInfo->iiAddress.Address.sa_family == AF_INET )
- {
- struct sockaddr_in * sa4;
-
- sa4 = &ifInfo->iiAddress.AddressIn;
- ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( *sa4 ) );
- require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
- memcpy( ifa->ifa_addr, sa4, sizeof( *sa4 ) );
-
- ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) );
- require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
-
- // <rdar://problem/4076478> Service won't start on Win2K. The address
- // family field was not being initialized.
-
- ifa->ifa_netmask->sa_family = AF_INET;
- ( ( struct sockaddr_in* ) ifa->ifa_netmask )->sin_addr = netmask.sin_addr;
- ifa->ifa_extra.index = ifIndex;
- }
- else
- {
- // Emulate an interface index.
-
- ifa->ifa_extra.index = (uint32_t)( i + 1 );
- }
-
- // Now get DHCP configuration information
-
- for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
- {
- if ( strcmp( inet_ntoa( ifInfo->iiAddress.AddressIn.sin_addr ), pAdapter->IpAddressList.IpAddress.String ) == 0 )
- {
- ifa->ifa_dhcpEnabled = pAdapter->DhcpEnabled;
- ifa->ifa_dhcpLeaseExpires = pAdapter->LeaseExpires;
- ifa->ifa_womp = IsWOMPEnabled( pAdapter->AdapterName );
- break;
- }
- }
- }
-
- // Success!
-
- if( outAddrs )
- {
- *outAddrs = head;
- head = NULL;
- }
- err = 0;
-
-exit:
-
- if ( pAdapterInfo )
- {
- free( pAdapterInfo );
- }
- if( head )
- {
- freeifaddrs( head );
- }
- if( buffer )
- {
- free( buffer );
- }
- if( sock != INVALID_SOCKET )
- {
- closesocket( sock );
- }
- return( err );
-}
-#endif // !TARGET_OS_WINDOWS_CE )
-
-#if( TARGET_OS_WINDOWS_CE )
-//===========================================================================================================================
-// getifaddrs_ce
-//===========================================================================================================================
-
-mDNSlocal int getifaddrs_ce( struct ifaddrs **outAddrs )
-{
- int err;
- SocketRef sock;
- DWORD size;
- void * buffer;
- SOCKET_ADDRESS_LIST * addressList;
- struct ifaddrs * head;
- struct ifaddrs ** next;
- struct ifaddrs * ifa;
- int n;
- int i;
-
- sock = kInvalidSocketRef;
+
+ sock = INVALID_SOCKET;
buffer = NULL;
head = NULL;
next = &head;
- // Open a temporary socket because one is needed to use WSAIoctl (we'll close it before exiting this function).
+ // Get the interface list. WSAIoctl is called with SIO_GET_INTERFACE_LIST, but since this does not provide a
+ // way to determine the size of the interface list beforehand, we have to start with an initial size guess and
+ // call WSAIoctl repeatedly with increasing buffer sizes until it succeeds. Limit this to 100 tries for safety.
sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
require_noerr( err, exit );
- // 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.
-
- size = 0;
- WSAIoctl( sock, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0, &size, NULL, NULL );
- require_action( size > 0, exit, err = -1 );
- size *= 2;
-
- buffer = calloc( 1, size );
- require_action( buffer, exit, err = -1 );
-
- // We now know the size of the list and have a buffer to hold so call WSAIoctl again to get it.
-
- err = WSAIoctl( sock, SIO_ADDRESS_LIST_QUERY, NULL, 0, buffer, size, &size, NULL, NULL );
- require_noerr( err, exit );
- addressList = (SOCKET_ADDRESS_LIST *) buffer;
-
- // 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.
-
- n = addressList->iAddressCount;
- if( n == 0 )
+ n = 0;
+ size = 16 * sizeof( INTERFACE_INFO );
+ for( ;; )
{
- n = 1;
+ tempBuffer = (INTERFACE_INFO *) realloc( buffer, size );
+ require_action( tempBuffer, exit, err = WSAENOBUFS );
+ buffer = tempBuffer;
+
+ err = WSAIoctl( sock, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, size, &actualSize, NULL, NULL );
+ if( err == 0 )
+ {
+ break;
+ }
+
+ ++n;
+ require_action( n < 100, exit, err = WSAEADDRNOTAVAIL );
+
+ size += ( 16 * sizeof( INTERFACE_INFO ) );
}
+ check( actualSize <= size );
+ check( ( actualSize % sizeof( INTERFACE_INFO ) ) == 0 );
+ n = (int)( actualSize / sizeof( INTERFACE_INFO ) );
+
+ // Process the raw interface list and build a linked list of IPv4 interfaces.
+
for( i = 0; i < n; ++i )
{
+ uint32_t ifIndex;
+ struct sockaddr_in netmask;
+
+ ifInfo = &buffer[ i ];
+ if( ifInfo->iiAddress.Address.sa_family != AF_INET )
+ {
+ continue;
+ }
+
+ // <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
+ // See comment in getifaddrs_ipv6
+
+ ifIndex = 0;
+ memset( &netmask, 0, sizeof( netmask ) );
+ err = AddressToIndexAndMask( ( struct sockaddr* ) &ifInfo->iiAddress.AddressIn, &ifIndex, ( struct sockaddr* ) &netmask );
+
+ if ( err )
+ {
+ continue;
+ }
+
ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
require_action( ifa, exit, err = WSAENOBUFS );
require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
sprintf( ifa->ifa_name, "%d", i + 1 );
- // Get flags. Note: SIO_ADDRESS_LIST_QUERY does not report flags so just fake IFF_UP and IFF_MULTICAST.
+ // Get interface flags.
- ifa->ifa_flags = IFF_UP | IFF_MULTICAST;
+ ifa->ifa_flags = (u_int) ifInfo->iiFlags;
// Get addresses.
- switch( addressList->Address[ i ].lpSockaddr->sa_family )
+ if ( ifInfo->iiAddress.Address.sa_family == AF_INET )
{
- case AF_INET:
- {
- struct sockaddr_in * sa4;
-
- sa4 = (struct sockaddr_in *) addressList->Address[ i ].lpSockaddr;
- ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( *sa4 ) );
- require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
- memcpy( ifa->ifa_addr, sa4, sizeof( *sa4 ) );
- break;
- }
+ struct sockaddr_in * sa4;
- default:
- break;
+ sa4 = &ifInfo->iiAddress.AddressIn;
+ ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( *sa4 ) );
+ require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
+ memcpy( ifa->ifa_addr, sa4, sizeof( *sa4 ) );
+
+ ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) );
+ require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
+
+ // <rdar://problem/4076478> Service won't start on Win2K. The address
+ // family field was not being initialized.
+
+ ifa->ifa_netmask->sa_family = AF_INET;
+ ( ( struct sockaddr_in* ) ifa->ifa_netmask )->sin_addr = netmask.sin_addr;
+ ifa->ifa_extra.index = ifIndex;
+ }
+ else
+ {
+ // Emulate an interface index.
+
+ ifa->ifa_extra.index = (uint32_t)( i + 1 );
}
}
err = 0;
exit:
+
if( head )
{
freeifaddrs( head );
}
return( err );
}
-#endif // TARGET_OS_WINDOWS_CE )
//===========================================================================================================================
// freeifaddrs
//===========================================================================================================================
-// FreeTCPConnectionData
+// TCPFreeSocket
//===========================================================================================================================
-mDNSlocal void
-FreeTCPSocket( TCPSocket *sock )
+mDNSlocal void CALLBACK
+TCPFreeSocket( TCPSocket *sock )
{
check( sock );
- if ( sock->pendingEvent )
+ dlog( kDebugLevelChatty, DEBUG_NAME "freeing TCPSocket 0x%x:%d\n", sock, sock->fd );
+
+ if ( sock->connectEvent )
{
- CloseHandle( sock->pendingEvent );
+ CloseHandle( sock->connectEvent );
+ sock->connectEvent = NULL;
}
if ( sock->fd != INVALID_SOCKET )
{
closesocket( sock->fd );
+ sock->fd = INVALID_SOCKET;
}
free( sock );
//===========================================================================================================================
-// FreeUDPSocket
+// UDPFreeSocket
//===========================================================================================================================
-mDNSlocal void
-FreeUDPSocket( UDPSocket * sock )
+mDNSlocal void CALLBACK
+UDPFreeSocket( UDPSocket * sock )
{
check( sock );
- if ( sock->readEvent )
- {
- CloseHandle( sock->readEvent );
- }
+ dlog( kDebugLevelChatty, DEBUG_NAME "freeing UDPSocket %d (%##a)\n", sock->fd, &sock->addr );
- if ( sock->sock != INVALID_SOCKET )
- {
- closesocket( sock->sock );
+ if ( sock->fd != INVALID_SOCKET )
+ {
+ closesocket( sock->fd );
+ sock->fd = INVALID_SOCKET;
}
free( sock );
}
+mDNSlocal VOID CALLBACK
+CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue )
+{
+ mDNS * const m = ( mDNS * const ) arg;
+
+ ( void ) dwTimerLowValue;
+ ( void ) dwTimerHighValue;
+
+ CheckFileShares( m );
+}
+
+
+mDNSlocal unsigned __stdcall
+SMBRegistrationThread( void * arg )
+{
+ mDNS * const m = ( mDNS * const ) arg;
+ DNSServiceRef sref = NULL;
+ HANDLE handles[ 3 ];
+ mDNSu8 txtBuf[ 256 ];
+ mDNSu8 * txtPtr;
+ size_t keyLen;
+ size_t valLen;
+ mDNSIPPort port = { { SMBPortAsNumber >> 8, SMBPortAsNumber & 0xFF } };
+ DNSServiceErrorType err;
+
+ DEBUG_UNUSED( arg );
+
+ handles[ 0 ] = gSMBThreadStopEvent;
+ handles[ 1 ] = gSMBThreadRegisterEvent;
+ handles[ 2 ] = gSMBThreadDeregisterEvent;
+
+ memset( txtBuf, 0, sizeof( txtBuf ) );
+ txtPtr = txtBuf;
+ keyLen = strlen( "netbios=" );
+ valLen = strlen( m->p->nbname );
+ require_action( valLen < 32, exit, err = kUnknownErr ); // This should never happen, but check to avoid further memory corruption
+ *txtPtr++ = ( mDNSu8 ) ( keyLen + valLen );
+ memcpy( txtPtr, "netbios=", keyLen );
+ txtPtr += keyLen;
+ if ( valLen ) { memcpy( txtPtr, m->p->nbname, valLen ); txtPtr += ( mDNSu8 ) valLen; }
+ keyLen = strlen( "domain=" );
+ valLen = strlen( m->p->nbdomain );
+ require_action( valLen < 32, exit, err = kUnknownErr ); // This should never happen, but check to avoid further memory corruption
+ *txtPtr++ = ( mDNSu8 )( keyLen + valLen );
+ memcpy( txtPtr, "domain=", keyLen );
+ txtPtr += keyLen;
+ if ( valLen ) { memcpy( txtPtr, m->p->nbdomain, valLen ); txtPtr += valLen; }
+
+ for ( ;; )
+ {
+ DWORD ret;
+
+ ret = WaitForMultipleObjects( 3, handles, FALSE, INFINITE );
+
+ if ( ret != WAIT_FAILED )
+ {
+ if ( ret == kSMBStopEvent )
+ {
+ break;
+ }
+ else if ( ret == kSMBRegisterEvent )
+ {
+ err = gDNSServiceRegister( &sref, 0, 0, NULL, "_smb._tcp,_file", NULL, NULL, ( uint16_t ) port.NotAnInteger, ( mDNSu16 )( txtPtr - txtBuf ), txtBuf, NULL, NULL );
+
+ if ( err )
+ {
+ LogMsg( "SMBRegistrationThread: DNSServiceRegister returned %d\n", err );
+ sref = NULL;
+ break;
+ }
+ }
+ else if ( ret == kSMBDeregisterEvent )
+ {
+ if ( sref )
+ {
+ gDNSServiceRefDeallocate( sref );
+ sref = NULL;
+ }
+ }
+ }
+ else
+ {
+ LogMsg( "SMBRegistrationThread: WaitForMultipleObjects returned %d\n", GetLastError() );
+ break;
+ }
+ }
+
+exit:
+
+ if ( sref != NULL )
+ {
+ gDNSServiceRefDeallocate( sref );
+ sref = NULL;
+ }
+
+ SetEvent( gSMBThreadQuitEvent );
+ _endthreadex( 0 );
+ return 0;
+}
+
+
mDNSlocal void
CheckFileShares( mDNS * const m )
{
DWORD entriesRead = 0;
DWORD totalEntries = 0;
DWORD resume = 0;
- mDNSBool enabled = mDNSfalse;
+ mDNSBool advertise = mDNSfalse;
+ mDNSBool fileSharing = mDNSfalse;
+ mDNSBool printSharing = mDNSfalse;
+ HKEY key = NULL;
+ BOOL retry = FALSE;
NET_API_STATUS res;
mStatus err;
check( m );
- if ( mDNSIsFileAndPrintSharingEnabled() )
+ // Only do this if we're not shutting down
+
+ require_action_quiet( m->AdvertiseLocalAddresses && !m->ShutdownTime, exit, err = kNoErr );
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Services\\SMB", &key );
+
+ if ( !err )
+ {
+ DWORD dwSize = sizeof( DWORD );
+ RegQueryValueEx( key, L"Advertise", NULL, NULL, (LPBYTE) &advertise, &dwSize );
+ }
+
+ if ( advertise && mDNSIsFileAndPrintSharingEnabled( &retry ) )
{
- dlog( kDebugLevelTrace, DEBUG_NAME "file and print sharing is enabled\n" );
+ dlog( kDebugLevelTrace, DEBUG_NAME "Sharing is enabled\n" );
res = NetShareEnum( NULL, 1, ( LPBYTE* )&bufPtr, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resume );
PSHARE_INFO_1 p = bufPtr;
DWORD i;
- for( i = 0; i <= totalEntries; i++ )
+ for( i = 0; i < entriesRead; i++ )
{
// We are only interested if the user is sharing anything other
// than the built-in "print$" source
if ( ( p->shi1_type == STYPE_DISKTREE ) && ( wcscmp( p->shi1_netname, TEXT( "print$" ) ) != 0 ) )
{
- enabled = mDNStrue;
- break;
+ fileSharing = mDNStrue;
+ }
+ else if ( p->shi1_type == STYPE_PRINTQ )
+ {
+ printSharing = mDNStrue;
}
p++;
NetApiBufferFree( bufPtr );
bufPtr = NULL;
+ retry = FALSE;
+ }
+ else if ( res == NERR_ServerNotStarted )
+ {
+ retry = TRUE;
}
}
+
+ if ( retry )
+ {
+ __int64 qwTimeout;
+ LARGE_INTEGER liTimeout;
+
+ qwTimeout = -m->p->checkFileSharesTimeout * 10000000;
+ liTimeout.LowPart = ( DWORD )( qwTimeout & 0xFFFFFFFF );
+ liTimeout.HighPart = ( LONG )( qwTimeout >> 32 );
+
+ SetWaitableTimer( m->p->checkFileSharesTimer, &liTimeout, 0, CheckFileSharesProc, m, FALSE );
+ }
- if ( enabled && !m->p->smbRegistered )
+ if ( !m->p->smbFileSharing && fileSharing )
{
- domainname type;
- domainname domain;
- mDNSIPPort port = { { SMBPortAsNumber >> 8, SMBPortAsNumber & 0xFF } };
- mDNSInterfaceID iid = mDNSPlatformInterfaceIDfromInterfaceIndex( m, 0 );
+ if ( !gSMBThread )
+ {
+ if ( !gDNSSDLibrary )
+ {
+ gDNSSDLibrary = LoadLibrary( TEXT( "dnssd.dll" ) );
+ require_action( gDNSSDLibrary, exit, err = GetLastError() );
+ }
- dlog( kDebugLevelTrace, DEBUG_NAME "registering smb type\n" );
-
- MakeDomainNameFromDNSNameString(&type, "_smb._tcp" );
- MakeDomainNameFromDNSNameString(&domain, "local.");
+ if ( !gDNSServiceRegister )
+ {
+ gDNSServiceRegister = ( DNSServiceRegisterFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRegister" );
+ require_action( gDNSServiceRegister, exit, err = GetLastError() );
+ }
- 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 );
+ if ( !gDNSServiceRefDeallocate )
+ {
+ gDNSServiceRefDeallocate = ( DNSServiceRefDeallocateFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRefDeallocate" );
+ require_action( gDNSServiceRefDeallocate, exit, err = GetLastError() );
+ }
+
+ if ( !gSMBThreadRegisterEvent )
+ {
+ gSMBThreadRegisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ require_action( gSMBThreadRegisterEvent != NULL, exit, err = GetLastError() );
+ }
+
+ if ( !gSMBThreadDeregisterEvent )
+ {
+ gSMBThreadDeregisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ require_action( gSMBThreadDeregisterEvent != NULL, exit, err = GetLastError() );
+ }
+
+ if ( !gSMBThreadStopEvent )
+ {
+ gSMBThreadStopEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ require_action( gSMBThreadStopEvent != NULL, exit, err = GetLastError() );
+ }
+
+ if ( !gSMBThreadQuitEvent )
+ {
+ gSMBThreadQuitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ require_action( gSMBThreadQuitEvent != NULL, exit, err = GetLastError() );
+ }
+
+ gSMBThread = ( HANDLE ) _beginthreadex( NULL, 0, SMBRegistrationThread, m, 0, NULL );
+ require_action( gSMBThread != NULL, exit, err = GetLastError() );
+ }
- m->p->smbRegistered = mDNStrue;
+ SetEvent( gSMBThreadRegisterEvent );
+
+ m->p->smbFileSharing = mDNStrue;
}
- else if ( !enabled && m->p->smbRegistered )
+ else if ( m->p->smbFileSharing && !fileSharing )
{
dlog( kDebugLevelTrace, DEBUG_NAME "deregistering smb type\n" );
-
- err = mDNS_DeregisterService( m, &m->p->smbSRS );
- require_noerr( err, exit );
- m->p->smbRegistered = mDNSfalse;
+ if ( gSMBThreadDeregisterEvent != NULL )
+ {
+ SetEvent( gSMBThreadDeregisterEvent );
+ }
+
+ m->p->smbFileSharing = mDNSfalse;
}
exit:
- return;
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
}
-void
-UpdateWOMPConfig( mDNS * const m )
+BOOL
+IsWOMPEnabled( mDNS * const m )
{
- mDNSInterfaceData * ifd;
+ BOOL enabled;
- mDNSPlatformLock( m );
+ mDNSInterfaceData * ifd;
- m->p->womp = mDNSfalse;
+ enabled = FALSE;
for( ifd = m->p->interfaceList; ifd; ifd = ifd->next )
{
- ifd->interfaceInfo.NetWake = IsWOMPEnabled( ifd->name );
-
- if ( ifd->interfaceInfo.NetWake )
+ if ( IsWOMPEnabledForAdapter( ifd->name ) )
{
- m->p->womp = mDNStrue;
+ enabled = TRUE;
+ break;
}
}
- mDNSPlatformUnlock( m );
+ return enabled;
}
mDNSlocal mDNSu8
-IsWOMPEnabled( const char * adapterName )
+IsWOMPEnabledForAdapter( const char * adapterName )
{
char fileName[80];
NDIS_OID oid;
NDIS_PNP_CAPABILITIES * pNPC = NULL;
int err;
mDNSu8 ok = TRUE;
+
+ require_action( adapterName != NULL, exit, ok = FALSE );
+
+ dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter: %s\n", adapterName );
// Construct a device name to pass to CreateFile
CloseHandle( handle );
}
+ dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter returns %s\n", ok ? "true" : "false" );
+
return ( mDNSu8 ) ok;
}
+
+
+void
+SetSocketEventsEnabled( mDNS * const inMDNS, BOOL enabled )
+{
+ DEBUG_UNUSED( inMDNS );
+
+ if ( enabled )
+ {
+ int numEvents = 0;
+
+ check( !gSocketEventsEnabled );
+
+ // If we're enabled, then drain the queue right now.
+
+ while ( gSocketEvents.Head && ( numEvents < 100 ) )
+ {
+ SocketEvent * event = ( SocketEvent* ) gSocketEvents.Head;
+ RemoveFromList( &gSocketEvents, event );
+ check( event->handler );
+
+ // At this point we're going to call our event handler, and
+ // gSocketEventsEnabled should be FALSE. So if the callback
+ // does anything that causes alertable I/O callbacks to be
+ // invoked, we'll queue the packets instead of invoking core
+ // callbacks reentrantly.
+ //
+ // One potential problem here is a pathological case of
+ // continuing to queue packets during invocation of
+ // the callback, and thus never exiting out of this loop.
+ // This is entirely theoretical as we've never seen it happen,
+ // but just to be overly cautious, we'll only process a maximum of
+ // 100 events here just in case.
+
+ event->handler( inMDNS, event );
+ free( event );
+
+ numEvents++;
+ }
+ }
+
+ gSocketEventsEnabled = enabled;
+}
+
+
+mDNSlocal void
+FreeSocketEventsForSocket( mDNS * const inMDNS, void * sock )
+{
+ SocketEvent * event;
+
+ DEBUG_UNUSED( inMDNS );
+
+ for ( event = ( SocketEvent* ) gSocketEvents.Head; event; event = event->next )
+ {
+ if ( event->sock == sock )
+ {
+ RemoveFromList( &gSocketEvents, event );
+ free( event );
+ break;
+ }
+ }
+}
+
+
+mDNSlocal void
+FreeSocketEvents( mDNS * const inMDNS )
+{
+ DEBUG_UNUSED( inMDNS );
+
+ while ( gSocketEvents.Head )
+ {
+ SocketEvent * event = ( SocketEvent* ) gSocketEvents.Head;
+ RemoveFromList( &gSocketEvents, event );
+ free( event );
+ }
+}
+
+
+mDNSlocal void
+TCPSocketEventHandler( mDNS * const inMDNS, void * v )
+{
+ TCPSocketEvent * event = ( TCPSocketEvent* ) v;
+ TCPSocket * sock = ( TCPSocket* ) event->super.sock;
+
+ DEBUG_UNUSED( inMDNS );
+ check( sock );
+
+ sock->lastError = event->error;
+
+ if ( !event->error )
+ {
+ if ( event->bytesTransferred )
+ {
+ memcpy( sock->buf, event->buf, event->bytesTransferred );
+ sock->bptr = sock->buf;
+ sock->eptr = sock->buf + event->bytesTransferred;
+ }
+ else
+ {
+ sock->closed = TRUE;
+ }
+ }
+
+ if ( sock->readEventHandler != NULL )
+ {
+ sock->readEventHandler( sock );
+ }
+}
+
+
+mDNSlocal void
+UDPSocketEventHandler( mDNS * const inMDNS, void * v )
+{
+ UDPSocketEvent * event = ( UDPSocketEvent* ) v;
+
+ mDNSCoreReceive( inMDNS, &event->packet, event->end, &event->srcAddr, event->srcPort, &event->dstAddr, event->dstPort, event->iid );
+}
* 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: mDNSWin32.h,v $
-Revision 1.30 2009/07/17 19:59:46 herscher
-<rdar://problem/7062660> Update the womp settings for each network adapter immediately preceding the call to mDNSCoreMachineSleep().
-
-Revision 1.29 2009/07/07 21:34:58 herscher
-<rdar://problem/6713286> windows platform changes to support use as sleep proxy client
-
-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
-
-Revision 1.25 2006/07/06 00:05:44 cheshire
-"dDNS.h" renamed to "uDNS.h"
-
-Revision 1.24 2006/02/26 19:31:04 herscher
-<rdar://problem/4455038> Bonjour For Windows takes 90 seconds to start. This was caused by a bad interaction between the VirtualPC check, and the removal of the WMI dependency. The problem was fixed by: 1) checking to see if WMI is running before trying to talk to it. 2) Retrying the VirtualPC check every 10 seconds upon failure, stopping after 10 unsuccessful tries.
-
-Revision 1.23 2005/10/05 20:55:14 herscher
-<rdar://problem/4096464> Don't call SetLLRoute on loopback interface
-
-Revision 1.22 2005/03/04 22:44:53 shersche
-<rdar://problem/4022802> mDNSResponder did not notice changes to DNS server config
-
-Revision 1.21 2005/03/03 02:29:00 shersche
-Use the RegNames.h header file for registry key names
-
-Revision 1.20 2005/01/25 08:12:52 shersche
-<rdar://problem/3947417> Enable Unicast and add Dynamic DNS support.
-Bug #: 3947417
-
-Revision 1.19 2004/12/15 07:34:45 shersche
-Add platform support for IPv4 and IPv6 unicast sockets
-
-Revision 1.18 2004/10/11 21:53:15 shersche
-<rdar://problem/3832450> Change GetWindowsVersionString link scoping from static to non-static so that it can be accessed from other compilation units. The information returned in this function will be used to determine what service dependencies to use when calling CreateService().
-Bug #: 3832450
-
-Revision 1.17 2004/09/17 01:08:57 cheshire
-Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
- The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
- declared in that file are ONLY appropriate to single-address-space embedded applications.
- For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
-
-Revision 1.16 2004/08/05 05:43:01 shersche
-<rdar://problem/3751566> Add HostDescriptionChangedCallback so callers can choose to handle it when mDNSWin32 core detects that the computer description string has changed
-Bug #: 3751566
-
-Revision 1.15 2004/07/26 05:42:50 shersche
-use "Computer Description" for nicename if available, track dynamic changes to "Computer Description"
-
-Revision 1.14 2004/07/13 21:24:25 rpantos
-Fix for <rdar://problem/3701120>.
+#ifndef __MDNS_WIN32__
+#define __MDNS_WIN32__
-Revision 1.13 2004/06/24 15:23:24 shersche
-Add InterfaceListChanged callback. This callback is used in Service.c to add link local routes to the routing table
-Submitted by: herscher
+#include "CommonServices.h"
-Revision 1.12 2004/06/18 05:22:16 rpantos
-Integrate Scott's changes
+#if( !defined( _WIN32_WCE ) )
+ #include <mswsock.h>
+#endif
-Revision 1.11 2004/01/30 02:44:32 bradley
-Added support for IPv6 (v4 & v6, v4-only, v6-only, AAAA over v4, etc.). Added support for DNS-SD
-InterfaceID<->Interface Index mappings. Added support for loopback usage when no other interfaces
-are available. Updated unlock signaling to no longer require timenow - NextScheduledTime to be >= 0
-(it no longer is). Added unicast-capable detection to avoid using unicast when there is other mDNS
-software running on the same machine. Removed unneeded sock_XtoY routines. Added support for
-reporting HINFO records with the Windows and mDNSResponder version information.
+#include "mDNSEmbeddedAPI.h"
+#include "uDNS.h"
-Revision 1.10 2003/10/24 23:23:02 bradley
-Removed legacy port 53 support as it is no longer needed.
+#ifdef __cplusplus
+ extern "C" {
+#endif
-Revision 1.9 2003/08/20 06:21:25 bradley
-Updated to latest internal version of the mDNSWindows platform layer: Added support
-for Windows CE/PocketPC 2003; re-did interface-related code to emulate getifaddrs/freeifaddrs for
-restricting usage to only active, multicast-capable, and non-point-to-point interfaces and to ease
-the addition of IPv6 support in the future; Changed init code to serialize thread initialization to
-enable ThreadID improvement to wakeup notification; Define platform support structure locally to
-allow portable mDNS_Init usage; Removed dependence on modified mDNSCore: define interface ID<->name
-structures/prototypes locally; Changed to use _beginthreadex()/_endthreadex() on non-Windows CE
-platforms (re-mapped to CreateThread on Window CE) to avoid a leak in the Microsoft C runtime;
-Added IPv4/IPv6 string<->address conversion routines; Cleaned up some code and added HeaderDoc.
+typedef void ( *TCPReadEventHandler )( TCPSocket * sock );
+typedef void ( *TCPUserCallback )();
-Revision 1.8 2003/08/12 19:56:27 cheshire
-Update to APSL 2.0
+struct TCPSocket_struct
+{
+ TCPSocketFlags flags; // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with TCPSocketFlags flags
+ SOCKET fd;
+ TCPReadEventHandler readEventHandler;
+ HANDLE connectEvent;
+ BOOL connected;
+ TCPUserCallback userCallback;
+ void * userContext;
+ DWORD lastError;
+ BOOL closed;\r
+ OVERLAPPED overlapped;
+ WSABUF wbuf;
+ uint8_t buf[ 4192 ];
+ uint8_t * bptr;
+ uint8_t * eptr;
+ mDNS * m;
+};
-Revision 1.7 2003/07/23 02:23:01 cheshire
-Updated mDNSPlatformUnlock() to work correctly, now that <rdar://problem/3160248>
-"ScheduleNextTask needs to be smarter" has refined the way m->NextScheduledEvent is set
-Revision 1.6 2003/07/02 21:20:04 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
+struct UDPSocket_struct
+{
+ mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
+ mDNSAddr addr; // This is initialized by our code. If we don't get the
+ // dstAddr from WSARecvMsg we use this value instead.
+ SOCKET fd;
+ LPFN_WSARECVMSG recvMsgPtr;
+ OVERLAPPED overlapped;
+ WSAMSG wmsg;
+ WSABUF wbuf;
+ DNSMessage packet;
+ uint8_t controlBuffer[ 128 ];
+ struct sockaddr_storage srcAddr; // This is filled in by the WSARecv* function
+ INT srcAddrLen; // See above
+ struct mDNSInterfaceData * ifd;
+ UDPSocket * next;
+ mDNS * m;
+};
-Revision 1.5 2003/04/29 00:06:09 cheshire
-<rdar://problem/3242673> mDNSWindows needs a wakeupEvent object to signal the main thread
-Revision 1.4 2003/03/22 02:57:44 cheshire
-Updated mDNSWindows to use new "mDNS_Execute" model (see "mDNSCore/Implementer Notes.txt")
+typedef void ( *SocketEventHandler )( mDNS * const inMDNS, void * v );
-Revision 1.3 2002/09/21 20:44:54 zarzycki
-Added APSL info
-Revision 1.2 2002/09/20 05:55:16 bradley
-Multicast DNS platform plugin for Win32
+typedef struct SocketEvent
+{
+ void * sock;
+ SocketEventHandler handler;
+ struct SocketEvent * next;
+} SocketEvent;
-*/
-#ifndef __MDNS_WIN32__
-#define __MDNS_WIN32__
+typedef struct TCPSocketEvent
+{
+ struct SocketEvent super;
+ DWORD error;
+ DWORD bytesTransferred;
+ uint8_t buf[ 4192 ];
+} TCPSocketEvent;
-#include "CommonServices.h"
-#if( !defined( _WIN32_WCE ) )
- #include <mswsock.h>
-#endif
+typedef struct UDPSocketEvent
+{
+ struct SocketEvent super;
+ mDNSInterfaceID iid;
+ DNSMessage packet;
+ mDNSu8 * end;
+ mDNSAddr srcAddr;
+ mDNSIPPort srcPort;
+ mDNSAddr dstAddr;
+ mDNSIPPort dstPort;
+} UDPSocketEvent;
-#include "mDNSEmbeddedAPI.h"
-#include "uDNS.h"
-#ifdef __cplusplus
- extern "C" {
-#endif
//---------------------------------------------------------------------------------------------------------------------------
/*! @struct mDNSInterfaceData
typedef struct mDNSInterfaceData mDNSInterfaceData;
struct mDNSInterfaceData
{
- mDNSInterfaceData * next;
char name[ 128 ];
uint32_t index;
uint32_t scopeID;
- SocketRef sock;
-#if( !defined( _WIN32_WCE ) )
- LPFN_WSARECVMSG wsaRecvMsgFunctionPtr;
-#endif
- HANDLE readPendingEvent;
+ struct UDPSocket_struct sock;
NetworkInterfaceInfo interfaceInfo;
- mDNSAddr defaultAddr;
mDNSBool hostRegistered;
+ mDNSInterfaceData * next;
};
-//---------------------------------------------------------------------------------------------------------------------------
-/*! @typedef IdleThreadCallback
- @abstract mDNSWin32 core will call out through this function pointer
- after calling mDNS_Execute
-*/
-typedef mDNSs32 (*IdleThreadCallback)(mDNS * const inMDNS, mDNSs32 interval);
//---------------------------------------------------------------------------------------------------------------------------
+/*! @typedef RegisterWaitableEventHandler
+*/
+typedef void (*RegisterWaitableEventHandler)(mDNS * const inMDNS, HANDLE event, void * context );
//---------------------------------------------------------------------------------------------------------------------------
-/*! @typedef InterfaceListChangedCallback
-
- @abstract mDNSWin32 core will call out through this function pointer
- after detecting an interface list changed event
+/*! @typedef RegisterWaitableEventFunc
*/
-typedef void (*InterfaceListChangedCallback)(mDNS * const inMDNS);
-//---------------------------------------------------------------------------------------------------------------------------
-
+typedef mStatus (*RegisterWaitableEventFunc)(mDNS * const inMDNS, HANDLE event, void * context, RegisterWaitableEventHandler handler );
//---------------------------------------------------------------------------------------------------------------------------
-/*! @typedef HostDescriptionChangedCallback
-
- @abstract mDNSWin32 core will call out through this function pointer
- after detecting that the computer description has changed
+/*! @typedef UnregisterWaitableEventHandler
*/
-typedef void (*HostDescriptionChangedCallback)(mDNS * const inMDNS);
+typedef void (*UnregisterWaitableEventFunc)(mDNS * const inMDNS, HANDLE event );
+
//---------------------------------------------------------------------------------------------------------------------------
+/*! @typedef ReportStatusFunc
+*/
+typedef void (*ReportStatusFunc)(int inType, const char *inFormat, ...);
//---------------------------------------------------------------------------------------------------------------------------
struct mDNS_PlatformSupport_struct
{
- CRITICAL_SECTION lock;
- mDNSBool lockInitialized;
- HANDLE cancelEvent;
- HANDLE quitEvent;
- HANDLE interfaceListChangedEvent;
- 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 mainThread;
+ HANDLE checkFileSharesTimer;
+ mDNSs32 checkFileSharesTimeout;
+ RegisterWaitableEventFunc registerWaitableEventFunc;
+ UnregisterWaitableEventFunc unregisterWaitableEventFunc;
+ ReportStatusFunc reportStatusFunc;
time_t nextDHCPLeaseExpires;
- mDNSBool womp; // Does any interface support wake-on-magic-packet
- HKEY descKey;
- HKEY tcpipKey;
- HKEY ddnsKey;
- HKEY fileShareKey;
- HKEY firewallKey;
- mDNSBool smbRegistered;
+ char nbname[ 32 ];
+ char nbdomain[ 32 ];
+ mDNSBool smbFileSharing;
+ mDNSBool smbPrintSharing;
ServiceRecordSet smbSRS;
- mStatus initStatus;
+ AuthRecord smbSubTypes[ 2 ];
mDNSBool registeredLoopback4;
- SocketRef interfaceListChangedSocket;
int interfaceCount;
mDNSInterfaceData * interfaceList;
mDNSInterfaceData * inactiveInterfaceList;
- DWORD threadID;
- IdleThreadCallback idleThreadCallback;
- InterfaceListChangedCallback interfaceListChangedCallback;
- HostDescriptionChangedCallback hostDescriptionChangedCallback;
- SocketRef unicastSock4;
- HANDLE unicastSock4ReadEvent;
- mDNSAddr unicastSock4DestAddr;
-#if( !defined( _WIN32_WCE ) )
- LPFN_WSARECVMSG unicastSock4RecvMsgPtr;
-#endif
- SocketRef unicastSock6;
- HANDLE unicastSock6ReadEvent;
- mDNSAddr unicastSock6DestAddr;
-#if( !defined( _WIN32_WCE ) )
- LPFN_WSARECVMSG unicastSock6RecvMsgPtr;
-#endif
+ struct UDPSocket_struct unicastSock4;
+ struct UDPSocket_struct unicastSock6;
};
//---------------------------------------------------------------------------------------------------------------------------
struct sockaddr * ifa_netmask;
struct sockaddr * ifa_broadaddr;
struct sockaddr * ifa_dstaddr;
+ BYTE ifa_physaddr[6];
BOOL ifa_dhcpEnabled;
time_t ifa_dhcpLeaseExpires;
mDNSu8 ifa_womp;
} ifa_extra;
};
-
-extern void UpdateWOMPConfig();
+\r
+extern void InterfaceListDidChange( mDNS * const inMDNS );
+extern void ComputerDescriptionDidChange( mDNS * const inMDNS );
+extern void TCPIPConfigDidChange( mDNS * const inMDNS );
+extern void DynDNSConfigDidChange( mDNS * const inMDNS );
+extern void FileSharingDidChange( mDNS * const inMDNS );
+extern void FirewallDidChange( mDNS * const inMDNS );
+extern mStatus TCPAddSocket( mDNS * const inMDNS, TCPSocket *sock );
+extern mStatus SetupInterfaceList( mDNS * const inMDNS );
+extern mStatus TearDownInterfaceList( mDNS * const inMDNS );
+extern BOOL IsWOMPEnabled();
+extern void SetSocketEventsEnabled( mDNS * const inMDNS, BOOL val );
#ifdef __cplusplus
* 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: 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
-
-Revision 1.19 2006/06/08 23:09:37 cheshire
-Updated comment: Correct IPv6LL reverse-mapping domains are '{8,9,A,B}.E.F.ip6.arpa.',
-not only '0.8.E.F.ip6.arpa.' (Actual code still needs to be fixed.)
-
-Revision 1.18 2005/10/17 05:45:36 herscher
-Fix typo in previous checkin
-
-Revision 1.17 2005/10/17 05:30:00 herscher
-<rdar://problem/4071610> NSP should handle IPv6 AAAA queries for dot-local names
-
-Revision 1.16 2005/09/16 22:22:48 herscher
-<rdar://problem/4261460> No longer set the PATH variable when NSP is loaded.
-
-Revision 1.15 2005/07/14 22:12:00 shersche
-<rdar://problem/4178448> Delay load dnssd.dll so that it gracefully handles library loading problems immediately after installing Bonjour
-
-Revision 1.14 2005/03/29 20:35:28 shersche
-<rdar://problem/4053899> Remove reverse lookup implementation due to NSP framework limitation
-
-Revision 1.13 2005/03/29 19:42:47 shersche
-Do label check before checking etc/hosts file
-
-Revision 1.12 2005/03/21 00:42:45 shersche
-<rdar://problem/4021486> Fix build warnings on Win32 platform
-
-Revision 1.11 2005/03/16 03:04:51 shersche
-<rdar://problem/4050633> Don't issue multicast query multilabel dot-local names
-
-Revision 1.10 2005/02/23 22:16:07 shersche
-Unregister the NSP before registering to workaround an installer problem during upgrade installs
-
-Revision 1.9 2005/02/01 01:45:55 shersche
-Change mdnsNSP timeout to 2 seconds
-
-Revision 1.8 2005/01/31 23:27:25 shersche
-<rdar://problem/3936771> Don't try and resolve .local hostnames that are referenced in the hosts file
-
-Revision 1.7 2005/01/28 23:50:13 shersche
-<rdar://problem/3942551> Implement DllRegisterServer,DllUnregisterServer so mdnsNSP.dll can self-register
-Bug #: 3942551
-
-Revision 1.6 2004/12/06 01:56:53 shersche
-<rdar://problem/3789425> Use the DNS types and classes defined in dns_sd.h
-Bug #: 3789425
-
-Revision 1.5 2004/07/13 21:24:28 rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.4 2004/07/09 18:03:33 shersche
-removed extraneous DNSServiceQueryRecord call
-
-Revision 1.3 2004/07/07 17:03:49 shersche
-<rdar://problem/3715582> Check for LUP_RETURN_ADDR as well as LUP_RETURN_BLOB in NSPLookupServiceBegin
-Bug #: 3715582
-
-Revision 1.2 2004/06/24 19:18:07 shersche
-Rename to mdnsNSP
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:13:44 rpantos
-Move up one level.
-
-Revision 1.2 2004/04/08 09:43:43 bradley
-Changed callback calling conventions to __stdcall so they can be used with C# delegates.
-
-Revision 1.1 2004/01/30 03:00:33 bradley
-mDNS NameSpace Provider (NSP). Hooks into the Windows name resolution system to perform
-.local name lookups using Multicast DNS in all Windows apps.
-
-*/
+ */
#include <stdio.h>
; See the License for the specific language governing permissions and
; limitations under the License.
;
-; Change History (most recent first):
-;
-; $Log: mdnsNSP.def,v $
-; Revision 1.4 2006/08/14 23:26:10 cheshire
-; Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-;
-; Revision 1.3 2005/01/28 23:48:46 shersche
-; <rdar://problem/3942551> Export DllRegisterServer, DllUnregisterServer which can be called from the Installer or regsvr32
-; Bug #: 3942551
-;
-; Revision 1.2 2004/07/13 21:24:28 rpantos
-; Fix for <rdar://problem/3701120>.
-;
-; Revision 1.1 2004/06/18 04:13:44 rpantos
-; Move up one level.
-;
-; Revision 1.1 2004/01/30 03:00:33 bradley
-; mDNS NameSpace Provider (NSP). Hooks into the Windows name resolution system to
-; perform .local name lookups using Multicast DNS in all Windows apps.
-;
-;
LIBRARY mdnsNSP