]> git.saurik.com Git - apple/mdnsresponder.git/commitdiff
mDNSResponder-107.5.tar.gz v107.5
authorApple <opensource@apple.com>
Fri, 6 Jan 2006 01:28:50 +0000 (01:28 +0000)
committerApple <opensource@apple.com>
Fri, 6 Jan 2006 01:28:50 +0000 (01:28 +0000)
127 files changed:
Clients/BonjourExample/BonjourExample.cpp [new file with mode: 0644]
Clients/BonjourExample/BonjourExample.sln [new file with mode: 0644]
Clients/BonjourExample/BonjourExample.vcproj [new file with mode: 0644]
Clients/BonjourExample/stdafx.cpp [new file with mode: 0644]
Clients/BonjourExample/stdafx.h [new file with mode: 0644]
Clients/DNS-SD.VisualStudio/dns-sd.vcproj
Clients/ExplorerPlugin/ExplorerBarWindow.cpp
Clients/ExplorerPlugin/ExplorerPlugin.cpp
Clients/ExplorerPlugin/ExplorerPlugin.vcproj
Clients/ExplorerPlugin/ExplorerPluginLocRes.rc
Clients/ExplorerPlugin/ExplorerPluginLocRes.vcproj
Clients/ExplorerPlugin/ExplorerPluginRes.rc
Clients/ExplorerPlugin/ExplorerPluginRes.vcproj
Clients/ExplorerPlugin/StdAfx.h
Clients/ExplorerPlugin/res/globe.bmp [deleted file]
Clients/ExplorerPlugin/resource_res.h
Clients/Java/JavaSamples.vcproj [new file with mode: 0755]
Clients/Java/nmakefile
Clients/Makefile
Clients/PrinterSetupWizard/FirstPage.cpp
Clients/PrinterSetupWizard/FirstPage.h
Clients/PrinterSetupWizard/FourthPage.cpp
Clients/PrinterSetupWizard/FourthPage.h
Clients/PrinterSetupWizard/PrinterSetupWizard.vcproj
Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp
Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc
Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj
Clients/PrinterSetupWizard/PrinterSetupWizardRes.vcproj
Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp
Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h
Clients/PrinterSetupWizard/SecondPage.cpp
Clients/PrinterSetupWizard/SecondPage.h
Clients/PrinterSetupWizard/ThirdPage.cpp
Clients/PrinterSetupWizard/ThirdPage.h
Clients/PrinterSetupWizard/UtilTypes.h
Clients/PrinterSetupWizard/res/NetworkPrinter.ico
Clients/PrinterSetupWizard/res/Print.ico
Clients/PrinterSetupWizard/resource.h
Clients/PrinterSetupWizard/stdafx.h
Clients/dns-sd.c
Makefile
buildResults.xml [new file with mode: 0644]
mDNSCore/DNSCommon.c
mDNSCore/mDNS.c
mDNSCore/mDNSDebug.h
mDNSCore/mDNSEmbeddedAPI.h
mDNSCore/uDNS.c
mDNSMacOS9/mDNSMacOS9.c
mDNSMacOSX/LegacyNATTraversal.c
mDNSMacOSX/PreferencePane/BonjourPref.icns [new file with mode: 0644]
mDNSMacOSX/PreferencePane/BonjourPref.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/ConfigurationAuthority.c
mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns [deleted file]
mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff [deleted file]
mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib
mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib
mDNSMacOSX/PreferencePane/PrivilegedOperations.c
mDNSMacOSX/PreferencePane/PrivilegedOperations.h
mDNSMacOSX/PreferencePane/ddnswriteconfig.m
mDNSMacOSX/PreferencePane/installtool [new file with mode: 0755]
mDNSMacOSX/daemon.c
mDNSMacOSX/mDNSMacOSX.c
mDNSMacOSX/mDNSMacOSX.h
mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj
mDNSPosix/Makefile
mDNSPosix/NetMonitor.c
mDNSPosix/PosixDaemon.c
mDNSPosix/ProxyResponder.c
mDNSPosix/ReadMe.txt
mDNSPosix/Responder.c
mDNSPosix/dnsextd.c
mDNSPosix/mDNSPosix.c
mDNSPosix/mDNSUNP.c
mDNSPosix/mDNSUNP.h
mDNSPosix/nss_mdns.c
mDNSResponder.sln
mDNSShared/Java/DNSSD.java
mDNSShared/Java/DNSSDException.java
mDNSShared/Java/JNISupport.c
mDNSShared/PlatformCommon.c
mDNSShared/PlatformCommon.h
mDNSShared/dns-sd.1
mDNSShared/dns_sd.h
mDNSShared/dnssd_clientlib.c
mDNSShared/dnssd_clientstub.c
mDNSShared/dnssd_ipc.h
mDNSShared/uds_daemon.c
mDNSVxWorks/mDNSVxWorks.c
mDNSVxWorks/mDNSVxWorks.h
mDNSWindows/ControlPanel/ConfigPropertySheet.cpp
mDNSWindows/ControlPanel/ControlPanel.rc
mDNSWindows/ControlPanel/ControlPanel.vcproj
mDNSWindows/ControlPanel/FirstPage.cpp
mDNSWindows/ControlPanel/SecondPage.cpp
mDNSWindows/ControlPanel/SecondPage.h
mDNSWindows/ControlPanel/SharedSecret.cpp
mDNSWindows/ControlPanel/SharedSecret.h
mDNSWindows/ControlPanel/ThirdPage.cpp
mDNSWindows/ControlPanel/resource.h
mDNSWindows/ControlPanel/stdafx.h
mDNSWindows/DLL.NET/Stdafx.h
mDNSWindows/DLL.NET/dnssd_NET.vcproj
mDNSWindows/DLL/dllmain.c
mDNSWindows/DLL/dnssd.vcproj
mDNSWindows/Installer/Main.ism [deleted file]
mDNSWindows/Installer/SDK.ism [deleted file]
mDNSWindows/Java/Java.vcproj [new file with mode: 0755]
mDNSWindows/Java/makefile
mDNSWindows/NSPTool/NSPTool.vcproj
mDNSWindows/RegNames.h
mDNSWindows/SystemService/Firewall.cpp
mDNSWindows/SystemService/Service.c
mDNSWindows/SystemService/Service.vcproj
mDNSWindows/SystemServiceTest/Prefix.h [deleted file]
mDNSWindows/SystemServiceTest/Tool.c [deleted file]
mDNSWindows/SystemServiceTest/Tool.mcp [deleted file]
mDNSWindows/SystemServiceTest/Tool2002.vcproj [deleted file]
mDNSWindows/VPCDetect.cpp [new file with mode: 0755]
mDNSWindows/VPCDetect.h [new file with mode: 0644]
mDNSWindows/WinVersRes.h
mDNSWindows/dDNS.c
mDNSWindows/dDNS.h
mDNSWindows/loclibrary.c
mDNSWindows/mDNSWin32.c
mDNSWindows/mDNSWin32.h
mDNSWindows/mdnsNSP/mdnsNSP.c
mDNSWindows/mdnsNSP/mdnsNSP.vcproj

diff --git a/Clients/BonjourExample/BonjourExample.cpp b/Clients/BonjourExample/BonjourExample.cpp
new file mode 100644 (file)
index 0000000..ec448f4
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+
+    Change History (most recent first):
+
+$Log: BonjourExample.cpp,v $
+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"
+
+#include       <assert.h>
+#include       <stdio.h>
+
+#include       "dns_sd.h"
+
+// Constants
+
+#define BONJOUR_EVENT          ( WM_USER + 0x100 )     // Message sent to the Window when a Bonjour event occurs.
+
+// Prototypes
+
+static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam );
+
+static void DNSSD_API
+       BrowserCallBack( 
+               DNSServiceRef           inServiceRef, 
+               DNSServiceFlags         inFlags,
+               uint32_t                        inIFI, 
+               DNSServiceErrorType     inError,
+               const char *            inName,
+               const char *            inType,
+               const char *            inDomain, 
+               void *                          inContext );
+
+// Globals
+
+DNSServiceRef          gServiceRef = NULL;
+
+// Main entry point for application.
+
+int _tmain( int argc, _TCHAR *argv[] )
+{
+       HINSTANCE                               instance;
+       WNDCLASSEX                              wcex;
+       HWND                                    wind;
+       MSG                                             msg;
+       DNSServiceErrorType             err;
+       
+       (void) argc; // Unused
+       (void) argv; // Unused
+       
+       // Create the window. This window won't actually be shown, but it demonstrates how to use Bonjour
+       // with Windows GUI applications by having Bonjour events processed as messages to a Window.
+       
+       instance = GetModuleHandle( NULL );
+       assert( instance );
+       
+       wcex.cbSize                     = sizeof( wcex );
+       wcex.style                      = 0;
+       wcex.lpfnWndProc        = (WNDPROC) WndProc;
+       wcex.cbClsExtra         = 0;
+       wcex.cbWndExtra         = 0;
+       wcex.hInstance          = instance;
+       wcex.hIcon                      = NULL;
+       wcex.hCursor            = NULL;
+       wcex.hbrBackground      = NULL;
+       wcex.lpszMenuName       = NULL;
+       wcex.lpszClassName      = TEXT( "BonjourExample" );
+       wcex.hIconSm            = NULL;
+       RegisterClassEx( &wcex );
+       
+       wind = CreateWindow( wcex.lpszClassName, wcex.lpszClassName, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT, 
+               0, NULL, NULL, instance, NULL );
+       assert( wind );
+       
+       // Start browsing for services and associate the Bonjour browser with our window using the 
+       // WSAAsyncSelect mechanism. Whenever something related to the Bonjour browser occurs, our 
+       // private Windows message will be sent to our window so we can give Bonjour a chance to 
+       // process it. This allows Bonjour to avoid using a secondary thread (and all the issues 
+       // with synchronization that would introduce), but still process everything asynchronously.
+       // This also simplifies app code because Bonjour will only run when we explicitly call it.
+       
+       err = DNSServiceBrowse( 
+               &gServiceRef,                                   // Receives reference to Bonjour browser object.
+               0,                                                              // No flags.
+               kDNSServiceInterfaceIndexAny,   // Browse on all network interfaces.
+               "_http._tcp",                                   // Browse for HTTP service types.
+               NULL,                                                   // Browse on the default domain (e.g. local.).
+               BrowserCallBack,                                // Callback function when Bonjour events occur.
+               NULL );                                                 // No callback context needed.
+       assert( err == kDNSServiceErr_NoError );
+       
+       err = WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, FD_READ | FD_CLOSE );
+       assert( err == kDNSServiceErr_NoError );
+       
+       fprintf( stderr, "Browsing for _http._tcp\n" );
+       
+       // Main event loop for the application. All Bonjour events are dispatched while in this loop.
+       
+       while( GetMessage( &msg, NULL, 0, 0 ) ) 
+       {
+               TranslateMessage( &msg );
+               DispatchMessage( &msg );
+       }
+       
+       // Clean up Bonjour. This is not strictly necessary since the normal process cleanup will 
+       // close Bonjour socket(s) and release memory, but it's here to demonstrate how to do it.
+       
+       if( gServiceRef )
+       {
+               WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, 0 );
+               DNSServiceRefDeallocate( gServiceRef );
+       }
+       return( 0 );
+}
+
+// Callback for the Window. Bonjour events are delivered here.
+
+static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam )
+{
+       LRESULT                                 result;
+       DNSServiceErrorType             err;
+       
+       switch( inMsg )
+       {
+               case BONJOUR_EVENT:
+                       
+                       // Process the Bonjour event. All Bonjour callbacks occur from within this function.
+                       // If an error occurs while trying to process the result, it most likely means that
+                       // something serious has gone wrong with Bonjour, such as it being terminated. This 
+                       // does not normally occur, but code should be prepared to handle it. If the error 
+                       // is ignored, the window will receive a constant stream of BONJOUR_EVENT messages so
+                       // if an error occurs, we disassociate the DNSServiceRef from the window, deallocate
+                       // it, and invalidate the reference so we don't try to deallocate it again on quit. 
+                       // Since this is a simple example app, if this error occurs, we quit the app too.
+                       
+                       err = DNSServiceProcessResult( gServiceRef );
+                       if( err != kDNSServiceErr_NoError )
+                       {
+                               fprintf( stderr, "### ERROR! serious Bonjour error: %d\n", err );
+                               
+                               WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), inWindow, BONJOUR_EVENT, 0 );
+                               DNSServiceRefDeallocate( gServiceRef );
+                               gServiceRef = NULL;
+                               
+                               PostQuitMessage( 0 );
+                       }
+                       result = 0;
+                       break;
+               
+               default:
+                       result = DefWindowProc( inWindow, inMsg, inWParam, inLParam );
+                       break;
+       }
+       return( result );
+}
+
+// Callback for Bonjour browser events. Called when services are added or removed.
+
+static void DNSSD_API
+       BrowserCallBack( 
+               DNSServiceRef           inServiceRef, 
+               DNSServiceFlags         inFlags,
+               uint32_t                        inIFI, 
+               DNSServiceErrorType     inError,
+               const char *            inName,
+               const char *            inType,
+               const char *            inDomain, 
+               void *                          inContext )
+{
+       (void) inServiceRef;    // Unused
+       (void) inContext;               // Unused
+       
+       if( inError == kDNSServiceErr_NoError )
+       {
+               const char *            action;
+               const char *            more;
+               
+               if( inFlags & kDNSServiceFlagsAdd )                     action  = "ADD";
+               else                                                                            action  = "RMV";
+               if( inFlags & kDNSServiceFlagsMoreComing )      more    = " (MORE)";
+               else                                                                            more    = "";
+               
+               fprintf( stderr, "%s %30s.%s%s on interface %d%s\n", action, inName, inType, inDomain, (int) inIFI, more );
+       }
+       else
+       {
+               fprintf( stderr, "Bonjour browser error occurred: %d\n", inError );
+       }
+}
diff --git a/Clients/BonjourExample/BonjourExample.sln b/Clients/BonjourExample/BonjourExample.sln
new file mode 100644 (file)
index 0000000..fb80330
--- /dev/null
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BonjourExample", "BonjourExample.vcproj", "{0A842379-799E-414C-BF1F-BF11A8D3A8A8}"
+       ProjectSection(ProjectDependencies) = postProject
+       EndProjectSection
+EndProject
+Global
+       GlobalSection(SolutionConfiguration) = preSolution
+               Debug = Debug
+               Release = Release
+       EndGlobalSection
+       GlobalSection(ProjectConfiguration) = postSolution
+               {0A842379-799E-414C-BF1F-BF11A8D3A8A8}.Debug.ActiveCfg = Debug|Win32
+               {0A842379-799E-414C-BF1F-BF11A8D3A8A8}.Debug.Build.0 = Debug|Win32
+               {0A842379-799E-414C-BF1F-BF11A8D3A8A8}.Release.ActiveCfg = Release|Win32
+               {0A842379-799E-414C-BF1F-BF11A8D3A8A8}.Release.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+       EndGlobalSection
+       GlobalSection(ExtensibilityAddIns) = postSolution
+       EndGlobalSection
+EndGlobal
diff --git a/Clients/BonjourExample/BonjourExample.vcproj b/Clients/BonjourExample/BonjourExample.vcproj
new file mode 100644 (file)
index 0000000..b58f3b1
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+       ProjectType="Visual C++"
+       Version="7.10"
+       Name="BonjourExample"
+       ProjectGUID="{0A842379-799E-414C-BF1F-BF11A8D3A8A8}"
+       Keyword="Win32Proj">
+       <Platforms>
+               <Platform
+                       Name="Win32"/>
+       </Platforms>
+       <Configurations>
+               <Configuration
+                       Name="Debug|Win32"
+                       OutputDirectory="Debug"
+                       IntermediateDirectory="Debug"
+                       ConfigurationType="1"
+                       CharacterSet="1">
+                       <Tool
+                               Name="VCCLCompilerTool"
+                               Optimization="0"
+                               AdditionalIncludeDirectories="../../mDNSShared"
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+                               StringPooling="TRUE"
+                               MinimalRebuild="TRUE"
+                               ExceptionHandling="FALSE"
+                               BasicRuntimeChecks="3"
+                               SmallerTypeCheck="TRUE"
+                               RuntimeLibrary="5"
+                               BufferSecurityCheck="TRUE"
+                               ForceConformanceInForLoopScope="TRUE"
+                               UsePrecompiledHeader="3"
+                               BrowseInformation="1"
+                               WarningLevel="4"
+                               WarnAsError="TRUE"
+                               Detect64BitPortabilityProblems="TRUE"
+                               DebugInformationFormat="4"/>
+                       <Tool
+                               Name="VCCustomBuildTool"/>
+                       <Tool
+                               Name="VCLinkerTool"
+                               AdditionalDependencies="ws2_32.lib"
+                               OutputFile="$(OutDir)/BonjourExample.exe"
+                               LinkIncremental="2"
+                               GenerateDebugInformation="TRUE"
+                               ProgramDatabaseFile="$(OutDir)/BonjourExample.pdb"
+                               SubSystem="1"
+                               TargetMachine="1"/>
+                       <Tool
+                               Name="VCMIDLTool"/>
+                       <Tool
+                               Name="VCPostBuildEventTool"/>
+                       <Tool
+                               Name="VCPreBuildEventTool"/>
+                       <Tool
+                               Name="VCPreLinkEventTool"/>
+                       <Tool
+                               Name="VCResourceCompilerTool"/>
+                       <Tool
+                               Name="VCWebServiceProxyGeneratorTool"/>
+                       <Tool
+                               Name="VCXMLDataGeneratorTool"/>
+                       <Tool
+                               Name="VCWebDeploymentTool"/>
+                       <Tool
+                               Name="VCManagedWrapperGeneratorTool"/>
+                       <Tool
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+               </Configuration>
+               <Configuration
+                       Name="Release|Win32"
+                       OutputDirectory="Release"
+                       IntermediateDirectory="Release"
+                       ConfigurationType="1"
+                       CharacterSet="1">
+                       <Tool
+                               Name="VCCLCompilerTool"
+                               GlobalOptimizations="TRUE"
+                               OmitFramePointers="TRUE"
+                               AdditionalIncludeDirectories="../../mDNSShared"
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+                               StringPooling="TRUE"
+                               RuntimeLibrary="4"
+                               BufferSecurityCheck="FALSE"
+                               ForceConformanceInForLoopScope="TRUE"
+                               UsePrecompiledHeader="3"
+                               WarningLevel="4"
+                               WarnAsError="TRUE"
+                               Detect64BitPortabilityProblems="TRUE"
+                               DebugInformationFormat="3"
+                               CompileAs="2"/>
+                       <Tool
+                               Name="VCCustomBuildTool"/>
+                       <Tool
+                               Name="VCLinkerTool"
+                               AdditionalDependencies="ws2_32.lib"
+                               OutputFile="$(OutDir)/BonjourExample.exe"
+                               LinkIncremental="1"
+                               GenerateDebugInformation="TRUE"
+                               SubSystem="1"
+                               OptimizeReferences="2"
+                               EnableCOMDATFolding="2"
+                               TargetMachine="1"/>
+                       <Tool
+                               Name="VCMIDLTool"/>
+                       <Tool
+                               Name="VCPostBuildEventTool"/>
+                       <Tool
+                               Name="VCPreBuildEventTool"/>
+                       <Tool
+                               Name="VCPreLinkEventTool"/>
+                       <Tool
+                               Name="VCResourceCompilerTool"/>
+                       <Tool
+                               Name="VCWebServiceProxyGeneratorTool"/>
+                       <Tool
+                               Name="VCXMLDataGeneratorTool"/>
+                       <Tool
+                               Name="VCWebDeploymentTool"/>
+                       <Tool
+                               Name="VCManagedWrapperGeneratorTool"/>
+                       <Tool
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+               </Configuration>
+       </Configurations>
+       <References>
+       </References>
+       <Files>
+               <File
+                       RelativePath=".\BonjourExample.cpp">
+               </File>
+               <File
+                       RelativePath="..\..\mDNSWindows\Dll\release\dnssd.lib">
+               </File>
+               <File
+                       RelativePath=".\stdafx.cpp">
+                       <FileConfiguration
+                               Name="Debug|Win32">
+                               <Tool
+                                       Name="VCCLCompilerTool"
+                                       UsePrecompiledHeader="1"/>
+                       </FileConfiguration>
+                       <FileConfiguration
+                               Name="Release|Win32">
+                               <Tool
+                                       Name="VCCLCompilerTool"
+                                       UsePrecompiledHeader="1"/>
+                       </FileConfiguration>
+               </File>
+               <File
+                       RelativePath=".\stdafx.h">
+               </File>
+       </Files>
+       <Globals>
+       </Globals>
+</VisualStudioProject>
diff --git a/Clients/BonjourExample/stdafx.cpp b/Clients/BonjourExample/stdafx.cpp
new file mode 100644 (file)
index 0000000..2b2483e
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+
+    Change History (most recent first):
+
+$Log: stdafx.cpp,v $
+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.
+
+#include       "stdafx.h"
diff --git a/Clients/BonjourExample/stdafx.h b/Clients/BonjourExample/stdafx.h
new file mode 100644 (file)
index 0000000..6ded040
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+
+    Change History (most recent first):
+
+$Log: stdafx.h,v $
+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.
+
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN            // Exclude rarely-used stuff from Windows headers
+
+#include       <windows.h>
+#include       <winsock2.h>
+
+#include       <stdlib.h>
+#include       <malloc.h>
+#include       <memory.h>
+#include       <tchar.h>
index dda633b971d544cd16cfb07b8e18b9aa3a45b437..4c3a515f6791447125a8c3630716fe2c79fa16f8 100755 (executable)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="dns-sd"\r
        ProjectGUID="{AA230639-E115-4A44-AA5A-44A61235BA50}"\r
        Keyword="Win32Proj">\r
@@ -20,7 +20,7 @@
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories="../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF"\r
+                               PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN"\r
                                MinimalRebuild="TRUE"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="5"\r
                                AdditionalIncludeDirectories="../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
+                       OutputDirectory=".\Release"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="1"\r
                        CharacterSet="2">\r
@@ -67,7 +73,7 @@
                                InlineFunctionExpansion="1"\r
                                OmitFramePointers="TRUE"\r
                                AdditionalIncludeDirectories="../../mDNSShared"\r
-                               PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF"\r
+                               PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN"\r
                                StringPooling="TRUE"\r
                                RuntimeLibrary="4"\r
                                EnableFunctionLevelLinking="TRUE"\r
                                AdditionalIncludeDirectories="../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
index a68880b2a643aae03584be98f22dd215f1973832..d4ea5c1d6849c8b6a3465f7d7f2b74ca7e151170 100644 (file)
     Change History (most recent first):
     
 $Log: ExplorerBarWindow.cpp,v $
+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
 
@@ -143,6 +152,10 @@ static char THIS_FILE[] = __FILE__;
 
 #define        kTXTRecordKeyPath                               "path"
 
+// IE Icon resource
+
+#define kIEIconResource                                        32529
+
 
 #if 0
 #pragma mark == Prototypes ==
@@ -205,6 +218,7 @@ int ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct )
 {
        AFX_MANAGE_STATE( AfxGetStaticModuleState() );
        
+       HINSTANCE               module = NULL;
        OSStatus                err;
        CRect                   rect;
        CBitmap                 bitmap;
@@ -231,7 +245,7 @@ int ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct )
        mServiceHandlers.Add( e );
 
        s.LoadString( IDS_ABOUT );
-       m_about = mTree.InsertItem( s, 1, 1 );
+       m_about = mTree.InsertItem( s, 0, 0 );
 
        err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
        require_noerr( err, exit );
@@ -241,17 +255,22 @@ int       ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct )
 
        m_serviceRefs.push_back(e->ref);
 
-       m_imageList.Create( 16, 16, ILC_COLORDDB, 2, 0);
-       bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_GLOBE ) ) );
-       m_imageList.Add( &bitmap, (CBitmap*) NULL );
-       bitmap.Detach();
+       m_imageList.Create( 16, 16, ILC_MASK | ILC_COLOR16, 2, 0);
+
        bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_LOGO ) ) );
        m_imageList.Add( &bitmap, (CBitmap*) NULL );
+       bitmap.Detach();
 
        mTree.SetImageList(&m_imageList, TVSIL_NORMAL);
        
 exit:
 
+       if ( module )
+       {
+               FreeLibrary( module );
+               module = NULL;
+       }
+
        // Cannot talk to the mDNSResponder service. Show the error message and exit (with kNoErr so they can see it).
        if ( err )
        {
index 766c1737c0bd7a55793614b7bc5f8459e49134e5..34b981e687175033607784a7f66711b4ba6ecbcb 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: ExplorerPlugin.cpp,v $
+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
 
@@ -125,6 +128,14 @@ GetLocalizedResources()
        return g_localizedResources;
 }
 
+// This is the class GUID for an undocumented hook into IE that will allow us to register
+// and have IE notice our new ExplorerBar without rebooting.
+// {8C7461EF-2B13-11d2-BE35-3078302C2030}
+
+DEFINE_GUID(CLSID_CompCatCacheDaemon, 
+0x8C7461EF, 0x2b13, 0x11d2, 0xbe, 0x35, 0x30, 0x78, 0x30, 0x2c, 0x20, 0x30);
+
+
 #if 0
 #pragma mark == Globals ==
 #endif
@@ -248,9 +259,10 @@ exit:
 
 STDAPI DllRegisterServer( void )
 {
-       HRESULT         err;
-       BOOL            ok;
-       CString         s;
+       IRunnableTask * pTask = NULL;
+       HRESULT                 err;
+       BOOL                    ok;
+       CString                 s;
        
        dlog( kDebugLevelTrace, "DllRegisterServer\n" );
        
@@ -262,7 +274,16 @@ STDAPI     DllRegisterServer( void )
        
        err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, TRUE );
        require_noerr( err, exit );
-       
+
+       // <rdar://problem/4130635> Clear IE cache so it will rebuild the cache when it runs next.  This
+       // will allow us to install and not reboot
+
+       err = CoCreateInstance(CLSID_CompCatCacheDaemon, NULL, CLSCTX_INPROC, IID_IRunnableTask, (void**) &pTask);
+       require_noerr( err, exit );
+
+       pTask->Run();
+       pTask->Release();
+
 exit:
        return( err );
 }
index c0f9af34ae589d969f2612305841c8d379a2743b..4d875a80ca0322461d000b4a4f13bb2d4449ff12 100644 (file)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="ExplorerPlugin"\r
        ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
        SccProjectName=""\r
                                AdditionalIncludeDirectories="../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
+                       OutputDirectory=".\Release"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="2"\r
                        UseOfMFC="1"\r
                                SuppressStartupBanner="TRUE"\r
                                Detect64BitPortabilityProblems="TRUE"\r
                                CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
                                AdditionalIncludeDirectories="../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Support"\r
                                RelativePath="..\..\mDNSWindows\DebugServices.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\WinServices.cpp">\r
+                               RelativePath="..\..\mDNSWindows\isocode.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\WinServices.h">\r
+                               RelativePath="..\..\mDNSWindows\loclibrary.c">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\isocode.h">\r
+                               RelativePath="..\..\mDNSWindows\loclibrary.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\loclibrary.c">\r
+                               RelativePath="..\..\mDNSWindows\WinServices.cpp">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSWindows\loclibrary.h">\r
+                               RelativePath="..\..\mDNSWindows\WinServices.h">\r
                        </File>\r
                </Filter>\r
                <Filter\r
                                RelativePath="Resource.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="StdAfx.h">\r
+                               RelativePath="resource_dll.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="resource_dll.h">\r
+                               RelativePath="StdAfx.h">\r
                        </File>\r
                </Filter>\r
                <Filter\r
index 7e025f271d645f34e9eb079174bfdb696d7fd697..34cf048a51f320cba9408d144ece006524978f1d 100755 (executable)
@@ -177,7 +177,7 @@ END
 STRINGTABLE \r
 BEGIN\r
     IDS_ABOUT               "About Bonjour"\r
-    IDS_ABOUT_URL           "http://www.apple.com/macosx/features/rendezvous"\r
+    IDS_ABOUT_URL           "http://www.apple.com/macosx/features/bonjour"\r
     IDS_NAME                "Bonjour"\r
     IDS_WEB_SITES           "Web Sites"\r
     IDS_PRINTERS            "Printers"\r
index bcb02693eae341813f5c3694b103db93aaed4517..71e630e01da2c4f90d699dec95da3b02417d4971 100755 (executable)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="ExplorerPluginLocRes"\r
        ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
        SccProjectName=""\r
@@ -13,7 +13,7 @@
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj"\r
+                       OutputDirectory=".\Debug\ExplorerPlugin.Resources\en.lproj"\r
                        IntermediateDirectory=".\Debug"\r
                        ConfigurationType="2"\r
                        UseOfMFC="1"\r
@@ -71,9 +71,9 @@
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                                Description="Building Output Directories"\r
-                               CommandLine="if not exist Debug\Resources mkdir Debug\Resources\r
-if not exist Debug\Resources\ExplorerPlugin.dll.Resources mkdir Debug\Resources\ExplorerPlugin.dll.Resources\r
-if not exist Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj mkdir Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj"/>\r
+                               CommandLine="if not exist Debug\ExplorerPlugin.Resources mkdir Debug\ExplorerPlugin.Resources\r
+if not exist Debug\ExplorerPlugin.Resources\en.lproj mkdir Debug\ExplorerPlugin.Resources\en.lproj\r
+"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
@@ -81,12 +81,18 @@ if not exist Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj mkdir Debug\R
                                AdditionalIncludeDirectories="../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj"\r
+                       OutputDirectory=".\Release\ExplorerPlugin.Resources\en.lproj"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="2"\r
                        UseOfMFC="1"\r
@@ -148,12 +154,10 @@ if not exist Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj mkdir Debug\R
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                                Description="Building Output Directories"\r
-                               CommandLine="if not exist Release\Root mkdir Release\Root\r
-if not exist &quot;Release\Root\Program Files&quot; mkdir &quot;Release\Root\Program Files&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour&quot; mkdir &quot;Release\Root\Program Files\Bonjour&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj&quot;"/>\r
+                               CommandLine="if not exist Release mkdir Release\r
+if not exist &quot;Release\ExplorerPlugin.Resources&quot; mkdir &quot;Release\ExplorerPlugin.Resources&quot;\r
+if not exist &quot;Release\ExplorerPlugin.Resources\en.lproj&quot; mkdir &quot;Release\ExplorerPlugin.Resources\en.lproj&quot;\r
+"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
@@ -161,10 +165,18 @@ if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.d
                                AdditionalIncludeDirectories="../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Header Files"\r
index d97ab2039ff502ffe359068f2609a788a9b85dae..5ed5f4e20e270d8993c2baf32a981f566579010b 100755 (executable)
@@ -104,7 +104,6 @@ END
 \r
 IDB_LOGO                BITMAP                  "res\\logo.bmp"\r
 IDB_ABOUT               BITMAP                  "res\\about.bmp"\r
-IDB_GLOBE                                      BITMAP                                          "res\\globe.bmp"\r
 \r
 /////////////////////////////////////////////////////////////////////////////\r
 //\r
index 0949120516428fcb676bdf3cb5a8b23635dd8f28..a0b83bb1176046926e68813e9bdc12c7f29ae19c 100755 (executable)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="ExplorerPluginRes"\r
        ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
        SccProjectName=""\r
@@ -13,7 +13,7 @@
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug\Resources\ExplorerPlugin.dll.Resources"\r
+                       OutputDirectory=".\Debug\ExplorerPlugin.Resources"\r
                        IntermediateDirectory=".\Debug"\r
                        ConfigurationType="2"\r
                        UseOfMFC="1"\r
@@ -70,8 +70,7 @@
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                                Description="Building Output Directories"\r
-                               CommandLine="if not exist Debug\Resources mkdir Debug\Resources\r
-if not exist Debug\Resources\ExplorerPlugin.dll.Resources mkdir Debug\Resources\ExplorerPlugin.dll.Resources"/>\r
+                               CommandLine="if not exist Debug\ExplorerPlugin.Resources mkdir Debug\ExplorerPlugin.Resources"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
@@ -79,12 +78,18 @@ if not exist Debug\Resources\ExplorerPlugin.dll.Resources mkdir Debug\Resources\
                                AdditionalIncludeDirectories="../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources"\r
+                       OutputDirectory=".\Release\ExplorerPlugin.Resources"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="2"\r
                        UseOfMFC="1"\r
@@ -145,11 +150,9 @@ if not exist Debug\Resources\ExplorerPlugin.dll.Resources mkdir Debug\Resources\
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                                Description="Building Output Directories"\r
-                               CommandLine="if not exist Release\Root mkdir Release\Root\r
-if not exist &quot;Release\Root\Program Files&quot; mkdir &quot;Release\Root\Program Files&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour&quot; mkdir &quot;Release\Root\Program Files\Bonjour&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources&quot;"/>\r
+                               CommandLine="if not exist Release mkdir Release\r
+if not exist &quot;Release\ExplorerPlugin.Resources&quot; mkdir &quot;Release\ExplorerPlugin.Resources&quot;\r
+"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
@@ -157,10 +160,18 @@ if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.d
                                AdditionalIncludeDirectories="../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Header Files"\r
@@ -173,17 +184,11 @@ if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.d
                        Name="Resource Files"\r
                        Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">\r
                        <File\r
-                               RelativePath="ExplorerPluginRes.rc">\r
-                       </File>\r
-                       <File\r
-                               RelativePath="Web.ico">\r
+                               RelativePath="res\about.bmp">\r
                        </File>\r
                        <File\r
                                RelativePath=".\about.bmp">\r
                        </File>\r
-                       <File\r
-                               RelativePath="res\about.bmp">\r
-                       </File>\r
                        <File\r
                                RelativePath="res\button-2k.ico">\r
                        </File>\r
@@ -193,14 +198,20 @@ if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.d
                        <File\r
                                RelativePath=".\res\cold.ico">\r
                        </File>\r
+                       <File\r
+                               RelativePath="ExplorerPluginRes.rc">\r
+                       </File>\r
                        <File\r
                                RelativePath=".\hot.ico">\r
                        </File>\r
+                       <File\r
+                               RelativePath="res\logo.bmp">\r
+                       </File>\r
                        <File\r
                                RelativePath=".\logo.bmp">\r
                        </File>\r
                        <File\r
-                               RelativePath="res\logo.bmp">\r
+                               RelativePath="Web.ico">\r
                        </File>\r
                </Filter>\r
        </Files>\r
index ca625a1327a06f27991cd202ab4c926969633955..407ff3c0a11a390d5a0f81dc00b329103a31cf2a 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: StdAfx.h,v $
+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>.
 
@@ -43,6 +46,10 @@ Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within
 #define VC_EXTRALEAN           // Exclude rarely-used stuff from Windows headers
 #endif
 
+#if !defined(_WSPIAPI_COUNTOF)
+#      define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#endif
+
 #include <afxwin.h>         // MFC core and standard components
 #include <afxext.h>         // MFC extensions
 #include <afxdtctl.h>          // MFC support for Internet Explorer 4 Common Controls
diff --git a/Clients/ExplorerPlugin/res/globe.bmp b/Clients/ExplorerPlugin/res/globe.bmp
deleted file mode 100755 (executable)
index af43b4e..0000000
Binary files a/Clients/ExplorerPlugin/res/globe.bmp and /dev/null differ
index 4f66a0cc966d16f34ef7f3bcbb18a6ed4743e831..c4aae0a10a7a0d598f9b94b4cc724b44fb209d40 100755 (executable)
@@ -11,7 +11,6 @@
 #define IDI_BUTTON_2K                   115\r
 #define IDI_BUTTON_XP                   118\r
 #define IDB_ABOUT                       119\r
-#define IDB_GLOBE                       149\r
 #define IDC_COMPONENT                   1001\r
 #define IDC_LEGAL                       1002\r
 #define IDC_LOGIN_USERNAME_TEXT         1182\r
diff --git a/Clients/Java/JavaSamples.vcproj b/Clients/Java/JavaSamples.vcproj
new file mode 100755 (executable)
index 0000000..fe6c134
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="JavaSamples"\r
+       ProjectGUID="{A987A0C1-344F-475C-869C-F082EB11EEBA}"\r
+       Keyword="MakeFileProj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="Debug"\r
+                       IntermediateDirectory="Debug"\r
+                       ConfigurationType="0">\r
+                       <Tool\r
+                               Name="VCNMakeTool"\r
+                               BuildCommandLine="nmake /f nmakefile DEBUG=1 DNS_SD=..\..\mDNSWindows\Java\build\debug\dns_sd.jar"\r
+                               ReBuildCommandLine="nmake /f nmakefile DEBUG=1 DNS_SD=..\..\mDNSWindows\Java\build\debug\dns_sd.jar"\r
+                               CleanCommandLine="nmake /f nmakefile DEBUG=1 CLEAN"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="Release"\r
+                       IntermediateDirectory="Release"\r
+                       ConfigurationType="0">\r
+                       <Tool\r
+                               Name="VCNMakeTool"\r
+                               BuildCommandLine="nmake /f nmakefile DNS_SD=..\..\mDNSWindows\Java\build\prod\dns_sd.jar"\r
+                               ReBuildCommandLine="nmake /f nmakefile DNS_SD=..\..\mDNSWindows\Java\build\prod\dns_sd.jar"\r
+                               CleanCommandLine="nmake /f nmakefile CLEAN"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
index 6fa95cbff246f3f8fb2ce9c88befdd4c9e26e370..4c016332c926e5eb3ed764af990655e7c54df527 100644 (file)
@@ -35,7 +35,7 @@
 
 ############################################################################
 
-JDK = \javasdk
+JDK = $(JAVA_HOME)
 
 CP = copy
 RM = del /Q
index 709bd2b922ae9deb959b4d987832ba9b4aa526e0..b79bf6f8875c1c38cb9ca671612e73256045946a 100755 (executable)
@@ -20,6 +20,9 @@
 # @APPLE_LICENSE_HEADER_END@
 #
 # $Log: Makefile,v $
+# 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"
 #
 
 #############################################################################
 
-
-# If library /usr/lib/libdns_sd.* exists, then link it
-ifneq "$(wildcard /usr/lib/libdns_sd.*)" ""
-LIBS = -ldns_sd
-else
+# On OS X the dns_sd library functions are included in libSystem, which is implicitly linked with every executable
+# If /usr/lib/libSystem.dylib exists, then we're on OS X, so we don't need also to link the "dns_sd" shared library
+ifneq "$(wildcard /usr/lib/libSystem.dylib)" ""
 LIBS =
+else
+LIBS = -L../mDNSPosix/build/prod/ -ldns_sd
 endif
 
 targets: build/dns-sd
index 530b26cf8520670fda0a3d7863f136f8c2e9adbf..b5131dac93c425425d112f3dbb9006d87639e425 100644 (file)
     Change History (most recent first):
     
 $Log: FirstPage.cpp,v $
+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
@@ -39,6 +45,7 @@ First checked in
 
 #include "stdafx.h"
 #include "PrinterSetupWizardApp.h"
+#include "PrinterSetupWizardSheet.h"
 #include "FirstPage.h"
 
 #include <DebugServices.h>
@@ -77,33 +84,41 @@ void CFirstPage::DoDataExchange(CDataExchange* pDX)
 BOOL
 CFirstPage::OnSetActive()
 {
-       static bool firstTime = true;
-
-       if ( firstTime )
-       {
-               CStatic * image = (CStatic*) GetDlgItem( IDC_INFO );
-               check( image );
-
-               image->SetIcon( LoadIcon( GetNonLocalizedResources(), MAKEINTRESOURCE( IDI_INFO ) ) );
-
-               firstTime = false;
-       }
+       CPrinterSetupWizardSheet * psheet;
+       CString greetingText;
 
-       CPropertySheet* psheet = (CPropertySheet*) GetParent();   
+       psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+       require_quiet( psheet, exit );   
    
        psheet->SetWizardButtons(PSWIZB_NEXT);
 
        m_greeting.SetFont(&m_largeFont);
 
-       CString greetingText;
-
        greetingText.LoadString(IDS_GREETING);
        m_greeting.SetWindowText(greetingText);
 
+exit:
+
        return CPropertyPage::OnSetActive();
 }
 
 
+BOOL
+CFirstPage::OnKillActive()
+{
+       CPrinterSetupWizardSheet * psheet;
+
+       psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+       require_quiet( psheet, exit );   
+   
+       psheet->SetLastPage(this);
+
+exit:
+
+       return CPropertyPage::OnKillActive();
+}
+
+
 BEGIN_MESSAGE_MAP(CFirstPage, CPropertyPage)
 END_MESSAGE_MAP()
 
index 5c23bdf86584dac1ae4717234f1f7f28bcbf7fe5..a798eb09c6656016de4236b592a0cd9c08c10ca8 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: FirstPage.h,v $
+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
 
@@ -49,6 +52,7 @@ public:
 protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
        virtual BOOL OnSetActive();
+       virtual BOOL OnKillActive();
        
 
        DECLARE_MESSAGE_MAP()
index a2a7a502893236ce9cb23c11adc313fe8603b243..876e28ba98382b75b9d172935e943c2dbfb25461 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: FourthPage.cpp,v $
+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
 
@@ -150,3 +153,19 @@ exit:
 
        return CPropertyPage::OnSetActive();
 }
+
+
+BOOL
+CFourthPage::OnKillActive()
+{
+       CPrinterSetupWizardSheet * psheet;
+
+       psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+       require_quiet( psheet, exit );   
+   
+       psheet->SetLastPage(this);
+
+exit:
+
+       return CPropertyPage::OnKillActive();
+}
index b488e20ef6fd231332d17b03161c5a04d5a6adaa..fca8cd1f2aee5f36ecefdf92e0afe7030e94dfae 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: FourthPage.h,v $
+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
 
@@ -50,6 +53,7 @@ public:
        enum { IDD = IDD_FOURTH_PAGE };
 
        virtual BOOL OnSetActive();
+       virtual BOOL OnKillActive();
 
 protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
index 4bff36a4540c5e3e8dadd3f17f7ffb97f9fb94a0..c407853fab33da00ada61bcf8a511d1dea4d0b9e 100644 (file)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "windows-1251"?>\r
+<?xml version="1.0" encoding="windows-1251"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="PrinterSetupWizard"\r
        ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
        Keyword="MFCProj">\r
@@ -20,7 +20,7 @@
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared;C:\WINDDK\2600.1106\inc;C:\WINDDK\2600.1106\inc\wxp"\r
+                               AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared"\r
                                PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0501;UNICODE;_UNICODE"\r
                                StringPooling="TRUE"\r
                                MinimalRebuild="TRUE"\r
                                AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
+                       OutputDirectory=".\Release"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="1"\r
                        UseOfMFC="1"\r
@@ -78,7 +84,7 @@
                                Optimization="2"\r
                                InlineFunctionExpansion="1"\r
                                OmitFramePointers="TRUE"\r
-                               AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared;C:\WINDDK\2600.1106\inc;C:\WINDDK\2600.1106\inc\wxp"\r
+                               AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared"\r
                                PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0501;UNICODE;_UNICODE"\r
                                StringPooling="TRUE"\r
                                MinimalRebuild="FALSE"\r
                                AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
                                RelativePath="SecondPage.cpp">\r
                        </File>\r
                        <File\r
-                               RelativePath=".\StdioFileEx.cpp">\r
+                               RelativePath="stdafx.cpp">\r
                        </File>\r
                        <File\r
-                               RelativePath="ThirdPage.cpp">\r
+                               RelativePath=".\StdioFileEx.cpp">\r
                        </File>\r
                        <File\r
-                               RelativePath="stdafx.cpp">\r
+                               RelativePath="ThirdPage.cpp">\r
                        </File>\r
                </Filter>\r
                <Filter\r
                                RelativePath="PrinterSetupWizardSheet.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="SecondPage.h">\r
+                               RelativePath="resource.h">\r
                        </File>\r
                        <File\r
-                               RelativePath=".\StdioFileEx.h">\r
+                               RelativePath="resource_exe.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="ThirdPage.h">\r
+                               RelativePath="SecondPage.h">\r
                        </File>\r
                        <File\r
-                               RelativePath=".\UtilTypes.h">\r
+                               RelativePath="stdafx.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="resource.h">\r
+                               RelativePath=".\StdioFileEx.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="resource_exe.h">\r
+                               RelativePath="ThirdPage.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="stdafx.h">\r
+                               RelativePath=".\UtilTypes.h">\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
+                       <File\r
+                               RelativePath="res\about.bmp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="res\banner_icon.bmp">\r
+                       </File>\r
                        <File\r
                                RelativePath="res\Info.ico">\r
                        </File>\r
                        <File\r
                                RelativePath="PrinterSetupWizard.rc">\r
                        </File>\r
-                       <File\r
-                               RelativePath="res\about.bmp">\r
-                       </File>\r
-                       <File\r
-                               RelativePath="res\banner_icon.bmp">\r
-                       </File>\r
                        <File\r
                                RelativePath="res\watermark.bmp">\r
                        </File>\r
                        <File\r
                                RelativePath="..\..\mDNSWindows\DebugServices.h">\r
                        </File>\r
-                       <File\r
-                               RelativePath="..\..\mDNSWindows\WinServices.cpp">\r
-                       </File>\r
-                       <File\r
-                               RelativePath="..\..\mDNSWindows\WinServices.h">\r
-                       </File>\r
                        <File\r
                                RelativePath="..\..\mDNSShared\dns_sd.h">\r
                        </File>\r
                        <File\r
                                RelativePath="..\..\mDNSWindows\loclibrary.h">\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSWindows\WinServices.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSWindows\WinServices.h">\r
+                       </File>\r
                </Filter>\r
                <File\r
                        RelativePath="ReadMe.txt">\r
index 08a0505ae4e6a05bf549a2c4af044bd975ff36fb..7b6544313604e74af47fcd109d2d7de20ca8349a 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: PrinterSetupWizardApp.cpp,v $
+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
 
@@ -123,7 +126,7 @@ BOOL CPrinterSetupWizardApp::InitInstance()
 
        // Load Resources
 
-       res = PathForResource( NULL, L"PrinterWizard.dll", resource, MAX_PATH );
+       res = PathForResource( NULL, L"PrinterWizardResources.dll", resource, MAX_PATH );
        err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
        require_noerr( err, exit );
 
index 7a2842fc498dd6c7626756245c29afb2fdc9e36b..56319c3b24a768e0ca6869bd5d89c1e5f7d92e23 100755 (executable)
@@ -79,11 +79,11 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 IDD_ABOUTBOX DIALOGEX 0, 0, 235, 55\r
 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
     WS_SYSMENU\r
-CAPTION "About Printer Setup Wizard"\r
+CAPTION "About Printer Wizard"\r
 FONT 8, "MS Shell Dlg", 0, 0, 0x1\r
 BEGIN\r
     ICON            128,IDC_STATIC,11,17,20,20\r
-    LTEXT           "Printer Setup Wizard Version 1.0",IDC_STATIC,40,10,119,\r
+    LTEXT           "Printer Wizard Version 1.0",IDC_STATIC,40,10,119,\r
                     8,SS_NOPREFIX\r
     LTEXT           "Copyright (C) 2002",IDC_STATIC,40,25,119,8\r
     DEFPUSHBUTTON   "OK",IDOK,178,7,50,16,WS_GROUP\r
@@ -93,7 +93,7 @@ IDD_PRINTERSETUPWIZARD_DIALOG DIALOGEX 0, 0, 320, 200
 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | \r
     WS_CAPTION | WS_SYSMENU\r
 EXSTYLE WS_EX_APPWINDOW\r
-CAPTION "Printer Setup Wizard"\r
+CAPTION "Bonjour Printer Wizard"\r
 FONT 8, "MS Shell Dlg", 0, 0, 0x1\r
 BEGIN\r
     DEFPUSHBUTTON   "OK",IDOK,263,7,50,16\r
@@ -123,12 +123,11 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
 CAPTION "Bonjour Printer Wizard"\r
 FONT 8, "MS Shell Dlg", 0, 0, 0x0\r
 BEGIN\r
-    LTEXT           "Welcome to the Bonjour Printer Setup Wizard",\r
+    LTEXT           "Welcome to the Bonjour Printer Wizard",\r
                     IDC_GREETING,114,7,171,46\r
-    LTEXT           "Click next to continue.",IDC_STATIC,115,188,143,8\r
+    LTEXT           "To continue, click Next.",IDC_STATIC,115,188,143,8\r
     LTEXT           "This wizard helps you connect to a shared printer using Bonjour.  Make sure your printer is turned on and connected to your network.",\r
-                    IDC_STATIC,146,60,139,62\r
-    ICON            "",IDC_INFO,118,60,20,20,SS_REALSIZEIMAGE\r
+                    IDC_STATIC,114,60,171,62\r
 END\r
 \r
 IDD_THIRD_PAGE DIALOGEX 0, 0, 290, 154\r
@@ -143,9 +142,9 @@ BEGIN
     CONTROL         "",IDC_PRINTER_MANUFACTURER,"SysListView32",LVS_REPORT | \r
                     LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | \r
                     LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,2,58,105,76\r
-    ICON            1017,1,0,0,20,27\r
+    ICON            1017,1,3,5,20,27\r
     LTEXT           "",IDC_PRINTER_NAME,40,5,173,8\r
-    LTEXT           "The Bonjour Printer Wizard has auto-selected the following printer settings.  Click 'Next' to continue installing this printer.",\r
+    LTEXT           "The Bonjour Printer Wizard has auto-selected the following printer settings.  To continue installing this printer, click Next.",\r
                     IDC_PRINTER_SELECTION_TEXT,40,18,243,33\r
     CONTROL         "Use this printer as the default printer",\r
                     IDC_DEFAULT_PRINTER,"Button",BS_AUTOCHECKBOX | \r
@@ -160,20 +159,20 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN\r
     LTEXT           "Completing the Bonjour Printer Wizard",IDC_GOODBYE,\r
                     116,7,171,27\r
-    LTEXT           "You have successfully completed the Bonjour Printer Wizard.  The printer has the following settings:",\r
-                    IDC_STATIC,116,42,158,31\r
+    LTEXT           "You are ready to complete the Bonjour Printer Wizard.  The printer has the following settings:",\r
+                    IDC_STATIC,116,42,171,31\r
     LTEXT           "Name:",IDC_STATIC,116,78,22,8\r
     LTEXT           "Manufacturer:",IDC_STATIC,116,91,47,8\r
     LTEXT           "Model:",IDC_STATIC,116,104,22,8\r
     LTEXT           "Protocol:",IDC_STATIC,116,117,38,8\r
     LTEXT           "Default:",IDC_STATIC,116,130,27,8\r
-    LTEXT           "",IDC_PRINTER_NAME,172,78,113,8\r
+    LTEXT           "",IDC_PRINTER_NAME,172,78,113,8,SS_ENDELLIPSIS\r
     LTEXT           "",IDC_PRINTER_MANUFACTURER,172,91,113,8\r
     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 close this wizard, click Finish.",IDC_STATIC,116,187,\r
-                    103,8\r
+    LTEXT           "To complete the installation, click Finish.",IDC_STATIC,116,187,\r
+                    171,8\r
 END\r
 \r
 IDD_DIALOG1 DIALOGEX 0, 0, 265, 130\r
@@ -236,15 +235,15 @@ END
 \r
 STRINGTABLE \r
 BEGIN\r
-    IDS_ABOUTBOX            "&About Printer Setup Wizard..."\r
-    IDS_GOODBYE             "Completing the Bonjour Printer Setup Wizard."\r
-    IDS_GREETING            "Welcome to the Bonjour Printer Setup Wizard"\r
+    IDS_ABOUTBOX            "&About Bonjour Printer Wizard..."\r
+    IDS_GOODBYE             "Completing the Bonjour Printer Wizard."\r
+    IDS_GREETING            "Welcome to the Bonjour Printer Wizard"\r
     IDS_BROWSE_TITLE        "Browse for Bonjour Printers"\r
     IDS_BROWSE_SUBTITLE     "Select the printer you want to use from the list below."\r
     IDS_CAPTION             "Bonjour Printer Wizard"\r
-    IDS_GOODBYE_GOOD1       "You have successfully completed the Bonjour Printer Wizard.  The printer has the following settings:"\r
+    IDS_GOODBYE_GOOD1       "You are ready to complete the Bonjour Printer Wizard.  The printer has the following settings:"\r
     IDS_SEARCHING           "Searching for printers..."\r
-    IDS_GOODBYTE_GOOD2      "To close this wizard, click Finish."\r
+    IDS_GOODBYTE_GOOD2      "To complete the installation, click Finish."\r
     IDS_INSTALL_TITLE       "Install Bonjour Printer"\r
     IDS_INSTALL_SUBTITLE    "The manufacturer and model determine which printer software to use."\r
 END\r
index c97e842287839ddad98870a7c1a412a758168118..b961304920550b72f10cb724e272c087fad65018 100755 (executable)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "windows-1251"?>\r
+<?xml version="1.0" encoding="windows-1251"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="PrinterSetupWizardLocRes"\r
        ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
        Keyword="MFCProj">\r
@@ -12,7 +12,7 @@
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug\Resources\PrinterWizard.exe.Resources\en.lproj"\r
+                       OutputDirectory=".\Debug\PrinterWizard.Resources\en.lproj"\r
                        IntermediateDirectory=".\Debug"\r
                        ConfigurationType="2"\r
                        UseOfMFC="1"\r
@@ -57,9 +57,8 @@
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                                Description="Building Output Directories"\r
-                               CommandLine="if not exist Debug\Resources mkdir Debug\Resources\r
-if not exist Debug\Resources\PrinterWizard.exe.Resources mkdir Debug\Resources\PrinterWizard.exe.Resources\r
-if not exist Debug\Resources\PrinterWizard.exe.Resources\en.lproj mkdir Debug\Resources\PrinterWizard.exe.Resources\en.lproj\r
+                               CommandLine="if not exist Debug\PrinterWizard.Resources mkdir Debug\PrinterWizard.Resources\r
+if not exist Debug\PrinterWizard.Resources\en.lproj mkdir Debug\PrinterWizard.Resources\en.lproj\r
 "/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
@@ -68,12 +67,18 @@ if not exist Debug\Resources\PrinterWizard.exe.Resources\en.lproj mkdir Debug\Re
                                AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj"\r
+                       OutputDirectory=".\Release\PrinterWizard.Resources\en.lproj"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="2"\r
                        UseOfMFC="1"\r
@@ -120,12 +125,10 @@ if not exist Debug\Resources\PrinterWizard.exe.Resources\en.lproj mkdir Debug\Re
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                                Description="Building Output Directories"\r
-                               CommandLine="if not exist Release\Root mkdir Release\Root\r
-if not exist &quot;Release\Root\Program Files&quot; mkdir &quot;Release\Root\Program Files&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour&quot; mkdir &quot;Release\Root\Program Files\Bonjour&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj&quot;"/>\r
+                               CommandLine="if not exist Release mkdir Release\r
+if not exist &quot;Release\PrinterWizard.Resources&quot; mkdir &quot;Release\PrinterWizard.Resources&quot;\r
+if not exist &quot;Release\PrinterWizard.Resources\en.lproj&quot; mkdir &quot;Release\PrinterWizard.Resources\en.lproj&quot;\r
+"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
@@ -133,10 +136,18 @@ if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.ex
                                AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Header Files"\r
index 79424ffad9c085e18a4775c576f1e4f615209d28..e23103d97809d9b258c8801022edf29ff3ba8f0e 100755 (executable)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "windows-1251"?>\r
+<?xml version="1.0" encoding="windows-1251"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="PrinterSetupWizardRes"\r
        ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
        Keyword="MFCProj">\r
@@ -12,7 +12,7 @@
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug\Resources\PrinterWizard.exe.Resources"\r
+                       OutputDirectory=".\Debug\PrinterWizard.Resources"\r
                        IntermediateDirectory=".\Debug"\r
                        ConfigurationType="2"\r
                        UseOfMFC="1"\r
@@ -38,7 +38,7 @@
                                Name="VCCustomBuildTool"/>\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="$(OutDir)/PrinterWizard.dll"\r
+                               OutputFile="$(OutDir)/PrinterWizardResources.dll"\r
                                LinkIncremental="2"\r
                                GenerateDebugInformation="TRUE"\r
                                SubSystem="2"\r
@@ -57,8 +57,7 @@
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                                Description="Building Output Directories"\r
-                               CommandLine="if not exist Debug\Resources mkdir Debug\Resources\r
-if not exist Debug\Resources\PrinterWizard.exe.Resources mkdir Debug\Resources\PrinterWizard.exe.Resources"/>\r
+                               CommandLine="if not exist Debug\PrinterWizard.Resources mkdir Debug\PrinterWizard.Resources"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="_DEBUG"\r
@@ -66,12 +65,18 @@ if not exist Debug\Resources\PrinterWizard.exe.Resources mkdir Debug\Resources\P
                                AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources"\r
+                       OutputDirectory=".\Release\PrinterWizard.Resources"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="2"\r
                        UseOfMFC="1"\r
@@ -97,7 +102,7 @@ if not exist Debug\Resources\PrinterWizard.exe.Resources mkdir Debug\Resources\P
                                Name="VCCustomBuildTool"/>\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="$(OutDir)/PrinterWizard.dll"\r
+                               OutputFile="$(OutDir)/PrinterWizardResources.dll"\r
                                LinkIncremental="1"\r
                                GenerateDebugInformation="FALSE"\r
                                SubSystem="2"\r
@@ -118,11 +123,9 @@ if not exist Debug\Resources\PrinterWizard.exe.Resources mkdir Debug\Resources\P
                        <Tool\r
                                Name="VCPreLinkEventTool"\r
                                Description="Building Output Directories"\r
-                               CommandLine="if not exist Release\Root mkdir Release\Root\r
-if not exist &quot;Release\Root\Program Files&quot; mkdir &quot;Release\Root\Program Files&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour&quot; mkdir &quot;Release\Root\Program Files\Bonjour&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources&quot;\r
-if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources&quot;"/>\r
+                               CommandLine="if not exist Release mkdir Release\r
+if not exist &quot;Release\PrinterWizard.Resources&quot; mkdir &quot;Release\PrinterWizard.Resources&quot;\r
+"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
@@ -130,10 +133,18 @@ if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.ex
                                AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Header Files"\r
@@ -145,6 +156,12 @@ if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.ex
                <Filter\r
                        Name="Resource Files"\r
                        Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">\r
+                       <File\r
+                               RelativePath=".\res\about.bmp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="res\banner_icon.bmp">\r
+                       </File>\r
                        <File\r
                                RelativePath=".\res\Info.ico">\r
                        </File>\r
@@ -172,12 +189,6 @@ if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.ex
                        <File\r
                                RelativePath="res\PrinterSetupWizardRes.rc2">\r
                        </File>\r
-                       <File\r
-                               RelativePath=".\res\about.bmp">\r
-                       </File>\r
-                       <File\r
-                               RelativePath="res\banner_icon.bmp">\r
-                       </File>\r
                        <File\r
                                RelativePath="res\watermark.bmp">\r
                        </File>\r
index 75cda89d51ec2a8a856a6023b0fbcb7aece14b1b..6c0c9f3739a7ae467fe292baa1f9b390afa7d2b4 100644 (file)
     Change History (most recent first):
     
 $Log: PrinterSetupWizardSheet.cpp,v $
+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"
 
@@ -163,7 +178,8 @@ CPrinterSetupWizardSheet::CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParen
        m_driverThreadFinished( false ),
        m_pdlBrowser( NULL ),
        m_ippBrowser( NULL ),
-       m_lprBrowser( NULL )
+       m_lprBrowser( NULL ),
+       m_lastPage( NULL )
 {
        m_arrow         =       LoadCursor(0, IDC_ARROW);
        m_wait          =       LoadCursor(0, IDC_APPSTARTING);
@@ -245,7 +261,7 @@ CPrinterSetupWizardSheet::LoadPrinterNames()
                {
                        PRINTER_INFO_4 * lppi4 = (PRINTER_INFO_4*) (buffer + index * sizeof(PRINTER_INFO_4));
 
-                       m_printerNames[lppi4->pPrinterName] = lppi4->pPrinterName;
+                       m_printerNames.push_back( lppi4->pPrinterName );
                }
        }
 
@@ -289,6 +305,7 @@ CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
        //
        // if the driver isn't installed, then install it
        //
+
        if ( !printer->driverInstalled )
        {
                DWORD           dwResult;
@@ -398,7 +415,7 @@ CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * s
        ok = OpenPrinter(L",XcvMonitor Standard TCP/IP Port", &hXcv, &printerDefaults);
        err = translate_errno( ok, errno_compat(), kUnknownErr );
        require_noerr( err, exit );
-       
+
        //
        // BUGBUG: MSDN said this is not required, but my experience shows it is required
        //
@@ -429,7 +446,7 @@ CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * s
        wcscpy(portData.sztQueue, q->name);
        wcscpy(portData.sztIPAddress, service->hostname); 
        wcscpy(portData.sztHostAddress, service->hostname);
-               
+
        ok = XcvData(hXcv, L"AddPort", (PBYTE) &portData, sizeof(PORT_DATA_1), pOutputData, cbInputData,  &cbOutputNeeded, &dwStatus);
        err = translate_errno( ok, errno_compat(), kUnknownErr );
        require_noerr( err, exit );
@@ -445,7 +462,7 @@ CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * s
        pInfo.pPortName                         =       printer->portName.GetBuffer();
        pInfo.pDriverName                       =       printer->modelName.GetBuffer();
        pInfo.pComment                          =       printer->displayModelName.GetBuffer();
-       pInfo.pLocation                         =       service->location.GetBuffer();
+       pInfo.pLocation                         =       q->location.GetBuffer();
        pInfo.pDevMode                          =       NULL;
        pInfo.pDevMode                          =       NULL;
        pInfo.pSepFile                          =       L"";
@@ -489,9 +506,12 @@ CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service
 {
        DEBUG_UNUSED( service );
 
+       Queue           *       q                = service->SelectedQueue();
        HANDLE                  hPrinter = NULL;
        PRINTER_INFO_2  pInfo;
        OSStatus                err;
+
+       check( q );
        
        //
        // add the printer
@@ -502,7 +522,7 @@ CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service
        pInfo.pPortName                 = printer->portName.GetBuffer();
        pInfo.pDriverName               = printer->modelName.GetBuffer();
        pInfo.pPrintProcessor   = L"winprint";
-       pInfo.pLocation                 = service->location.GetBuffer();
+       pInfo.pLocation                 = q->location.GetBuffer();
        pInfo.pComment                  = printer->displayModelName.GetBuffer();
        pInfo.Attributes                = PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL;
        
@@ -886,8 +906,6 @@ CPrinterSetupWizardSheet::OnResolve(
        CPrinterSetupWizardSheet        *       self;
        Service                                         *       service;
        Queue                                           *       q;
-       uint32_t                                                qpriority = kDefaultPriority;
-       CString                                                 qname;
        int                                                             idx;
        OSStatus                                                err;
 
@@ -925,13 +943,6 @@ CPrinterSetupWizardSheet::OnResolve(
        //
        service->portNumber = ntohs(inPort);
 
-       //
-       // parse the text record.
-       //
-
-       err = self->ParseTextRecord( service, inTXTSize, inTXT, qname, qpriority );
-       require_noerr( err, exit );
-
        if ( service->qtotal == 1 )
        {       
                //
@@ -948,10 +959,13 @@ CPrinterSetupWizardSheet::OnResolve(
 
                require_action( q, exit, err = E_OUTOFMEMORY );
 
+               //
+               // parse the text record.
+               //
+
+               err = self->ParseTextRecord( service, q, inTXTSize, inTXT );
+               require_noerr( err, exit );
 
-               q->name         = qname;
-               q->priority = qpriority;
-               
                service->queues.push_back( q );
 
                //
@@ -1033,7 +1047,7 @@ CPrinterSetupWizardSheet::OnQuery(
 
                require_action( q, exit, err = E_OUTOFMEMORY );
 
-               err = service->printer->window->ParseTextRecord( service, inRDLen, inTXT, q->name, q->priority );
+               err = service->printer->window->ParseTextRecord( service, q, inRDLen, inTXT );
                require_noerr( err, exit );
 
                //
@@ -1121,9 +1135,18 @@ CPrinterSetupWizardSheet::OnAddPrinter(
 
        for (;;)
        {
-               CPrinterSetupWizardSheet::PrinterNameMap::iterator it;
+               CPrinterSetupWizardSheet::PrinterNames::iterator it;
+
+               // <rdar://problem/4141221> Don't use find to do comparisons because we need to
+               // do a case insensitive string comparison
 
-               it = m_printerNames.find(printer->actualName);
+               for ( it = m_printerNames.begin(); it != m_printerNames.end(); it++ )
+               {
+                       if ( (*it).CompareNoCase( printer->actualName ) == 0 )
+                       {
+                               break;
+                       }
+               }
 
                if (it != m_printerNames.end())
                {
@@ -1267,7 +1290,7 @@ CPrinterSetupWizardSheet::OnResolveService( Service * service )
 {
        // Make sure that the active page is page 2
 
-       check( GetActivePage() == &m_pgSecond );
+       require_quiet( GetActivePage() == &m_pgSecond, exit );
 
        if ( !--service->printer->resolving )
        {
@@ -1289,6 +1312,10 @@ CPrinterSetupWizardSheet::OnResolveService( Service * service )
 
                m_pgSecond.OnResolveService( service );
        }               
+
+exit:
+
+       return;
 }
 
 
@@ -1512,8 +1539,11 @@ exit:
 
 
 OSStatus
-CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, CString & qname, uint32_t & qpriority )
+CPrinterSetupWizardSheet::ParseTextRecord( Service * service, Queue * q, uint16_t inTXTSize, const char * inTXT )
 {
+       check( service );
+       check( q );
+
        // <rdar://problem/3946587> Use TXTRecord APIs declared in dns_sd.h
        
        bool                    qtotalDefined   = false;
@@ -1524,11 +1554,11 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize
 
        // <rdar://problem/3987680> Default to queue "lp"
 
-       qname = L"lp";
+       q->name = L"lp";
 
        // <rdar://problem/4003710> Default pdl key to be "application/postscript"
 
-       service->pdl = L"application/postscript";
+       q->pdl = L"application/postscript";
 
        if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "rp", &len ) ) != NULL )
        {
@@ -1537,7 +1567,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize
                memcpy( buf, val, len );
                buf[len] = '\0';
 
-               err = UTF8StringToStringObject( buf, qname );
+               err = UTF8StringToStringObject( buf, q->name );
                require_noerr( err, exit );
        }
        
@@ -1548,7 +1578,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize
                memcpy( buf, val, len );
                buf[len] = '\0';
 
-               err = UTF8StringToStringObject( buf, service->pdl );
+               err = UTF8StringToStringObject( buf, q->pdl );
                require_noerr( err, exit );
        }
        
@@ -1560,7 +1590,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize
                memcpy( buf, val, len );
                buf[len] = '\0';
 
-               err = UTF8StringToStringObject( buf, service->usb_MFG );
+               err = UTF8StringToStringObject( buf, q->usb_MFG );
                require_noerr( err, exit );
        }
        
@@ -1572,7 +1602,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize
                memcpy( buf, val, len );
                buf[len] = '\0';
 
-               err = UTF8StringToStringObject( buf, service->usb_MDL );
+               err = UTF8StringToStringObject( buf, q->usb_MDL );
                require_noerr( err, exit );
        }
 
@@ -1583,7 +1613,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize
                memcpy( buf, val, len );
                buf[len] = '\0';
 
-               err = UTF8StringToStringObject( buf, service->description );
+               err = UTF8StringToStringObject( buf, q->description );
                require_noerr( err, exit );
        }
                
@@ -1594,7 +1624,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize
                memcpy( buf, val, len );
                buf[len] = '\0';
 
-               err = UTF8StringToStringObject( buf, service->product );
+               err = UTF8StringToStringObject( buf, q->product );
                require_noerr( err, exit );
        }
 
@@ -1605,7 +1635,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize
                memcpy( buf, val, len );
                buf[len] = '\0';
 
-               err = UTF8StringToStringObject( buf, service->location );
+               err = UTF8StringToStringObject( buf, q->location );
                require_noerr( err, exit );
        }
 
@@ -1627,20 +1657,27 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize
                memcpy( buf, val, len );
                buf[len] = '\0';
 
-               qpriority = atoi( buf );
+               q->priority = atoi( buf );
+       }
+
+       // <rdar://problem/4124524> Was this printer discovered via OS X Printer Sharing?
+
+       if ( TXTRecordContainsKey( inTXTSize, inTXT, "printer-state" ) || TXTRecordContainsKey( inTXTSize, inTXT, "printer-type" ) )
+       {
+               service->printer->isSharedFromOSX = true;
        }
 
 exit:
 
        // The following code is to fix a problem with older HP 
        // printers that don't include "qtotal" in their text
-       // record.  We'll check to see if the qname is "TEXT"
+       // record.  We'll check to see if the q->name is "TEXT"
        // and if so, we're going to modify it to be "lp" so
        // that we don't use the wrong queue
 
-       if ( !err && !qtotalDefined && ( qname == L"TEXT" ) )
+       if ( !err && !qtotalDefined && ( q->name == L"TEXT" ) )
        {
-               qname = "lp";
+               q->name = "lp";
        }
 
        return err;
index cf7f096f76b84b8b628efdcb3ddddc34d67d3746..63dc0c0ab0bb5fbb87d25e6d14dba90463f9676b 100644 (file)
     Change History (most recent first):
     
 $Log: PrinterSetupWizardSheet.h,v $
+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()
 
@@ -86,6 +95,12 @@ public:
        CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
        virtual ~CPrinterSetupWizardSheet();
 
+       CPropertyPage*
+       GetLastPage();
+
+       void
+       SetLastPage(CPropertyPage * page );
+
        void
        SetSelectedPrinter(Printer * printer);
 
@@ -241,7 +256,7 @@ private:
        StopResolve( Service * service );
 
        OSStatus
-       ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, CString & qname, uint32_t & qpriority );
+       ParseTextRecord( Service * service, Queue * q, uint16_t inTXTSize, const char * inTXT );
 
        OSStatus
        LoadPrinterNames();
@@ -261,10 +276,10 @@ private:
        static unsigned WINAPI
        InstallDriverThread( LPVOID inParam );
 
-       typedef std::map<CString,CString>       PrinterNameMap;
+       typedef std::list<CString>                      PrinterNames;
        typedef std::list<DNSServiceRef>        ServiceRefList;
        static CPrinterSetupWizardSheet *       m_self;
-       PrinterNameMap                                          m_printerNames;
+       PrinterNames                                            m_printerNames;
        Printer                                                 *       m_selectedPrinter;
        bool                                                            m_driverThreadFinished;
        DWORD                                                           m_driverThreadExitCode;
@@ -273,6 +288,8 @@ private:
        DNSServiceRef                                           m_lprBrowser;
        DNSServiceRef                                           m_ippBrowser;
        DNSServiceRef                                           m_resolver;
+
+       CPropertyPage                                   *       m_lastPage;
 };
 
 
@@ -290,6 +307,20 @@ CPrinterSetupWizardSheet::GetCursor()
 }
 
 
+inline CPropertyPage*
+CPrinterSetupWizardSheet::GetLastPage()
+{
+       return m_lastPage;
+}
+
+
+inline void
+CPrinterSetupWizardSheet::SetLastPage(CPropertyPage * lastPage)
+{
+       m_lastPage = lastPage;
+}
+
+
 // Service Types
 
 #define        kPDLServiceType         "_pdl-datastream._tcp."
index 63665ee8f1f9e6bf05b10d4127b5711b32b18cc9..c64030d203c31289dfff0f0ff25bdf62f501c81d 100644 (file)
     Change History (most recent first):
     
 $Log: SecondPage.cpp,v $
+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
 
@@ -115,6 +130,12 @@ CSecondPage::InitBrowseList()
        psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
        require_quiet( psheet, exit );
 
+       // Initialize so that nothing is selected when we add to the list
+
+       psheet->SetSelectedPrinter( NULL );
+       m_gotChoice = false;
+       m_browseList.Select( NULL, TVGN_FIRSTVISIBLE );
+
        //
        // load the no printers message until something shows up in the browse list
        //
@@ -131,6 +152,8 @@ CSecondPage::InitBrowseList()
        // disable the printer information box
        //
        SetPrinterInformationState( FALSE );
+       m_descriptionField.SetWindowText( L"" );
+       m_locationField.SetWindowText( L"" );
 
 exit:
 
@@ -182,44 +205,63 @@ CSecondPage::OnSetActive()
        Printer                                         *       printer;
        Printers::iterator                              it;
        OSStatus                                                err = kNoErr;
+       BOOL                                                    b;
+
+       b = CPropertyPage::OnSetActive();
 
        psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
        require_action( psheet, exit, err = kUnknownErr );
 
+       // Stash the selected printer if any
+
+       printer = psheet->GetSelectedPrinter();
+
        // initialize the browse list...this will remove everything currently
        // in it, and add the no printers item
 
        InitBrowseList();
 
-       // And populate the list with any printers that we currently know about
+       // Populate the list with any printers that we currently know about
 
        for ( it = psheet->m_printers.begin(); it != psheet->m_printers.end(); it++ )
        {
                OnAddPrinter( *it, false );
        }
 
-       printer = psheet->GetSelectedPrinter();
+       // And if we hit 'Back' from page 3, then re-select printer
 
-       if ( printer != NULL )
+       if ( ( psheet->GetLastPage() == psheet->GetPage( 2 ) ) && printer )
        {
+               psheet->SetSelectedPrinter( printer );
                m_browseList.Select( printer->item, TVGN_FIRSTVISIBLE );
        }
 
 exit:
 
-       return CPropertyPage::OnSetActive();
+       return b;
 }
 
 
 BOOL
 CSecondPage::OnKillActive()
 {
+       CPrinterSetupWizardSheet * psheet;
+
+       psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+       require_quiet( psheet, exit );   
+   
+       psheet->SetLastPage(this);
+
+exit:
+
        return CPropertyPage::OnKillActive();
 }
 
 
 BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
        ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList)
+       ON_NOTIFY(NM_CLICK, IDC_BROWSE_LIST, OnNmClickBrowseList)
+       ON_NOTIFY(TVN_KEYDOWN, IDC_BROWSE_LIST, OnTvnKeyDownBrowseList)
        ON_WM_SETCURSOR()
 END_MESSAGE_MAP()
 
@@ -245,11 +287,6 @@ CSecondPage::OnAddPrinter(
        m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
 
        m_browseList.SortChildren(TVI_ROOT);
-               
-       if ( printer->name == m_selectedName )
-       {
-               m_browseList.SelectItem( printer->item );
-       }
 
        //
        // if the searching item is still in the list
@@ -333,9 +370,14 @@ CSecondPage::OnResolveService( Service * service )
 {
        CPrinterSetupWizardSheet * psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
        require_quiet( psheet, exit );
-       
+
        check( service );
 
+       Queue * q = service->SelectedQueue();
+
+       check( q );
+       
+
        //
        // and set it to selected
        //
@@ -347,8 +389,8 @@ CSecondPage::OnResolveService( Service * service )
        //
        SetPrinterInformationState( TRUE );
 
-       m_descriptionField.SetWindowText( service->description );
-       m_locationField.SetWindowText( service->location );
+       m_descriptionField.SetWindowText( q->description );
+       m_locationField.SetWindowText( q->location );
 
        //
        // reset the cursor
@@ -366,15 +408,43 @@ void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
 {
        LPNMTREEVIEW                                    pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
        CPrinterSetupWizardSheet        *       psheet;
+       Printer                                         *       printer;
        int                                                             err = 0;
 
-       HTREEITEM item = m_browseList.GetSelectedItem();
-       require_quiet( item, exit );
-
        psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-       require_action( psheet, exit, err = kUnknownErr );      
+       require_action( psheet, exit, err = kUnknownErr );
 
-       Printer * printer;
+       // The strange code here is to workaround a bug in the CTreeCtrl, whereupon the item
+       // we selected isn't passed through correctly to this callback routine.
+
+       if ( !m_gotChoice )
+       {
+               printer = psheet->GetSelectedPrinter();
+
+               // If we really haven't selected a printer, then re-select NULL and exit
+
+               if ( !printer )
+               {
+                       m_browseList.SelectItem( NULL );
+
+                       goto exit;
+               }
+
+               // If we already have selected a printer, fake like we've clicked on it, but only
+               // if the CTreeCtrl hasn't already selected it
+               
+               else if ( printer->item != m_browseList.GetSelectedItem() )
+               {
+                       m_gotChoice = true;
+
+                       m_browseList.SelectItem( printer->item );
+
+                       goto exit;
+               }
+       }
+
+       HTREEITEM item = m_browseList.GetSelectedItem();
+       require_quiet( item, exit );
 
        printer = reinterpret_cast<Printer*>(m_browseList.GetItemData( item ) );
        require_quiet( printer, exit );
@@ -410,6 +480,26 @@ exit:
 }
 
 
+void CSecondPage::OnNmClickBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
+{
+       DEBUG_UNUSED( pNMHDR );
+
+       m_gotChoice = true;
+
+       *pResult = 0;
+}
+
+
+void CSecondPage::OnTvnKeyDownBrowseList( NMHDR * pNMHDR, LRESULT * pResult)
+{
+       DEBUG_UNUSED( pNMHDR );
+
+       m_gotChoice = true;
+
+       *pResult = 0;
+}
+
+
 void
 CSecondPage::LoadTextAndDisableWindow( CString & text )
 {
index aa0826083f910da34319936e6f2bf1ca53639569..5cf1852aa8093a5b0c5b0a75bd20fe31bf7405f7 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: SecondPage.h,v $
+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.
 
@@ -95,6 +98,8 @@ public:
        bool                    m_waiting;
 
        afx_msg void    OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);
+       afx_msg void    OnNmClickBrowseList(NMHDR * pNMHDR, LRESULT * pResult);
+       afx_msg void    OnTvnKeyDownBrowseList(NMHDR * pNMHDR, LRESULT * pResult );
 
        OSStatus
        OnAddPrinter(
@@ -126,4 +131,6 @@ private:
        CStatic m_descriptionField;\r
        CStatic m_locationLabel;\r
        CStatic m_locationField;\r
+
+       bool    m_gotChoice;
 };
index acd8d3c5374d4ece89560516cf26577f7ac8b033..bf16fe2cc769c183baec938f6e528e8f9bd9e1ce 100644 (file)
     Change History (most recent first):
     
 $Log: ThirdPage.cpp,v $
+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
 
@@ -183,7 +204,7 @@ CThirdPage::CThirdPage()
        require_noerr(err, exit);
 
        //
-       // and lastly load our own special generic printer defs
+       // load our own special generic printer defs
        //
        err = LoadGenericPrintDriverDefs( m_manufacturers );
        require_noerr( err, exit );
@@ -231,7 +252,7 @@ CThirdPage::~CThirdPage()
 //
 // ----------------------------------------------------
 void
-CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturers & manufacturers, Manufacturer * manufacturer, Model * model)
+CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model)
 {
        LVFINDINFO      info;
        int                     nIndex;
@@ -240,8 +261,6 @@ CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturers & ma
        check( manufacturer != NULL );
        check( model != NULL );
 
-       PopulateUI( manufacturers );
-
        //
        // select the manufacturer
        //
@@ -276,6 +295,15 @@ CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturers & ma
 }
 
 
+void
+CThirdPage::SelectMatch(Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer * manufacturer, Model * model)
+{
+       PopulateUI( manufacturers );
+
+       SelectMatch( printer, service, manufacturer, model );
+}
+
+
 // --------------------------------------------------------
 // CopyPrinterSettings
 //
@@ -824,7 +852,7 @@ CThirdPage::LoadGenericPrintDriverDefs( Manufacturers & manufacturers )
 
        // First try and find our generic driver names
 
-       iter = manufacturers.find(L"HP");
+       iter = m_manufacturers.find(L"HP");
        require_action( iter != manufacturers.end(), exit, err = kUnknownErr );
        manufacturer = iter->second;
 
@@ -1028,7 +1056,7 @@ CThirdPage::NormalizeManufacturerName( const CString & name )
 // MatchManufacturer and MatchModel in turn.
 //
 
-OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service)
+OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service, bool useCUPSWorkaround)
 {
        CString                                 normalizedProductName;
        Manufacturer            *       manufacturer            =       NULL;
@@ -1039,20 +1067,27 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
        CString                                 text;
        OSStatus                                err                                     =       kNoErr;
 
+       check( printer );
+       check( service );
+
+       Queue * q = service->SelectedQueue();
+
+       check( q );
+
        //
        // first look to see if we have a usb_MFG descriptor
        //
-       if (service->usb_MFG.GetLength() > 0)
+       if ( q->usb_MFG.GetLength() > 0)
        {
-               manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( service->usb_MFG ) );
+               manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( q->usb_MFG ) );
        }
 
        if ( manufacturer == NULL )
        {
-               service->product.Remove('(');
-               service->product.Remove(')');
+               q->product.Remove('(');
+               q->product.Remove(')');
 
-               manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( service->product ) );
+               manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( q->product ) );
        }
        
        //
@@ -1060,25 +1095,48 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
        //
        if ( manufacturer != NULL )
        {
-               if (service->usb_MDL.GetLength() > 0)
+               if ( q->usb_MDL.GetLength() > 0 )
                {
-                       model = MatchModel ( manufacturer, ConvertToModelName ( service->usb_MDL ) );
+                       model = MatchModel ( manufacturer, ConvertToModelName ( q->usb_MDL ) );
                }
 
-               if ( ( model == NULL ) && ( service->product.GetLength() > 0 ) )
+               if ( ( model == NULL ) && ( q->product.GetLength() > 0 ) )
                {
-                       service->product.Remove('(');
-                       service->product.Remove(')');
+                       q->product.Remove('(');
+                       q->product.Remove(')');
 
-                       model = MatchModel ( manufacturer, ConvertToModelName ( service->product ) );
+                       model = MatchModel ( manufacturer, ConvertToModelName ( q->product ) );
                }
 
                if ( model != NULL )
                {
-                       Manufacturers manufacturers;
-                       
-                       manufacturers[manufacturer->name] = manufacturer;
-                       SelectMatch(printer, service, manufacturers, manufacturer, model);
+                       // <rdar://problem/4124524> Offer Generic printers if printer advertises Postscript or PCL.  Workaround
+                       // bug in OS X CUPS printer sharing by selecting Generic driver instead of matched printer.
+                       bool hasGenericDriver = false;
+
+                       if ( MatchGeneric( manufacturers, printer, service, &genericManufacturer, &genericModel ) )
+                       {
+                               hasGenericDriver = true;
+                       }
+
+                       // <rdar://problem/4190104> Use "application/octet-stream" to determine if CUPS 
+                       // shared queue supports raw
+
+                       if ( q->pdl.Find( L"application/octet-stream" ) != -1 )
+                       {
+                               useCUPSWorkaround = false;
+                       }
+
+                       if ( useCUPSWorkaround && printer->isSharedFromOSX && hasGenericDriver )
+                       {
+                               SelectMatch(manufacturers, printer, service, genericManufacturer, genericModel );
+                       }
+                       else
+                       {
+                               SelectMatch(manufacturers, printer, service, manufacturer, model);
+                       }
+
                        found = true;
                }
        }
@@ -1091,26 +1149,18 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
        {
                text.LoadString(IDS_PRINTER_MATCH_GOOD);
        }
-       else if ( MatchGeneric( printer, service, &genericManufacturer, &genericModel ) )
-       {
-               Manufacturers * pManufacturers;
-               Manufacturers   manufacturers;
-               
-               text.LoadString(IDS_PRINTER_MATCH_MAYBE);
-               
-               if ( manufacturer )
+       else if ( MatchGeneric( manufacturers, printer, service, &genericManufacturer, &genericModel ) )
+       {       
+               if ( printer->isSharedFromOSX )
                {
-                       manufacturers[genericManufacturer->name]        = genericManufacturer;
-                       manufacturers[manufacturer->name]                       = manufacturer;
-
-                       pManufacturers = &manufacturers;
+                       text.LoadString(IDS_PRINTER_MATCH_GOOD);
                }
                else
                {
-                       pManufacturers = &m_manufacturers;
+                       text.LoadString(IDS_PRINTER_MATCH_MAYBE);
                }
 
-               SelectMatch( printer, service, *pManufacturers, genericManufacturer, genericModel );
+               SelectMatch( manufacturers, printer, service, genericManufacturer, genericModel );
        }
        else
        {
@@ -1247,19 +1297,25 @@ CThirdPage::MatchModel(Manufacturer * manufacturer, const CString & name)
 // specifically
 //
 BOOL
-CThirdPage::MatchGeneric( Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model )
+CThirdPage::MatchGeneric( Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model )
 {
        CString pdl;
        BOOL    ok = FALSE;
 
        DEBUG_UNUSED( printer );
 
-       Manufacturers::iterator iter = m_manufacturers.find( kGenericManufacturer );
-       require_action_quiet( iter != m_manufacturers.end(), exit, ok = FALSE );
+       check( service );
+
+       Queue * q = service->SelectedQueue();
+
+       check( q );
+
+       Manufacturers::iterator iter = manufacturers.find( kGenericManufacturer );
+       require_action_quiet( iter != manufacturers.end(), exit, ok = FALSE );
 
        *manufacturer = iter->second;
 
-       pdl = service->pdl;
+       pdl = q->pdl;
        pdl.MakeLower();
 
        if ( pdl.Find( kPDLPCLKey ) != -1 )
@@ -1323,11 +1379,11 @@ OSStatus CThirdPage::OnInitPage()
        // selection notice
        //
        header.LoadString(IDS_MANUFACTURER_HEADING);
-       m_manufacturerListCtrl.InsertColumn(0, header, LVCFMT_LEFT, 138);
+       m_manufacturerListCtrl.InsertColumn(0, header, LVCFMT_LEFT, -1 );
        m_manufacturerSelected = NULL;
 
        header.LoadString(IDS_MODEL_HEADING);
-       m_modelListCtrl.InsertColumn(0, header, LVCFMT_LEFT, 247);
+       m_modelListCtrl.InsertColumn(0, header, LVCFMT_LEFT, -1 );
        m_modelSelected = NULL;
 
        return (err);
@@ -1363,15 +1419,7 @@ CThirdPage::OnSetActive()
        psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
        require_quiet( psheet, exit );
    
-       if ((m_manufacturerListCtrl.GetFirstSelectedItemPosition() != NULL) &&
-           (m_modelListCtrl.GetFirstSelectedItemPosition() != NULL))
-       {
-               psheet->SetWizardButtons( PSWIZB_BACK|PSWIZB_NEXT );
-       }
-       else
-       {
-               psheet->SetWizardButtons( PSWIZB_BACK );
-       }
+       psheet->SetWizardButtons( PSWIZB_BACK );
 
        printer = psheet->GetSelectedPrinter();
        require_quiet( printer, exit );
@@ -1402,7 +1450,15 @@ CThirdPage::OnSetActive()
        //
        // and try and match the printer
        //
-       MatchPrinter( m_manufacturers, printer, service );
+
+       if ( psheet->GetLastPage() == psheet->GetPage(1) )
+       {
+               MatchPrinter( m_manufacturers, printer, service, true );
+       }
+       else
+       {
+               SelectMatch(printer, service, m_manufacturerSelected, m_modelSelected);
+       }
 
 exit:
 
@@ -1410,6 +1466,22 @@ exit:
 }
 
 
+BOOL
+CThirdPage::OnKillActive()
+{
+       CPrinterSetupWizardSheet * psheet;
+
+       psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+       require_quiet( psheet, exit );   
+   
+       psheet->SetLastPage(this);
+
+exit:
+
+       return CPropertyPage::OnKillActive();
+}
+
+
 // -------------------------------------------------------
 // PopulateUI
 //
@@ -1431,6 +1503,8 @@ CThirdPage::PopulateUI(Manufacturers & manufacturers)
                nIndex = m_manufacturerListCtrl.InsertItem(0, manufacturer->name);
 
                m_manufacturerListCtrl.SetItemData(nIndex, (DWORD_PTR) manufacturer);
+
+               m_manufacturerListCtrl.SetColumnWidth( 0, LVSCW_AUTOSIZE_USEHEADER );
        }
 
        return 0;
@@ -1471,6 +1545,8 @@ void CThirdPage::OnLvnItemchangedManufacturer(NMHDR *pNMHDR, LRESULT *pResult)
                        int nItem = m_modelListCtrl.InsertItem( 0, model->displayName );
 
                        m_modelListCtrl.SetItemData(nItem, (DWORD_PTR) model);
+
+                       m_modelListCtrl.SetColumnWidth( 0, LVSCW_AUTOSIZE_USEHEADER );
                }
 
                m_modelListCtrl.SetRedraw(TRUE);
@@ -1531,7 +1607,7 @@ void CThirdPage::OnBnClickedDefaultPrinter()
        printer = psheet->GetSelectedPrinter();
        require_quiet( printer, exit );
 
-       printer->deflt = m_defaultPrinterCtrl.GetState() ? true : false;
+       printer->deflt = ( m_defaultPrinterCtrl.GetCheck() == BST_CHECKED ) ? true : false;
 
 exit:
 
@@ -1543,6 +1619,7 @@ void CThirdPage::OnBnClickedHaveDisk()
        CPrinterSetupWizardSheet        *       psheet;
        Printer                                         *       printer;
        Service                                         *       service;
+       Manufacturers                                   manufacturers;
 
        CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_FILEMUSTEXIST, L"Setup Information (*.inf)|*.inf||", this);
 
@@ -1555,16 +1632,29 @@ void CThirdPage::OnBnClickedHaveDisk()
        service = printer->services.front();
        require_quiet( service, exit );
 
-       if ( dlg.DoModal() == IDOK )
+       for ( ;; )
        {
-               Manufacturers   manufacturers;
-               CString                 filename = dlg.GetPathName();
+               if ( dlg.DoModal() == IDOK )
+               {
+                       CString filename = dlg.GetPathName();
 
-               LoadPrintDriverDefsFromFile( manufacturers, filename, true );
+                       LoadPrintDriverDefsFromFile( manufacturers, filename, true );
    
-               PopulateUI( manufacturers );
+                       // Sanity check
 
-               MatchPrinter( manufacturers, printer, service );
+                       if ( manufacturers.size() > 0 )
+                       {
+                               PopulateUI( manufacturers );
+
+                               MatchPrinter( manufacturers, printer, service, false );
+
+                               break;
+                       }
+               }
+               else
+               {
+                       break;
+               }
        }
 
 exit:
index a5a9bb6c46bdb1db61111d5c888e1288800f0862..8331421fd557c6e0a47eb85d4558a45daf01637d 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: ThirdPage.h,v $
+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
 
@@ -67,6 +70,7 @@ public:
 protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
        virtual BOOL OnSetActive();
+       virtual BOOL OnKillActive();
 
        DECLARE_MESSAGE_MAP()
 
@@ -107,7 +111,7 @@ private:
        //
        // Tries to match printer based on manufacturer and model
        //
-       OSStatus MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service);
+       OSStatus MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service, bool useCUPSWorkaround);
 
        //
        // OnInitPage
@@ -125,12 +129,13 @@ private:
 
        Manufacturer    *       MatchManufacturer( Manufacturers & manufacturer, const CString & name );
        Model                   *       MatchModel( Manufacturer * manufacturer, const CString & name );
-       BOOL                            MatchGeneric( Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model );
-       void                            SelectMatch(Printer * printer, Service * service, Manufacturers & manufacturers, Manufacturer * manufacturer, Model * model);
+       BOOL                            MatchGeneric( Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model );
+       void                            SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
+       void                            SelectMatch(Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
        void                            CopyPrinterSettings(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
 
        Manufacturers           m_manufacturers;
-       
+
        CListCtrl                       m_manufacturerListCtrl;
        Manufacturer    *       m_manufacturerSelected;
        
index 5e2fe196ef91357c12bc4e211281a1b83ce7ac21..e5512b982da3332e0b5e78395c856cc06aa6c678 100644 (file)
     Change History (most recent first):
     
 $Log: UtilTypes.h,v $
+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
 
@@ -135,6 +144,11 @@ namespace PrinterSetupWizard
                CString                 portName;
                bool                    deflt;
 
+               // 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;
+               
                //
                // state
                //
@@ -149,6 +163,9 @@ namespace PrinterSetupWizard
 
                ~Service();
 
+               Queue*
+               SelectedQueue();
+
                void
                EmptyQueues();
 
@@ -163,12 +180,6 @@ namespace PrinterSetupWizard
                DNSServiceRef   serviceRef;
                CString                 hostname;
                unsigned short  portNumber;
-               CString                 pdl;
-               CString                 usb_MFG;
-               CString                 usb_MDL;
-               CString                 description;
-               CString                 location;
-               CString                 product;
                CString                 protocol;
                unsigned short  qtotal;
 
@@ -194,6 +205,12 @@ namespace PrinterSetupWizard
 
                CString         name;
                uint32_t        priority;
+               CString         pdl;
+               CString         usb_MFG;
+               CString         usb_MDL;
+               CString         description;
+               CString         location;
+               CString         product;
        };
 
 
@@ -219,6 +236,8 @@ namespace PrinterSetupWizard
 
        inline
        Printer::Printer()
+       :
+               isSharedFromOSX( false )
        {
        }
 
@@ -269,6 +288,12 @@ namespace PrinterSetupWizard
                EmptyQueues();
        }
 
+       inline Queue*
+       Service::SelectedQueue()
+       {
+               return queues.front();
+       }
+
        inline void
        Service::EmptyQueues()
        {
@@ -301,7 +326,7 @@ namespace PrinterSetupWizard
                {
                        Model * model = *it;
 
-                       if ( model->name = name )
+                       if ( model->name == name )
                        {
                                return model;
                        }
index 22130b3de3ee242e78b347bc07d177cf3cd44a10..b737f473253cde006f562cdca30f025db8646439 100644 (file)
Binary files a/Clients/PrinterSetupWizard/res/NetworkPrinter.ico and b/Clients/PrinterSetupWizard/res/NetworkPrinter.ico differ
index 22130b3de3ee242e78b347bc07d177cf3cd44a10..b737f473253cde006f562cdca30f025db8646439 100644 (file)
Binary files a/Clients/PrinterSetupWizard/res/Print.ico and b/Clients/PrinterSetupWizard/res/Print.ico differ
index 639d2d94a177273427a104e2b97c074661eec4f7..5d21d404b112667a18a999905aee09c8ff858564 100644 (file)
@@ -1,24 +1,24 @@
 /*\r
  * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.\r
  *\r
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_LICENSE_HEADER_START@\r
+ * \r
+ * This file contains Original Code and/or Modifications of Original Code\r
+ * as defined in and that are subject to the Apple Public Source License\r
+ * Version 2.0 (the 'License'). You may not use this file except in\r
+ * compliance with the License. Please obtain a copy of the License at\r
+ * http://www.opensource.apple.com/apsl/ and read it before using this\r
+ * file.\r
+ * \r
+ * The Original Code and all software distributed under the License are\r
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER\r
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\r
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.\r
+ * Please see the License for the specific language governing rights and\r
+ * limitations under the License.\r
+ * \r
+ * @APPLE_LICENSE_HEADER_END@\r
 \r
     Change History (most recent first):\r
 \r
index 160644b29c22186d77a8c6addedbc948a00e8446..8ec4bdb3433535669d48782597395e4113415bef 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: stdafx.h,v $
+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
 
@@ -59,6 +62,10 @@ First checked in
 // turns off MFC's hiding of some common and often safely ignored warning messages
 #define _AFX_ALL_WARNINGS
 
+#if !defined(_WSPIAPI_COUNTOF)
+#      define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#endif
+
 #include <afxwin.h>         // MFC core and standard components
 #include <afxext.h>         // MFC extensions
 #include <afxdisp.h>        // MFC Automation classes
index 699a93286da4ad51aa85c27cf8f944ddc1a808cc..34af2d67b7504bce7a100000ef69473a759dee09 100644 (file)
@@ -58,7 +58,7 @@ POSIX systems:
 gcc dns-sd.c -o dns-sd -I../mDNSShared -ldns_sd
 
 Windows:
-cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT -DNOT_HAVE_SETLINEBUF ws2_32.lib ..\mDNSWindows\DLL\Release\dnssd.lib
+cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT ws2_32.lib ..\mDNSWindows\DLL\Release\dnssd.lib
 (may require that you run a Visual Studio script such as vsvars32.bat first)
 */
 
@@ -67,20 +67,25 @@ cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT -DNOT_HAVE_SETLINEBUF ws2_32.lib .
 #include <stdio.h>                     // For stdout, stderr
 #include <stdlib.h>                    // For exit()
 #include <string.h>                    // For strlen(), strcpy(), bzero()
-#include <errno.h>          // For errno, EINTR
+#include <errno.h>                     // For errno, EINTR
 #include <time.h>
-#include <sys/types.h>      // For u_char
+#include <sys/types.h>         // For u_char
 
 #ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
 #include <process.h>
-typedef        int     pid_t;
-#define        getpid  _getpid
-#define        strcasecmp      _stricmp
-#define snprintf _snprintf
+typedef int        pid_t;
+#define getpid     _getpid
+#define strcasecmp _stricmp
+#define snprintf   _snprintf
 #else
+#include <unistd.h>                    // For getopt() and optind
+#include <netdb.h>                     // For getaddrinfo()
 #include <sys/time.h>          // For struct timeval
-#include <unistd.h>         // For getopt() and optind
 #include <arpa/inet.h>         // For inet_addr()
+#include <netinet/in.h>                // For struct sockaddr_in()
+#include <sys/socket.h>                // For AF_INET
 #endif
 
 
@@ -214,9 +219,10 @@ static const char *GetNextLabel(const char *cstr, char label[64])
        return(cstr);
        }
 
-static void DNSSD_API enum_reply(DNSServiceRef client, DNSServiceFlags flags, uint32_t ifIndex,
+static void DNSSD_API enum_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t ifIndex,
        DNSServiceErrorType errorCode, const char *replyDomain, void *context)
        {
+       DNSServiceFlags partialflags = flags & ~(kDNSServiceFlagsMoreComing | kDNSServiceFlagsAdd | kDNSServiceFlagsDefault);
        int labels = 0, depth = 0, i, initial = 0;
        char text[64];
        const char *label[128];
@@ -233,10 +239,7 @@ static void DNSSD_API enum_reply(DNSServiceRef client, DNSServiceFlags flags, ui
        printtimestamp();
        printf("%-10s", DomainMsg(flags));
        printf("%-8s", (flags & kDNSServiceFlagsMoreComing) ? "(More)" : "");
-       flags &= ~kDNSServiceFlagsMoreComing;
-       flags &= ~kDNSServiceFlagsAdd;
-       flags &= ~kDNSServiceFlagsDefault;
-       if (flags) printf("Flags: %4X  ", flags);
+       if (partialflags) printf("Flags: %4X  ", partialflags);
        else printf("             ");
        
        // 2. Count the labels
@@ -270,68 +273,59 @@ static void DNSSD_API enum_reply(DNSServiceRef client, DNSServiceFlags flags, ui
                printf("> %s\n", text);
                }
 
-       fflush( stdout );
+       if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
        }
 
-static void DNSSD_API browse_reply(DNSServiceRef client, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
+static void DNSSD_API browse_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
        const char *replyName, const char *replyType, const char *replyDomain, void *context)
        {
        char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
        (void)client;       // Unused
        (void)errorCode;    // Unused
        (void)context;      // Unused
-       if (num_printed++ == 0) printf("Timestamp     A/R Flags if %-24s %-24s %s\n", "Domain", "Service Type", "Instance Name");
+       if (num_printed++ == 0) printf("Timestamp     A/R Flags if %-25s %-25s %s\n", "Domain", "Service Type", "Instance Name");
        printtimestamp();
-       printf("%s%6X%3d %-24s %-24s %s\n", op, flags, ifIndex, replyDomain, replyType, replyName);
-       fflush( stdout );
+       printf("%s%6X%3d %-25s %-25s %s\n", op, flags, ifIndex, replyDomain, replyType, replyName);
+       if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
        }
 
-static void DNSSD_API resolve_reply(DNSServiceRef client, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
+static void DNSSD_API resolve_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
        const char *fullname, const char *hosttarget, uint16_t opaqueport, uint16_t txtLen, const char *txtRecord, void *context)
        {
-       const char *src = txtRecord;
        union { uint16_t s; u_char b[2]; } port = { opaqueport };
        uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1];
 
        (void)client;       // Unused
        (void)ifIndex;      // Unused
        (void)errorCode;    // Unused
-       (void)txtLen;       // Unused
        (void)context;      // Unused
 
        printtimestamp();
        printf("%s can be reached at %s:%u", fullname, hosttarget, PortAsNumber);
 
        if (flags) printf(" Flags: %X", flags);
-       if (*src)
+       if (txtLen > 1)     // Don't show degenerate TXT records containing nothing but a single empty string
                {
-               char txtInfo[64];                               // Display at most first 64 characters of TXT record
-               char *dst = txtInfo;
-               const char *const lim = &txtInfo[sizeof(txtInfo)];
-               while (*src && dst < lim-1)
+               const char *ptr = txtRecord;
+               const char *max = txtRecord + txtLen;
+               printf(" TXT");
+               while (ptr < max)
                        {
-                       if (*src == '\\') *dst++ = '\\';            // '\' displays as "\\"
-                       if (*src >= ' ') *dst++ = *src++;           // Display normal characters as-is
-                       else
+                       const char *end = ptr + 1 + ptr[0];
+                       if (end > max) { printf("<< invalid data >>"); break; }
+                       if (++ptr < end) printf(" ");   // As long as string is non-empty, begin with a space
+                       while (ptr < end)
                                {
-                               *dst++ = '\\';                          // Display a backslash
-                               if (*src ==    1) *dst++ = ' ';         // String boundary displayed as "\ "
-                               else                                    // Other chararacters displayed as "\0xHH"
-                                       {
-                                       static const char hexchars[16] = "0123456789ABCDEF";
-                                       *dst++ = '0';
-                                       *dst++ = 'x';
-                                       *dst++ = hexchars[*src >> 4];
-                                       *dst++ = hexchars[*src & 0xF];
-                                       }
-                               src++;
+                               if      (*ptr == '\\') printf("\\\\");          // '\' displays as "\\"
+                               else if (*ptr == ' ' ) printf("\\ ");           // ' ' displays as "\ "
+                               else if (*ptr >  ' ' ) printf("%c", *ptr);      // Display normal characters as-is
+                               else                   printf("\\x%02X", *ptr); // ther chararacters displayed as "\xHH"
+                               ptr++;
                                }
                        }
-               *dst++ = 0;
-               printf(" TXT %s", txtInfo);
                }
        printf("\n");
-       fflush( stdout );
+       if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
        }
 
 static void myTimerCallBack(void)
@@ -387,7 +381,7 @@ static void myTimerCallBack(void)
                }
        }
 
-static void DNSSD_API reg_reply(DNSServiceRef client, DNSServiceFlags flags, DNSServiceErrorType errorCode,
+static void DNSSD_API reg_reply(DNSServiceRef client, const DNSServiceFlags flags, DNSServiceErrorType errorCode,
        const char *name, const char *regtype, const char *domain, void *context)
        {
        (void)client;   // Unused
@@ -403,10 +397,10 @@ static void DNSSD_API reg_reply(DNSServiceRef client, DNSServiceFlags flags, DNS
                }
 
        if (operation == 'A' || operation == 'U' || operation == 'N') timeOut = 5;
-       fflush( stdout );
+       if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
        }
 
-static void DNSSD_API qr_reply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
+static void DNSSD_API qr_reply(DNSServiceRef sdRef, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
        const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
        {
        char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
@@ -433,7 +427,7 @@ static void DNSSD_API qr_reply(DNSServiceRef sdRef, DNSServiceFlags flags, uint3
        if (num_printed++ == 0) printf("Timestamp     A/R Flags if %-30s%4s%4s Rdata\n", "Name", "T", "C");
        printtimestamp();
        printf("%s%6X%3d %-30s%4d%4d %s\n", op, flags, ifIndex, fullname, rrtype, rrclass, rdb);
-       fflush( stdout );
+       if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
        }
 
 //*************************************************************************************************************
@@ -507,7 +501,7 @@ static int getfirstoption( int argc, char **argv, const char *optstr, int *pOptI
        }
 #endif
 
-static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordRef record, DNSServiceFlags flags,
+static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordRef record, const DNSServiceFlags flags,
     DNSServiceErrorType errorCode, void * context)
        {
        char *name = (char *)context;
@@ -523,16 +517,43 @@ static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordR
                case kDNSServiceErr_NameConflict: printf("Name in use, please choose another\n"); exit(-1);
                default:                          printf("Error %d\n", errorCode); return;
                }
-       fflush( stdout );
+       if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
+       }
+
+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)
+               {
+               ip = ((struct sockaddr_in*) addrs->ai_addr)->sin_addr.s_addr;
+               }
+
+       if (addrs)
+               {
+               freeaddrinfo(addrs);
+               }
+
+       return(ip);
        }
 
 static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef *sdRef, const char *host, const char *ip)
        {
-       unsigned long addr = inet_addr(ip);
+       // Call getip() after the call DNSServiceCreateConnection(). On the Win32 platform, WinSock must
+       // be initialized for getip() to succeed.  Any DNSService* call will initialize WinSock for us,
+       // so make sure DNSServiceCreateConnection() is called before getip() is.
+       unsigned long addr = 0;
        DNSServiceErrorType err = DNSServiceCreateConnection(sdRef);
        if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); }
+       addr = getip(ip);
        return(DNSServiceRegisterRecord(*sdRef, &record, kDNSServiceFlagsUnique, kDNSServiceInterfaceIndexAny, 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
        }
 
 static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef,
@@ -547,18 +568,23 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef,
        if (nam[0] == '.' && nam[1] == 0) nam = "";   // We allow '.' on the command line as a synonym for empty string
        if (dom[0] == '.' && dom[1] == 0) dom = "";   // We allow '.' on the command line as a synonym for empty string
        
+       printf("Registering Service %s.%s%s%s", nam[0] ? nam : "<<Default>>", typ, dom[0] ? "." : "", dom);
+       if (host && *host) printf(" host %s", host);
+       printf(" port %s\n", port);
+
        for (i = 0; i < argc; i++)
                {
-               unsigned char *len = ptr++;
-               *len = strlen(argv[i]);
-               strcpy((char*)ptr, argv[i]);
-               ptr += *len;
+               int length = strlen(argv[i]);
+               if (length <= 255)
+                       {
+                       *ptr++ = (unsigned char)length;
+                       strcpy((char*)ptr, argv[i]);
+                       ptr += length;
+                       printf("TXT %s\n", argv[i]);
+                       }
                }
        
-       printf("Registering Service %s.%s%s", nam, typ, dom);
-       if (host && *host) printf(" host %s", host);
-       printf(" port %s %s\n", port, txt);
-       return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, ptr-txt, txt, reg_reply, NULL));
+       return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, (uint16_t) (ptr-txt), txt, reg_reply, NULL));
        }
 
 int main(int argc, char **argv)
@@ -572,9 +598,6 @@ int main(int argc, char **argv)
        char *dom;
        int     optind;
        const char *progname = strrchr(argv[0], kFilePathSep) ? strrchr(argv[0], kFilePathSep) + 1 : argv[0];
-#ifndef NOT_HAVE_SETLINEBUF
-       setlinebuf(stdout);             // Want to see lines as they appear, not block buffered
-#endif
 
        if (argc > 1 && !strcmp(argv[1], "-lo"))
                {
@@ -584,6 +607,14 @@ int main(int argc, char **argv)
                printf("Using LocalOnly\n");
                }
 
+       if (argc > 2 && !strcmp(argv[1], "-i") && atoi(argv[2]))
+               {
+               opinterface = atoi(argv[2]);
+               argc -= 2;
+               argv += 2;
+               printf("Using interface %d\n", opinterface);
+               }
+
        if (argc < 2) goto Fail;        // Minimum command line is the command name and one argument
        operation = getfirstoption( argc, argv, "EFBLQRPAUNTMI", &optind);
        if (operation == -1) goto Fail;
@@ -605,7 +636,7 @@ int main(int argc, char **argv)
                case 'B':       if (argc < optind+1) goto Fail;
                                        dom = (argc < optind+2) ? "" : argv[optind+1];
                                        if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;   // We allow '.' on the command line as a synonym for empty string
-                                       printf("Browsing for %s%s\n", argv[optind+0], dom);
+                                       printf("Browsing for %s%s%s\n", argv[optind+0], dom[0] ? "." : "", dom);
                                        err = DNSServiceBrowse(&client, 0, opinterface, argv[optind+0], dom, browse_reply, NULL);
                                        break;
 
index 56dedd981c0088210a444aa47dea80cd001cf307..e4a757441109526b6bcf80f7e913b401bfcade2f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 
 include /Developer/Makefiles/pb_makefiles/platform.make
 
-MVERS = "mDNSResponder-107.4"
+MVERS = "mDNSResponder-107.5"
 
 install:
        cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install     OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS)
diff --git a/buildResults.xml b/buildResults.xml
new file mode 100644 (file)
index 0000000..b45ac9a
--- /dev/null
@@ -0,0 +1,50 @@
+<buildResults>\r\r
+       <dest dir="ExplorerPluginModule_msm">\r\r
+               <dest dir="Program Files/Bonjour">\r\r
+                       <src file="Clients/ExplorerPlugin/Release/*.dll"/>\r\r
+               </dest>\r\r
+       </dest>\r\r
+       <dest dir="JavaModule_msm">\r\r
+               <dest dir="Program Files/Bonjour">\r\r
+                       <src file="mDNSWindows/Java/build/prod/dns_sd.jar"/>\r\r
+               </dest>\r\r
+               <dest dir="System32">\r\r
+                       <src file="mDNSWindows/Java/build/prod/jdns_sd.dll"/>\r\r
+               </dest>\r\r
+       </dest>\r\r
+       <dest dir="mDNSResponder_msm">\r\r
+               <dest dir="Program Files/Bonjour">\r\r
+                       <src file="mDNSWindows/SystemService/Release/mDNSResponder.exe"/>\r\r
+                       <src file="mDNSWindows/mdnsNSP/Release/mdnsNSP.dll"/>\r\r
+               </dest>\r\r
+               <dest dir="System32">\r\r
+                       <src file="mDNSWindows/DLL/Release/dnssd.dll"/>\r\r
+                       <src file="Clients/DNS-SD.VisualStudio/Release/dns-sd.exe"/>\r\r
+               </dest>\r\r
+       </dest>\r\r
+       <dest dir="PrinterSetupModule_msm">\r\r
+               <dest dir="Program Files/Bonjour">\r\r
+                       <src file="Clients/PrinterSetupWizard/Release/*.exe"/>\r\r
+                       <src file="Clients/PrinterSetupWizard/Release/*.dll"/>\r\r
+               </dest>\r\r
+       </dest>\r\r
+       <dest dir="sdk_root/Program Files/Bonjour SDK">\r
+               <dest dir="include">\r\r
+                       <src file="mDNSShared/dns_sd.h"/>\r
+               </dest>\r\r
+               <dest dir="lib">\r\r
+                       <src file="mDNSWindows/DLL/Release/dnssd.lib"/>\r
+               </dest>\r\r
+               <dest dir="samples/C">\r\r
+                       <src file="Clients/dns-sd.c"/>\r
+                       <src file="Clients/DNS-SD.VisualStudio/Release/dns-sd.exe"/>\r\r
+               </dest>\r\r
+               <dest dir="samples/Java">\r\r
+                       <src file="Clients/Java/nmakefile"/>\r
+                       <src file="Clients/Java/BrowserApp.java"/>\r
+                       <src file="Clients/Java/SimpleChat.java"/>\r
+                       <src file="Clients/Java/Swing*.java"/>\r
+                       <src file="Clients/Java/build/prod/*.jar"/>\r
+               </dest>\r\r
+       </dest>\r\r
+</buildResults>\r\r
index 2ce24894e8665cb9216b3c06239340b2449742ad..a1b7dc43d596387399c6e0e418a0095f2ac3e041 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* -*- Mode: C; tab-width: 4 -*-
+ *
  * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
     Change History (most recent first):
 
 $Log: DNSCommon.c,v $
+Revision 1.92  2005/09/16 21:06:49  cheshire
+Use mDNS_TimeNow_NoLock macro, instead of writing "mDNSPlatformRawTime() + m->timenow_adjust" all over the place
+
+Revision 1.91  2005/07/10 22:10:37  cheshire
+The getOptRdata routine implicitly assumes the destination ResourceRecord is large enough to
+hold MaximumRDSize bytes, but its parameter was a generic ResourceRecord, which need not be that
+large. Changing the parameter to a LargeCacheRecord makes it clearer what the routine requires.
+
 Revision 1.90  2005/03/21 00:33:51  shersche
 <rdar://problem/4021486> Fix build warnings on Win32 platform
 
@@ -1383,9 +1392,10 @@ mDNSlocal mDNSu16 getVal16(const mDNSu8 **ptr)
        return val;
        }
 
-mDNSlocal const mDNSu8 *getOptRdata(const mDNSu8 *ptr, const mDNSu8 *limit, ResourceRecord *rr, mDNSu16 pktRDLen)
+mDNSlocal const mDNSu8 *getOptRdata(const mDNSu8 *ptr, const mDNSu8 *const limit, LargeCacheRecord *const cr, mDNSu16 pktRDLen)
        {
        int nread = 0;
+       ResourceRecord *const rr = &cr->r.resrec;
        rdataOpt *opt = (rdataOpt *)rr->rdata->u.data;
 
        while (nread < pktRDLen && (mDNSu8 *)opt < rr->rdata->u.data + MaximumRDSize - sizeof(rdataOpt))
@@ -1884,7 +1894,7 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
                                        rr->resrec.rdata->u.soa.min     = (mDNSu32) ((mDNSu32)ptr[0x10] << 24 | (mDNSu32)ptr[0x11] << 16 | (mDNSu32)ptr[0x12] << 8 | ptr[0x13]);
                                        break;
 
-               case kDNSType_OPT:  getOptRdata(ptr, end, &rr->resrec, pktrdlength); break;
+               case kDNSType_OPT:  getOptRdata(ptr, end, largecr, pktrdlength); break;
 
                default:                        if (pktrdlength > rr->resrec.rdata->MaxRDLength)
                                                                {
@@ -2047,14 +2057,14 @@ mDNSexport void mDNS_Lock(mDNS *const m)
        if (m->mDNS_busy == 0)
                {
                if (m->timenow)
-                       LogMsg("mDNS_Lock: m->timenow already set (%ld/%ld)", m->timenow, mDNSPlatformRawTime() + m->timenow_adjust);
-               m->timenow = mDNSPlatformRawTime() + m->timenow_adjust;
+                       LogMsg("mDNS_Lock: m->timenow already set (%ld/%ld)", 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);
-               m->timenow = mDNSPlatformRawTime() + m->timenow_adjust;
+               m->timenow = mDNS_TimeNow_NoLock(m);
                if (m->timenow == 0) m->timenow = 1;
                }
 
index db6d0e537fbeb6f4fd98ba9e55cdfb96f4b1c402..2098e1e8a8b5cde8662f772ced92fb7b856eb589 100755 (executable)
     Change History (most recent first):
 
 $Log: mDNS.c,v $
+Revision 1.532  2005/12/02 20:24:36  cheshire
+<rdar://problem/4363209> Adjust cutoff time for KA list by one second
+
+Revision 1.531  2005/12/02 19:05:42  cheshire
+Tidy up constants
+
+Revision 1.530  2005/11/07 01:49:48  cheshire
+For consistency, use NonZeroTime() function instead of ?: expression
+
+Revision 1.529  2005/10/25 23:42:24  cheshire
+<rdar://problem/4316057> Error in ResolveSimultaneousProbe() when type or class don't match
+Changed switch statement to an "if"
+
+Revision 1.528  2005/10/25 23:34:22  cheshire
+<rdar://problem/4316048> RequireGoodbye state not set/respected sometimes when machine going to sleep
+
+Revision 1.527  2005/10/25 22:43:59  cheshire
+Add clarifying comments
+
 Revision 1.526  2005/10/20 00:10:33  cheshire
 <rdar://problem/4290265> Add check to avoid crashing NAT gateways that have buggy DNS relay code
 
@@ -1747,12 +1766,12 @@ mDNSexport const mDNSv6Addr AllDNSLinkGroupv6  = { { 0xFF,0x02,0x00,0x00, 0x00,0
 mDNSexport const mDNSAddr   AllDNSLinkGroup_v4 = { mDNSAddrType_IPv4, { { { 224,   0,   0, 251 } } } };
 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 mDNSOpaque16 zeroID = { { 0, 0 } };
-mDNSexport const mDNSOpaque16 QueryFlags    = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery,                0 } };
-mDNSexport const mDNSOpaque16 uQueryFlags   = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery | kDNSFlag0_RD, 0 } };
-mDNSexport const mDNSOpaque16 ResponseFlags = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery | kDNSFlag0_AA, 0 } };
-mDNSexport const mDNSOpaque16 UpdateReqFlags= { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_Update,                  0 } };
-mDNSexport const mDNSOpaque16 UpdateRespFlags={ { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update,                  0 } };
+mDNSexport const mDNSOpaque16 zeroID          = { { 0, 0 } };
+mDNSexport const mDNSOpaque16 QueryFlags      = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery,                0 } };
+mDNSexport const mDNSOpaque16 uQueryFlags     = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery | kDNSFlag0_RD, 0 } };
+mDNSexport const mDNSOpaque16 ResponseFlags   = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery | kDNSFlag0_AA, 0 } };
+mDNSexport const mDNSOpaque16 UpdateReqFlags  = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_Update,                  0 } };
+mDNSexport const mDNSOpaque16 UpdateRespFlags = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update,                  0 } };
 
 // Any records bigger than this are considered 'large' records
 #define SmallRecordLimit 1024
@@ -3121,7 +3140,7 @@ mDNSlocal void SendResponses(mDNS *const m)
                                        numDereg++;
                                        responseptr = newptr;
                                        }
-                               else if (rr->NewRData)                                                  // If we have new data for this record
+                               else if (rr->NewRData && !m->SleepState)                                        // If we have new data for this record
                                        {
                                        RData *OldRData     = rr->resrec.rdata;
                                        mDNSu16 oldrdlength = rr->resrec.rdlength;
@@ -3132,6 +3151,7 @@ mDNSlocal void SendResponses(mDNS *const m)
                                                if (!newptr && m->omsg.h.numAnswers) break;
                                                numDereg++;
                                                responseptr = newptr;
+                                               rr->RequireGoodbye = mDNSfalse;
                                                }
                                        // 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);
@@ -3139,7 +3159,7 @@ mDNSlocal void SendResponses(mDNS *const m)
                                                rr->resrec.rrclass |= kDNSClass_UniqueRRSet;            // Temporarily set the cache flush bit so PutResourceRecord will set it
                                        newptr = PutResourceRecord(&m->omsg, 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;
+                                       if (newptr) { responseptr = newptr; rr->RequireGoodbye = mDNStrue; }
                                        SetNewRData(&rr->resrec, OldRData, oldrdlength);
                                        }
                                else
@@ -3367,7 +3387,8 @@ mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **quer
                                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
                                ResourceRecordAnswersQuestion(&rr->resrec, q) &&                        // which answers our question
-                               rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >= 0)                        // and it is less than half-way to expiry
+                               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)
                                {
                                *ka = rr;       // Link this record into our known answer chain
                                ka = &rr->NextInKAList;
@@ -3892,7 +3913,7 @@ mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *c
                        if (threshhold - RRExpireTime(rr) >= 0)         // If we have records about to expire within a second
                                if (delay - RRExpireTime(rr) < 0)               // then delay until after they've been deleted
                                        delay = RRExpireTime(rr);
-       if (delay - start > 0) return(delay ? delay : 1);       // Make sure we return non-zero if we want to delay
+       if (delay - start > 0) return(NonZeroTime(delay));
        else return(0);
        }
 
@@ -4651,7 +4672,7 @@ mDNSlocal int CompareRData(AuthRecord *our, CacheRecord *pkt)
        if (*pktptr > *ourptr) return(-1);                                                              // Our data is numerically lower; We lost
        if (*pktptr < *ourptr) return(+1);                                                              // Packet data is numerically lower; We won
        
-       debugf("CompareRData: How did we get here?");
+       LogMsg("CompareRData ERROR: Invalid state");
        return(-1);
        }
 
@@ -4754,14 +4775,13 @@ mDNSlocal void ResolveSimultaneousProbe(mDNS *const m, const DNSMessage *const q
                                int result          = (int)our->resrec.rrclass - (int)m->rec.r.resrec.rrclass;
                                if (!result) result = (int)our->resrec.rrtype  - (int)m->rec.r.resrec.rrtype;
                                if (!result) result = CompareRData(our, &m->rec.r);
-                               switch (result)
+                               if (result > 0)
+                                       debugf("ResolveSimultaneousProbe: %##s (%s): We won",  our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
+                               else if (result < 0)
                                        {
-                                       case  1:        debugf("ResolveSimultaneousProbe: %##s (%s): We won",  our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
-                                                               break;
-                                       case  0:        break;
-                                       case -1:        debugf("ResolveSimultaneousProbe: %##s (%s): We lost", our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
-                                                               mDNS_Deregister_internal(m, our, mDNS_Dereg_conflict);
-                                                               goto exit;
+                                       debugf("ResolveSimultaneousProbe: %##s (%s): We lost", our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
+                                       mDNS_Deregister_internal(m, our, mDNS_Dereg_conflict);
+                                       goto exit;
                                        }
                                }
                        }
@@ -5251,8 +5271,14 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
        const mDNSInterfaceID InterfaceID)
        {
        int i;
-       const mDNSu8 *ptr = LocateAnswers(response, end);       // We ignore questions (if any) in a DNS response packet
-       CacheRecord *CacheFlushRecords = (CacheRecord*)1;       // "(CacheRecord*)1" is special (non-zero) end-of-list marker
+
+       // We ignore questions (if any) in a DNS response packet
+       const mDNSu8 *ptr = LocateAnswers(response, end);
+
+       // "(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
+       // set non-zero, and that tells GetCacheEntity() that they're not, at this moment, eligible for recycling.
+       CacheRecord *CacheFlushRecords = (CacheRecord*)1;
        CacheRecord **cfp = &CacheFlushRecords;
 
        // All records in a DNS response packet are treated as equally valid statements of truth. If we want
index 11c97378dd1d09d19be8e3ac8a27cde7af03407e..0ff368f3c62a0b49de8a862cdb56d6e067b3aff1 100755 (executable)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: mDNSDebug.h,v $
+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
 
@@ -154,6 +157,8 @@ extern void LogMsgNoIdent(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,
 #if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
 extern void *mallocL(char *msg, unsigned int size);
 extern void freeL(char *msg, void *x);
+extern void LogMemCorruption(const char *format, ...);
+extern void uds_validatelists(void);
 #else
 #define mallocL(X,Y) malloc(Y)
 #define freeL(X,Y) free(Y)
@@ -179,6 +184,8 @@ extern void freeL(char *msg, void *x);
 #define        LogOperation debugf
 #endif
 
+#define ForceAlerts 0
+
 #ifdef __cplusplus
        }
 #endif
index e2d402d518de18b7f4e5b6a54c5a6b13fa95ba8a..9f81dc83aa8ad1fda7444d73f84a7dbe5369c9c7 100755 (executable)
@@ -60,6 +60,9 @@
     Change History (most recent first):
 
 $Log: mDNSEmbeddedAPI.h,v $
+Revision 1.288  2005/12/21 03:24:58  cheshire
+<rdar://problem/4388858> Code changes required to compile on EFI
+
 Revision 1.287  2005/10/20 00:10:33  cheshire
 <rdar://problem/4290265> Add check to avoid crashing NAT gateways that have buggy DNS relay code
 
@@ -998,7 +1001,17 @@ Merge in license terms from Quinn's copy, in preparation for Darwin release
 #ifndef __mDNSClientAPI_h
 #define __mDNSClientAPI_h
 
+#if defined(EFI32) || defined(EFI64)
+// EFI doesn't have stdarg.h
+#include "Tiano.h"
+#define va_list                        VA_LIST
+#define va_start(a, b) VA_START(a, b)
+#define va_end(a)              VA_END(a)
+#define va_arg(a, b)   VA_ARG(a, b)
+#else
 #include <stdarg.h>            // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
+#endif
+
 #include "mDNSDebug.h"
 
 #ifdef __cplusplus
index c129f9d07146dcf386819a8c4fe9e7de852b9e52..2e7c354fee6413c97733c6ce073a935a9131a759 100755 (executable)
     Change History (most recent first):
 
 $Log: uDNS.c,v $
+Revision 1.226  2005/12/20 02:46:33  cheshire
+<rdar://problem/4175520> mDNSPosix wide-area registration broken
+Check too strict -- we can still do wide-area registration (without NAT-PMP)
+without having to know our gateway address
+
 Revision 1.225  2005/10/21 22:51:17  cheshire
 <rdar://problem/4290265> Add check to avoid crashing NAT gateways that have buggy DNS relay code
 Refinement: Shorten "check-for-broken-dns-relay" to just "dnsbugtest"
@@ -1962,7 +1967,7 @@ mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, co
        if (router) u->Router       = *router;  else u->Router.ip.v4.NotAnInteger = 0;
        // setting router to zero indicates that nat mappings must be reestablished when router is reset
        
-       if ((v4Changed || RouterChanged || v6Changed) && (v4addr && router))
+       if ((v4Changed || RouterChanged || v6Changed) && v4addr)
                {
                // don't update these unless we've got V4
                UpdateHostnameRegistrations(m);
index 61da0a088156bb506e5b3b72b0168709275b53e2..0dbbe5e397923bf2816c8d89cbcca27b2ee5d9f6 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: mDNSMacOS9.c,v $
+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)
@@ -705,7 +708,7 @@ mDNSlocal void ScheduleNextTimerCallback(const mDNS *const m)
        {
        if (m->mDNSPlatformStatus == mStatus_NoError)
                {
-               SInt32 interval = m->NextScheduledEvent - (mDNSPlatformRawTime() + m->timenow_adjust);
+               SInt32 interval = m->NextScheduledEvent - mDNS_TimeNow_NoLock(m);
                if      (interval < 1)                 interval = 1;
                else if (interval > 0x70000000 / 1000) interval = 0x70000000 / mDNSPlatformOneSecond;
                else                                   interval = (interval * 1000 + mDNSPlatformOneSecond-1)/ mDNSPlatformOneSecond;
index 7a57d9288a9cf9ed2483be9b2d43e9cf186ef845..3816d58d72ab971af4aec57bf340c7c5e67638d9 100644 (file)
@@ -3,14 +3,14 @@
  * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
 
     Change History (most recent first):
 
 $Log: LegacyNATTraversal.c,v $
+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
 
@@ -106,6 +112,8 @@ Revision 1.1  2004/08/18 17:35:41  ksekar
 // TODO: remove later and do variable length
 #define MAX_SOAPMSGSIZE                65536
 
+// This code accidentally closes fd 0 all over the place
+// To stop that messing up the mDNSResponder core, we trap it and prevent it
 static int safe_close(int fd)
        {
        if (fd < 3) { /* LogMsg("safe_close: ERROR sd %d < 3", fd); */ return(-1); }
@@ -114,6 +122,10 @@ static int safe_close(int fd)
 
 #define close safe_close
 
+// This code uses fprintf(stderr, ...) and similar to log error messages
+// We redirect all of them to syslog using our LogMsg mechanism
+#define fprintf(file, ...) LogMsg(__VA_ARGS__)
+
 ////////////////////////////////////////////////////////////////////////
 // NetAddr Functions
 ////////////////////////////////////////////////////////////////////////
@@ -436,7 +448,7 @@ typedef struct tagIPINFO
 {
         int                             iFlags;
         char                    szIfName[IFNAMELEN];    /* Interface name                       */
-        unsigned char   abIP[IPLEN];                    /* IP in host byte order        */
+        unsigned char   abIP[IPLEN];
         unsigned short  wPort;
 } IPINFO, *PIPINFO, **PPIPINFO;
 
@@ -444,10 +456,13 @@ typedef struct hostent    HOSTENT, *PHOSTENT;
 
 static unsigned long GetNATIPNetmask(unsigned long dwIP)
 {
-       if ((dwIP & 0xFF000000) == 0x0A000000)  return 0xFF000000;
-       if ((dwIP & 0xFFF00000) == 0xAC100000)  return 0xFFF00000;
-       if ((dwIP & 0xFFFF0000) == 0xC0a80000)  return 0xFFFF0000;
-
+       static const union { uint8_t b[4]; uint32_t l; } mask_10 = { { 255, 0,   0, 0 } };      // Mask for 10/8
+       static const union { uint8_t b[4]; uint32_t l; } mask172 = { { 255, 240, 0, 0 } };      // Mask for 172.16/12
+       static const union { uint8_t b[4]; uint32_t l; } mask192 = { { 255, 255, 0, 0 } };      // Mask for 192.168/16
+       uint8_t *p = (uint8_t *)&dwIP;
+       if (p[0] ==  10                       ) return mask_10.l;
+       if (p[0] == 172 && (p[1] & 0xF0) == 16) return mask172.l;
+       if (p[0] == 192 && p[1] == 168        ) return mask192.l;
        return 0;       /* No NAT IP */
 }
 
@@ -531,8 +546,7 @@ static int GetIPInfo(PPIPINFO ppIPInfo)
                {
                case AF_INET:
                        memcpy(pIPInfo[iNum].szIfName, ifr->ifr_name, IFNAMELEN);
-                       dwIP =
-                               ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr);
+                       dwIP = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr;
                        memcpy(pIPInfo[iNum].abIP, &dwIP, sizeof(unsigned long));
                        if (ifrcopy.ifr_flags & IFF_POINTOPOINT)
                                pIPInfo[iNum].iFlags |= ISPPP;
@@ -605,7 +619,7 @@ static int SSDPListen()
        saddr.sin_family = AF_INET;
        //saddr.sin_addr.s_addr = inet_addr(SSDP_IP);
        //saddr.sin_port = htons(SSDP_PORT);
-       saddr.sin_addr.s_addr = htonl(g_dwLocalIP);
+       saddr.sin_addr.s_addr = g_dwLocalIP;
        saddr.sin_port = 0;
 
        // and set the multicast add_member structure
@@ -650,7 +664,7 @@ static int EventListen()
                bzero(&saddr, sizeof(saddr));
                saddr.sin_len = sizeof(saddr);
                saddr.sin_family = AF_INET;
-               saddr.sin_addr.s_addr = htonl(g_dwLocalIP);
+               saddr.sin_addr.s_addr = g_dwLocalIP;
                saddr.sin_port = htons(g_wEventPort);
 
                // return if okay
@@ -721,7 +735,7 @@ static void DumpHex(char *buf, int len)
                        nexti = i + 16;
                        endj = (nexti > len) ? len : nexti;
                        for (j = i; j < endj; j++)
-                               fprintf(g_log, "%02x ", buf[j] & 0xff);
+                               fprintf(g_log, "%02x %c ", buf[j] & 0xff, buf[j]);
                        if (j == len) {
                                if ((j % 16) != 0) {
                                        char pad[3 * 16 + 1];  // don't need the last 3 bytes anyway
@@ -760,7 +774,7 @@ static char *FindHTTPHeaderNewLine(char *pbuf, int iBufSize, int *pfEOH)
                result = memchr(pbuf, '\r', iBufSize);
                if (result == NULL) {
                        if (g_fLogging & NALOG_INFO0) {
-                               fprintf(g_log, "FindHTTPHeaderNewLine: er @(%d)\n", i);
+                               fprintf(g_log, "FindHTTPHeaderNewLine: er @(%d/%d)\n", i, iBufSize);
                                fflush(g_log);
                        }
                        return NULL;
@@ -898,7 +912,15 @@ static PHTTPResponse NewHTTPResponse_sz(
                pszEOL = FindHTTPHeaderNewLine(pszEOL,
                        iBufferSize - (pszEOL - pBuf),  // remainder size
                        &fEOH);
-               if (pszEOL == NULL) goto cleanup;  // syntax error
+               if (pszEOL == NULL) {
+                       if (g_fLogging & NALOG_INFO0) {
+                               fprintf(g_log, "NewHTTPResponse_sz: er reading header field %d @ %lu / %lu\n",
+                                       iNumHeaders, pHeader->pszName - pBuf, iBufferSize);
+                               DumpHex(pszHTTPResponse, iBufferSize);
+                               fflush(g_log);
+                       }
+                       goto cleanup;  // syntax error
+               }
 
                *pszEOL = '\0';  // terminate this string
                pszEOL += 2;  // point to beginning of next line
@@ -1308,12 +1330,9 @@ static void *TCPProc(void *in)
                char response[2000];
                PHTTPResponse resp;
                int n;
-               sprintf(callback, "%lu.%lu.%lu.%lu:%u", 
-                       (g_dwLocalIP >> 24) & 0xFF,
-                       (g_dwLocalIP >> 16) & 0xFF,
-                       (g_dwLocalIP >> 8) & 0xFF,
-                       (g_dwLocalIP >> 0) & 0xFF,
-                       g_wEventPort);
+               sprintf(callback, "%u.%u.%u.%u:%u",
+                       ((uint8_t*)&g_dwLocalIP)[0], ((uint8_t*)&g_dwLocalIP)[1],
+                       ((uint8_t*)&g_dwLocalIP)[2], ((uint8_t*)&g_dwLocalIP)[3], g_wEventPort);
 
                n = sprintf((char *)buf,
                        szEventMsgSubscribeFMT,
@@ -1328,7 +1347,7 @@ static void *TCPProc(void *in)
                if (n > 0)
                {
                        response[n] = '\0';
-                       resp = NewHTTPResponse_sz((char *)buf, n, TRUE);
+                       resp = NewHTTPResponse_sz((char *)response, n+1, TRUE);
                        if (NULL != resp)
                        {
 ////TracePrint(ELL_TRACE, "UPnP Subscribe returns %s/%d\n", resp->pszStatus, n);
@@ -1504,7 +1523,7 @@ static void *UDPProc(void *in)
 
                if (!FD_ISSET(g_sUDP, &readfds)) continue;
                recvaddrlen = sizeof(recvaddr);
-               n = recvfrom(g_sUDP, buf, sizeof(buf), 0,
+               n = recvfrom(g_sUDP, buf, sizeof(buf)-1, 0,
                        (struct sockaddr *)&recvaddr, &recvaddrlen);
                if (n < 0) {
                        if (g_fLogging & NALOG_ERROR)
@@ -1517,7 +1536,7 @@ static void *UDPProc(void *in)
                }
                buf[n] = '\0';
                if (strncmp((char *)buf, "HTTP/1.1", 8) == 0) {
-                       PHTTPResponse pResponse = NewHTTPResponse_sz((char *)buf, n, TRUE);
+                       PHTTPResponse pResponse = NewHTTPResponse_sz((char *)buf, n+1, TRUE);
                        PrintHTTPResponse(pResponse);
                        if (DiscoverRouter(pResponse) == 0)
                        {
@@ -1536,7 +1555,7 @@ static void *UDPProc(void *in)
                        // temporarily use this to fudge - will have the exact same
                        // parsing, only status/reason set to "*" and "HTTP/1.1".
                        // TODO: add support for HTTP requests
-                       PHTTPResponse pResponse = NewHTTPResponse_sz((char *)buf, n, TRUE);
+                       PHTTPResponse pResponse = NewHTTPResponse_sz((char *)buf, n+1, TRUE);
                        if (DiscoverRouter(pResponse) == 0)
                        {
                                time_t  now = time(NULL);
@@ -1858,13 +1877,14 @@ GetTimeElapsed(&tv_start, &tv_end, &tv_elapsed);
 
                FD_ZERO(&readfds);
                FD_SET(s, &readfds);
-               //timeout.tv_sec = g_iFunctionTimeout / U_TOGRAN;
-               //timeout.tv_usec = (g_iFunctionTimeout % U_TOGRAN) * 1000000 / U_TOGRAN;
-               // just do flat 2 sec now, since connection already established
-               timeout.tv_sec = 1;
-               timeout.tv_usec = 0;
-
 
+               // In testing, the Linksys Wireless-G Broadband Router "WRT54GS" takes
+               // up to four seconds to respond, and even then only a partial response,
+               // with the remainder coming in a second TCP segment half a second later.
+               // Accordingly, we wait up to five seconds for the initial data, and then after that
+               // wait one second after subsequent TCP segments, in care more data is still coming.
+               timeout.tv_sec  = iBufLen ? 1 : 5;
+               timeout.tv_usec = 0;
                iRet = select(s+1, &readfds, NULL, NULL, &timeout);
                if (iRet <= 0)
                {
@@ -1929,7 +1949,7 @@ GetTimeElapsed(&tv_start, &tv_end, &tv_elapsed);
 //fprintf(stderr, "2 -- \n");
 
        if (g_fLogging & NALOG_INFO1)
-               fprintf(g_log, "done recv @%lu\n", time(NULL));
+               fprintf(g_log, "SendTCPMsg_saddr_2part done recv %d @ %lu\n", iBufLen, time(NULL));
 
        if (result == NULL) {    // if caller just want to send/display msgs
                if (g_fLogging & NALOG_DUMP)
@@ -2018,7 +2038,7 @@ static int SendTCPMsg_saddr_parse(
        }
 
        if (g_fLogging & NALOG_INFO1)
-               fprintf(g_log, "SendTCPMsg/parse: Before Sending TCP Msg: %d == %lu?\n",
+               fprintf(g_log, "SendTCPMsg_saddr_parse: Before Sending TCP Msg: %d == %lu?\n",
                        iLen, strlen(msg));
        if (g_fLogging & NALOG_DUMP)
                fprintf(g_log,"Sending TCP msg:\n[%s]\n", msg);
@@ -2070,12 +2090,14 @@ static int SendTCPMsg_saddr_parse(
 
                FD_ZERO(&readfds);
                FD_SET(s, &readfds);
-               //timeout.tv_sec = g_iFunctionTimeout / U_TOGRAN;
-               //timeout.tv_usec = (g_iFunctionTimeout % U_TOGRAN) * 1000000 / U_TOGRAN;
-               // just do flat 2 sec now, since connection already established
-               timeout.tv_sec = 1;
-               timeout.tv_usec = 0;
 
+               // In testing, the Linksys Wireless-G Broadband Router "WRT54GS" takes
+               // up to four seconds to respond, and even then only a partial response,
+               // with the remainder coming in a second TCP segment half a second later.
+               // Accordingly, we wait up to five seconds for the initial data, and then after that
+               // wait one second after subsequent TCP segments, in care more data is still coming.
+               timeout.tv_sec  = iBufLen ? 1 : 5;
+               timeout.tv_usec = 0;
                iRet = select(s+1, &readfds, NULL, NULL, &timeout);
                if (iRet <= 0) {
 //fprintf(stderr, "**********: select failed (%d/%d)\n", iRet, errno);
@@ -2102,6 +2124,8 @@ static int SendTCPMsg_saddr_parse(
                if (resultSize <= iBufLen) {
                        char    t[1000];
                        i = recv(s, &t, 1000, 0);
+                       if (g_fLogging & NALOG_INFO1)
+                               fprintf(g_log, "SendTCPMsg_saddr_parse discarding %d bytes\n", i);
                        if (i== 0) break;
                        // Note that there's no dump here - prevents DoS attack from
                        // flooding the logs/diskspace
@@ -2109,6 +2133,8 @@ static int SendTCPMsg_saddr_parse(
                }
 
                i = recv(s, result + iBufLen, resultSize - iBufLen, 0);
+               if (g_fLogging & NALOG_INFO1)
+                       fprintf(g_log, "SendTCPMsg_saddr_parse read %d bytes (%d/%d)\n", i, iBufLen, resultSize);
                if (0 == i) {
 
                        break;
@@ -2131,7 +2157,7 @@ static int SendTCPMsg_saddr_parse(
 //fprintf(stderr, "p -- \n");
 
        if (g_fLogging & NALOG_INFO1)
-               fprintf(g_log, "done recv @%lu\n", time(NULL));
+               fprintf(g_log, "SendTCPMsg_saddr_parse done recv %d @ %lu\n", iBufLen, time(NULL));
 
        if (result == NULL) {    // if caller just want to send/display msgs
                if (g_fLogging & NALOG_DUMP)
@@ -2243,6 +2269,8 @@ static PHTTPResponse SendSOAPMsgControlAction(
                        &g_saddrRouterSOAP);
        }
 
+       if (g_fLogging & NALOG_INFO1)
+               fprintf(g_log, "SendSOAPMsgControlAction iResultLen %d\n", iResultLen);
        if (iResultLen > 0) {
                if (iResultLen > MAX_SOAPMSGSIZE) {
                        if (g_fLogging & NALOG_ALERT)
@@ -2473,10 +2501,8 @@ static void ParseURL(
        szBuf,
        pszHostPort?pszHostPort:"",
        pszPath?pszPath:"",
-       (psaddr->sin_addr.s_addr >> 24) & 0xff,
-       (psaddr->sin_addr.s_addr >> 16) & 0xff,
-       (psaddr->sin_addr.s_addr >> 8) & 0xff,
-       (psaddr->sin_addr.s_addr >> 0) & 0xff,
+       ((uint8_t*)&psaddr->sin_addr.s_addr)[0], ((uint8_t*)&psaddr->sin_addr.s_addr)[1],
+       ((uint8_t*)&psaddr->sin_addr.s_addr)[2], ((uint8_t*)&psaddr->sin_addr.s_addr)[3],
        psaddr->sin_port);
 #endif
 }
@@ -2606,17 +2632,13 @@ static void GetIPByName(char *hostname, unsigned long *ip_ret)
                if (pHEnt == NULL) {
                        if (g_fLogging & NALOG_ALERT)
                                fprintf(g_log, "Can't translate [%s] to IP...\n", hostname);
-                       g_dwLocalIP = htonl(INADDR_ANY);
+                       g_dwLocalIP = INADDR_ANY;
                        return;
                }
-               ip = ntohl(*(unsigned long *)(pHEnt->h_addr));
+               ip = *(unsigned long *)(pHEnt->h_addr);
                if (g_fLogging & NALOG_INFO1)
-                       fprintf(g_log, "hostname [%s] to ip: %ld.%ld.%ld.%ld\n",
-                               hostname,
-                               (ip >> 24) & 0xff,
-                               (ip >> 16) & 0xff,
-                               (ip >> 8) & 0xff,
-                               (ip >> 0) & 0xff);
+                       fprintf(g_log, "hostname [%s] to ip: %u.%u.%u.%u\n", hostname,
+                               ((uint8_t*)&ip)[0], ((uint8_t*)&ip)[1], ((uint8_t*)&ip)[2], ((uint8_t*)&ip)[3]);
        }
        *ip_ret = ip;
 }
@@ -2684,9 +2706,8 @@ mStatus LNT_UnmapPort(mDNSIPPort PubPort, mDNSBool tcp)
        //unsigned              long dwIP;
        Property                propArgs[3];
        PHTTPResponse   resp;
-    unsigned short port = PubPort.NotAnInteger;
     int protocol = tcp ? IPPROTO_TCP : IPPROTO_UDP;
-       sprintf(szEPort, "%u", port);
+       sprintf(szEPort, "%u", mDNSVal16(PubPort));
 
        bzero(propArgs, sizeof(propArgs));
        propArgs[0].pszName = "NewRemoteHost";
@@ -2734,26 +2755,19 @@ extern mStatus LNT_MapPort(mDNSIPPort priv, mDNSIPPort pub, mDNSBool tcp)
        char                    descr[40];
        Property                propArgs[8];
        PHTTPResponse   resp;
-    unsigned short iport = priv.NotAnInteger;
-    unsigned short eport = pub.NotAnInteger;
     int protocol = tcp ? IPPROTO_TCP : IPPROTO_UDP;
 
-
-       if (NA_E_EXISTS == GetMappingUnused(eport, protocol))
+       if (NA_E_EXISTS == GetMappingUnused(mDNSVal16(pub), protocol))
                return mStatus_AlreadyRegistered;
 
        //DeletePortMapping(eport, protocol);
 
-       sprintf(szEPort, "%u", eport);
-
-       sprintf(szIPort, "%u", iport);
+       sprintf(szEPort, "%u", mDNSVal16(pub));
+       sprintf(szIPort, "%u", mDNSVal16(priv));
 
        dwIP = g_dwLocalIP;
        sprintf(szLocalIP, "%u.%u.%u.%u",
-               (unsigned int)((dwIP >> 24) & 0xff),
-               (unsigned int)((dwIP >> 16) & 0xff),
-               (unsigned int)((dwIP >> 8) & 0xff),
-               (unsigned int)((dwIP >> 0) & 0xff));
+               ((uint8_t*)&dwIP)[0], ((uint8_t*)&dwIP)[1], ((uint8_t*)&dwIP)[2], ((uint8_t*)&dwIP)[3]);
 
        bzero(propArgs, sizeof(propArgs));
        propArgs[0].pszName = "NewRemoteHost";
@@ -2783,7 +2797,7 @@ extern mStatus LNT_MapPort(mDNSIPPort priv, mDNSIPPort pub, mDNSBool tcp)
        propArgs[5].pszValue = "1";
        propArgs[5].pszType = "boolean";
        propArgs[6].pszName = "NewPortMappingDescription";
-       sprintf(descr, "iC%u", eport);
+       sprintf(descr, "iC%u", mDNSVal16(pub));
        //propArgs[6].pszValue = "V";
        propArgs[6].pszValue = descr;
        propArgs[6].pszType = "string";
@@ -2791,9 +2805,15 @@ extern mStatus LNT_MapPort(mDNSIPPort priv, mDNSIPPort pub, mDNSBool tcp)
        propArgs[7].pszValue = "0";
        propArgs[7].pszType = "ui4";
 
+       if (g_fLogging & NALOG_INFO1)
+               fprintf(g_log, "Sending AddPortMapping priv %u pub %u\n", mDNSVal16(priv), mDNSVal16(pub));
+
        resp = SendSOAPMsgControlAction(
                "AddPortMapping", 8, propArgs, FALSE);
 
+       if (g_fLogging & NALOG_INFO1)
+               fprintf(g_log, "AddPortMapping resp %p\n", resp);
+
        if (resp == NULL) {
                return mStatus_NATTraversal;
        }
@@ -2914,11 +2934,13 @@ int LegacyNATInit(void)
        pthread_attr_t  attr;
        int                             iRet;
        //struct timeval        tv;
+       LogOperation("LegacyNATInit");
 
        static int              fFirstInitLocks = TRUE;
        FILE *log = NULL;       
        
        g_fLogging = 0;
+       //g_fLogging = ~0;              // Turns ALL logging on
        g_log = stderr;
 
        SetLocalIP();
diff --git a/mDNSMacOSX/PreferencePane/BonjourPref.icns b/mDNSMacOSX/PreferencePane/BonjourPref.icns
new file mode 100644 (file)
index 0000000..97b560f
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/BonjourPref.icns differ
diff --git a/mDNSMacOSX/PreferencePane/BonjourPref.tiff b/mDNSMacOSX/PreferencePane/BonjourPref.tiff
new file mode 100644 (file)
index 0000000..55cb212
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/BonjourPref.tiff differ
index b0464a833b6bfaceb868357bf1e47446ec3cff93..a42d9a50aaa6df11e583f7f69631fc76fb68f66d 100644 (file)
@@ -44,6 +44,9 @@
     Change History (most recent first):
 
 $Log: ConfigurationAuthority.c,v $
+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
 
@@ -144,8 +147,6 @@ OSStatus InitConfigAuthority(void)
        }
        require_noerr( err, AuthSetFailed);
 
-       (void) AttemptAcquireAuthority( false);
-
 AuthSetFailed:
 GetStrFailed:
 NewAuthFailed:
@@ -177,11 +178,7 @@ OSStatus ReleaseAuthority(void)
 
 Boolean        CurrentlyAuthorized(void)
 {
-       OSStatus err;
-
-       err = AuthorizationCopyRights(gAuthRef, &gAuthSet, (AuthorizationEnvironment*) NULL,
-                                                                       (AuthorizationFlags) 0, (AuthorizationRights**) NULL);
-
+       OSStatus err = AttemptAcquireAuthority(true);
        return err == noErr;
 }
 
diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns
deleted file mode 100644 (file)
index 028a3a2..0000000
Binary files a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns and /dev/null differ
diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff
deleted file mode 100644 (file)
index 985ae19..0000000
Binary files a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff and /dev/null differ
index 3759d87c194ebc952d667c52bfc14deb1e3b3aa4..e8dbd926df9f5c52e30a9a0c500e214535369b96 100644 (file)
@@ -5,14 +5,14 @@
        <key>IBDocumentLocation</key>
        <string>32 63 547 281 0 0 1024 746 </string>
        <key>IBFramework Version</key>
-       <string>364.0</string>
+       <string>439.0</string>
        <key>IBOpenObjects</key>
        <array>
-               <integer>12</integer>
                <integer>255</integer>
                <integer>333</integer>
+               <integer>12</integer>
        </array>
        <key>IBSystem Version</key>
-       <string>7U13</string>
+       <string>8F23</string>
 </dict>
 </plist>
index d024da1bdedbb92d7a5eb555d2a430fbb2e6b9c9..eec01ee4ea446697e9234bbacc843e0b268ca2a9 100644 (file)
Binary files a/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib and b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib differ
index 242d42637289be4329b902babfa46eddc75844c3..89b9736caababb867e39c9542b0cf24f518e1073 100644 (file)
 
     Change History (most recent first):
 $Log: PrivilegedOperations.c,v $
+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
 
@@ -88,7 +92,8 @@ OSStatus EnsureToolInstalled(void)
        int                             status;
        OSStatus                err = noErr;
        const char              *args[] = { kToolPath, "0", "V", NULL };
-       char                    toolPath[PATH_MAX] = {};
+       char                    toolSourcePath[PATH_MAX] = {};
+       char                    toolInstallerPath[PATH_MAX] = {};
 
        if (gToolApproved) 
                return noErr;
@@ -106,15 +111,17 @@ OSStatus EnsureToolInstalled(void)
        bundleURL = CFBundleCopyBundleURL(CFBundleGetBundleWithIdentifier(CFSTR("com.apple.preference.bonjour")) );
        if (bundleURL != NULL)
        {
-               CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolPath, sizeof toolPath);
-               strcat(toolPath, "/Contents/Resources/" kToolName);
+               CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolSourcePath, sizeof toolSourcePath);
+               if (strlcat(toolSourcePath,    "/Contents/Resources/" kToolName,      sizeof toolSourcePath   ) >= sizeof toolSourcePath   ) return(-1);
+               CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolInstallerPath, sizeof toolInstallerPath);
+               if (strlcat(toolInstallerPath, "/Contents/Resources/" kToolInstaller, sizeof toolInstallerPath) >= sizeof toolInstallerPath) return(-1);
        }
        else
                return coreFoundationUnknownErr;
        
        // Obtain authorization and run in-bundle copy as root to install it
        {
-               AuthorizationItem               aewpRight = { kAuthorizationRightExecute, strlen(toolPath), toolPath, 0 };
+               AuthorizationItem               aewpRight = { kAuthorizationRightExecute, strlen(toolInstallerPath), toolInstallerPath, 0 };
                AuthorizationItemSet    rights = { 1, &aewpRight };
                AuthorizationRef                authRef;
                
@@ -123,8 +130,8 @@ OSStatus EnsureToolInstalled(void)
                                        kAuthorizationFlagPreAuthorize, &authRef);
                if (err == noErr)
                {
-                       args[2] = "I";
-                       err = AuthorizationExecuteWithPrivileges(authRef, toolPath, 0, (char * const *)&args[1], (FILE**) NULL);
+                       char *installerargs[] = { toolSourcePath, NULL };
+                       err = AuthorizationExecuteWithPrivileges(authRef, toolInstallerPath, 0, installerargs, (FILE**) NULL);
                        if (err == noErr)
                                gToolApproved = true;
                        (void) AuthorizationFree(authRef, kAuthorizationFlagDestroyRights);
index 706be05e2cf45ca5574f15a76acf12d4c473f787..c5c68a0b5ad7d3a7d88d51b30e8cc06358a9bc62 100644 (file)
 
     Change History (most recent first):
 $Log: PrivilegedOperations.h,v $
+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.
@@ -57,12 +61,11 @@ Add Preference Pane to facilitate testing of DDNS & wide-area features
 #include <CoreServices/CoreServices.h>
 #include <CoreFoundation/CoreFoundation.h>
 
-#define        PRIV_OP_TOOL_VERS       2
+#define        PRIV_OP_TOOL_VERS       3
 
-#define        kToolHome       "/Library/Application Support/"
-#define        kToolDir        "Bonjour"
-#define        kToolName       "ddnswriteconfig"
-#define        kToolPath       kToolHome kToolDir "/" kToolName
+#define        kToolName      "ddnswriteconfig"
+#define        kToolPath      "/Library/Application Support/Bonjour/" kToolName
+#define        kToolInstaller "installtool"
 
 #define        SC_DYNDNS_SETUP_KEY                     CFSTR("Setup:/Network/DynamicDNS")
 #define        SC_DYNDNS_STATE_KEY                     CFSTR("State:/Network/DynamicDNS")
index f9383c690f714de11f11899e45f261ae61ef67ca..ff3080ef37193ebd2c9de1872294ab29ca6986c4 100644 (file)
 
     Change History (most recent first):
 $Log: ddnswriteconfig.m,v $
+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.
@@ -80,54 +84,6 @@ Add Preference Pane to facilitate testing of DDNS & wide-area features
 
 static AuthorizationRef        gAuthRef = 0;
 
-int
-CopySUIDTool(const char *srcPath, const char *dstPath)
-// Copy a tool from srcPath to dstPath and set its 'x' and SUID bits. Return 0 on success.
-{
-       int             srcFD, dstFD, err = 0;
-       off_t   len, written;
-       void    *pSrc;
-       
-       srcFD = open( srcPath, O_RDONLY, (mode_t) 0);
-       require_action( srcFD > 0, OpenSrcFailed, err=errno;);
-
-       len = lseek( srcFD, 0, SEEK_END);
-       require_action( len > 0, GetSrcLenFailed, err=errno;);
-       pSrc = mmap( NULL, len, PROT_READ, MAP_FILE, srcFD, 0);
-       require_action( pSrc != (void*)-1, MMapFailed, err=errno;);
-
-       dstFD = open( dstPath, O_RDWR | O_CREAT | O_TRUNC, (mode_t) 0);
-       require_action( dstFD > 0, OpenDstFailed, err=errno;);
-
-       written = write( dstFD, pSrc, len);
-       require_action( written == len, WriteFailed, err=errno;);
-
-       err = fchmod( dstFD, S_IRUSR | S_IXUSR | S_ISUID | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
-
-WriteFailed:
-       close( dstFD);
-OpenDstFailed:
-       munmap( pSrc, len);
-MMapFailed:
-GetSrcLenFailed:
-       close( srcFD);
-OpenSrcFailed:
-       return err;
-}
-
-
-int    
-InstallRootTool( const char *srcPath)
-{
-       if (geteuid() != 0)
-               return -1;              // failure; not running as root
-
-       (void) mkdir(kToolHome kToolDir, S_IRUSR | S_IXUSR | S_IWUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
-
-       return CopySUIDTool( srcPath, kToolPath);
-}
-
-
 OSStatus
 WriteArrayToDynDNS(CFStringRef arrayKey, CFArrayRef domainArray)
 {
@@ -435,7 +391,6 @@ int main( int argc, char **argv)
 /* argv[0] is the exec path; argv[1] is a fd for input data; argv[2]... are operation codes.
    The tool supports the following operations:
        V               -- exit with status PRIV_OP_TOOL_VERS
-       I               -- install self as suid-root tool into system (must be run as root)
        A               -- read AuthInfo from input pipe
        Wd              -- write registration domain to dynamic store
        Wb              -- write browse domain to dynamic store
@@ -444,19 +399,10 @@ int       main( int argc, char **argv)
 */
 {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-       int     commFD = -1, iArg, savedUID, result = 0;
-
-       if ( argc == 3 && 0 == strcmp( argv[2], "I")) {
-               return InstallRootTool( argv[0]);
-       }
+       int     commFD = -1, iArg, result = 0;
 
-       savedUID = geteuid();
-#if 1
        if ( 0 != seteuid( 0))
                return -1;
-#else
-       sleep( 10);
-#endif
 
        if ( argc == 3 && 0 == strcmp( argv[2], "V"))
                return PRIV_OP_TOOL_VERS;
diff --git a/mDNSMacOSX/PreferencePane/installtool b/mDNSMacOSX/PreferencePane/installtool
new file mode 100755 (executable)
index 0000000..8fa79ad
--- /dev/null
@@ -0,0 +1,100 @@
+#!/usr/bin/perl
+#
+# File: installtool
+# 
+# Abstract: Copy "ddnswriteconfig" to Application Support and make it setuid root.
+# 
+# Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
+# 
+# Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+# ("Apple") in consideration of your agreement to the following terms, and your
+# use, installation, modification or redistribution of this Apple software
+# constitutes acceptance of these terms.  If you do not agree with these terms,
+# please do not use, install, modify or redistribute this Apple software.
+# 
+# In consideration of your agreement to abide by the following terms, and subject
+# to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+# copyrights in this original Apple software (the "Apple Software"), to use,
+# reproduce, modify and redistribute the Apple Software, with or without
+# modifications, in source and/or binary forms; provided that if you redistribute
+# the Apple Software in its entirety and without modifications, you must retain
+# this notice and the following text and disclaimers in all such redistributions of
+# the Apple Software.  Neither the name, trademarks, service marks or logos of
+# Apple Computer, Inc. may be used to endorse or promote products derived from the
+# Apple Software without specific prior written permission from Apple.  Except as
+# expressly stated in this notice, no other rights or licenses, express or implied,
+# are granted by Apple herein, including but not limited to any patent rights that
+# may be infringed by your derivative works or by other works in which the Apple
+# Software may be incorporated.
+# 
+# The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+# WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+# WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+# COMBINATION WITH YOUR PRODUCTS.
+# 
+# IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+# OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+# (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# 
+# Change History (most recent first):
+# 
+# $Log: installtool,v $
+# 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.
+#
+# This script will be run as root by the AEWP trampoline.
+#
+
+use File::Temp qw/ :mktemp /;
+
+$dest_dir = "/Library/Application Support/Bonjour";
+$dest = $dest_dir . "/ddnswriteconfig";
+
+$template = ".XXXXXX";
+
+# Perl seems to think this code is running setuid root, so it applies its security checks.
+# See <http://www.monster-submit.com/resources/docs/pod/perlsec.html>.
+# In fact this is NOT a setuid script. It is a normal unprivileged user-level script --
+# but it is run as root when properly authorized by a user with an admin password,
+# via the AuthorizationExecuteWithPrivileges() call.
+# We therefore have to do this trick pattern match to 'untaint' the source file specified in $ARGV[0].
+if ($ARGV[0] =~ /^(.+)$/) { $src = $1; }
+
+# Also clear $ENV{PATH} so we don't get "Insecure $ENV{PATH}" fatal errors
+$ENV{PATH} = "";
+
+if (! -d $dest_dir) {
+   $dest_tmp_dir = mkdtemp ($dest_dir . $template);
+   (chown 0, 80, $dest_tmp_dir) or cleanup_dir();
+   (chmod 0755, $dest_tmp_dir) or cleanup_dir();
+   (rename $dest_tmp_dir, $dest_dir) or cleanup_dir();
+}
+
+$dest_tmp = mktemp ($dest . $template);
+
+if ($src ne '') {
+   system ('/bin/cp', '-f', $src, $dest_tmp) and cleanup();
+   (chown 0, 80, $dest_tmp) or cleanup();
+   (chmod 04555, $dest_tmp) or cleanup();
+   (rename $dest_tmp, $dest) or cleanup();
+}
+exit (0);
+
+sub cleanup {
+   unlink $dest_tmp;
+   exit (1);
+}
+
+sub cleanup_dir {
+   unlink $dest_tmp_dir;
+   exit (1);
+}
index 779447941c2ad40e0534f25c854d9fe909f3b7ae..d2b1b16148650b46ea188cd82c05f1d178c62579 100644 (file)
     Change History (most recent first):
 
 $Log: daemon.c,v $
-Revision 1.255.2.1  2005/07/22 21:45:04  ksekar
+Revision 1.260  2005/11/07 01:51:58  cheshire
+<rdar://problem/4331591> Include list of configured DNS servers in SIGINFO output
+
+Revision 1.259  2005/07/22 21:50:55  ksekar
 Fix GCC 4.0/Intel compiler warnings
 
+Revision 1.258  2005/07/04 22:40:26  cheshire
+Additional debugging code to help catch memory corruption
+
+Revision 1.257  2005/03/28 19:28:55  cheshire
+Fix minor typos in LogOperation() messages
+
+Revision 1.256  2005/03/17 22:01:22  cheshire
+Tidy up alignment of lines to make code more readable
+
 Revision 1.255  2005/03/09 00:48:43  cheshire
 <rdar://problem/4015157> QU packets getting sent too early on wake from sleep
 Move "m->p->NetworkChanged = 0;" line from caller to callee
@@ -749,59 +761,104 @@ static DNSServiceRegistration      *DNSServiceRegistrationList      = NULL;
 
 char _malloc_options[] = "AXZ";
 
+mDNSexport void LogMemCorruption(const char *format, ...)
+       {
+       char buffer[512];
+       va_list ptr;
+       va_start(ptr,format);
+       buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
+       va_end(ptr);
+       LogMsg("!!!! %s !!!!", buffer);
+       NotifyOfElusiveBug("Memory Corruption", 0, buffer);
+       }
+
 mDNSlocal void validatelists(mDNS *const m)
        {
+       // Check Mach client lists
+       
        DNSServiceDomainEnumeration *e;
-       DNSServiceBrowser           *b;
-       DNSServiceResolver          *l;
-       DNSServiceRegistration      *r;
-       AuthRecord                  *rr;
-       CacheGroup                  *cg;
-       CacheRecord                 *cr;
-       DNSQuestion                 *q;
-       mDNSu32 slot;
-       NetworkInterfaceInfoOSX     *i;
-
        for (e = DNSServiceDomainEnumerationList; e; e=e->next)
                if (e->ClientMachPort == 0 || e->ClientMachPort == (mach_port_t)~0)
-                       LogMsg("!!!! DNSServiceDomainEnumerationList: %p is garbage (%X) !!!!", e, e->ClientMachPort);
+                       LogMemCorruption("DNSServiceDomainEnumerationList: %p is garbage (%X)", e, e->ClientMachPort);
 
+       DNSServiceBrowser           *b;
        for (b = DNSServiceBrowserList; b; b=b->next)
                if (b->ClientMachPort == 0 || b->ClientMachPort == (mach_port_t)~0)
-                       LogMsg("!!!! DNSServiceBrowserList: %p is garbage (%X) !!!!", b, b->ClientMachPort);
+                       LogMemCorruption("DNSServiceBrowserList: %p is garbage (%X)", b, b->ClientMachPort);
 
+       DNSServiceResolver          *l;
        for (l = DNSServiceResolverList; l; l=l->next)
                if (l->ClientMachPort == 0 || l->ClientMachPort == (mach_port_t)~0)
-                       LogMsg("!!!! DNSServiceResolverList: %p is garbage (%X) !!!!", l, l->ClientMachPort);
+                       LogMemCorruption("DNSServiceResolverList: %p is garbage (%X)", l, l->ClientMachPort);
 
+       DNSServiceRegistration      *r;
        for (r = DNSServiceRegistrationList; r; r=r->next)
                if (r->ClientMachPort == 0 || r->ClientMachPort == (mach_port_t)~0)
-                       LogMsg("!!!! DNSServiceRegistrationList: %p is garbage (%X) !!!!", r, r->ClientMachPort);
+                       LogMemCorruption("DNSServiceRegistrationList: %p is garbage (%X)", r, r->ClientMachPort);
+
+       // Check UDS client lists
+       uds_validatelists();
 
+       // Check core mDNS lists
+       AuthRecord                  *rr;
        for (rr = m->ResourceRecords; rr; rr=rr->next)
                {
                if (rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
-                       LogMsg("!!!! ResourceRecords list: %p is garbage (%X) !!!!", rr, rr->resrec.RecordType);
+                       LogMemCorruption("ResourceRecords list: %p is garbage (%X)", rr, rr->resrec.RecordType);
                if (rr->resrec.name != &rr->namestorage)
-                       LogMsg("!!!! ResourceRecords list: %p name %p does not point to namestorage %p %##s",
+                       LogMemCorruption("ResourceRecords list: %p name %p does not point to namestorage %p %##s",
                                rr, rr->resrec.name->c, rr->namestorage.c, rr->namestorage.c);
                }
 
        for (rr = m->DuplicateRecords; rr; rr=rr->next)
                if (rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
-                       LogMsg("!!!! DuplicateRecords list: %p is garbage (%X) !!!!", rr, rr->resrec.RecordType);
+                       LogMemCorruption("DuplicateRecords list: %p is garbage (%X)", rr, rr->resrec.RecordType);
 
+       DNSQuestion                 *q;
        for (q = m->Questions; q; q=q->next)
                if (q->ThisQInterval == (mDNSs32)~0)
-                       LogMsg("!!!! Questions list: %p is garbage (%lX) !!!!", q, q->ThisQInterval);
+                       LogMemCorruption("Questions list: %p is garbage (%lX)", q, q->ThisQInterval);
 
+       CacheGroup                  *cg;
+       CacheRecord                 *cr;
+       mDNSu32 slot;
        FORALL_CACHERECORDS(slot, cg, cr)
                if (cr->resrec.RecordType == 0 || cr->resrec.RecordType == 0xFF)
-                       LogMsg("!!!! Cache slot %lu: %p is garbage (%X) !!!!", slot, rr, rr->resrec.RecordType);
+                       LogMemCorruption("Cache slot %lu: %p is garbage (%X)", slot, rr, rr->resrec.RecordType);
+
+       // Check platform-layer lists
 
+       NetworkInterfaceInfoOSX     *i;
        for (i = m->p->InterfaceList; i; i = i->next)
                if (!i->ifa_name)
-                       LogMsg("!!!! InterfaceList: %p is garbage !!!!", i);
+                       LogMemCorruption("InterfaceList: %p is garbage", i);
+
+       // Check uDNS lists
+
+       for (q = m->uDNS_info.ActiveQueries; q; q=q->next)
+               if (*(long*)q == (mDNSs32)~0)
+                       LogMemCorruption("uDNS_info.ActiveQueries: %p is garbage (%lX)", q, *(long*)q);
+
+       ServiceRecordSet            *s;
+       for (s = m->uDNS_info.ServiceRegistrations; s; s=s->next)
+               if (s->next == (ServiceRecordSet*)~0)
+                       LogMemCorruption("uDNS_info.ServiceRegistrations: %p is garbage (%lX)", s, s->next);
+
+       for (rr = m->uDNS_info.RecordRegistrations; rr; rr=rr->next)
+               {
+               if (rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
+                       LogMemCorruption("uDNS_info.RecordRegistrations: %p is garbage (%X)", rr, rr->resrec.RecordType);
+               if (rr->resrec.name != &rr->namestorage)
+                       LogMemCorruption("uDNS_info.RecordRegistrations: %p name %p does not point to namestorage %p %##s",
+                               rr, rr->resrec.name->c, rr->namestorage.c, rr->namestorage.c);
+               }
+
+       NATTraversalInfo            *n;
+       for (n = m->uDNS_info.NATTraversals; n; n=n->next)
+               if (n->op > 2) LogMemCorruption("uDNS_info.NATTraversals: %p is garbage", n);
+
+       for (n = m->uDNS_info.LLQNatInfo; n; n=n->next)
+               if (n->op > 2) LogMemCorruption("uDNS_info.LLQNatInfo: %p is garbage", n);
        }
 
 void *mallocL(char *msg, unsigned int size)
@@ -902,8 +959,8 @@ mDNSlocal void AbortClient(mach_port_t ClientMachPort, void *m)
                while (qptr)
                        {
                        if (m && m != x)
-                               LogMsg("%5d: DNSServiceBrowser(%##s) STOP; WARNING m %p != x %p", ClientMachPort, qptr->q.qname.c, m, x);
-                       else LogOperation("%5d: DNSServiceBrowser(%##s) STOP", ClientMachPort, qptr->q.qname.c);
+                               LogMsg("%5d: DNSServiceBrowse(%##s) STOP; WARNING m %p != x %p", ClientMachPort, qptr->q.qname.c, m, x);
+                       else LogOperation("%5d: DNSServiceBrowse(%##s) STOP", ClientMachPort, qptr->q.qname.c);
                        mDNS_StopBrowse(&mDNSStorage, &qptr->q);
                        freePtr = qptr;
                        qptr = qptr->next;
@@ -925,8 +982,8 @@ mDNSlocal void AbortClient(mach_port_t ClientMachPort, void *m)
                DNSServiceResolver *x = *l;
                *l = (*l)->next;
                if (m && m != x)
-                       LogMsg("%5d: DNSServiceResolver(%##s) STOP; WARNING m %p != x %p", ClientMachPort, x->i.name.c, m, x);
-               else LogOperation("%5d: DNSServiceResolver(%##s) STOP", ClientMachPort, x->i.name.c);
+                       LogMsg("%5d: DNSServiceResolve(%##s) STOP; WARNING m %p != x %p", ClientMachPort, x->i.name.c, m, x);
+               else LogOperation("%5d: DNSServiceResolve(%##s) STOP", ClientMachPort, x->i.name.c);
                mDNS_StopResolveService(&mDNSStorage, &x->q);
                freeL("DNSServiceResolver", x);
                return;
@@ -976,19 +1033,21 @@ mDNSlocal void AbortClientWithLogMessage(mach_port_t c, char *reason, char *msg,
        while (b && b->ClientMachPort != c) b = b->next;
        while (l && l->ClientMachPort != c) l = l->next;
        while (r && r->ClientMachPort != c) r = r->next;
-       if      (e)     LogMsg("%5d: DomainEnumeration(%##s) %s%s",                   c, e->dom.qname.c,            reason, msg);
+
+       if      (e) LogMsg("%5d: DomainEnumeration(%##s) %s%s",                   c, e->dom.qname.c,                reason, msg);
        else if (b)
-               {
-               for (qptr = b->qlist; qptr; qptr = qptr->next)
-                               LogMsg("%5d: Browser(%##s) %s%s",                             c, qptr->q.qname.c,              reason, msg);
-               }
-       else if (l)     LogMsg("%5d: Resolver(%##s) %s%s",                            c, l->i.name.c,               reason, msg);
+                       {
+                       for (qptr = b->qlist; qptr; qptr = qptr->next)
+                               LogMsg("%5d: Browser(%##s) %s%s",                             c, qptr->q.qname.c,               reason, msg);
+                       }
+       else if (l) LogMsg("%5d: Resolver(%##s) %s%s",                            c, l->i.name.c,                   reason, msg);
        else if (r)
-               {
-               ServiceInstance *si;
-               for (si = r->regs; si; si = si->next) LogMsg("%5d: Registration(%##s) %s%s", c, si->srs.RR_SRV.resrec.name->c, reason, msg);
-               }
-       else            LogMsg("%5d: (%s) %s, but no record of client can be found!", c,                            reason, msg);
+                       {
+                       ServiceInstance *si;
+                       for (si = r->regs; si; si = si->next)
+                               LogMsg("%5d: Registration(%##s) %s%s",                        c, si->srs.RR_SRV.resrec.name->c, reason, msg);
+                       }
+       else        LogMsg("%5d: (%s) %s, but no record of client can be found!", c,                                reason, msg);
 
        AbortClient(c, m);
        }
@@ -1410,7 +1469,7 @@ mDNSexport kern_return_t provide_DNSServiceResolverResolve_rpc(mach_port_t unuse
        DNSServiceResolverList = x;
 
        // Do the operation
-       LogOperation("%5d: DNSServiceResolver(%##s) START", client, x->i.name.c);
+       LogOperation("%5d: DNSServiceResolve(%##s) START", client, x->i.name.c);
        err = mDNS_StartResolveService(&mDNSStorage, &x->q, &x->i, FoundInstanceInfo, x);
        if (err) { AbortClient(client, x); errormsg = "mDNS_StartResolveService"; goto fail; }
 
@@ -2283,6 +2342,7 @@ mDNSlocal void INFOCallback(void)
        DNSServiceResolver          *l;
        DNSServiceRegistration      *r;
        NetworkInterfaceInfoOSX     *i;
+       DNSServer *s;
 
        LogMsgIdent(mDNSResponderVersionString, "---- BEGIN STATE LOG ----");
        
@@ -2324,6 +2384,9 @@ mDNSlocal void INFOCallback(void)
                                &i->ifinfo.ip);
                }
 
+       for (s = mDNSStorage.uDNS_info.Servers; s; s = s->next)
+               LogMsgNoIdent("DNS Server %#a %##s", &s->addr, s->domain.c);
+
        LogMsgIdent(mDNSResponderVersionString, "----  END STATE LOG  ----");
        }
 
index 59806c480a3ef87f06bb02bc21144def4efea9c9..d926cb12f17bb59cee5f68ddad46cd9a935088ec 100644 (file)
@@ -3,14 +3,14 @@
  * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
 
     Change History (most recent first):
 
 $Log: mDNSMacOSX.c,v $
+Revision 1.323  2006/01/05 21:45:27  cheshire
+<rdar://problem/4400118> Fix uninitialized structure member in IPv6 code
+
+Revision 1.322  2006/01/05 21:41:50  cheshire
+<rdar://problem/4108164> Reword "mach_absolute_time went backwards" dialog
+
+Revision 1.321  2006/01/05 21:35:06  cheshire
+Add (commented out) trigger value for testing "mach_absolute_time went backwards" notice
+
+Revision 1.320  2005/12/03 01:39:28  cheshire
+<rdar://problem/4363411> Improve diagnostic message to indicate that message will not appear to customers
+
+Revision 1.319  2005/12/02 00:02:15  cheshire
+Include recvmsg return value in error message
+
 Revision 1.318  2005/10/20 00:10:34  cheshire
 <rdar://problem/4290265> Add check to avoid crashing NAT gateways that have buggy DNS relay code
 
@@ -1116,7 +1131,7 @@ mDNSlocal void RemoveDefRegDomain(domainname *d)
        debugf("Requested removal of default registration domain %##s not in contained in list", d->c); 
        }
 
-mDNSexport void NotifyOfElusiveBug(const char *title, mDNSu32 radarid, const char *msg)
+mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both strings are UTF-8 text
        {
        static int notifyCount = 0;
        if (notifyCount) return;
@@ -1138,11 +1153,15 @@ mDNSexport void NotifyOfElusiveBug(const char *title, mDNSu32 radarid, const cha
                }
        #endif
 
-       // Send a notification to the user to contact coreos-networking
+       LogMsg("%s", title);
+       LogMsg("%s", msg);
+       // Display a notification to the user
        notifyCount++;
-       CFStringRef alertHeader  = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
-       CFStringRef alertFormat  = CFSTR("Congratulations, you've reproduced an elusive bug. Please contact the owner of <rdar://problem/%d>. %s");
-       CFStringRef alertMessage = CFStringCreateWithFormat(NULL, NULL, alertFormat, radarid, msg);
+       static const char footer[] = "(Note: This message only appears on machines with 17.x.x.x IP addresses — i.e. at Apple — not on customer machines.)";
+       CFStringRef alertHeader  = CFStringCreateWithCString(NULL, title,  kCFStringEncodingUTF8);
+       CFStringRef alertBody    = CFStringCreateWithCString(NULL, msg,    kCFStringEncodingUTF8);
+       CFStringRef alertFooter  = CFStringCreateWithCString(NULL, footer, kCFStringEncodingUTF8);
+       CFStringRef alertMessage = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\r\r%@"), alertBody, alertFooter);
        CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, NULL);
        }
 
@@ -1342,8 +1361,8 @@ mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
                }
        if (msg.msg_controllen < (int)sizeof(struct cmsghdr))
                {
-               if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
-                       s, msg.msg_controllen, 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)
@@ -1518,8 +1537,10 @@ mDNSlocal void myCFSocketCallBack(const CFSocketRef cfs, const CFSocketCallBackT
                        LogMsg("myCFSocketCallBack 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)", 3375328,
-                               "Alternatively, you can send email to radar-3387020@group.apple.com. "
+                       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
@@ -1981,7 +2002,7 @@ mDNSlocal mStatus SetupSocket(mDNS *const m, CFSocketSet *cp, mDNSBool mcast, co
                listening_sockaddr6.sin6_family      = AF_INET6;
                listening_sockaddr6.sin6_port        = port.NotAnInteger;
                listening_sockaddr6.sin6_flowinfo    = 0;
-//             listening_sockaddr6.sin6_addr = IN6ADDR_ANY_INIT; // Want to receive multicasts AND unicasts on this socket
+               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; }
@@ -1999,8 +2020,10 @@ mDNSlocal mStatus SetupSocket(mDNS *const m, CFSocketSet *cp, mDNSBool mcast, co
 fail:
        LogMsg("%s error %ld errno %d (%s)", errstr, err, errno, strerror(errno));
        if (!strcmp(errstr, "bind") && errno == EADDRINUSE)
-               NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed", 3814904,
-                       "Alternatively, you can send email to radar-3387020@group.apple.com. "
+               NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed",
+                       "Congratulations, you've reproduced an elusive bug.\r"
+                       "Please contact the current assignee of <rdar://problem/3814904>.\r"
+                       "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
                        "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
        close(skt);
        return(err);
@@ -3643,6 +3666,7 @@ mDNSexport mDNSs32 mDNSPlatformRawTime(void)
        if (clockdivisor == 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); }
 
        static uint64_t last_mach_absolute_time = 0;
+       //static uint64_t last_mach_absolute_time = 0x8000000000000000LL;       // Use this value for testing the alert display
        uint64_t this_mach_absolute_time = mach_absolute_time();
        if ((int64_t)this_mach_absolute_time - (int64_t)last_mach_absolute_time < 0)
                {
@@ -3650,9 +3674,14 @@ mDNSexport mDNSs32 mDNSPlatformRawTime(void)
                LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time);
                // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
                last_mach_absolute_time = this_mach_absolute_time;
-               // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xyyy) or later
+               // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xyyy) or later.
+               // (This bug happens all the time on 10.3, and we know that's not going to be fixed.)
                if (mDNSMacOSXSystemBuildNumber(NULL) >= 8)
-                       NotifyOfElusiveBug("mach_absolute_time went backwards!", 3438376, "");
+                       NotifyOfElusiveBug("mach_absolute_time went backwards!",
+                               "This error occurs from time to time, often on newly released hardware, "
+                               "and usually the exact cause is different in each instance.\r\r"
+                               "Please file a new Radar bug report with the title “mach_absolute_time went backwards” "
+                               "and assign it to Radar Component “Kernel” Version “X”.");
                }
        last_mach_absolute_time = this_mach_absolute_time;
 
index 7dd31be64f3d2a58bfd29ff715d3b2207f5deb24..638f09501a564eae326cbf8ba7964b797798c19a 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: mDNSMacOSX.h,v $
+Revision 1.52  2006/01/05 21:41:49  cheshire
+<rdar://problem/4108164> Reword "mach_absolute_time went backwards" dialog
+
 Revision 1.51  2005/07/04 22:24:36  cheshire
 Export NotifyOfElusiveBug() so other files can call it
 
@@ -258,7 +261,7 @@ struct mDNS_PlatformSupport_struct
     CFRunLoopSourceRef       PowerRLS;
     };
 
-extern void NotifyOfElusiveBug(const char *title, mDNSu32 radarid, const char *msg);
+extern void NotifyOfElusiveBug(const char *title, const char *msg);    // Both strings are UTF-8 text
 extern void mDNSMacOSXNetworkChanged(mDNS *const m);
 extern int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring);
 
index 8eac6b3f23a5ef06508157664f788ce6e06f2a6d..6c923772b58c2618587bf59fc3e081f0805f9976 100644 (file)
                        buildSettings = {
                                FRAMEWORK_SEARCH_PATHS = "";
                                GCC_TREAT_WARNINGS_AS_ERRORS = YES;
-                               HEADER_SEARCH_PATHS = "../mDNSShared \"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\" \"$(OBJROOT)\"";
-                               LIBRARY_SEARCH_PATHS = "";
+                               HEADER_SEARCH_PATHS = "../mDNSShared \"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers\" \"${OBJROOT}/mDNSResponder.build\"";
+                               LIBRARY_SEARCH_PATHS = "\"${OBJROOT}/mDNSResponder.build\"";
                                MACOSX_DEPLOYMENT_TARGET = 10.2;
                                OPTIMIZATION_CFLAGS = "-O0";
-                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=$(MVERS) -D_LEGACY_NAT_TRAVERSAL_ -DMDNS_DEBUGMSGS=1";
+                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=${MVERS} -D_LEGACY_NAT_TRAVERSAL_ -DMDNS_DEBUGMSGS=1";
                                OTHER_LDFLAGS = "-ldnsinfo";
                                OTHER_REZFLAGS = "";
                                PRODUCT_NAME = mDNSResponder.debug;
                        buildSettings = {
                                FRAMEWORK_SEARCH_PATHS = "";
                                GCC_TREAT_WARNINGS_AS_ERRORS = YES;
-                               HEADER_SEARCH_PATHS = "../mDNSShared \"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\" \"$(OBJROOT)\"";
+                               HEADER_SEARCH_PATHS = "../mDNSShared \"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers\" \"${OBJROOT}/mDNSResponder.build\"";
                                INSTALL_PATH = /usr/sbin;
-                               LIBRARY_SEARCH_PATHS = "";
+                               LIBRARY_SEARCH_PATHS = "\"${OBJROOT}/mDNSResponder.build\"";
                                MACOSX_DEPLOYMENT_TARGET = 10.2;
-                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=$(MVERS) -D_LEGACY_NAT_TRAVERSAL_";
+                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=${MVERS} -D_LEGACY_NAT_TRAVERSAL_";
                                OTHER_LDFLAGS = "-ldnsinfo";
                                OTHER_REZFLAGS = "";
                                PRODUCT_NAME = mDNSResponder;
                        );
                        isa = PBXToolTarget;
                        name = mDNSResponder;
-                       productInstallPath = "$(HOME)/bin";
+                       productInstallPath = "${HOME}/bin";
                        productName = mDNSResponder;
                        productReference = 034768E2FF38A6DC11DB9C8B;
                };
                                GCC_TREAT_WARNINGS_AS_ERRORS = YES;
                                INSTALL_PATH = /usr/bin;
                                MACOSX_DEPLOYMENT_TARGET = 10.2;
-                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=$(MVERS)";
+                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=${MVERS}";
                                OTHER_LDFLAGS = "";
                                OTHER_REZFLAGS = "";
                                PRODUCT_NAME = mDNS;
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
                                DYLIB_CURRENT_VERSION = 1;
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Java/Extensions";
+                               INSTALL_PATH = "${SYSTEM_LIBRARY_DIR}/Java/Extensions";
                                JAVA_ARCHIVE_CLASSES = YES;
                                JAVA_ARCHIVE_COMPRESSION = YES;
                                JAVA_ARCHIVE_TYPE = JAR;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "javah -force -classpath ${OBJROOT}/mDNSResponder.build/dns_sd.jar.build/JavaClasses/ -o ${OBJROOT}/mDNSResponder.build/dns_sd.jar.build/DNSSD.java.h com.apple.dnssd.AppleDNSSD com.apple.dnssd.AppleBrowser com.apple.dnssd.AppleResolver com.apple.dnssd.AppleRegistration com.apple.dnssd.AppleQuery com.apple.dnssd.AppleDomainEnum com.apple.dnssd.AppleService";
+                       shellScript = "if [ -d ${OBJROOT}/mDNSResponder.build/${CONFIGURATION} ]; then BUILD_DIR=${OBJROOT}/mDNSResponder.build/${CONFIGURATION}; else BUILD_DIR=${OBJROOT}/mDNSResponder.build; fi\njavah -force -classpath ${BUILD_DIR}/dns_sd.jar.build/JavaClasses/ -o ${BUILD_DIR}/dns_sd.jar.build/DNSSD.java.h com.apple.dnssd.AppleDNSSD com.apple.dnssd.AppleBrowser com.apple.dnssd.AppleResolver com.apple.dnssd.AppleRegistration com.apple.dnssd.AppleQuery com.apple.dnssd.AppleDomainEnum com.apple.dnssd.AppleService";
                };
                DB2CC4560662DE4500335AB3 = {
                        fileRef = DB2CC4430662DD1100335AB3;
                                DEBUGGING_SYMBOLS = NO;
                                DYLIB_COMPATIBILITY_VERSION = 1;
                                DYLIB_CURRENT_VERSION = 1;
-                               HEADER_SEARCH_PATHS = "../mDNSShared \"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/A/Headers\" \"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/1.3.1/Headers\" \"$(OBJROOT)/mDNSResponder.build/dns_sd.jar.build\"";
+                               HEADER_SEARCH_PATHS = "../mDNSShared \"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/A/Headers\" \"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/1.3.1/Headers\" \"${OBJROOT}/mDNSResponder.build/dns_sd.jar.build\" \"${OBJROOT}/mDNSResponder.build/${CONFIGURATION}/dns_sd.jar.build\"";
                                INSTALL_PATH = /usr/lib/java;
                                LIBRARY_STYLE = DYNAMIC;
                                MACOSX_DEPLOYMENT_TARGET = 10.2;
                                GCC_TREAT_WARNINGS_AS_ERRORS = YES;
                                INSTALL_PATH = /usr/bin;
                                MACOSX_DEPLOYMENT_TARGET = 10.2;
-                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=$(MVERS) -I../mDNSShared";
+                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=${MVERS} -I../mDNSShared";
                                OTHER_LDFLAGS = "";
                                OTHER_REZFLAGS = "";
                                PRODUCT_NAME = "dns-sd";
                        buildSettings = {
                                FRAMEWORK_SEARCH_PATHS = "";
                                GCC_TREAT_WARNINGS_AS_ERRORS = YES;
-                               HEADER_SEARCH_PATHS = "\"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\"";
+                               HEADER_SEARCH_PATHS = "\"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers\"";
                                INSTALL_PATH = /usr/sbin;
                                LIBRARY_SEARCH_PATHS = "";
                                MACOSX_DEPLOYMENT_TARGET = 10.2;
-                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=$(MVERS)";
+                               OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=${MVERS}";
                                OTHER_LDFLAGS = "";
                                OTHER_REZFLAGS = "";
                                PRODUCT_NAME = dnsextd;
                                FF260A4D07B4477F00CE10E5,
                                FF2A870607B447EF00B14068,
                                FF08480707CEB8E800AE6769,
+                               FF354EB208516C63007C00E1,
                        );
                        isa = PBXResourcesBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                        );
                        buildSettings = {
                                EXPORTED_SYMBOLS_FILE = "";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/PreferencePanes";
+                               INSTALL_PATH = "${SYSTEM_LIBRARY_DIR}/PreferencePanes";
                                MACOSX_DEPLOYMENT_TARGET = 10.2;
                                OTHER_CFLAGS = "";
                                OTHER_LDFLAGS = "-twolevel_namespace";
                        );
                        isa = PBXBundleTarget;
                        name = PreferencePane;
-                       productInstallPath = "$(SYSTEM_LIBRARY_DIR)/PreferencePanes";
+                       productInstallPath = "${SYSTEM_LIBRARY_DIR}/PreferencePanes";
                        productName = PreferencePane;
                        productReference = FF2609E207B440DD00CE10E5;
                        productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
        <key>CFBundleGetInfoString</key>
        <string></string>
        <key>CFBundleIconFile</key>
-       <string>DNSServiceDiscoveryPref</string>
+       <string>BonjourPref</string>
        <key>CFBundleIdentifier</key>
        <string>com.apple.preference.bonjour</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <key>NSMainNibFile</key>
        <string>DNSServiceDiscoveryPref</string>
        <key>NSPrefPaneIconFile</key>
-       <string>DNSServiceDiscoveryPref.tiff</string>
+       <string>BonjourPref.tiff</string>
        <key>NSPrefPaneIconLabel</key>
        <string>Bonjour</string>
        <key>NSPrincipalClass</key>
                                FF260A2A07B4464B00CE10E5,
                                FF260A3207B4466900CE10E5,
                                FF260A3307B4466900CE10E5,
+                               FF354EB108516C63007C00E1,
                                FF260A4807B4475600CE10E5,
                                FF260A4B07B4477F00CE10E5,
                        );
                };
                FF260A3207B4466900CE10E5 = {
                        isa = PBXFileReference;
-                       name = DNSServiceDiscoveryPref.icns;
-                       path = PreferencePane/DNSServiceDiscoveryPref.icns;
+                       name = BonjourPref.icns;
+                       path = PreferencePane/BonjourPref.icns;
                        refType = 2;
                };
                FF260A3307B4466900CE10E5 = {
                        isa = PBXFileReference;
-                       name = DNSServiceDiscoveryPref.tiff;
-                       path = PreferencePane/DNSServiceDiscoveryPref.tiff;
+                       name = BonjourPref.tiff;
+                       path = PreferencePane/BonjourPref.tiff;
                        refType = 2;
                };
                FF260A3407B4466900CE10E5 = {
                        isa = PBXTargetDependency;
                        target = FF2609E107B440DD00CE10E5;
                };
+               FF354EB108516C63007C00E1 = {
+                       fileEncoding = 4;
+                       isa = PBXExecutableFileReference;
+                       name = installtool;
+                       path = PreferencePane/installtool;
+                       refType = 2;
+               };
+               FF354EB208516C63007C00E1 = {
+                       fileRef = FF354EB108516C63007C00E1;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
                FF37BE9207614059003C0420 = {
                        buildActionMask = 2147483647;
                        files = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/dnsinfo.h\"\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/dnsinfo.h\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi";
+                       shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/mDNSResponder.build/dnsinfo.h\"\nrm -f \"${OBJROOT}/mDNSResponder.build/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/mDNSResponder.build/dnsinfo.h\ntouch ${OBJROOT}/mDNSResponder.build/empty.c\ncc ${OBJROOT}/mDNSResponder.build/empty.c -c -o \"${OBJROOT}/mDNSResponder.build/libdnsinfo.a\"\nrm -f ${OBJROOT}/mDNSResponder.build/empty.c\nfi";
                };
                FF485D5105632E0000130380 = {
                        fileEncoding = 4;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "rm -f ${BUILD_DIR}/dns_sd";
+                       shellScript = "rm -f ${BUILD_DIR}/${CONFIGURATION}/dns_sd";
                };
                FFD41DDF06641BBB00F0C438 = {
                        isa = PBXTargetDependency;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/dnsinfo.h\"\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/dnsinfo.h\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi";
+                       shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/mDNSResponder.build/dnsinfo.h\"\nrm -f \"${OBJROOT}/mDNSResponder.build/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/mDNSResponder.build/dnsinfo.h\ntouch ${OBJROOT}/mDNSResponder.build/empty.c\ncc ${OBJROOT}/mDNSResponder.build/empty.c -c -o \"${OBJROOT}/mDNSResponder.build/libdnsinfo.a\"\nrm -f ${OBJROOT}/mDNSResponder.build/empty.c\nfi";
                };
                FFFB0DA407B43BED00B88D48 = {
                        children = (
index 638b56d36ad4e7194113d793512b351b22c0768b..7176e0ed37e6714e0ea4f6c465ac982dfb5efa3e 100755 (executable)
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
 # $Log: Makefile,v $
+# 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
 #
@@ -221,7 +254,6 @@ RM = rm
 LN = ln -s -f
 CFLAGS_COMMON = -I. -I$(COREDIR) -I$(SHAREDDIR) -W -Wall -DPID_FILE=\"/var/run/mdnsd.pid\" -DMDNS_UDS_SERVERPATH=\"/var/run/mdnsd\"
 LIBFLAGS =
-DNSEXT_FLAGS = -D_REENTRANT -g -Wall -lpthread
 LDSUFFIX = so
 JAVACFLAGS_OS = -fPIC -shared -ldns_sd
 
@@ -233,7 +265,10 @@ OBJDIR = objects/debug
 BUILDDIR = build/debug
 STRIP = echo 
 else
-CFLAGS_DEBUG = -O0 -DMDNS_DEBUGMSGS=0 
+# We use -Os for two reasons:
+# 1. We want to make small binaries, suitable for putting into hardware devices
+# 2. Some of the code analysis warnings only work when some form of optimization is enabled
+CFLAGS_DEBUG = -Os -DMDNS_DEBUGMSGS=0 
 OBJDIR = objects/prod
 BUILDDIR = build/prod
 STRIP = strip -S 
@@ -242,7 +277,7 @@ endif
 # Configure per-OS peculiarities
 ifeq ($(os),solaris)
 CFLAGS_OS = -DNOT_HAVE_DAEMON -DNOT_HAVE_SA_LEN -DNOT_HAVE_SOCKLEN_T -DNOT_HAVE_IF_NAMETOINDEX \
-        -DLOG_PERROR=0 -D_XPG4_2 -D__EXTENSIONS__ -DHAVE_BROKEN_RECVIF_NAME -DUSE_TCP_LOOPBACK
+        -DLOG_PERROR=0 -D_XPG4_2 -D__EXTENSIONS__ -DHAVE_BROKEN_RECVIF_NAME
 CC = gcc
 LD = gcc -shared
 LIBFLAGS = -lsocket -lnsl -lresolv
@@ -253,7 +288,7 @@ endif
 else
 
 ifeq ($(os),linux)
-CFLAGS_OS = -DNOT_HAVE_SA_LEN -DUSES_NETLINK
+CFLAGS_OS = -DNOT_HAVE_SA_LEN -DUSES_NETLINK -DHAVE_LINUX
 JAVACFLAGS_OS += -I$(JDK)/include/linux
 OPTIONALTARG = nss_mdns
 OPTINSTALL   = InstalledNSS
@@ -281,7 +316,7 @@ LDCONFIG = ldconfig
 else
 
 ifeq ($(os),jaguar)
-CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -DNOT_HAVE_SOCKLEN_T
+CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror -DNOT_HAVE_SOCKLEN_T
 LD = libtool -dynamic
 LIBFLAGS = -lSystem
 LDSUFFIX = dylib
@@ -290,7 +325,7 @@ JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Header
 else
 
 ifeq ($(os),panther)
-CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp #-pedantic
+CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror
 LD = libtool -dynamic
 LIBFLAGS = -lSystem
 LDSUFFIX = dylib
@@ -299,9 +334,9 @@ JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Header
 else
 
 ifeq ($(os),tiger)
-CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Wdeclaration-after-statement
+CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror -Wdeclaration-after-statement #-Wunreachable-code
 CC = @gcc-4.0
-LD = libtool -dynamic
+LD = $(CC) -dynamiclib
 LIBFLAGS = -lSystem
 LDSUFFIX = dylib
 JDK = /System/Library/Frameworks/JavaVM.framework/Home
@@ -309,7 +344,7 @@ JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Header
 else
 
 $(error ERROR: Must specify target OS on command-line, e.g. "make os=tiger [target]".\
-Supported operating systems include: jaguar, panther, linux, netbsd, freebsd, openbsd, solaris) 
+Supported operating systems include: jaguar, panther, tiger, linux, netbsd, freebsd, openbsd, solaris) 
 endif
 endif
 endif
@@ -370,9 +405,9 @@ CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_OS) $(CFLAGS_DEBUG)
 
 #############################################################################
 
-all: setup Daemon libdns_sd Client Responder ProxyResponder Identify NetMonitor dnsextd $(OPTIONALTARG)
+all: setup Daemon libdns_sd Clients SAClient SAResponder SAProxyResponder Identify NetMonitor dnsextd $(OPTIONALTARG)
 
-install: setup InstalledDaemon InstalledLib InstalledStartup InstalledManPages $(OPTINSTALL)
+install: setup InstalledDaemon InstalledStartup InstalledLib InstalledManPages InstalledClients $(OPTINSTALL)
 
 # 'setup' sets up the build directory structure the way we want
 setup:
@@ -383,8 +418,9 @@ setup:
 
 # clean removes targets and objects
 clean:
-       if test -d $(OBJDIR)   ; then rm -r $(OBJDIR)   ; fi
-       if test -d $(BUILDDIR) ; then rm -r $(BUILDDIR) ; fi
+       @if test -d $(OBJDIR)   ; then rm -r $(OBJDIR)   ; fi
+       @if test -d $(BUILDDIR) ; then rm -r $(BUILDDIR) ; fi
+       @$(MAKE) -C ../Clients clean
 
 #############################################################################
 
@@ -410,6 +446,12 @@ $(BUILDDIR)/libdns_sd.$(LDSUFFIX): $(CLIENTLIBOBJS)
        @$(LD) $(LIBFLAGS) -o $@ $+
        @$(STRIP) $@
 
+Clients: setup libdns_sd ../Clients/build/dns-sd
+       @echo "Clients done"
+
+../Clients/build/dns-sd:
+       @$(MAKE) -C ../Clients
+
 # nss_mdns target builds the Name Service Switch module
 nss_mdns: setup $(BUILDDIR)/$(NSSLIBFILE)
        @echo "Name Service Switch module done"
@@ -430,13 +472,18 @@ InstalledLib: $(INSTBASE)/lib/libdns_sd.$(LDSUFFIX).$(LIBVERS) $(INSTBASE)/inclu
 InstalledStartup: $(STARTUPSCRIPTDIR)/$(STARTUPSCRIPTNAME)
        @echo $+ " installed"
 
-InstalledNSS: $(NSSINSTPATH)/$(NSSLINKNAME) /etc/nss_mdns.conf $(MANPATH)/man5/nss_mdns.conf.5 $(MANPATH)/man8/libnss_mdns.8
+InstalledManPages: $(MANPATH)/man8/mdnsd.8
        @echo $+ " installed"
 
-InstalledManPages: $(MANPATH)/man8/mdnsd.8
+InstalledClients: $(INSTBASE)/bin/dns-sd
+       @echo $+ " installed"
+
+InstalledNSS: $(NSSINSTPATH)/$(NSSLINKNAME) /etc/nss_mdns.conf $(MANPATH)/man5/nss_mdns.conf.5 $(MANPATH)/man8/libnss_mdns.8
        @echo $+ " installed"
 
+# Note: If daemon already installed, we make sure it's stopped before overwriting it
 $(INSTBASE)/sbin/mdnsd: $(BUILDDIR)/mdnsd
+       @if test -x $@; then $(STARTUPSCRIPTDIR)/$(STARTUPSCRIPTNAME) stop; fi
        $(CP) $< $@
 
 $(INSTBASE)/lib/libdns_sd.$(LDSUFFIX).$(LIBVERS): $(BUILDDIR)/libdns_sd.$(LDSUFFIX)
@@ -450,9 +497,12 @@ endif
 $(INSTBASE)/include/dns_sd.h: $(SHAREDDIR)/dns_sd.h
        $(CP) $< $@
 
-$(STARTUPSCRIPTDIR)/$(STARTUPSCRIPTNAME): mdnsd.sh $(STARTUPSCRIPTDIR)
+# We make this target dependent on $(INSTBASE)/sbin/mdnsd because we need to ensure
+# that the daemon is installed *before* we try to execute the command to start it.
+$(STARTUPSCRIPTDIR)/$(STARTUPSCRIPTNAME): mdnsd.sh $(STARTUPSCRIPTDIR) $(INSTBASE)/sbin/mdnsd
        $(CP) $< $@
        chmod ugo+x $@
+       $@ start
 ifdef RUNLEVELSCRIPTSDIR
 ifeq ($(wildcard $(RUNLEVELSCRIPTSDIR)/runlevels/default), $(RUNLEVELSCRIPTSDIR)/runlevels/default)
        $(LN) $@ $(RUNLEVELSCRIPTSDIR)/runlevels/default/mdns
@@ -466,6 +516,21 @@ else
 endif
 endif
 
+$(MANPATH)/man5/%.5: %.5
+       cp $< $@
+       chmod 444 $@
+
+$(MANPATH)/man8/%.8: %.8
+       cp $< $@
+       chmod 444 $@
+
+$(MANPATH)/man8/mdnsd.8: $(SHAREDDIR)/mDNSResponder.8
+       cp $< $@
+       chmod 444 $@
+
+$(INSTBASE)/bin/dns-sd: ../Clients/build/dns-sd
+       $(CP) $< $@
+
 $(NSSINSTPATH)/$(NSSLINKNAME): $(NSSINSTPATH)/$(NSSLIBFILE)
        $(LN) $< $@
        ldconfig
@@ -482,18 +547,6 @@ $(NSSINSTPATH)/$(NSSLIBFILE): $(BUILDDIR)/$(NSSLIBFILE)
        cp -f /etc/nsswitch.conf /etc/nsswitch.conf.pre-mdns
        sed -e '/mdns/!s/^\(hosts:.*\)dns\(.*\)/\1mdns dns\2/' /etc/nsswitch.conf.pre-mdns > /etc/nsswitch.conf
 
-$(MANPATH)/man5/%.5: %.5
-       cp $< $@
-       chmod 444 $@
-
-$(MANPATH)/man8/%.8: %.8
-       cp $< $@
-       chmod 444 $@
-
-$(MANPATH)/man8/mdnsd.8: $(SHAREDDIR)/mDNSResponder.8
-       cp $< $@
-       chmod 444 $@
-
 #############################################################################
 
 # The following targets build Java wrappers for the dns-sd.h API.
@@ -509,8 +562,8 @@ Java: setup $(BUILDDIR)/dns_sd.jar $(BUILDDIR)/libjdns_sd.$(LDSUFFIX)
 
 JAVASRC        = $(SHAREDDIR)/Java
 JARCONTENTS =  $(OBJDIR)/com/apple/dnssd/DNSSDService.class \
-                               $(OBJDIR)/com/apple/dnssd/DNSRecord.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/BaseListener.class \
@@ -521,11 +574,11 @@ JARCONTENTS =     $(OBJDIR)/com/apple/dnssd/DNSSDService.class \
                                $(OBJDIR)/com/apple/dnssd/DomainListener.class \
                                $(OBJDIR)/com/apple/dnssd/DNSSD.class
 
-$(BUILDDIR)/dns_sd.jar: $(JARCONTENTS)
+$(BUILDDIR)/dns_sd.jar: $(JARCONTENTS) setup
        $(JAR) -cf $@ -C $(OBJDIR) com
 
-$(BUILDDIR)/libjdns_sd.$(LDSUFFIX): $(JAVASRC)/JNISupport.c $(OBJDIR)/DNSSD.java.h
-       $(CC) -o $@ $< $(JAVACFLAGS) -I$(OBJDIR)
+$(BUILDDIR)/libjdns_sd.$(LDSUFFIX): $(JAVASRC)/JNISupport.c $(OBJDIR)/DNSSD.java.h setup libdns_sd
+       $(CC) -o $@ $< $(JAVACFLAGS) -I$(OBJDIR) -L$(BUILDDIR)
 
 $(OBJDIR)/com/apple/dnssd/%.class:     $(JAVASRC)/%.java
        $(JAVAC) -d $(OBJDIR) -classpath $(OBJDIR) $<
@@ -544,7 +597,7 @@ $(OBJDIR)/DNSSD.java.h: $(OBJDIR)/com/apple/dnssd/DNSSD.class
 
 # The following target builds documentation for the Java wrappers.
 
-JavaDoc: setup Java
+JavaDoc: Java setup
        $(JAVADOC) $(JAVASRC)/*.java -classpath $(OBJDIR) -d $(BUILDDIR) -public
 
 #############################################################################
@@ -554,13 +607,13 @@ SPECIALOBJ = $(OBJDIR)/mDNSPosix.c.o $(OBJDIR)/mDNSUNP.c.o $(OBJDIR)/mDNSDebug.c
 COMMONOBJ  = $(SPECIALOBJ) $(OBJDIR)/mDNS.c.o
 APPOBJ     = $(COMMONOBJ) $(OBJDIR)/ExampleClientApp.c.o
 
-Client: setup $(BUILDDIR)/mDNSClientPosix
+SAClient: setup $(BUILDDIR)/mDNSClientPosix
        @echo "Embedded Standalone Client done"
 
-Responder: setup $(BUILDDIR)/mDNSResponderPosix
+SAResponder: setup $(BUILDDIR)/mDNSResponderPosix
        @echo "Embedded Standalone Responder done"
 
-ProxyResponder: setup $(BUILDDIR)/mDNSProxyResponderPosix
+SAProxyResponder: setup $(BUILDDIR)/mDNSProxyResponderPosix
        @echo "Embedded Standalone ProxyResponder done"
 
 Identify: setup $(BUILDDIR)/mDNSIdentify
@@ -584,11 +637,13 @@ $(BUILDDIR)/mDNSProxyResponderPosix: $(COMMONOBJ)  $(OBJDIR)/ProxyResponder.c.o
 $(BUILDDIR)/mDNSIdentify:            $(SPECIALOBJ) $(OBJDIR)/Identify.c.o
        $(CC) $+ -o $@ $(LIBFLAGS)
 
+$(OBJDIR)/Identify.c.o:              $(COREDIR)/mDNS.c # Note: Identify.c textually imports mDNS.c
+
 $(BUILDDIR)/mDNSNetMonitor:          $(SPECIALOBJ) $(OBJDIR)/NetMonitor.c.o
        $(CC) $+ -o $@ $(LIBFLAGS)
 
-$(BUILDDIR)/dnsextd:                 $(SPECIALOBJ) $(OBJDIR)/dnsextd.c.o
-       $(CC) $+ -o $@ $(LIBFLAGS) $(DNSEXT_FLAGS)
+$(BUILDDIR)/dnsextd:                 $(SPECIALOBJ) $(OBJDIR)/dnsextd.c.threadsafe.o
+       $(CC) $+ -o $@ $(LIBFLAGS) -lpthread
 
 #############################################################################
 
@@ -602,6 +657,9 @@ $(OBJDIR)/%.c.o:    $(COREDIR)/%.c
 $(OBJDIR)/%.c.o:       $(SHAREDDIR)/%.c
        $(CC) $(CFLAGS) -c -o $@ $<
 
+$(OBJDIR)/%.c.threadsafe.o:    %.c
+       $(CC) $(CFLAGS) -D_REENTRANT -c -o $@ $<
+
 $(OBJDIR)/%.c.so.o:    %.c
        $(CC) $(CFLAGS) -c -fPIC -o $@ $<
 
index 4fce88d3514363022b753bdd8feb0384ef505623..6c53cc8b420e74fe7fb09a73c4f4346b42f63516 100644 (file)
     Change History (most recent first):
 
 $Log: NetMonitor.c,v $
+Revision 1.75  2006/01/05 22:33:58  cheshire
+Use IFNAMSIZ (more portable) instead of IF_NAMESIZE
+
+Revision 1.74  2005/12/02 20:08:39  cheshire
+Update "No HINFO" message
+
+Revision 1.73  2005/12/02 19:19:53  cheshire
+<rdar://problem/4331590> Include interface index and name in mDNSNetMonitor output
+
+Revision 1.72  2005/11/07 01:47:45  cheshire
+<rdar://problem/4331590> Include interface index in mDNSNetMonitor output
+
 Revision 1.71  2004/12/16 20:17:11  cheshire
 <rdar://problem/3324626> Cache memory management improvements
 
@@ -286,6 +298,7 @@ Added NetMonitor.c
 #include <netdb.h>                     // For gethostbyname()
 #include <sys/socket.h>                // For AF_INET, AF_INET6, etc.
 #include <arpa/inet.h>         // For inet_addr()
+#include <net/if.h>                    // For IF_NAMESIZE
 #include <netinet/in.h>                // For INADDR_NONE
 
 #include "mDNSPosix.h"      // Defines the specific types needed to run mDNS on this platform
@@ -595,7 +608,7 @@ mDNSlocal void ShowSortedHostList(HostList *list, int max)
                if (e->pkts[HostPkt_B]) mprintf("Bad: %8lu", e->pkts[HostPkt_B]);
                mprintf("\n");
                if (!e->HISoftware.c[0] && e->NumQueries > 2)
-                       mDNSPlatformMemCopy("\x0E*** Jaguar ***", &e->HISoftware, 15);
+                       mDNSPlatformMemCopy("\x27*** Unknown (Jaguar, Windows, etc.) ***", &e->HISoftware, 0x28);
                if (e->hostname.c[0] || e->HIHardware.c[0] || e->HISoftware.c[0])
                        mprintf("%##-45s %#-14s %#s\n", e->hostname.c, e->HIHardware.c, e->HISoftware.c);
                }
@@ -695,21 +708,20 @@ mDNSlocal const mDNSu8 *FindUpdate(mDNS *const m, const DNSMessage *const query,
        return(mDNSNULL);
        }
 
-mDNSlocal void DisplayTimestamp(void)
+mDNSlocal void DisplayPacketHeader(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID)
        {
+       const char *const ptype =   (msg->h.flags.b[0] & kDNSFlag0_QR_Response)             ? "-R- " :
+                                                               (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger) ? "-Q- " : "-LQ-";
+
        struct timeval tv;
        struct tm tm;
+       const mDNSu32 index = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID);
+       char if_name[IFNAMSIZ];         // Older Linux distributions don't define IF_NAMESIZE
+       if_indextoname(index, if_name);
        gettimeofday(&tv, NULL);
        localtime_r((time_t*)&tv.tv_sec, &tm);
-       mprintf("\n%d:%02d:%02d.%06d\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec);
-       }
-
-mDNSlocal void DisplayPacketHeader(const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr)
-       {
-       const char *const ptype =   (msg->h.flags.b[0] & kDNSFlag0_QR_Response)             ? "-R- " :
-                                                               (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger) ? "-Q- " : "-LQ-";
+       mprintf("\n%d:%02d:%02d.%06d Interface %d/%s\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec, index, if_name);
 
-       DisplayTimestamp();
        mprintf("%#-16a %s             Q:%3d  Ans:%3d  Auth:%3d  Add:%3d  Size:%5d bytes",
                srcaddr, ptype, msg->h.numQuestions, msg->h.numAnswers, msg->h.numAuthorities, msg->h.numAdditionals, end - (mDNSu8 *)msg);
 
@@ -822,7 +834,7 @@ mDNSlocal void DisplayQuery(mDNS *const m, const DNSMessage *const msg, const mD
        HostEntry *entry = GotPacketFromHost(srcaddr, MQ ? HostPkt_Q : HostPkt_L, msg->h.id);
        LargeCacheRecord pkt;
 
-       DisplayPacketHeader(msg, end, srcaddr, srcport, dstaddr);
+       DisplayPacketHeader(m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
        if (msg->h.id.NotAnInteger != 0xFFFF)
                {
                if (MQ) NumPktQ++; else NumPktL++;
@@ -888,7 +900,7 @@ mDNSlocal void DisplayResponse(mDNS *const m, const DNSMessage *const msg, const
        HostEntry *entry = GotPacketFromHost(srcaddr, HostPkt_R, msg->h.id);
        LargeCacheRecord pkt;
 
-       DisplayPacketHeader(msg, end, srcaddr, srcport, dstaddr);
+       DisplayPacketHeader(m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
        if (msg->h.id.NotAnInteger != 0xFFFF) NumPktR++;
 
        for (i=0; i<msg->h.numQuestions; i++)
index 6b991ecd149cec30ce57e9264a9b6ff1e3447df9..5963f20b1bb39dd454621d71287922f6b9d95791 100644 (file)
        Change History (most recent first):
 
 $Log: PosixDaemon.c,v $
+Revision 1.29  2005/08/04 03:37:45  mkrochma
+Temporary workaround to fix posix after mDNS_SetPrimaryInterfaceInfo changed
+
+Revision 1.28  2005/07/19 11:21:09  cheshire
+<rdar://problem/4170449> Unix Domain Socket leak in mdnsd
+
 Revision 1.27  2005/02/04 00:39:59  cheshire
 Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
 
@@ -143,14 +149,14 @@ extern const char mDNSResponderVersionString[];
 static void Reconfigure(mDNS *m)
        {
        mDNSAddr DynDNSIP;
-       mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL);
+       mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
        mDNS_DeleteDNSServers(m);
        if (ParseDNSServers(m, uDNS_SERVERS_FILE) < 0)
                LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
        ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &DynDNSHostname, &DynDNSZone, NULL);
        FindDefaultRouteIP(&DynDNSIP);
        if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
-       if (DynDNSIP.type)       mDNS_SetPrimaryInterfaceInfo(m, &DynDNSIP, NULL);
+       if (DynDNSIP.type)       mDNS_SetPrimaryInterfaceInfo(m, &DynDNSIP, NULL, NULL);
        }
 
 // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
@@ -288,8 +294,9 @@ mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *cont
 
 mStatus udsSupportRemoveFDFromEventLoop(int fd)                // Note: This also CLOSES the file descriptor
        {
-       return mDNSPosixRemoveFDFromEventLoop(fd);
+       mStatus err = mDNSPosixRemoveFDFromEventLoop(fd);
        close(fd);
+       return err;
        }
 
 mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
index f113d6525e75a1df6d9db0ceaf343f7611c61eb9..293ee0a293a0bc10fc5f839c170b0cbedc0cf534 100644 (file)
@@ -24,6 +24,9 @@
     Change History (most recent first):
 
 $Log: ProxyResponder.c,v $
+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
 
@@ -171,6 +174,7 @@ mDNSlocal mStatus mDNS_RegisterProxyHost(mDNS *m, ProxyHost *p)
 
        mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p->ip.b[3], p->ip.b[2], p->ip.b[1], p->ip.b[0]);
        MakeDomainNameFromDNSNameString(p->RR_PTR.resrec.name, buffer);
+       p->RR_PTR.ForceMCast = mDNStrue; // This PTR points to our dot-local name, so don't ever try to write it into a uDNS server
 
        p->RR_A.  resrec.rdata->u.ipv4 = p->ip;
        AssignDomainName(&p->RR_PTR.resrec.rdata->u.name, p->RR_A.resrec.name);
index 80f8fa3db9ed9f34688a7cdde2fbaf02015133b7..35be2b19818164cfc7c7087f90fdc01be877302b 100755 (executable)
@@ -1,24 +1,31 @@
 ReadMe About mDNSPosix
 ----------------------
 
-mDNSPosix is a port of Apple's core mDNS code to Posix platforms.
+mDNSPosix is a port of Apple's Multicast DNS and DNS Service Discovery
+code to Posix platforms.
 
-mDNS is short for "multicast DNS", which is a technology that allows you
-to register IP services and browse the network for those services.  For
-more information about mDNS, see the mDNS web site.
+Multicast DNS and DNS Service Discovery are technologies that allow you
+to register IP-based services and browse the network for those services.
+For more information about mDNS, see the mDNS web site.
 
   <http://www.multicastdns.org/>
 
-mDNS is part of a family of technologies resulting from the efforts of
-the IETF zeroconf working group.  For information about other zeroconf
-technologies, see the zeroconf web site.
+Multicast DNS is part of a family of technologies resulting from the
+efforts of the IETF Zeroconf working group.  For information about
+other Zeroconf technologies, see the Zeroconf web site.
 
   <http://www.zeroconf.org/>
 
 Apple uses the trade mark "Bonjour" to describe our implementation of
-zeroconf technologies.  This sample is designed to show how easy it is
+Zeroconf technologies.  This sample is designed to show how easy it is
 to make a device "Bonjour compatible".
 
+The "Bonjour" trade mark can also be licensed at no charge for
+inclusion on your own products, packaging, manuals, promotional
+materials, or web site. For details and licensing terms, see
+
+  <http://developer.apple.com/bonjour/>
+
 The code in this sample was compiled and tested on Mac OS X (10.1.x,
 10.2, 10.3), Solaris (SunOS 5.8), Linux (Redhat 2.4.9-21, Fedora Core 1), 
 and OpenBSD (2.9). YMMV.
@@ -79,26 +86,30 @@ o Standalone products for dedicated devices (printer, network camera, etc.)
   - mDNSResponderPosix
   - mDNSProxyResponderPosix
 
-o Debugging tools
+o Testing and Debugging tools
+  - dns-sd command-line tool (from the "Clients" folder)
   - mDNSNetMonitor
   - mDNSIdentify
 
-As root type "make install" to install six things:
+As root type "make install" to install eight things:
 o mdnsd                   (usually in /usr/sbin)
 o libmdns                 (usually in /usr/lib)
 o dns_sd.h                (usually in /usr/include)
 o startup scripts         (e.g. in /etc/rc.d)
 o manual pages            (usually in /usr/share/man)
+o dns-sd tool             (usually in /usr/bin)
 o nss_mdns                (usually in /lib)
 o nss configuration files (usually in /etc)
 
-Once you've installed the files in their respective places,
-you need to start the daemon running, either by rebooting,
-or by running the startup script "/etc/init.d/mdns start"
-(the exact path may be different on your system).
-Then you can cd to the "Clients" folder and type "make".
-This builds a test client showing how to exercise all the major
-functionality of the daemon.
+The "make install" concludes by executing the startup script
+(usually "/etc/init.d/mdns start") to start the daemon running.
+You shouldn't need to reboot unless you really want to.
+
+Once the daemon is running, you can use the dns-sd test tool
+to exercise all the major functionality of the daemon. Running
+"dns-sd" with no arguments gives a summary of the available options.
+This test tool is also described in detail, with several examples,
+in Chapter 6 of the O'Reilly "Zero Configuration Networking" book.
 
 
 How It Works
@@ -243,17 +254,19 @@ Caveats
 -------
 Currently the program uses a simple make file.
 
-There are various problems with loopback-only self discovery.  The code
-will attempt service discovery on the loopback interface only if no
-other interfaces are available.  However, this exposes a number of
-problems with the underlying network stack (at least on Mac OS X).
+The Multicast DNS protocol can also operate locally over the loopback
+interface, but this exposed some problems with the underlying network
+stack in early versions of Mac OS X and may expose problems with other
+network stacks too.
 
-o On Mac OS X 10.1.x the code fails to start on the loopback interface
+o On Mac OS X 10.1.x the code failed to start on the loopback interface
   because the IP_ADD_MEMBERSHIP option returns ENOBUFS.
 
-o On Mac OS X 10.2 the loopback-only case fails because
-  mDNSPlatformSendUDP's call to "sendto" fails with error EHOSTUNREACH
-  [Radar ID 3016042].
+o On Mac OS X 10.2 the loopback-only case failed because
+  "sendto" calls fails with error EHOSTUNREACH. (3016042)
+
+Consequently, the code will attempt service discovery on the loopback
+interface only if no other interfaces are available.
 
 I haven't been able to test the loopback-only case on other platforms
 because I don't have access to the physical machine.
index 7765669be537b1600cbb12eeda6f75511ce259b8..986333b05892b0ba9a293f956f3ea43d332886b2 100755 (executable)
@@ -24,6 +24,9 @@
     Change History (most recent first):
 
 $Log: Responder.c,v $
+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
 
@@ -591,7 +594,7 @@ static mStatus RegisterServicesInFile(const char *filePath)
                        const char *dom = kDefaultServiceDomain;
                        char rawText[1024];
                        mDNSu8  text[sizeof(RDataBody)];
-                       mDNSu16 textLen = 0;
+                       unsigned int textLen = 0;
                        char port[256];
 
             // Skip over any blank lines.
@@ -626,10 +629,11 @@ static mStatus RegisterServicesInFile(const char *filePath)
                                        len = strlen(rawText);
                                        if (len <= 255)
                                                {
+                                               unsigned int newlen = textLen + 1 + len;
+                                               if (len == 0 || newlen >= sizeof(text)) break;
                                                text[textLen] = len;
-                                               if (text[textLen] == 0) break;
-                                               memcpy(text + textLen + 1, rawText, text[textLen]);
-                                               textLen += 1 + text[textLen];
+                                               memcpy(text + textLen + 1, rawText, len);
+                                               textLen = newlen;
                                                }
                                        else
                                                fprintf(stderr, "%s: TXT attribute too long for name = %s, type = %s, port = %s\n", 
index 6acf92ef42a06bf580fca2719b6ce9937f4d91bf..ab1071d40ac8a27388149f95f4be8116ef791a22 100644 (file)
     Change History (most recent first):
 
 $Log: dnsextd.c,v $
-Revision 1.33.2.1  2005/08/05 21:14:00  ksekar
-<rdar://problem/4012279> Long-lived queries not working on windows
-Change constant names
+Revision 1.41  2005/09/24 01:10:54  cheshire
+Fix comment typos
+
+Revision 1.40  2005/09/07 21:54:37  ksekar
+<rdar://problem/4046465> dnsextd doesn't clean up on exit
+Close sockets before cleanup so clients can't make new requests
+
+Revision 1.39  2005/08/22 23:30:30  ksekar
+<rdar://problem/4158123> memory leak in dnsextd.c
+
+Revision 1.38  2005/06/29 10:03:56  cheshire
+Fix compile errors and warnings
+
+Revision 1.37  2005/06/27 22:12:17  ksekar
+<rdar://problem/4163315> dnsextd performance improvements
+
+Revision 1.36  2005/06/14 23:14:41  ksekar
+<rdar://problem/3934233> Unable to refresh LLQs
+
+Revision 1.35  2005/03/17 03:57:43  cheshire
+LEASE_OPT_SIZE is now LEASE_OPT_RDLEN; LLQ_OPT_SIZE is now LLQ_OPT_RDLEN
+
+Revision 1.34  2005/03/16 18:47:37  ksekar
+<rdar://problem/4046465> dnsextd doesn't clean up on exit
 
 Revision 1.33  2005/03/11 19:09:02  ksekar
 Fixed ZERO_LLQID macro
@@ -156,6 +177,7 @@ Revision 1.1  2004/08/11 00:43:26  ksekar
 #include <syslog.h>
 #include <string.h>
 #include <sys/time.h>
+#include <sys/resource.h>
 #include <time.h>
 #include <errno.h>
 
@@ -233,7 +255,9 @@ typedef struct AnswerListElem
     mDNSu16 type;
     CacheRecord *KnownAnswers;  // All valid answers delivered to client
     CacheRecord *EventList;     // New answers (adds/removes) to be sent to client
-    int refcount;          
+    int refcount;
+    mDNSBool UseTCP;            // Use TCP if UDP would cause truncation
+    pthread_t tid;              // Allow parallel list updates
        } AnswerListElem;
 
 // llq table entry
@@ -254,7 +278,7 @@ typedef struct LLQEntry
 typedef struct 
        {
     // server variables - read only after initialization (no locking)
-    struct in_addr saddr;      // server address
+    struct sockaddr_in saddr;  // server address
     domainname zone;           // zone being updated
     int tcpsd;                 // listening TCP socket
     int udpsd;                 // listening UDP socket
@@ -272,8 +296,9 @@ typedef struct
     // LLQ table variables
     LLQEntry *LLQTable[LLQ_TABLESIZE];  // !!!KRS change this and RRTable to use a common data structure
     AnswerListElem *AnswerTable[LLQ_TABLESIZE];
-    int LLQEventListenSock;       // Unix domain socket pair - polling thread writes to ServPollSock, which wakes
-    int LLQServPollSock;          // the main thread listening on EventListenSock, indicating that the zone has changed
+    int AnswerTableCount;
+    int LLQEventNotifySock;          // Unix domain socket pair - update handling thread writes to EventNotifySock, which wakes
+    int LLQEventListenSock;          // the main thread listening on EventListenSock, indicating that the zone has changed
        } DaemonInfo;
 
 // args passed to UDP request handler thread as void*
@@ -292,6 +317,13 @@ typedef struct
     DaemonInfo *d;
        } TCPRequestArgs;
 
+// args passed to UpdateAnswerList thread as void*
+typedef struct
+       {
+    DaemonInfo *d;
+    AnswerListElem *a;
+       } UpdateAnswerListArgs;
+
 //
 // Global Variables
 //
@@ -353,11 +385,12 @@ mDNSlocal void Log(const char *format, ...)
 
 // Error Logging
 // prints message "dnsextd <function>: <operation> - <error message>" 
-// must be compiled w/ -D_REENTRANT  for thread-safe errno usage
+// must be compiled w/ -D_REENTRANT for thread-safe errno usage
 mDNSlocal void LogErr(const char *fn, const char *operation)
        {
-       char buf[512];
-       snprintf(buf, sizeof(buf), "%s: %s - %s", fn, operation, strerror(errno));
+       char buf[512], errbuf[256];
+       strerror_r(errno, errbuf, sizeof(errbuf));
+       snprintf(buf, sizeof(buf), "%s: %s - %s", fn, operation, errbuf);
        PrintLog(buf);
        }
 
@@ -400,30 +433,40 @@ mDNSlocal void HdrHToN(PktMsg *pkt)
 // caller terminates connection via close()
 mDNSlocal int ConnectToServer(DaemonInfo *d)
        {
-       struct sockaddr_in servaddr;
-       int sd;
-       
-       bzero(&servaddr, sizeof(servaddr));
-       if (d->saddr.s_addr) servaddr.sin_addr = d->saddr;
-       else                 inet_pton(AF_INET, LOOPBACK, &d->saddr);  // use loopback if server not explicitly specified                       
-       servaddr.sin_port = htons(NS_PORT);
-       servaddr.sin_family = AF_INET;
-#ifndef NOT_HAVE_SA_LEN
-       servaddr.sin_len = sizeof(servaddr); 
-#endif
-       sd = socket(AF_INET, SOCK_STREAM, 0);
-       if (sd < 0) { LogErr("ConnectToServer", "socket");  return -1; }
-       if (connect(sd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { LogErr("ConnectToServer", "connect"); return -1; }
-       return sd;
+       int ntries = 0, retry = 0;
+
+       while (1)
+               {
+           int sd = socket(AF_INET, SOCK_STREAM, 0);
+               if (sd < 0) { LogErr("ConnectToServer", "socket");  return -1; }
+               if (!connect(sd, (struct sockaddr *)&d->saddr, sizeof(d->saddr))) return sd;
+               close(sd);
+               if (++ntries < 10)
+                       {
+                       LogErr("ConnectToServer", "connect");
+                       Log("ConnectToServer - retrying connection");
+                       if (!retry) retry = 500000 + random() % 500000;
+                       usleep(retry);
+                       retry *= 2;
+                       }
+               else { Log("ConnectToServer - %d failed attempts.  Aborting.", ntries); return -1; }
+               }
        }
 
-// send an entire block of data over a connected socket, blocking if buffers are full
+// send an entire block of data over a connected socket
 mDNSlocal int MySend(int sd, const void *msg, int len)
        {
-       int n, nsent = 0;
-
+       int selectval, n, nsent = 0;
+       fd_set wset;    
+       struct timeval timeout = { 3, 0 };  // until we remove all calls from main thread, keep timeout short
+       
        while (nsent < len)
                {
+               FD_ZERO(&wset);
+               FD_SET(sd, &wset);
+               selectval = select(sd+1, NULL, &wset, NULL, &timeout);
+               if (selectval < 0) { LogErr("MySend", "select");  return -1; }
+               if (!selectval || !FD_ISSET(sd, &wset)) { Log("MySend - timeout"); return -1; }
                n = send(sd, (char *)msg + nsent, len - nsent, 0);
                if (n < 0) { LogErr("MySend", "send");  return -1; }
                nsent += n;
@@ -450,11 +493,21 @@ static int my_recv(const int sd, void *const buf, const int len)
     // use an explicit while() loop instead.
     // Also, don't try to do '+=' arithmetic on the original "void *" pointer --
     // arithmetic on "void *" pointers is compiler-dependent.
-    int remaining = len;
+
+       fd_set rset;    
+       struct timeval timeout = { 3, 0 };  // until we remove all calls from main thread, keep timeout short   
+    int selectval, remaining = len;
     char *ptr = (char *)buf;
-    while (remaining)
+       ssize_t num_read;
+       
+       while (remaining)
        {
-       ssize_t num_read = recv(sd, ptr, remaining, 0);
+               FD_ZERO(&rset);
+               FD_SET(sd, &rset);
+               selectval = select(sd+1, &rset, NULL, NULL, &timeout);
+               if (selectval < 0) { LogErr("my_recv", "select");  return -1; }
+               if (!selectval || !FD_ISSET(sd, &rset)) { Log("my_recv - timeout"); return -1; }
+       num_read = recv(sd, ptr, remaining, 0);
        if ((num_read == 0) || (num_read < 0) || (num_read > remaining)) return -1;
        ptr       += num_read;
        remaining -= num_read;
@@ -475,7 +528,7 @@ mDNSlocal PktMsg *ReadTCPMsg(int sd, PktMsg *storage)
        unsigned int srclen;
        
        nread = my_recv(sd, &msglen, sizeof(msglen));
-       if (nread < 0) { LogErr("TCPRequestForkFn", "recv"); goto error; }
+       if (nread < 0) { LogErr("ReadTCPMsg", "recv"); goto error; }
        msglen = ntohs(msglen);
        if (nread != sizeof(msglen)) { Log("Could not read length field of message"); goto error; }     
 
@@ -499,7 +552,7 @@ mDNSlocal PktMsg *ReadTCPMsg(int sd, PktMsg *storage)
        if (getpeername(sd, (struct sockaddr *)&pkt->src, &srclen) ||
                srclen != sizeof(pkt->src)) { LogErr("ReadTCPMsg", "getpeername"); bzero(&pkt->src, sizeof(pkt->src)); }
        nread = my_recv(sd, &pkt->msg, msglen);
-       if (nread < 0) { LogErr("TCPRequestForkFn", "recv"); goto error; }
+       if (nread < 0) { LogErr("ReadTCPMsg", "recv"); goto error; }
        if (nread != msglen) { Log("Could not read entire message"); goto error; }
        if (pkt->len < sizeof(DNSMessageHeader))
                { Log("ReadTCPMsg: Message too short (%d bytes)", pkt->len);  goto error; }     
@@ -511,6 +564,33 @@ mDNSlocal PktMsg *ReadTCPMsg(int sd, PktMsg *storage)
        return NULL;
        }
 
+mDNSlocal int UDPServerTransaction(const DaemonInfo *d, const PktMsg *request, PktMsg *reply, mDNSBool *trunc)
+       {
+       fd_set rset;    
+       struct timeval timeout = { 3, 0 };  // until we remove all calls from main thread, keep timeout short
+       int selectval, err = -1, sd = socket(AF_INET, SOCK_DGRAM, 0);
+
+       *trunc = mDNSfalse;
+       if (sd < 0) { LogErr("UDPServerTransaction", "socket"); goto end; }
+       if (sendto(sd, (char *)&request->msg, request->len, 0, (struct sockaddr *)&d->saddr, sizeof(d->saddr)) != (int)request->len)
+               { LogErr("UDPServerTransaction", "sendto"); goto end; }
+
+       FD_ZERO(&rset);
+       FD_SET(sd, &rset);
+       selectval = select(sd+1, &rset, NULL, NULL, &timeout);
+       if (selectval < 0) { LogErr("UDPServerTransaction", "select");  goto end; }
+       if (!selectval || !FD_ISSET(sd, &rset)) { Log("UDPServerTransaction - timeout"); goto end; }
+       reply->len = recvfrom(sd, &reply->msg, sizeof(reply->msg), 0, NULL, NULL);
+       if ((int)reply->len < 0) { LogErr("UDPServerTransaction", "recvfrom"); goto end; }
+       if (reply->len < sizeof(DNSMessageHeader)) { Log("UDPServerTransaction - Message too short (%d bytes)", reply->len); goto end; }
+       if (reply->msg.h.flags.b[0] & kDNSFlag0_TC) *trunc = mDNStrue;
+       err = 0;
+
+       end:
+       if (sd >= 0) close(sd);
+       return err;     
+       }
+
 //
 // Dynamic Update Utility Routines
 //
@@ -846,10 +926,14 @@ mDNSlocal void PrintHelp(void)
 mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d)
        {
        int opt;
-
+       struct in_addr server;
+       
        if (argc < 2) goto arg_error;
+       
+    // defaults, may be overriden by command option
+       d->port.NotAnInteger = htons(DAEMON_PORT);  
+       inet_pton(AF_INET, LOOPBACK, &server);  // use loopback if server not explicitly specified
 
-       d->port.NotAnInteger = htons(DAEMON_PORT);  // default, may be overriden by command option
        while ((opt = getopt(argc, argv, "z:p:hfvs:k:")) != -1)
                {
                switch(opt)
@@ -860,8 +944,8 @@ mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d)
                        case 'h': PrintHelp();    return -1;
                        case 'f': foreground = 1; break;
                        case 'v': verbose = 1;    break;
-                       case 's': if (!inet_pton(AF_INET, optarg, &d->saddr)) goto arg_error;
-                                     break;
+                       case 's': if (!inet_pton(AF_INET, optarg, &server)) goto arg_error;
+                               break;
                        case 'k': if (ReadAuthKey(argc, argv, d) < 0) goto arg_error;
                                      break;
                        case 'z': if (!MakeDomainNameFromDNSNameString(&d->zone, optarg))
@@ -876,6 +960,16 @@ mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d)
                
        if (!d->zone.c[0]) goto arg_error;  // zone is the only required argument
        if (d->AuthInfo) AssignDomainName(&d->AuthInfo->zone, &d->zone); // if we have a shared secret, use it for the entire zone
+
+       // setup server's sockaddr
+       bzero(&d->saddr, sizeof(d->saddr));
+       d->saddr.sin_addr = server;   
+       d->saddr.sin_port = htons(NS_PORT);
+       d->saddr.sin_family = AF_INET;
+#ifndef NOT_HAVE_SA_LEN
+       d->saddr.sin_len = sizeof(d->saddr); 
+#endif
+
        return 0;
        
        arg_error:
@@ -924,7 +1018,7 @@ mDNSlocal int SetupSockets(DaemonInfo *daemon)
        // set up Unix domain socket pair for LLQ polling thread to signal main thread that a change to the zone occurred
        if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockpair) < 0) { LogErr("SetupSockets", "socketpair"); return -1; }
        daemon->LLQEventListenSock = sockpair[0];
-       daemon->LLQServPollSock = sockpair[1];
+       daemon->LLQEventNotifySock = sockpair[1];
        return 0;
        }
 
@@ -933,9 +1027,9 @@ mDNSlocal int SetupSockets(DaemonInfo *daemon)
 //
 
 // Delete a resource record from the nameserver via a dynamic update
-mDNSlocal void DeleteRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone)
+// sd is a socket already connected to the server
+mDNSlocal void DeleteOneRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone, int sd)
        {
-       int sd = -1;
        mDNSOpaque16 id;
        PktMsg pkt;
        mDNSu8 *ptr = pkt.msg.data;
@@ -945,8 +1039,6 @@ mDNSlocal void DeleteRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone)
        PktMsg *reply = NULL;
        
        VLog("Expiring record %s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, buf));     
-       sd = ConnectToServer(d);
-       if (sd < 0) { Log("DeleteRecord: ConnectToServer failed"); goto end; }
        
        id.NotAnInteger = 0;
        InitializeDNSMessage(&pkt.msg.h, id, UpdateReqFlags);
@@ -968,51 +1060,45 @@ mDNSlocal void DeleteRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone)
        pkt.len = ptr - (mDNSu8 *)&pkt.msg;
        pkt.src.sin_addr.s_addr = htonl(INADDR_ANY); // address field set solely for verbose logging in subroutines
        pkt.src.sin_family = AF_INET;
-       if (SendTCPMsg(sd, &pkt)) { Log("DeleteRecord: SendTCPMsg failed"); }
+       if (SendTCPMsg(sd, &pkt)) { Log("DeleteOneRecord: SendTCPMsg failed"); }
        reply = ReadTCPMsg(sd, NULL);
        if (!SuccessfulUpdateTransaction(&pkt, reply))
-               Log("Expiration update failed with rcode %d", reply->msg.h.flags.b[1] & kDNSFlag1_RC);
+               Log("Expiration update failed with rcode %d", reply ? reply->msg.h.flags.b[1] & kDNSFlag1_RC : -1);
                                          
        end:
-       if (!ptr) { Log("DeleteRecord: Error constructing lease expiration update"); }
-       if (sd >= 0) close(sd); 
+       if (!ptr) { Log("DeleteOneRecord: Error constructing lease expiration update"); }
        if (reply) free(reply);
        }
 
-// iterate over table, deleting expired records
-mDNSlocal void DeleteExpiredRecords(DaemonInfo *d)
+// iterate over table, deleting expired records (or all records if DeleteAll is true)
+mDNSlocal void DeleteRecords(DaemonInfo *d, mDNSBool DeleteAll)
        {
-       int i;
-       RRTableElem *ptr, *prev, *fptr; 
        struct timeval now;
+       int i, sd = ConnectToServer(d);
+       if (sd < 0) { Log("DeleteRecords: ConnectToServer failed"); return; }  
+       if (gettimeofday(&now, NULL)) { LogErr("DeleteRecords ", "gettimeofday"); return; }
+       if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteRecords", "pthread_mutex_lock"); return; }
 
-       if (gettimeofday(&now, NULL)) { LogErr("DeleteExpiredRecords ", "gettimeofday"); return; }
-       if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteExpiredRecords", "pthread_mutex_lock"); return; }
        for (i = 0; i < d->nbuckets; i++)
                {
-               ptr = d->table[i];
-               prev = NULL;
-               while (ptr)
+               RRTableElem **ptr = &d->table[i];
+               while (*ptr)
                        {
-                       if (ptr->expire - now.tv_sec < 0)
+                       if (DeleteAll || (*ptr)->expire - now.tv_sec < 0)
                                {
+                               RRTableElem *fptr;
                                // delete record from server
-                               DeleteRecord(d, &ptr->rr, &ptr->zone);
-                               if (prev) prev->next = ptr->next;
-                               else d->table[i] = ptr->next;
-                               fptr = ptr;
-                               ptr = ptr->next;
+                               DeleteOneRecord(d, &(*ptr)->rr, &(*ptr)->zone, sd);
+                               fptr = *ptr;
+                               *ptr = (*ptr)->next;
                                free(fptr);
                                d->nelems--;
                                }
-                       else
-                               {
-                               prev = ptr;
-                               ptr = ptr->next;
-                               }
+                       else ptr = &(*ptr)->next;
                        }
                }
        pthread_mutex_unlock(&d->tablelock);
+       close(sd);
        }
 
 //
@@ -1149,32 +1235,54 @@ mDNSlocal PktMsg *FormatLeaseReply(DaemonInfo *d, PktMsg *orig, mDNSu32 lease)
 mDNSlocal PktMsg *HandleRequest(PktMsg *pkt, DaemonInfo *d)
        {
        int sd = -1;
-       PktMsg *reply = NULL, *LeaseReply;
+       PktMsg *reply = NULL, *LeaseReply, buf;
        mDNSs32 lease;
-       char buf[32];
+       char addrbuf[32], pingmsg[4];
        
        // send msg to server, read reply
-       sd = ConnectToServer(d);
-       if (sd < 0)
-               { Log("Discarding request from %s due to connection errors", inet_ntop(AF_INET, &pkt->src.sin_addr, buf, 32)); goto cleanup; }
-       if (SendTCPMsg(sd, pkt) < 0)
-               { Log("Couldn't relay message from %s to server.  Discarding.", inet_ntop(AF_INET, &pkt->src.sin_addr, buf, 32)); goto cleanup; }
-       reply = ReadTCPMsg(sd, NULL);
-       
+
+       if (pkt->len <= 512)
+               {
+               mDNSBool trunc;
+               if (UDPServerTransaction(d, pkt, &buf, &trunc) < 0)
+                       Log("HandleRequest - UDPServerTransaction failed.  Trying TCP");
+               else if (trunc) VLog("HandleRequest - answer truncated.  Using TCP");
+               else reply = &buf; // success
+               }
+
+       if (!reply)
+               {
+               sd = ConnectToServer(d);
+               if (sd < 0)
+                       { Log("Discarding request from %s due to connection errors", inet_ntop(AF_INET, &pkt->src.sin_addr, addrbuf, 32)); goto cleanup; }
+               if (SendTCPMsg(sd, pkt) < 0)
+                       { Log("Couldn't relay message from %s to server.  Discarding.", inet_ntop(AF_INET, &pkt->src.sin_addr, addrbuf, 32)); goto cleanup; }           
+               reply = ReadTCPMsg(sd, &buf);
+               }
+               
        // process reply
        if (!SuccessfulUpdateTransaction(pkt, reply))
-               { VLog("Message from %s not a successful update.", inet_ntop(AF_INET, &pkt->src.sin_addr, buf, 32));  goto cleanup; }   
+               { VLog("Message from %s not a successful update.", inet_ntop(AF_INET, &pkt->src.sin_addr, addrbuf, 32));  goto cleanup; }       
        lease = GetPktLease(pkt);
        UpdateLeaseTable(pkt, d, lease);
        if (lease > 0)
                {
                LeaseReply = FormatLeaseReply(d, reply, lease);
                if (!LeaseReply) Log("HandleRequest - unable to format lease reply");
-               free(reply); 
                reply = LeaseReply;
                }
+
+       // tell the main thread there was an update so it can send LLQs
+       if (send(d->LLQEventNotifySock, pingmsg, sizeof(pingmsg), 0) != sizeof(pingmsg)) LogErr("HandleRequest", "send");
+
        cleanup:
        if (sd >= 0) close(sd);
+       if (reply == &buf)
+               {
+               reply = malloc(sizeof(*reply));
+               if (!reply) LogErr("HandleRequest", "malloc");
+               else { reply->len = buf.len; memcpy(&reply->msg, &buf.msg, buf.len); }
+               }
        return reply;
        }
 
@@ -1219,9 +1327,13 @@ mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e)
        inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
        VLog("Deleting LLQ table entry for %##s client %s", e->qname.c, addr);
 
-       // free shared answer structure if ref count drops to zero
-       if (a && !(--a->refcount))
+       if (a && !(--a->refcount) && d->AnswerTableCount >= LLQ_TABLESIZE)
                {
+               // currently, generating initial answers blocks the main thread, so we keep the answer list
+               // even if the ref count drops to zero.  To prevent unbounded table growth, we free shared answers
+               // if the ref count drops to zero AND there are more table elements than buckets
+               // !!!KRS update this when we make the table dynamically growable
+
                CacheRecord *cr = a->KnownAnswers, *tmp;
                AnswerListElem **tbl = &d->AnswerTable[bucket];
 
@@ -1233,7 +1345,7 @@ mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e)
                        }
 
                while (*tbl && *tbl != a) tbl = &(*tbl)->next;
-               if (*tbl) { *tbl = (*tbl)->next; free(a); }
+               if (*tbl) { *tbl = (*tbl)->next; free(a); d->AnswerTableCount--; }
                else Log("Error: DeleteLLQ - AnswerList not found in table");
                }
 
@@ -1260,20 +1372,17 @@ mDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst)
        return err;
        }
 
-// if non-negative, sd is a TCP socket connected to the nameserver
-// otherwise, this routine creates and closes its own socket
-mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e, int sd)
+mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e)
        {
        PktMsg q;
-       int i;
+       int i, sd = -1;
        const mDNSu8 *ansptr;
        mDNSu8 *end = q.msg.data;
        mDNSOpaque16 id, flags = QueryFlags;
-       PktMsg *reply = NULL;
+       PktMsg buf, *reply = NULL;
        LargeCacheRecord lcr;
        CacheRecord *AnswerList = NULL;
        mDNSu8 rcode;
-       mDNSBool CloseSDOnExit = sd < 0;
        
        VLog("Querying server for %##s type %d", e->name.c, e->type);
        
@@ -1284,11 +1393,26 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e, int sd)
        end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->name, e->type, kDNSClass_IN);
        if (!end) { Log("Error: AnswerQuestion - putQuestion returned NULL"); goto end; }
        q.len = (int)(end - (mDNSu8 *)&q.msg);
+
+       if (!e->UseTCP)
+               {
+               mDNSBool trunc;
+
+               if (UDPServerTransaction(d, &q, &buf, &trunc) < 0)
+                       Log("AnswerQuestion %##s - UDPServerTransaction failed.  Trying TCP", e->name.c);
+               else if (trunc)
+                       { VLog("AnswerQuestion %##s - answer truncated.  Using TCP", e->name.c); e->UseTCP = mDNStrue; }
+               else reply = &buf;  // success
+               }
        
-       if (sd < 0) sd = ConnectToServer(d);
-       if (sd < 0) { Log("AnswerQuestion: ConnectToServer failed"); goto end; }
-       if (SendTCPMsg(sd, &q)) { Log("AnswerQuestion: SendTCPMsg failed"); close(sd); goto end; }
-       reply = ReadTCPMsg(sd, NULL);
+       if (!reply)
+               {
+               sd = ConnectToServer(d);
+               if (sd < 0) { Log("AnswerQuestion: ConnectToServer failed"); goto end; }
+               if (SendTCPMsg(sd, &q)) { Log("AnswerQuestion: SendTCPMsg failed"); close(sd); goto end; }
+               reply = ReadTCPMsg(sd, NULL);
+               close(sd);
+               }
 
        if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery))
                { Log("AnswerQuestion: %##s type %d - Invalid response flags from server"); goto end; }
@@ -1318,18 +1442,22 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e, int sd)
                }
        
        end:
-       if (sd > -1 && CloseSDOnExit) close(sd);
-       if (reply) free(reply);
+       if (reply && reply != &buf) free(reply);
        return AnswerList;
        }
 
-// Routine sets EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list
-mDNSlocal void UpdateAnswerList(DaemonInfo *d, AnswerListElem *a, int sd)
+// Routine forks a thread to set EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list
+mDNSlocal void *UpdateAnswerList(void *args)
        {
        CacheRecord *cr, *NewAnswers, **na, **ka; // "new answer", "known answer"
+       DaemonInfo *d = ((UpdateAnswerListArgs *)args)->d;
+       AnswerListElem *a = ((UpdateAnswerListArgs *)args)->a;
 
+       free(args);
+       args = NULL;
+       
        // get up to date answers
-       NewAnswers = AnswerQuestion(d, a, sd);
+       NewAnswers = AnswerQuestion(d, a);
        
        // first pass - mark all answers for deletion
        for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
@@ -1383,7 +1511,9 @@ mDNSlocal void UpdateAnswerList(DaemonInfo *d, AnswerListElem *a, int sd)
                cr = NewAnswers;
                NewAnswers = NewAnswers->next;
                free(cr);
-               }       
+               }
+       
+       return NULL;
        }
 
 mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e)
@@ -1407,7 +1537,7 @@ mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e)
                if (verbose) GetRRDisplayString_rdb(&cr->resrec, &cr->resrec.rdata->u, rrbuf);
                VLog("%s (%s): %s", addrbuf, (mDNSs32)cr->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf);                            
                end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &cr->resrec, cr->resrec.rroriginalttl);
-               if (!end) { Log("Error: SendEvents - UpdateAnswerList returned NULL"); return; }
+               if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo returned NULL"); return; }
                }
                           
        FormatLLQOpt(&opt, kLLQOp_Event, e->id, LLQLease(e));
@@ -1418,6 +1548,28 @@ mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e)
        if (SendLLQ(d, &response, e->cli) < 0) LogMsg("Error: SendEvents - SendLLQ");           
        }
 
+mDNSlocal void PrintLLQAnswers(DaemonInfo *d)
+       {
+       int i;
+       char rrbuf[80];
+       
+       Log("Printing LLQ Answer Table contents");
+
+       for (i = 0; i < LLQ_TABLESIZE; i++)
+               {
+               AnswerListElem *a = d->AnswerTable[i];
+               while(a)
+                       {
+                       int ancount = 0;
+                       const CacheRecord *rr = a->KnownAnswers;
+                       while (rr) { ancount++; rr = rr->next; }                
+                       Log("%p : Question %##s;  type %d;  referenced by %d LLQs; %d answers:", a, a->name.c, a->type, a->refcount, ancount);
+                       for (rr = a->KnownAnswers; rr; rr = rr->next) Log("\t%s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, rrbuf));
+                       a = a->next;
+                       }
+               }
+       }
+
 mDNSlocal void PrintLLQTable(DaemonInfo *d)
        {
        LLQEntry *e;
@@ -1431,9 +1583,19 @@ mDNSlocal void PrintLLQTable(DaemonInfo *d)
                e = d->LLQTable[i];
                while(e)
                        {
-                       inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
-                       Log("LLQ from %##s type %d lease %d (%d remaining)",
-                               addr, e->qname.c, e->qtype, e->lease, LLQLease(e));
+                       char *state;
+                       
+                       switch (e->state)
+                               {
+                               case RequestReceived: state = "RequestReceived"; break;
+                               case ChallengeSent:   state = "ChallengeSent";   break;
+                               case Established:     state = "Established";     break;
+                               default:              state = "unknown";                                        
+                               }
+                       inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);                         
+                       
+                       Log("LLQ from %s in state %s; %##s; type %d; orig lease %d; remaining lease %d; AnswerList %p)",
+                               addr, state, e->qname.c, e->qtype, e->lease, LLQLease(e), e->AnswerList);
                        e = e->next;
                        }
                }
@@ -1443,14 +1605,13 @@ mDNSlocal void PrintLLQTable(DaemonInfo *d)
 mDNSlocal void GenLLQEvents(DaemonInfo *d)
        {
        LLQEntry **e;
-       int i, sd;
+       int i;
        struct timeval t;
-
+       UpdateAnswerListArgs *args;
+       
        VLog("Generating LLQ Events");
 
        gettimeofday(&t, NULL);
-       sd = ConnectToServer(d);
-       if (sd < 0) { Log("GenLLQEvents: ConnectToServer failed"); return; }
 
        // get all answers up to date
        for (i = 0; i < LLQ_TABLESIZE; i++)
@@ -1458,11 +1619,26 @@ mDNSlocal void GenLLQEvents(DaemonInfo *d)
                AnswerListElem *a = d->AnswerTable[i];
                while(a)
                        {
-                       UpdateAnswerList(d, a, sd);
+                       args = malloc(sizeof(*args));
+                       if (!args) { LogErr("GenLLQEvents", "malloc"); return; }                        
+                       args->d = d;
+                       args->a = a;
+                       if (pthread_create(&a->tid, NULL, UpdateAnswerList, args) < 0) { LogErr("GenLLQEvents", "pthread_create"); return; }
+                       usleep(1);
                        a = a->next;
                        }
                }
 
+       for (i = 0; i < LLQ_TABLESIZE; i++)
+               {
+               AnswerListElem *a = d->AnswerTable[i];
+               while(a)
+                       {
+                       if (pthread_join(a->tid, NULL))  LogErr("GenLLQEvents", "pthread_join");
+                       a = a->next;
+                       }
+               }
+       
     // for each established LLQ, send events
        for (i = 0; i < LLQ_TABLESIZE; i++)
                {
@@ -1504,79 +1680,6 @@ mDNSlocal void GenLLQEvents(DaemonInfo *d)
                        a = a->next;
                        }
                }       
-               
-       close(sd);
-       }
-
-// Monitor zone for changes that may produce LLQ events
-mDNSlocal void *LLQEventMonitor(void *DInfoPtr)
-       {
-       DaemonInfo *d = DInfoPtr;
-       PktMsg q;
-       mDNSu8 *end = q.msg.data;
-       const mDNSu8 *ptr;
-       mDNSOpaque16 id, flags = QueryFlags;
-       PktMsg reply;
-       mDNSs32 serial = 0;
-       mDNSBool SerialInitialized = mDNSfalse;
-       int sd;
-    LargeCacheRecord lcr;
-       ResourceRecord *rr = &lcr.r.resrec;
-       int i, sleeptime = 0;
-       domainname zone;
-       char pingmsg[4];
-       
-       // create question
-       id.NotAnInteger = 0;
-       InitializeDNSMessage(&q.msg.h, id, flags);
-       AssignDomainName(&zone, &d->zone);
-       end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &zone, kDNSType_SOA, kDNSClass_IN);
-       if (!end) { Log("Error: LLQEventMonitor - putQuestion returned NULL"); return NULL; }
-       q.len = (int)(end - (mDNSu8 *)&q.msg);
-
-       sd = ConnectToServer(d);
-       if (sd < 0) { Log("LLQEventMonitor: ConnectToServer failed"); return NULL; }
-
-       while(1)
-               {
-               usleep(sleeptime);
-               sleeptime = LLQ_MONITOR_ERR_INTERVAL;  // if we bail on error below, rate limit retry
-               
-               // send message, receive response
-               if (SendTCPMsg(sd, &q)) { Log("LLQEventMonitor: SendTCPMsg failed"); continue; }
-               if (!ReadTCPMsg(sd, &reply)) { Log("LLQEventMonitor: ReadTCPMsg failed"); continue; }
-               end = (mDNSu8 *)&reply.msg + reply.len;
-               if (reply.msg.h.flags.b[1] & kDNSFlag1_RC) { Log("LLQEventMonitor - received non-zero rcode"); continue; }
-
-               // find answer
-               ptr = LocateAnswers(&reply.msg, end);
-               if (!ptr) { Log("Error: LLQEventMonitor - LocateAnswers returned NULL"); continue; }
-               for (i = 0; i < reply.msg.h.numAnswers; i++)
-                       {
-                       ptr = GetLargeResourceRecord(NULL, &reply.msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
-                       if (!ptr) { Log("Error: LLQEventMonitor - GetLargeResourceRecord  returned NULL"); continue; }
-                       if (rr->rrtype != kDNSType_SOA || rr->rrclass != kDNSClass_IN || !SameDomainName(rr->name, &zone)) continue;
-                       if (!SerialInitialized)
-                               {
-                               // first time through loop
-                               SerialInitialized = mDNStrue;
-                               serial = rr->rdata->u.soa.serial;
-                               sleeptime = LLQ_MONITOR_INTERVAL;
-                               break;
-                               }
-                       else if (rr->rdata->u.soa.serial != serial)
-                               {
-                               // update serial, wake main thread
-                               serial = rr->rdata->u.soa.serial;
-                               VLog("LLQEventMonitor: zone changed. Signaling main thread.");
-                               if (send(d->LLQServPollSock, pingmsg, sizeof(pingmsg), 0) != sizeof(pingmsg))
-                                       { LogErr("LLQEventMonitor", "send"); break; }
-                               }
-                       sleeptime = LLQ_MONITOR_INTERVAL;
-                       break;                  
-                       }
-               if (!ptr) Log("LLQEventMonitor: response to query did not contain SOA");
-               }
        }
 
 mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e)
@@ -1591,15 +1694,12 @@ mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e)
                AssignDomainName(&a->name, &e->qname);
                a->type = e->qtype;
                a->refcount = 0;
-               a->KnownAnswers = NULL;
                a->EventList = NULL;
+               a->UseTCP = mDNSfalse;
                a->next = d->AnswerTable[bucket];
                d->AnswerTable[bucket] = a;
-
-               // to get initial answer list, call UpdateAnswerList and move cache records from EventList to KnownAnswers
-               UpdateAnswerList(d, a, -1);
-               a->KnownAnswers = a->EventList;
-               a->EventList = NULL;
+               d->AnswerTableCount++;
+               a->KnownAnswers = AnswerQuestion(d, a);
                }
        
        e->AnswerList = a;
@@ -1654,8 +1754,11 @@ mDNSlocal void LLQRefresh(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaqu
        
        if (llq->lease)
                {
+               struct timeval t;
                if (llq->lease < LLQ_MIN_LEASE) llq->lease = LLQ_MIN_LEASE;
                else if (llq->lease > LLQ_MAX_LEASE) llq->lease = LLQ_MIN_LEASE;
+               gettimeofday(&t, NULL);
+               e->expire = t.tv_sec + llq->lease;
                }
        
        ack.src.sin_addr.s_addr = 0; // unused 
@@ -1987,6 +2090,7 @@ mDNSlocal void *TCPRequestForkFn(void *vptr)
                }
                
        cleanup:
+       close(req->sd);
        free(req);
        if (in) free(in);
        if (out) free(out);
@@ -1995,31 +2099,34 @@ mDNSlocal void *TCPRequestForkFn(void *vptr)
 
 mDNSlocal int RecvTCPRequest(int sd, DaemonInfo *d)
        {
-       TCPRequestArgs *req;
+       TCPRequestArgs *req = NULL;
        pthread_t tid;
        unsigned int clilen = sizeof(req->cliaddr);
        
        req = malloc(sizeof(TCPRequestArgs));
-       if (!req) { LogErr("RecvTCPRequest", "malloc"); return -1; }
+       if (!req) { LogErr("RecvTCPRequest", "malloc"); goto error; }
        bzero(req, sizeof(*req));
        req->d = d;
        req->sd = accept(sd, (struct sockaddr *)&req->cliaddr, &clilen);
-       if (req->sd < 0) { LogErr("RecvTCPRequest", "accept"); return -1; }     
-       if (clilen != sizeof(req->cliaddr)) { Log("Client address of unknown size %d", clilen); free(req); return -1; }
-       if (pthread_create(&tid, NULL, TCPRequestForkFn, req)) { LogErr("RecvTCPRequest", "pthread_create"); free(req); return -1; }
+       if (req->sd < 0) { LogErr("RecvTCPRequest", "accept"); goto error; }    
+       if (clilen != sizeof(req->cliaddr)) { Log("Client address of unknown size %d", clilen); goto error; }
+       if (pthread_create(&tid, NULL, TCPRequestForkFn, req)) { LogErr("RecvTCPRequest", "pthread_create"); goto error; }
        pthread_detach(tid);
        return 0;
+
+       error:
+       if (req) free(req);
+       return -1;
        }
 
 // main event loop
 // listen for incoming requests, periodically check table for expired records, respond to signals
 mDNSlocal int ListenForUpdates(DaemonInfo *d)
        {
-       int err;
-       int maxfdp1;
+       int maxfdp1, nfds;
        fd_set rset;
-       struct timeval timenow, timeout = { 0, 0 };
-       long NextTableCheck = 0;
+       struct timeval timenow, timeout, EventTS, tablecheck = { 0, 0 };
+       mDNSBool EventsPending = mDNSfalse;
        
        VLog("Listening for requests...");
 
@@ -2030,42 +2137,72 @@ mDNSlocal int ListenForUpdates(DaemonInfo *d)
        
        while(1)
                {
-               // expire records if necessary, set timeout
+               // set timeout
+               timeout.tv_sec = timeout.tv_usec = 0;
                if (gettimeofday(&timenow, NULL)) { LogErr("ListenForUpdates", "gettimeofday"); return -1; }
-               if (timenow.tv_sec >= NextTableCheck)
+               if (EventsPending)
                        {
-                       DeleteExpiredRecords(d);
-                       NextTableCheck = timenow.tv_sec + EXPIRATION_INTERVAL;
+                       if (timenow.tv_sec - EventTS.tv_sec >= 5)           // if we've been waiting 5 seconds for a "quiet" period to send
+                               { GenLLQEvents(d); EventsPending = mDNSfalse; } // events, we go ahead and do it now
+                       else timeout.tv_usec = 500000;                      // else do events after 1/2 second with no new events or LLQs
+                       }
+               if (!EventsPending)
+                       {
+                       // if no pending events, timeout when we need to check for expired records
+                       if (tablecheck.tv_sec && timenow.tv_sec - tablecheck.tv_sec >= 0)
+                               { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; } // table check overdue                          
+                       if (!tablecheck.tv_sec) tablecheck.tv_sec = timenow.tv_sec + EXPIRATION_INTERVAL;
+                       timeout.tv_sec = tablecheck.tv_sec - timenow.tv_sec;
                        }
-               timeout.tv_sec = NextTableCheck - timenow.tv_sec;
                
                FD_SET(d->tcpsd, &rset);
                FD_SET(d->udpsd, &rset);
                FD_SET(d->LLQEventListenSock, &rset);
                
-               err = select(maxfdp1, &rset, NULL, NULL, &timeout);             
-               if (err < 0)
+               nfds = select(maxfdp1, &rset, NULL, NULL, &timeout);            
+               if (nfds < 0)
                        {
                        if (errno == EINTR)
                                {
-                               if (terminate) { DeleteExpiredRecords(d); return 0; }
-                               else if (dumptable) { PrintLeaseTable(d); PrintLLQTable(d); dumptable = 0; }
+                               if (terminate)
+                                       {
+                                       // close sockets to prevent clients from making new requests during shutdown
+                                       close(d->tcpsd);
+                                       close(d->udpsd);
+                                       d->tcpsd = d->udpsd = -1;
+                                       DeleteRecords(d, mDNStrue);
+                                       return 0;
+                                       }
+                               else if (dumptable) { PrintLeaseTable(d); PrintLLQTable(d); PrintLLQAnswers(d); dumptable = 0; }
                                else Log("Received unhandled signal - continuing"); 
                                }
-                       else { LogErr("ListenForUpdates", "select"); return -1; }
+                       else
+                               {
+                               LogErr("ListenForUpdates", "select"); return -1;
+                               }
                        }
-               else
+               else if (nfds)
                        {
                        if (FD_ISSET(d->tcpsd, &rset)) RecvTCPRequest(d->tcpsd, d);
                        if (FD_ISSET(d->udpsd, &rset)) RecvUDPRequest(d->udpsd, d); 
                        if (FD_ISSET(d->LLQEventListenSock, &rset))
                                {
                                // clear signalling data off socket
-                               char buf[32];
-                               recv(d->LLQEventListenSock, buf, 32, 0);
-                               GenLLQEvents(d);
+                               char buf[256];
+                               recv(d->LLQEventListenSock, buf, 256, 0);
+                               if (!EventsPending)
+                                       {
+                                       EventsPending = mDNStrue;
+                                       if (gettimeofday(&EventTS, NULL)) { LogErr("ListenForUpdates", "gettimeofday"); return -1; }                                    
+                                       }
                                }
                        }
+               else
+                       {
+                       // timeout
+                       if (EventsPending) { GenLLQEvents(d); EventsPending = mDNSfalse; }
+                       else { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; }
+                       }
                }
        return 0;
        }
@@ -2080,17 +2217,26 @@ mDNSlocal void HndlSignal(int sig)
 
 int main(int argc, char *argv[])
        {
-       pthread_t LLQtid;
        DaemonInfo *d;
-
+       struct rlimit rlim;
+       
        d = malloc(sizeof(*d));
        if (!d) { LogErr("main", "malloc"); exit(1); }
-       bzero(d, sizeof(DaemonInfo));
+       bzero(d, sizeof(DaemonInfo));   
        
        if (signal(SIGTERM,     HndlSignal) == SIG_ERR) perror("Can't catch SIGTERM");
        if (signal(INFO_SIGNAL, HndlSignal) == SIG_ERR) perror("Can't catch SIGINFO");
        if (signal(SIGINT,      HndlSignal) == SIG_ERR) perror("Can't catch SIGINT");
        if (signal(SIGPIPE,     SIG_IGN  )  == SIG_ERR) perror("Can't ignore SIGPIPE");
+
+       // remove open file limit
+       rlim.rlim_max = RLIM_INFINITY;
+       rlim.rlim_cur = RLIM_INFINITY;
+       if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
+               {
+               LogErr("main", "setrlimit");
+               Log("Using default file descriptor resource limit");
+               }
        
        if (ProcessArgs(argc, argv, d) < 0) exit(1);
 
@@ -2107,14 +2253,8 @@ int main(int argc, char *argv[])
        if (InitLeaseTable(d) < 0) exit(1);
        if (SetupSockets(d) < 0) exit(1); 
        if (SetUpdateSRV(d) < 0) exit(1);
-       
-       if (pthread_create(&LLQtid, NULL, LLQEventMonitor, d)) { LogErr("main", "pthread_create"); }    
-       else
-               {
-               pthread_detach(LLQtid);
-               ListenForUpdates(d);
-               }
-               
+
+       ListenForUpdates(d);
        if (ClearUpdateSRV(d) < 0) exit(1);  // clear update srv's even if ListenForUpdates or pthread_create returns an error
        free(d);
        exit(0);
index 3970b4b87bc9e0b32790b977a777105a3b2a00e2..4b0ab0b3d496417b01fed71721ba779eefb2287a 100755 (executable)
        Change History (most recent first):
 
 $Log: mDNSPosix.c,v $
+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
+
+Revision 1.73  2005/10/11 21:31:46  cheshire
+<rdar://problem/4296177> Don't depend on IP_RECVTTL succeeding (not available on all platforms)
+
+Revision 1.72  2005/09/08 20:45:26  cheshire
+Default dot-local host name should be "Computer" not "Macintosh",
+since the machine this is running on is most likely NOT a Mac.
+
 Revision 1.71  2005/02/26 01:29:12  cheshire
 Ignore multicasts accidentally delivered to our unicast receiving socket
 
@@ -434,11 +447,15 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
        if      (err > 0) err = 0;
        else if (err < 0)
                {
+        // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
+               if (!mDNSAddressIsAllDNSLinkGroup(dst))
+                       if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
+
                if (thisIntf)
-                       verbosedebugf("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a on interface %#a/%s/%d",
+                       LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a on interface %#a/%s/%d",
                                                  errno, strerror(errno), dst, &thisIntf->coreIntf.ip, thisIntf->intfName, thisIntf->index);
                else
-                       verbosedebugf("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a", errno, strerror(errno), dst);
+                       LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a", errno, strerror(errno), dst);
                }
 
        return PosixErrorToStatus(err);
@@ -733,6 +750,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
        static const int kOn = 1;
        static const int kIntTwoFiveFive = 255;
        static const unsigned char kByteTwoFiveFive = 255;
+       const mDNSBool JoinMulticastGroup = (port.NotAnInteger != 0);
        
        (void) interfaceIndex;  // This parameter unused on plaforms that don't have IPv6
        assert(intfAddr != NULL);
@@ -790,13 +808,13 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
        #if defined(IP_RECVTTL)                                                                 // Linux
                if (err == 0)
                        {
-                       err = setsockopt(*sktPtr, IPPROTO_IP, IP_RECVTTL, &kOn, sizeof(kOn));
-                       if (err < 0) { err = errno; perror("setsockopt - IP_RECVTTL"); }
+                       setsockopt(*sktPtr, IPPROTO_IP, IP_RECVTTL, &kOn, sizeof(kOn));
+                       // We no longer depend on being able to get the received TTL, so don't worry if the option fails
                        }
        #endif
 
                // Add multicast group membership on this interface
-               if (err == 0 && port.NotAnInteger)
+               if (err == 0 && JoinMulticastGroup)
                        {
                        imr.imr_multiaddr.s_addr = AllDNSLinkGroupv4.NotAnInteger;
                        imr.imr_interface        = ((struct sockaddr_in*)intfAddr)->sin_addr;
@@ -805,7 +823,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
                        }
 
                // Specify outgoing interface too
-               if (err == 0 && port.NotAnInteger)
+               if (err == 0 && JoinMulticastGroup)
                        {
                        err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_IF, &((struct sockaddr_in*)intfAddr)->sin_addr, sizeof(struct in_addr));
                        if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_IF"); }
@@ -862,7 +880,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
        #endif
 
                // Add multicast group membership on this interface
-               if (err == 0 && port.NotAnInteger)
+               if (err == 0 && JoinMulticastGroup)
                        {
                        imr6.ipv6mr_multiaddr       = *(const struct in6_addr*)&AllDNSLinkGroupv6;
                        imr6.ipv6mr_interface       = interfaceIndex;
@@ -876,7 +894,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
                        }
 
                // Specify outgoing interface too
-               if (err == 0 && port.NotAnInteger)
+               if (err == 0 && JoinMulticastGroup)
                        {
                        u_int   multicast_if = interfaceIndex;
                        err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_if, sizeof(multicast_if));
@@ -918,7 +936,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
                        bindAddr6.sin6_family      = AF_INET6;
                        bindAddr6.sin6_port        = port.NotAnInteger;
                        bindAddr6.sin6_flowinfo    = 0;
-//                     bindAddr6.sin6_addr.s_addr = IN6ADDR_ANY_INIT; // Want to receive multicasts AND unicasts on this socket
+                       bindAddr6.sin6_addr        = in6addr_any; // Want to receive multicasts AND unicasts on this socket
                        bindAddr6.sin6_scope_id    = 0;
                        err = bind(*sktPtr, (struct sockaddr *) &bindAddr6, sizeof(bindAddr6));
                        if (err < 0) { err = errno; perror("bind"); fflush(stderr); }
@@ -1345,12 +1363,12 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
        // Set up the nice label
        m->nicelabel.c[0] = 0;
        GetUserSpecifiedFriendlyComputerName(&m->nicelabel);
-       if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Macintosh");
+       if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Computer");
 
        // Set up the RFC 1034-compliant label
        m->hostlabel.c[0] = 0;
        GetUserSpecifiedRFC1034ComputerName(&m->hostlabel);
-       if (m->hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->hostlabel, "Macintosh");
+       if (m->hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->hostlabel, "Computer");
 
        mDNS_SetFQDN(m);
 
index 32a016cdd2ba15f13fdc2638afe196667db856aa..f9bd4a6e42304b21dfaf5eca7fae3847d1eab418 100755 (executable)
     Change History (most recent first):
 
 $Log: mDNSUNP.c,v $
+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
@@ -111,6 +141,15 @@ First checkin
 #include <unistd.h>
 #include <stdio.h>
 
+/* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P)
+   macro, usually defined in <sys/param.h> or someplace like that, to make sure the
+   CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
+   should be set to the name of the header to include to get the ALIGN(P) macro.
+*/
+#ifdef NEED_ALIGN_MACRO
+#include NEED_ALIGN_MACRO
+#endif
+
 /* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but 
    other platforms don't even have that include file.  So, 
    if we haven't yet got a definition, let's try to find 
@@ -129,10 +168,135 @@ First checkin
     #include <net/if_dl.h>
 #endif
 
-#if defined(AF_INET6) && HAVE_IPV6
+#if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX
 #include <netinet6/in6_var.h>
 #endif
 
+#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
+#include <netdb.h>
+#include <arpa/inet.h>
+
+/* Converts a prefix length to IPv6 network mask */
+void plen_to_mask(int plen, char *addr) {
+       int i;
+       int colons=7; /* Number of colons in IPv6 address */
+       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;
+               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;
+               }
+       }
+
+/* Gets IPv6 interface information from the /proc filesystem in linux*/
+struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
+       {
+       struct ifi_info *ifi, *ifihead, **ifipnext;
+       FILE *fp;
+       char addr[8][5];
+       int flags, myflags, index, plen, scope;
+       char ifname[8], lastname[IFNAMSIZ];
+       char addr6[32+7+1]; /* don't forget the seven ':' */
+       struct addrinfo hints, *res0;
+       struct sockaddr_in6 *sin6;
+       struct in6_addr *addrptr;
+       int err;
+
+       res0=NULL;
+       ifihead = NULL;
+       ifipnext = &ifihead;
+       lastname[0] = 0;
+
+       if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
+               while (fscanf(fp,
+                                         "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
+                                         addr[0],addr[1],addr[2],addr[3],
+                                         addr[4],addr[5],addr[6],addr[7],
+                                         &index, &plen, &scope, &flags, ifname) != EOF) {
+
+                       myflags = 0;
+                       if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
+                               if (doaliases == 0)
+                                       continue;   /* already processed this interface */
+                               myflags = IFI_ALIAS;
+                               }
+                       memcpy(lastname, ifname, IFNAMSIZ);
+                       ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
+                       if (ifi == NULL) {
+                               goto gotError;
+                               }
+
+                       *ifipnext = ifi;            /* prev points to this new one */
+                       ifipnext = &ifi->ifi_next;  /* pointer to next one goes here */
+
+                       sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
+                                       addr[0],addr[1],addr[2],addr[3],
+                                       addr[4],addr[5],addr[6],addr[7]);
+
+                       /* Add address of the interface */
+                       memset(&hints, 0, sizeof(hints));
+                       hints.ai_family = AF_INET6;
+                       hints.ai_flags = AI_NUMERICHOST;
+                       err = getaddrinfo(addr6, NULL, &hints, &res0);
+                       if (err) {
+                               goto gotError;
+                               }
+                       ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
+                       if (ifi->ifi_addr == NULL) {
+                               goto gotError;
+                               }
+                       memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
+
+                       /* Add netmask of the interface */
+                       char ipv6addr[INET6_ADDRSTRLEN];
+                       plen_to_mask(plen, ipv6addr);
+                       ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
+                       if (ifi->ifi_addr == NULL) {
+                               goto gotError;
+                               }
+                       sin6=calloc(1, sizeof(struct sockaddr_in6));
+                       addrptr=calloc(1, sizeof(struct in6_addr));
+                       inet_pton(family, ipv6addr, addrptr);
+                       sin6->sin6_family=family;
+                       sin6->sin6_addr=*addrptr;
+                       sin6->sin6_scope_id=scope;
+                       memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
+                       free(sin6);
+
+
+                       /* Add interface name */
+                       memcpy(ifi->ifi_name, ifname, IFI_NAME);
+
+                       /* Add interface index */
+                       ifi->ifi_index = index;
+
+                       /* If interface is in /proc then it is up*/
+                       ifi->ifi_flags = IFF_UP;
+
+                       freeaddrinfo(res0);
+                       res0=NULL;
+                       }
+               }
+       goto done;
+
+       gotError:
+       if (ifihead != NULL) {
+               free_ifi_info(ifihead);
+               ifihead = NULL;
+               }
+       if (res0 != NULL) {
+               freeaddrinfo(res0);
+               res0=NULL;
+               }
+       done:
+       return(ifihead);    /* pointer to first structure in linked list */
+       }
+#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
+
 struct ifi_info *get_ifi_info(int family, int doaliases)
 {
     int                 junk;
@@ -150,7 +314,11 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
     struct sockaddr_in6 *sinptr6;
 #endif
 
-    sockfd = -1;
+#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
+ if(family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
+#endif
+
+       sockfd = -1;
     sockf6 = -1;
     buf = NULL;
     ifihead = NULL;
@@ -190,10 +358,13 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
     for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
         ifr = (struct ifreq *) ptr;
 
-               len = GET_SA_LEN(ifr->ifr_addr);
-        ptr += sizeof(ifr->ifr_name) + len; /* for next one in buffer */
-    
-//        fprintf(stderr, "intf %d name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
+        /* Advance to next one in buffer */
+        if (sizeof(struct ifreq) > sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr))
+            ptr += sizeof(struct ifreq);
+        else
+            ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr);
+
+//      fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
         
         if (ifr->ifr_addr.sa_family != family)
             continue;   /* ignore if not desired address family */
@@ -230,9 +401,11 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
         ifi->ifi_index = if_nametoindex(ifr->ifr_name);
 #else
         ifrcopy = *ifr;
+#ifdef SIOCGIFINDEX
                if ( 0 >= ioctl(sockfd, SIOCGIFINDEX, &ifrcopy))
             ifi->ifi_index = ifrcopy.ifr_index;
         else
+#endif
             ifi->ifi_index = index++;  /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
 #endif
         memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
@@ -254,6 +427,11 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
                                ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
                                if (ifi->ifi_netmask == NULL) goto gotError;
                                sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
+                               /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
+#ifndef NOT_HAVE_SA_LEN
+                               sinptr->sin_len    = sizeof(struct sockaddr_in);
+#endif
+                               sinptr->sin_family = AF_INET;
                                memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
 #endif
 
@@ -263,6 +441,11 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
                         goto gotError;
                     }
                     sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
+                                       /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
+#ifndef NOT_HAVE_SA_LEN
+                                       sinptr->sin_len    = sizeof( struct sockaddr_in );
+#endif
+                                       sinptr->sin_family = AF_INET;
                     ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
                     if (ifi->ifi_brdaddr == NULL) {
                         goto gotError;
@@ -277,6 +460,11 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
                         goto gotError;
                     }
                     sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
+                    /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
+#ifndef NOT_HAVE_SA_LEN
+                                       sinptr->sin_len    = sizeof( struct sockaddr_in );
+#endif
+                                       sinptr->sin_family = AF_INET;
                     ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
                     if (ifi->ifi_dstaddr == NULL) {
                         goto gotError;
@@ -534,6 +722,8 @@ struct in_pktinfo
 #ifdef NOT_HAVE_DAEMON
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <sys/signal.h>
+
 int daemon(int nochdir, int noclose)
     {
        switch (fork())
index 786fef7e50a42940d444d7d4f95af61569defac5..912c9d8ff1a75c3ed7547b2114e1e4c2e693954b 100755 (executable)
@@ -24,6 +24,9 @@
     Change History (most recent first):
 
 $Log: mDNSUNP.h,v $
+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
 
@@ -90,6 +93,10 @@ First checkin
 #include <net/if.h>
 #include <netinet/in.h>
 
+#ifdef HAVE_LINUX
+#include <linux/socket.h>
+#endif
+
 #ifdef  __cplusplus
     extern "C" {
 #endif
@@ -99,8 +106,12 @@ First checkin
 #endif
 
 #if !defined(_SS_MAXSIZE)
-    #define sockaddr_storage sockaddr
-#endif
+#if HAVE_IPV6
+#define sockaddr_storage sockaddr_in6
+#else
+#define sockaddr_storage sockaddr
+#endif // HAVE_IPV6    
+#endif // !defined(_SS_MAXSIZE)
 
 #ifndef NOT_HAVE_SA_LEN
 #define GET_SA_LEN(X) (sizeof(struct sockaddr) > ((struct sockaddr*)&(X))->sa_len ? \
@@ -146,6 +157,17 @@ struct ifi_info {
   struct ifi_info  *ifi_next;   /* next of these structures */
 };
 
+#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
+#define PROC_IFINET6_PATH "/proc/net/if_inet6"
+extern struct ifi_info  *get_ifi_info_linuxv6(int family, int doaliases);
+#endif
+       
+#if defined(AF_INET6) && HAVE_IPV6
+#define INET6_ADDRSTRLEN 46 /*Maximum length of IPv6 address */
+#endif
+       
+
+       
 #define IFI_ALIAS   1           /* ifi_addr is an alias */
 
 /* From the text (Stevens, section 16.6): */
index 6baeccafc8e6d8631ff4846343ce8f5d1bb82f32..35e02fccad407574602b2eba0570c2f97d0d4d53 100755 (executable)
@@ -868,6 +868,7 @@ mdns_lookup_name (
        DNSServiceErrorType errcode;
        DNSServiceRef sdref;
        ns_type_t rrtype;
+       nss_status status;
        
        if (MDNS_VERBOSE)
                syslog (LOG_DEBUG,
@@ -919,7 +920,9 @@ mdns_lookup_name (
                return set_err_mdns_failed (result);
        }
 
-       return handle_events (sdref, result, fullname);
+       status = handle_events (sdref, result, fullname);
+       DNSServiceRefDeallocate (sdref);
+       return status;
 }
 
 
@@ -952,6 +955,7 @@ mdns_lookup_addr (
 {
        DNSServiceErrorType errcode;
        DNSServiceRef sdref;
+       nss_status status;
        
        if (MDNS_VERBOSE)
                syslog (LOG_DEBUG,
@@ -991,7 +995,9 @@ mdns_lookup_addr (
                return set_err_mdns_failed (result);
        }
 
-       return handle_events (sdref, result, addr_str);
+       status = handle_events (sdref, result, addr_str);
+       DNSServiceRefDeallocate (sdref);
+       return status;
 }
 
 
index 423805fa990269c2ba755e1c3bc6f0a5c9f98ee5..353c2deb09216754f56550323260ad09d9c9b57d 100755 (executable)
@@ -1,43 +1,78 @@
-Microsoft Visual Studio Solution File, Format Version 7.00\r
+Microsoft Visual Studio Solution File, Format Version 8.00\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLL", "mDNSWindows\DLL\dnssd.vcproj", "{AB581101-18F0-46F6-B56A-83A6B1EA657E}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mDNSResponder", "mDNSWindows\SystemService\Service.vcproj", "{C1D98254-BA27-4427-A3BE-A68CA2CC5F69}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NSPTool", "mDNSWindows\NSPTool\NSPTool.vcproj", "{208B3A9F-1CA0-4D1D-9D6C-C61616F94705}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdnsNSP", "mDNSWindows\mdnsNSP\mdnsNSP.vcproj", "{F4F15529-F0EB-402F-8662-73C5797EE557}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPlugin", "Clients\ExplorerPlugin\ExplorerPlugin.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizard", "Clients\PrinterSetupWizard\PrinterSetupWizard.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLL.NET", "mDNSWindows\DLL.NET\dnssd_NET.vcproj", "{9C6701E2-82B7-44B7-9B5E-3897D9153F79}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       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", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizardRes", "Clients\PrinterSetupWizard\PrinterSetupWizardRes.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginLocRes", "Clients\ExplorerPlugin\ExplorerPluginLocRes.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginRes", "Clients\ExplorerPlugin\ExplorerPluginRes.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dns-sd", "Clients\DNS-SD.VisualStudio\dns-sd.vcproj", "{AA230639-E115-4A44-AA5A-44A61235BA50}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Java", "mDNSWindows\Java\Java.vcproj", "{9CE2568A-3170-41C6-9F20-A0188A9EC114}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {AB581101-18F0-46F6-B56A-83A6B1EA657E} = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JavaSamples", "Clients\Java\JavaSamples.vcproj", "{A987A0C1-344F-475C-869C-F082EB11EEBA}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114} = {9CE2568A-3170-41C6-9F20-A0188A9EC114}\r
+       EndProjectSection\r
 EndProject\r
 Global\r
        GlobalSection(SolutionConfiguration) = preSolution\r
-               ConfigName.0 = Debug\r
-               ConfigName.1 = Release\r
-       EndGlobalSection\r
-       GlobalSection(ProjectDependencies) = postSolution\r
-               {F4F15529-F0EB-402F-8662-73C5797EE557}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
-               {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
-               {BB8AC1B5-6587-4163-BDC6-788B157705CA}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+               Debug = Debug\r
+               Release = Release\r
        EndGlobalSection\r
        GlobalSection(ProjectConfiguration) = postSolution\r
                {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug.ActiveCfg = Debug|Win32\r
@@ -92,6 +127,14 @@ Global
                {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug.Build.0 = Debug|Win32\r
                {AA230639-E115-4A44-AA5A-44A61235BA50}.Release.ActiveCfg = Release|Win32\r
                {AA230639-E115-4A44-AA5A-44A61235BA50}.Release.Build.0 = Release|Win32\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Debug.ActiveCfg = Debug|Win32\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Debug.Build.0 = Debug|Win32\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release.ActiveCfg = Release|Win32\r
+               {9CE2568A-3170-41C6-9F20-A0188A9EC114}.Release.Build.0 = Release|Win32\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug.ActiveCfg = Debug|Win32\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Debug.Build.0 = Debug|Win32\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Release.ActiveCfg = Release|Win32\r
+               {A987A0C1-344F-475C-869C-F082EB11EEBA}.Release.Build.0 = Release|Win32\r
        EndGlobalSection\r
        GlobalSection(ExtensibilityGlobals) = postSolution\r
        EndGlobalSection\r
index d8a7ce1aba660215aef13e99c99cb2a7ce414b4c..50d29e411e7e2722ef69255afa867780652ffe4d 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: DNSSD.java,v $
+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
 
@@ -652,8 +655,8 @@ class       AppleService implements DNSSDService, Runnable
 
        public void                             stop() { this.HaltOperation(); }
 
-       /* Block for timeout ms (or forever if -1). Returns 1 if data present, 0 if timed out, -1 if not browsing. */
-       protected native int    BlockForData( int msTimeout);
+       /* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */
+       protected native int    BlockForData();
 
        /* Call ProcessResults when data appears on socket descriptor. */
        protected native int    ProcessResults();
@@ -672,7 +675,9 @@ class       AppleService implements DNSSDService, Runnable
        {
                while ( true )
                {
-                       // We have to be very careful here. Suppose our DNS-SD operation is stopped from some other thread,
+                       // Note: We want to allow our DNS-SD operation to be stopped from other threads, so we have to
+                       // block waiting for data *outside* the synchronized section. Because we're doing this unsynchronized
+                       // we have to write some careful code. Suppose our DNS-SD operation is stopped from some other thread,
                        // and then immediately afterwards that thread (or some third, unrelated thread) starts a new DNS-SD
                        // operation. The Unix kernel always allocates the lowest available file descriptor to a new socket,
                        // so the same file descriptor is highly likely to be reused for the new operation, and if our old
@@ -691,11 +696,11 @@ class     AppleService implements DNSSDService, Runnable
                        // locking DOESN'T prevent the callback routine from stopping its own operation, but DOES prevent
                        // any other thread from stopping it until after the callback has completed and returned to us here.
 
-                       int result = BlockForData(-1);
-                       if (result != 1) break; // If socket has been closed, time to terminate this thread
+                       int result = BlockForData();
                        synchronized (this)
                        {
                                if (fNativeContext == 0) break; // Some other thread stopped our DNSSD operation; time to terminate this thread
+                               if (result == 0) continue;              // If BlockForData() said there was no data, go back and block again
                                result = ProcessResults();
                                if (fNativeContext == 0) break; // Event listener stopped its own DNSSD operation; terminate this thread
                                if (result != 0) { fListener.operationFailed(this, result); break; }    // If error, notify listener
index 595e405463ffa02a8e9f9c620c6a4e62a8275ab7..0ab05875d402b3322509d113234b52ea4494af91 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: DNSSDException.java,v $
+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.
 
@@ -50,11 +53,23 @@ abstract public class       DNSSDException extends Exception
     public static final int            BAD_FLAGS           = -65543;
     public static final int            UNSUPPORTED         = -65544;
     public static final int            NOT_INITIALIZED     = -65545;
+    public static final int            NO_CACHE            = -65546;
     public static final int            ALREADY_REGISTERED  = -65547;
     public static final int            NAME_CONFLICT       = -65548;
     public static final int            INVALID             = -65549;
+    public static final int            FIREWALL            = -65550;
     public static final int            INCOMPATIBLE        = -65551;
     public static final int            BAD_INTERFACE_INDEX = -65552;
+    public static final int            REFUSED             = -65553;
+    public static final int            NOSUCHRECORD        = -65554;
+    public static final int            NOAUTH              = -65555;
+    public static final int            NOSUCHKEY           = -65556;
+    public static final int            NATTRAVERSAL        = -65557;
+    public static final int            DOUBLENAT           = -65558;
+    public static final int            BADTIME             = -65559;
+    public static final int            BADSIG              = -65560;
+    public static final int            BADKEY              = -65561;
+    public static final int            TRANSIENT           = -65562;
 
        /** Returns the sub-code that identifies the particular error. */
        abstract public int                     getErrorCode();
index 902e85d02cefb95eb86823cbc54e1ec1cbabd158..d7c6243eb1798fc11a9d6642610c24e48c74c985 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: JNISupport.c,v $
+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
@@ -262,15 +265,13 @@ JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv *
 }
 
 
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis, jint msTimeout)
-/* Block for timeout ms (or forever if -1). Returns 1 if data present, 0 if timed out, -1 if not browsing. */
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis)
+/* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */
 {
-#if AUTO_CALLBACKS
-       return -1;                              // BlockForData() not supported with AUTO_CALLBACKS 
-#else // AUTO_CALLBACKS
+// BlockForData() not supported with AUTO_CALLBACKS 
+#if !AUTO_CALLBACKS
        jclass                  cls = (*pEnv)->GetObjectClass( pEnv, pThis);
        jfieldID                contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
-       jint                    rc = -1;
 
        if ( contextField != 0)
        {
@@ -279,18 +280,32 @@ JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *p
                {
                        fd_set                  readFDs;
                        int                             sd = DNSServiceRefSockFD( pContext->ServiceRef);
-                       struct timeval  timeout = { msTimeout / 1000, 10 * (msTimeout % 1000) };
-                       struct timeval  *pTimeout = msTimeout == -1 ? NULL : &timeout;
-                       
+                       struct timeval  timeout = { 1, 0 };
                        FD_ZERO( &readFDs);
                        FD_SET( sd, &readFDs);
 
-                       rc = select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, pTimeout);
+                       // Q: Why do we poll here?
+                       // A: Because there's no other thread-safe way to do it.
+                       // Mac OS X terminates a select() call if you close one of the sockets it's listening on, but Linux does not,
+                       // and arguably Linux is correct (See <http://www.ussg.iu.edu/hypermail/linux/kernel/0405.1/0418.html>)
+                       // The problem is that the Mac OS X behaviour assumes that it's okay for one thread to close a socket while
+                       // some other thread is monitoring that socket in select(), but the difficulty is that there's no general way
+                       // to make that thread-safe, because there's no atomic way to enter select() and release a lock simultaneously.
+                       // If we try to do this without holding any lock, then right as we jump to the select() routine,
+                       // some other thread could stop our operation (thereby closing the socket),
+                       // and then that thread (or even some third, unrelated thread)
+                       // could do some other DNS-SD operation (or some other operation that opens a new file descriptor)
+                       // and then we'd blindly resume our fall into the select() call, now blocking on a file descriptor
+                       // that may coincidentally have the same numerical value, but is semantically unrelated
+                       // to the true file descriptor we thought we were blocking on.
+                       // We can't stop this race condition from happening, but at least if we wake up once a second we can detect
+                       // when fNativeContext has gone to zero, and thereby discover that we were blocking on the wrong fd.
+
+                       if (select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout) == 1) return(1);
                }
        }
-
-       return rc;
-#endif // AUTO_CALLBACKS
+#endif // !AUTO_CALLBACKS
+       return(0);
 }
 
 
index 27b14175c2cf868ddd83d328ecf0aeb15e07ebc9..6ec40da052ad9c2a8856cb36a3e852db4e4f1d79 100644 (file)
@@ -3,14 +3,14 @@
  * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
 
     Change History (most recent first):
 
 $Log: PlatformCommon.c,v $
+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
 
@@ -44,7 +48,7 @@ Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
 #include <stdio.h>                             // Needed for fopen() etc.
 #include <unistd.h>                            // Needed for close()
 #include <string.h>                            // Needed for strlen() etc.
-#include <sys/errno.h>                 // Needed for errno etc.
+#include <errno.h>                     // Needed for errno etc.
 #include <sys/socket.h>                        // Needed for socket() etc.
 #include <netinet/in.h>                        // Needed for sockaddr_in
 
index 624c3702e764d8e292458b1cfe9fa239c318ff6a..46a672ad66b4b591347dd11f526fbabfc8c9a1b2 100644 (file)
@@ -3,14 +3,14 @@
  * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -18,7 +18,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
 
     Change History (most recent first):
index 3611200db597036fc98a6f8bfb66e019fc779bab..6089ae655a07bafec13b1b50efb9dff2618b4cc4 100644 (file)
@@ -20,6 +20,9 @@
 .\" @APPLE_LICENSE_HEADER_END@
 .\"
 .\" $Log: dns-sd.1,v $
+.\" 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
 .\"
@@ -211,4 +214,4 @@ bugs are tracked in Apple Radar component "mDNSResponder".
 .Sh HISTORY
 The
 .Nm
-command first appeared in Mac OS X 10.3 (Panther).
+command first appeared in Mac OS X 10.4 (Tiger).
index 81e0856d9a42f76856ec5e51563804b1a440ea33..3fd58ef309c7d51048fabd519f90f1829617224d 100755 (executable)
 #endif
 
 /* standard calling convention under Win32 is __stdcall */
-#if defined(_WIN32)
+/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */
+/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */
+#if defined(_WIN32) && !defined(EFI32) && !defined(EFI64)
 #define DNSSD_API __stdcall
 #else
 #define DNSSD_API
 #endif
 
-#if defined(__FreeBSD_version) && (__FreeBSD_version < 500000)
 /* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */
+#if defined(__FreeBSD_version) && (__FreeBSD_version < 500000)
 #include <sys/types.h>
+
+/* Likewise, on Sun, standard integer types are in sys/types.h */
 #elif defined(__sun__)
 #include <sys/types.h>
+
+/* EFI does not have stdint.h, or anything else equivalent */
+#elif defined(EFI32) || defined(EFI64)
+typedef UINT8       uint8_t;
+typedef INT8        int8_t;
+typedef UINT16      uint16_t;
+typedef INT16       int16_t;
+typedef UINT32      uint32_t;
+typedef INT32       int32_t;
+
+/* Windows has its own differences */
 #elif defined(_WIN32)
 #include <windows.h>
 #define _UNUSED
 #define bzero(a, b) memset(a, 0, b)
+#ifndef _MSL_STDINT_H
 typedef UINT8       uint8_t;
 typedef INT8        int8_t;
 typedef UINT16      uint16_t;
 typedef INT16       int16_t;
 typedef UINT32      uint32_t;
 typedef INT32       int32_t;
+#endif
+
+/* All other Posix platforms use stdint.h */
 #else
 #include <stdint.h>
 #endif
@@ -1298,7 +1317,7 @@ int DNSSD_API DNSServiceConstructFullName
  * Note: Represents a DNS-SD TXT record.
  */
 
-typedef struct _TXTRecordRef_t { char privatedata[16]; } TXTRecordRef;
+typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignment; } TXTRecordRef;
 
 
 /* TXTRecordCreate()
@@ -1661,6 +1680,17 @@ DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser
        
 #endif //__APPLE_API_PRIVATE
 
+// Some C compiler cleverness. We can make the compiler check certain things for us,
+// and report errors at compile-time if anything is wrong. The usual way to do this would
+// be to use a run-time "if" statement or the conventional run-time "assert" mechanism, but
+// then you don't find out what's wrong until you run the software. This way, if the assertion
+// condition is false, the array size is negative, and the complier complains immediately.
+
+struct DNS_SD_CompileTimeAssertionChecks
+       {
+       char assert0[(sizeof(union _TXTRecordRef_t) == 16) ? 1 : -1];
+       };
+
 #ifdef  __cplusplus
     }
 #endif
index 40ab0d0edbdbbf4a9c067e4e5f2c0bfcfe4f5fd4..6284b1e388170b1666fed01d5d72147fdea12b03 100755 (executable)
@@ -27,6 +27,9 @@
    Change History (most recent first):
 
 $Log: dnssd_clientlib.c,v $
+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)"
 
@@ -196,7 +199,7 @@ struct dnssd_clientlib_CompileTimeAssertionCheck
        char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1];
        };
 
-void TXTRecordCreate
+void DNSSD_API TXTRecordCreate
        (
        TXTRecordRef     *txtRecord,
        uint16_t         bufferLen,
@@ -209,12 +212,12 @@ void TXTRecordCreate
        txtRec->malloced = 0;
        }
 
-void TXTRecordDeallocate(TXTRecordRef *txtRecord)
+void DNSSD_API TXTRecordDeallocate(TXTRecordRef *txtRecord)
        {
        if (txtRec->malloced) free(txtRec->buffer);
        }
 
-DNSServiceErrorType TXTRecordSetValue
+DNSServiceErrorType DNSSD_API TXTRecordSetValue
        (
        TXTRecordRef     *txtRecord,
        const char       *key,
@@ -259,7 +262,7 @@ DNSServiceErrorType TXTRecordSetValue
        return(kDNSServiceErr_NoError);
        }
 
-DNSServiceErrorType TXTRecordRemoveValue
+DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
        (
        TXTRecordRef     *txtRecord,
        const char       *key
@@ -276,8 +279,8 @@ DNSServiceErrorType TXTRecordRemoveValue
        return(kDNSServiceErr_NoError);
        }
 
-uint16_t       TXTRecordGetLength  (const TXTRecordRef *txtRecord) { return(txtRec->datalen); }
-const void *   TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtRec->buffer); }
+uint16_t DNSSD_API TXTRecordGetLength  (const TXTRecordRef *txtRecord) { return(txtRec->datalen); }
+const void * DNSSD_API TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtRec->buffer); }
 
 /*********************************************************************************************
  *
@@ -285,7 +288,7 @@ const void *   TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtR
  *
  *********************************************************************************************/
 
-int TXTRecordContainsKey
+int DNSSD_API TXTRecordContainsKey
        (
        uint16_t         txtLen,
        const void       *txtRecord,
@@ -296,7 +299,7 @@ int TXTRecordContainsKey
        return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0);
        }
 
-const void * TXTRecordGetValuePtr
+const void * DNSSD_API TXTRecordGetValuePtr
        (
        uint16_t         txtLen,
        const void       *txtRecord,
@@ -311,7 +314,7 @@ const void * TXTRecordGetValuePtr
        return (item + 1 + keylen + 1);
        }
 
-uint16_t TXTRecordGetCount
+uint16_t DNSSD_API TXTRecordGetCount
        (
        uint16_t         txtLen,
        const void       *txtRecord
@@ -324,7 +327,7 @@ uint16_t TXTRecordGetCount
        return((p>e) ? (uint16_t)0 : count);
        }
 
-DNSServiceErrorType TXTRecordGetItemAtIndex
+DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
        (
        uint16_t         txtLen,
        const void       *txtRecord,
index 8cf98d32bae83e344404bf7c1ad0715f625f45fc..b5582592127c18ebcddff69a11d2332397becce4 100755 (executable)
     Change History (most recent first):
 
 $Log: dnssd_clientstub.c,v $
+Revision 1.48  2005/06/30 18:01:00  shersche
+<rdar://problem/4096913> Clients shouldn't wait ten seconds to connect to mDNSResponder
+
+Revision 1.47  2005/03/31 02:19:56  cheshire
+<rdar://problem/4021486> Fix build warnings
+Reviewed by: Scott Herscher
+
+Revision 1.46  2005/03/21 00:39:31  shersche
+<rdar://problem/4021486> Fix build warnings on Win32 platform
+
 Revision 1.45  2005/02/01 01:25:06  shersche
 Define sleep() to be Sleep() for Windows compatibility
 
@@ -171,6 +181,8 @@ Update to APSL 2.0
 #include <windows.h>
 #define sockaddr_mdns sockaddr_in
 #define AF_MDNS AF_INET
+extern BOOL
+IsSystemServiceDisabled();
 #else
 #include <sys/time.h>
 #include <sys/socket.h>
@@ -195,6 +207,11 @@ static int g_initWinsock = 0;
 #endif
 
 
+// <rdar://problem/4096913> Specifies how many times we'll try and connect to the
+// server.
+
+#define DNSSD_CLIENT_MAXTRIES  4
+
 #define CTL_PATH_PREFIX "/tmp/dnssd_clippath."
 // error socket (if needed) is named "dnssd_clipath.[pid].xxx:n" where xxx are the
 // last 3 digits of the time (in seconds) and n is the 6-digit microsecond time
@@ -266,7 +283,9 @@ static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int
     char *msg = NULL;
     ipc_msg_hdr *hdr;
     int datalen;
+#if !defined(USE_TCP_LOOPBACK)
     char ctrl_path[256];
+#endif
 
     if (!reuse_socket)
         {
@@ -325,6 +344,15 @@ static DNSServiceRef connect_to_server(void)
 
                if (err != 0) return NULL;
                }
+
+       // <rdar://problem/4096913> If the system service is disabled, we only want to try 
+       // to connect once
+
+       if ( IsSystemServiceDisabled() )
+               {
+               NumTries = DNSSD_CLIENT_MAXTRIES;
+               }
+
 #endif
 
        sdr = malloc(sizeof(_DNSServiceRef_t));
@@ -346,9 +374,9 @@ static DNSServiceRef connect_to_server(void)
                // If we failed, then it may be because the daemon is still launching.
                // This can happen for processes that launch early in the boot process, while the
                // daemon is still coming up. Rather than fail here, we'll wait a bit and try again.
-               // If, after ten seconds, we still can't connect to the daemon,
+               // If, after four seconds, we still can't connect to the daemon,
                // then we give up and return a failure code.
-               if (++NumTries < 10)
+               if (++NumTries < DNSSD_CLIENT_MAXTRIES)
                        sleep(1);               // Sleep a bit, then try again
                else
                        {
@@ -369,7 +397,7 @@ static DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reu
     char *data = (char *)msg + sizeof(ipc_msg_hdr);
     dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
        int ret;
-       unsigned int len = sizeof(caddr);
+       dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
     DNSServiceErrorType err = kDNSServiceErr_Unknown;
 
     if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown;
index a04eaccc3096f2827ac99fadd3b8cb0b5c6d7d89..32d7872e1c420ef71f4b427acd3c2fdb439514ce 100644 (file)
@@ -27,6 +27,9 @@
     Change History (most recent first):
 
 $Log: dnssd_ipc.h,v $
+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
 
@@ -90,7 +93,6 @@ Update to APSL 2.0
 #      define dnssd_InvalidSocket      INVALID_SOCKET
 #      define dnssd_EWOULDBLOCK        WSAEWOULDBLOCK
 #      define dnssd_EINTR                      WSAEINTR
-#      define MSG_WAITALL                      0
 #      define dnssd_sock_t                     SOCKET
 #      define dnssd_socklen_t          int
 #      define dnssd_sockbuf_t          const char*
index 406b7ab520ed7370d002c22789cbbcd0097d0937..9ba0ccc53e57e495cd17491680dc57941f7efcc2 100644 (file)
     Change History (most recent first):
 
 $Log: uds_daemon.c,v $
+Revision 1.189  2006/01/06 00:56:31  cheshire
+<rdar://problem/4400573> Should remove PID file on exit
+
+Revision 1.188  2005/10/11 22:15:03  cheshire
+<rdar://problem/4296042> Add memory corruption safeguards to uds_daemon.c
+Only compile uds_validatelists() when building for Mac OS X
+
+Revision 1.187  2005/10/11 20:30:27  cheshire
+<rdar://problem/4296042> Add memory corruption safeguards to uds_daemon.c
+
+Revision 1.186  2005/09/12 07:11:53  herscher
+<rdar://problem/4248878> Lazily call RegisterSearchDomains to workaround crashes of several routers. This code is conditionally compiled, and currently is only enabled on Windows platforms.
+
+Revision 1.185  2005/07/29 00:55:10  ksekar
+Removed validation check in uds_validatelists which generated false alarms
+
+Revision 1.184  2005/07/04 22:40:26  cheshire
+Additional debugging code to help catch memory corruption
+
 Revision 1.183  2005/06/13 22:39:11  cheshire
 <rdar://problem/4144870> Missing return statement in handle_enum_request() error handling
 
@@ -590,9 +609,10 @@ Update to APSL 2.0
 
 #if defined(_WIN32)
 #include <process.h>
+#define MDNS_LAZY_REGISTER_SEARCH_DOMAINS
 #define dnssd_strerror(X)      win32_strerror(X)
 #define usleep(X)                              Sleep(((X)+999)/1000)
-static char * win32_strerror(int inErrorCode);
+static char *  win32_strerror(int inErrorCode);
 #else
 #include <fcntl.h>
 #include <errno.h>
@@ -619,6 +639,10 @@ static char * win32_strerror(int inErrorCode);
 #endif // LOCAL_PEERCRED
 #endif //__MACOSX__
 
+#if defined(MDNS_LAZY_REGISTER_SEARCH_DOMAINS)
+extern mStatus dDNS_RegisterSearchDomains( mDNS * const m );
+#endif
+
 // Types and Data Structures
 // ----------------------------------------------------------------------
 
@@ -819,53 +843,53 @@ static request_state      *       all_requests    =       NULL;
 #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
 // private function prototypes
-static void connect_callback(void *info);
-static int read_msg(request_state *rs);
-static int send_msg(reply_state *rs);
-static void abort_request(request_state *rs);
-static void request_callback(void *info);
-static void handle_resolve_request(request_state *rstate);
-static void question_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
-static void question_termination_callback(void *context);
-static void handle_browse_request(request_state *request);
-static void browse_termination_callback(void *context);
-static void browse_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
-static void handle_regservice_request(request_state *request);
-static void regservice_termination_callback(void *context);
-static void process_service_registration(ServiceRecordSet *const srs, mDNSBool SuppressError);
-static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
-static mStatus handle_add_request(request_state *rstate);
-static mStatus handle_update_request(request_state *rstate);
-static mStatus gen_rr_response(domainname *servicename, mDNSInterfaceID id, request_state *request, reply_state **rep);
-static void append_reply(request_state *req, reply_state *rep);
-static int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain);
-static void enum_termination_callback(void *context);
-static void enum_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
-static void handle_query_request(request_state *rstate);
-static reply_state *format_enumeration_reply(request_state *rstate, const char *domain, DNSServiceFlags flags, uint32_t ifi, DNSServiceErrorType err);
-static void handle_enum_request(request_state *rstate);
-static mStatus handle_regrecord_request(request_state *rstate);
-static void regrecord_callback(mDNS *const m, AuthRecord * rr, mStatus result);
-static void connected_registration_termination(void *context);
-static void handle_reconfirm_request(request_state *rstate);
-static AuthRecord *read_rr_from_ipc_msg(char *msgbuf, int ttl, int validate_flags);
-static mStatus handle_removerecord_request(request_state *rstate);
-static void reset_connected_rstate(request_state *rstate);
-static int deliver_error(request_state *rstate, mStatus err);
-static int deliver_async_error(request_state *rs, reply_op_t op, mStatus err);
-static transfer_state send_undelivered_error(request_state *rs);
-static reply_state *create_reply(reply_op_t op, size_t datalen, request_state *request);
-static void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd);
-static void my_perror(char *errmsg);
-static void unlink_request(request_state *rs);
-static void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
-static void resolve_termination_callback(void *context);
-static int validate_message(request_state *rstate);
-static mStatus remove_extra(request_state *rstate, service_instance *serv);
-static mStatus remove_record(request_state *rstate);
-static void free_service_instance(service_instance *srv);
-static uint32_t dnssd_htonl(uint32_t l);
-static void handle_setdomain_request(request_state *rstate);
+mDNSlocal void connect_callback(void *info);
+mDNSlocal int read_msg(request_state *rs);
+mDNSlocal int send_msg(reply_state *rs);
+mDNSlocal void abort_request(request_state *rs);
+mDNSlocal void request_callback(void *info);
+mDNSlocal void handle_resolve_request(request_state *rstate);
+mDNSlocal void question_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
+mDNSlocal void question_termination_callback(void *context);
+mDNSlocal void handle_browse_request(request_state *request);
+mDNSlocal void browse_termination_callback(void *context);
+mDNSlocal void browse_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
+mDNSlocal void handle_regservice_request(request_state *request);
+mDNSlocal void regservice_termination_callback(void *context);
+mDNSlocal void process_service_registration(ServiceRecordSet *const srs, mDNSBool SuppressError);
+mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
+mDNSlocal mStatus handle_add_request(request_state *rstate);
+mDNSlocal mStatus handle_update_request(request_state *rstate);
+mDNSlocal mStatus gen_rr_response(domainname *servicename, mDNSInterfaceID id, request_state *request, reply_state **rep);
+mDNSlocal void append_reply(request_state *req, reply_state *rep);
+mDNSlocal int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain);
+mDNSlocal void enum_termination_callback(void *context);
+mDNSlocal void enum_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
+mDNSlocal void handle_query_request(request_state *rstate);
+mDNSlocal reply_state *format_enumeration_reply(request_state *rstate, const char *domain, DNSServiceFlags flags, uint32_t ifi, DNSServiceErrorType err);
+mDNSlocal void handle_enum_request(request_state *rstate);
+mDNSlocal mStatus handle_regrecord_request(request_state *rstate);
+mDNSlocal void regrecord_callback(mDNS *const m, AuthRecord * rr, mStatus result);
+mDNSlocal void connected_registration_termination(void *context);
+mDNSlocal void handle_reconfirm_request(request_state *rstate);
+mDNSlocal AuthRecord *read_rr_from_ipc_msg(char *msgbuf, int ttl, int validate_flags);
+mDNSlocal mStatus handle_removerecord_request(request_state *rstate);
+mDNSlocal void reset_connected_rstate(request_state *rstate);
+mDNSlocal int deliver_error(request_state *rstate, mStatus err);
+mDNSlocal int deliver_async_error(request_state *rs, reply_op_t op, mStatus err);
+mDNSlocal transfer_state send_undelivered_error(request_state *rs);
+mDNSlocal reply_state *create_reply(reply_op_t op, size_t datalen, request_state *request);
+mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd);
+mDNSlocal void my_perror(char *errmsg);
+mDNSlocal void unlink_request(request_state *rs);
+mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
+mDNSlocal void resolve_termination_callback(void *context);
+mDNSlocal int validate_message(request_state *rstate);
+mDNSlocal mStatus remove_extra(request_state *rstate, service_instance *serv);
+mDNSlocal mStatus remove_record(request_state *rstate);
+mDNSlocal void free_service_instance(service_instance *srv);
+mDNSlocal uint32_t dnssd_htonl(uint32_t l);
+mDNSlocal void handle_setdomain_request(request_state *rstate);
 
 // initialization, setup/teardown functions
 
@@ -900,7 +924,7 @@ mDNSlocal void LogClientInfo(request_state *req)
                }
        }
 
-static void FatalError(char *errmsg)
+mDNSlocal void FatalError(char *errmsg)
        {
        LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno()));
        *(long*)0 = 0;  // On OS X abort() doesn't generate a crash log, but writing to zero does
@@ -1037,6 +1061,8 @@ int udsserver_exit(void)
                debugf("Unable to remove %s", MDNS_UDS_SERVERPATH);
 #endif
 
+       if (PID_FILE[0]) unlink(PID_FILE);
+
     return 0;
     }
 
@@ -1088,7 +1114,7 @@ mDNSs32 udsserver_idle(mDNSs32 nextevent)
                        else if (nextevent - now > mDNSPlatformOneSecond) nextevent = now + mDNSPlatformOneSecond;  // try again in a second
                        }
         if (result == t_terminated || result == t_error)
-        //since we're already doing a list traversal, we unlink the request manunally instead of calling unlink_request()
+        //since we're already doing a list traversal, we unlink the request manually instead of calling unlink_request()
             {
             tmp = req;
             if (prev) prev->next = req->next;
@@ -1105,7 +1131,7 @@ mDNSs32 udsserver_idle(mDNSs32 nextevent)
     return nextevent;
     }
 
-void udsserver_info(mDNS *const m)
+mDNSexport void udsserver_info(mDNS *const m)
     {
        mDNSs32 now = mDNS_TimeNow(m);
        mDNSu32 CacheUsed = 0, CacheActive = 0;
@@ -1146,7 +1172,17 @@ void udsserver_info(mDNS *const m)
     LogMsgNoIdent("Timenow 0x%08lX (%ld)", (mDNSu32)now, now);
     }
 
-static void rename_service(service_instance *srv)
+#if __MACOSX__ && MACOSX_MDNS_MALLOC_DEBUGGING
+mDNSexport void uds_validatelists(void)
+       {
+       request_state *req;
+       for (req = all_requests; req; req=req->next)
+               if (req->sd < 0 && req->sd != -2)
+                       LogMemCorruption("UDS request list: %p is garbage (%X)", req, req->sd);
+       }
+#endif
+
+mDNSlocal void rename_service(service_instance *srv)
        {
        if (srv->autoname && !SameDomainLabel(srv->name.c, gmDNS->nicelabel.c))
                {
@@ -1156,11 +1192,10 @@ static void rename_service(service_instance *srv)
                }
        }
 
-void udsserver_handle_configchange(void)
+mDNSexport void udsserver_handle_configchange(void)
     {
     request_state *req;
 
-    
     for (req = all_requests; req; req = req->next)
         {
                if (req->service_registration)
@@ -1172,7 +1207,7 @@ void udsserver_handle_configchange(void)
                }
     }
 
-static void connect_callback(void *info)
+mDNSlocal void connect_callback(void *info)
     {
     dnssd_sock_t sd;
        dnssd_socklen_t len;
@@ -1229,7 +1264,7 @@ static void connect_callback(void *info)
     }
 
 // handler
-static void request_callback(void *info)
+mDNSlocal void request_callback(void *info)
        {
        request_state *rstate = info;
        transfer_state result;
@@ -1381,7 +1416,7 @@ static void request_callback(void *info)
 // massage the name parameters appropriately, but the rest of the operations (making the query call,
 // delivering the result to the client, and termination) are identical.
 
-static void handle_query_request(request_state *rstate)
+mDNSlocal void handle_query_request(request_state *rstate)
     {
     DNSServiceFlags flags;
     uint32_t ifi;
@@ -1447,7 +1482,7 @@ error:
     return;
     }
 
-static void handle_resolve_request(request_state *rstate)
+mDNSlocal void handle_resolve_request(request_state *rstate)
     {
     DNSServiceFlags flags;
     uint32_t interfaceIndex;
@@ -1547,7 +1582,7 @@ bad_param:
     unlink_request(rstate);
     }
     
-static void resolve_termination_callback(void *context)
+mDNSlocal void resolve_termination_callback(void *context)
     {
     resolve_termination_t *term = context;
     request_state *rs;
@@ -1567,7 +1602,7 @@ static void resolve_termination_callback(void *context)
     rs->termination_context = NULL;
     }
 
-static void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
 {
     size_t len = 0;
     char fullname[MAX_ESCAPED_DOMAIN_NAME], target[MAX_ESCAPED_DOMAIN_NAME];
@@ -1650,7 +1685,7 @@ static void resolve_result_callback(mDNS *const m, DNSQuestion *question, const
     }
 
 // what gets called when a resolve is completed and we need to send the data back to the client
-static void question_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void question_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
     {
     char *data;
     char name[MAX_ESCAPED_DOMAIN_NAME];
@@ -1690,7 +1725,7 @@ static void question_result_callback(mDNS *const m, DNSQuestion *question, const
     return;
     }
 
-static void question_termination_callback(void *context)
+mDNSlocal void question_termination_callback(void *context)
     {
     DNSQuestion *q = context;
        LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) STOP", ((request_state *)q->QuestionContext)->sd, q->qname.c, DNSTypeName(q->qtype));
@@ -1701,7 +1736,7 @@ static void question_termination_callback(void *context)
 // If there's a comma followed by another character,
 // FindFirstSubType overwrites the comma with a nul and returns the pointer to the next character.
 // Otherwise, it returns a pointer to the final nul at the end of the string
-static char *FindFirstSubType(char *p)
+mDNSlocal char *FindFirstSubType(char *p)
        {
        while (*p)
                {
@@ -1716,7 +1751,7 @@ static char *FindFirstSubType(char *p)
 // FindNextSubType overwrites the comma with a nul and returns the pointer to the next character.
 // If it finds an illegal unescaped dot in the subtype name, it returns mDNSNULL
 // Otherwise, it returns a pointer to the final nul at the end of the string
-static char *FindNextSubType(char *p)
+mDNSlocal char *FindNextSubType(char *p)
        {
        while (*p)
                {
@@ -1770,14 +1805,14 @@ mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p)
        }
 
 #ifdef _HAVE_SETDOMAIN_SUPPORT_
-static void free_defdomain(mDNS *const m, AuthRecord *const rr, mStatus result)
+mDNSlocal void free_defdomain(mDNS *const m, AuthRecord *const rr, mStatus result)
        {
        (void)m;  // unused
        if (result == mStatus_MemFree) free(rr->RecordContext);  // context is the enclosing list structure
        }
 #endif
 
-static void handle_setdomain_request(request_state *request)
+mDNSlocal void handle_setdomain_request(request_state *request)
        {
        mStatus err = mStatus_NoError;
        char *ptr;
@@ -1866,7 +1901,7 @@ static void handle_setdomain_request(request_state *request)
     unlink_request(request);
     }
 
-static mStatus add_domain_to_browser(browser_info_t *info, const domainname *d)
+mDNSlocal mStatus add_domain_to_browser(browser_info_t *info, const domainname *d)
        {
        browser_t *b, *p;
        mStatus err;
@@ -1894,7 +1929,7 @@ static mStatus add_domain_to_browser(browser_info_t *info, const domainname *d)
                return err;
        }
 
-static void handle_browse_request(request_state *request)
+mDNSlocal void handle_browse_request(request_state *request)
     {
     DNSServiceFlags flags;
     uint32_t interfaceIndex;
@@ -1928,6 +1963,13 @@ static void handle_browse_request(request_state *request)
     InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(gmDNS, interfaceIndex);
     if (interfaceIndex && !InterfaceID) { err = mStatus_BadParamErr;  goto error; }
 
+#if defined(MDNS_LAZY_REGISTER_SEARCH_DOMAINS)
+       if ( !domain || ( domain[0] == '\0' ) )
+               {
+               dDNS_RegisterSearchDomains( gmDNS );
+               }
+#endif
+               
        typedn.c[0] = 0;
        NumSubTypes = ChopSubTypes(regtype);    // Note: Modifies regtype string to remove trailing subtypes
        if (NumSubTypes < 0 || NumSubTypes > 1) { err = mStatus_BadParamErr;  goto error; }
@@ -1989,7 +2031,7 @@ error:
     unlink_request(request);
     }
 
-static void browse_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void browse_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
     {
     request_state *req = question->QuestionContext;
     reply_state *rep;
@@ -2013,7 +2055,7 @@ static void browse_result_callback(mDNS *const m, DNSQuestion *question, const R
     return;
     }
 
-static void browse_termination_callback(void *context)
+mDNSlocal void browse_termination_callback(void *context)
     {
        browser_info_t *info = context;
        browser_t *ptr;
@@ -2108,7 +2150,7 @@ mDNSexport int CountExistingRegistrations(domainname *srv, mDNSIPPort port)
        return(count);
        }
 
-static mStatus register_service_instance(request_state *request, const domainname *domain)
+mDNSlocal mStatus register_service_instance(request_state *request, const domainname *domain)
        {
        service_info *info = request->service_registration;
        service_instance *ptr, *instance;
@@ -2193,7 +2235,7 @@ mDNSexport void udsserver_default_reg_domain_changed(const domainname *d, mDNSBo
        }
 
 // service registration
-static void handle_regservice_request(request_state *request)
+mDNSlocal void handle_regservice_request(request_state *request)
     {
     DNSServiceFlags flags;
     uint32_t ifi;
@@ -2246,7 +2288,7 @@ static void handle_regservice_request(request_state *request)
                if (!service->txtdata) { my_perror("ERROR: malloc"); result = mStatus_NoMemoryErr; goto finish; }
                memcpy(service->txtdata, get_rdata(&ptr, service->txtlen), service->txtlen);
                }
-       else service->txtdata = NULL;              
+       else service->txtdata = NULL;
 
        // Check for sub-types after the service type
        service->num_subtypes = ChopSubTypes(service->type_as_string);  // Note: Modifies regtype string to remove trailing subtypes
@@ -2342,7 +2384,7 @@ bad_param:
 // handles name conflicts, and delivers completed registration information to the client (via
 // process_service_registraion())
 
-static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
+mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
     {
     mStatus err;
        mDNSBool SuppressError = mDNSfalse;
@@ -2356,7 +2398,7 @@ static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mSta
                service_info *info = instance->request->service_registration;
                if (info->default_domain && !instance->default_local) SuppressError = mDNStrue;
         // don't send errors up to client for wide-area, empty-string registrations
-               }                       
+               }
        
     if (result == mStatus_NoError)
                LogOperation("%3d: DNSServiceRegister(%##s, %u) REGISTERED  ",  instance->sd, srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port));
@@ -2453,7 +2495,7 @@ mDNSexport void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result)
        freeL("ExtraResourceRecord", extra);
        }
 
-static mStatus add_record_to_service(request_state *rstate, service_instance *instance, uint16_t rrtype, uint16_t rdlen, char *rdata, uint32_t ttl)
+mDNSlocal mStatus add_record_to_service(request_state *rstate, service_instance *instance, uint16_t rrtype, uint16_t rdlen, char *rdata, uint32_t ttl)
        {
        ServiceRecordSet *srs = &instance->srs;
     ExtraResourceRecord *extra;
@@ -2483,7 +2525,7 @@ static mStatus add_record_to_service(request_state *rstate, service_instance *in
        return result;
        }
 
-static mStatus handle_add_request(request_state *rstate)
+mDNSlocal mStatus handle_add_request(request_state *rstate)
     {
     uint32_t ttl;
     uint16_t rrtype, rdlen;
@@ -2517,7 +2559,7 @@ static mStatus handle_add_request(request_state *rstate)
        return(result);
     }
 
-static mStatus update_record(AuthRecord *rr, uint16_t rdlen, char *rdata, uint32_t ttl)
+mDNSlocal mStatus update_record(AuthRecord *rr, uint16_t rdlen, char *rdata, uint32_t ttl)
        {
        int rdsize;
        RData *newrd;
@@ -2540,7 +2582,7 @@ static mStatus update_record(AuthRecord *rr, uint16_t rdlen, char *rdata, uint32
        return result;
        }
 
-static mStatus handle_update_request(request_state *rstate)
+mDNSlocal mStatus handle_update_request(request_state *rstate)
     {
        uint16_t rdlen;
     char *ptr, *rdata;
@@ -2599,13 +2641,13 @@ end:
     return(result);
     }
     
-static void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd)
+mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd)
     {
     (void)m; // Unused
     if (oldrd != &rr->rdatastorage) freeL("update_callback", oldrd);
     }
     
-static void process_service_registration(ServiceRecordSet *const srs, mDNSBool SuppressError)
+mDNSlocal void process_service_registration(ServiceRecordSet *const srs, mDNSBool SuppressError)
     {
     reply_state *rep;
     transfer_state send_result;
@@ -2635,7 +2677,7 @@ static void process_service_registration(ServiceRecordSet *const srs, mDNSBool S
     else append_reply(req, rep);
     }
 
-static void free_service_instance(service_instance *srv)
+mDNSlocal void free_service_instance(service_instance *srv)
        {
        request_state *rstate = srv->request;
        ExtraResourceRecord *e = srv->srs.Extras, *tmp;
@@ -2669,7 +2711,7 @@ static void free_service_instance(service_instance *srv)
        freeL("regservice_callback", srv);
        }
 
-static void regservice_termination_callback(void *context)
+mDNSlocal void regservice_termination_callback(void *context)
     {
        service_info *info = context;
        service_instance *i, *p;
@@ -2690,7 +2732,7 @@ static void regservice_termination_callback(void *context)
        freeL("service_info", info);
        }
 
-static mStatus handle_regrecord_request(request_state *rstate)
+mDNSlocal mStatus handle_regrecord_request(request_state *rstate)
     {
     AuthRecord *rr;
     registered_record_entry *re;
@@ -2733,7 +2775,7 @@ static mStatus handle_regrecord_request(request_state *rstate)
     return(result);
     }
 
-static void regrecord_callback(mDNS *const m, AuthRecord * rr, mStatus result)
+mDNSlocal void regrecord_callback(mDNS *const m, AuthRecord * rr, mStatus result)
     {
     registered_record_entry *re = rr->RecordContext;
        request_state *rstate = re ? re->rstate : NULL;
@@ -2785,7 +2827,7 @@ static void regrecord_callback(mDNS *const m, AuthRecord * rr, mStatus result)
     else if (ts == t_morecoming) append_reply(rstate, reply);   // client is blocked, link reply into list
        }
 
-static void connected_registration_termination(void *context)
+mDNSlocal void connected_registration_termination(void *context)
     {
     int shared;
     registered_record_entry *fptr, *ptr = ((request_state *)context)->reg_recs;
@@ -2800,7 +2842,7 @@ static void connected_registration_termination(void *context)
                }
        }
     
-static mStatus handle_removerecord_request(request_state *rstate)
+mDNSlocal mStatus handle_removerecord_request(request_state *rstate)
     {
     mStatus err = mStatus_BadReferenceErr;
     char *ptr;
@@ -2828,7 +2870,7 @@ static mStatus handle_removerecord_request(request_state *rstate)
     }
 
 // remove a resource record registered via DNSServiceRegisterRecord()
-static mStatus remove_record(request_state *rstate)
+mDNSlocal mStatus remove_record(request_state *rstate)
     {
     int shared;
     mStatus err = mStatus_UnknownErr;
@@ -2852,7 +2894,7 @@ static mStatus remove_record(request_state *rstate)
        return err;
     }
 
-static mStatus remove_extra(request_state *rstate, service_instance *serv)
+mDNSlocal mStatus remove_extra(request_state *rstate, service_instance *serv)
        {
        mStatus err = mStatus_BadReferenceErr;
        ExtraResourceRecord *ptr;
@@ -2866,7 +2908,7 @@ static mStatus remove_extra(request_state *rstate, service_instance *serv)
        }
 
 // domain enumeration
-static void handle_enum_request(request_state *rstate)
+mDNSlocal void handle_enum_request(request_state *rstate)
     {
     DNSServiceFlags flags;
     uint32_t ifi;
@@ -2902,6 +2944,10 @@ static void handle_enum_request(request_state *rstate)
     term = mallocL("handle_enum_request", sizeof(enum_termination_t));
     if (!def || !all || !term) FatalError("ERROR: malloc");
 
+#if defined(MDNS_LAZY_REGISTER_SEARCH_DOMAINS)
+       dDNS_RegisterSearchDomains( gmDNS );
+#endif
+               
     // enumeration requires multiple questions, so we must link all the context pointers so that
     // necessary context can be reached from the callbacks
     def->rstate = rstate;
@@ -2938,7 +2984,7 @@ static void handle_enum_request(request_state *rstate)
         }
     }
 
-static void enum_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void enum_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
     {
     char domain[MAX_ESCAPED_DOMAIN_NAME];
     domain_enum_t *de = question->QuestionContext;
@@ -2954,7 +3000,7 @@ static void enum_result_callback(mDNS *const m, DNSQuestion *question, const Res
         flags |= kDNSServiceFlagsAdd;
         if (de->type == mDNS_DomainTypeRegistrationDefault || de->type == mDNS_DomainTypeBrowseDefault)
             flags |= kDNSServiceFlagsDefault;
-       }       
+       }
     ConvertDomainNameToCString(&answer->rdata->u.name, domain);
        // note that we do NOT propagate specific interface indexes to the client - for example, a domain we learn from
        // a machine's system preferences may be discovered on the LocalOnly interface, but should be browsed on the
@@ -2970,18 +3016,17 @@ static void enum_result_callback(mDNS *const m, DNSQuestion *question, const Res
     return;
     }
 
-static reply_state *format_enumeration_reply(request_state *rstate, const char *domain, DNSServiceFlags flags, uint32_t ifi, DNSServiceErrorType err)
+mDNSlocal reply_state *format_enumeration_reply(request_state *rstate, const char *domain, DNSServiceFlags flags, uint32_t ifi, DNSServiceErrorType err)
     {
     size_t len;
     reply_state *reply;
     char *data;
-    
-    
+
     len = sizeof(DNSServiceFlags);
     len += sizeof(uint32_t);
     len += sizeof(DNSServiceErrorType);
     len += strlen(domain) + 1;
-  
+
     reply = create_reply(enumeration_reply, len, rstate);
     reply->rhdr->flags = dnssd_htonl(flags);
     reply->rhdr->ifi = dnssd_htonl(ifi);
@@ -2991,7 +3036,7 @@ static reply_state *format_enumeration_reply(request_state *rstate, const char *
     return reply;
     }
 
-static void enum_termination_callback(void *context)
+mDNSlocal void enum_termination_callback(void *context)
     {
     enum_termination_t *t = context;
     mDNS *coredata = gmDNS;
@@ -3004,7 +3049,7 @@ static void enum_termination_callback(void *context)
     freeL("enum_termination_callback", t);
     }
 
-static void handle_reconfirm_request(request_state *rstate)
+mDNSlocal void handle_reconfirm_request(request_state *rstate)
     {
     AuthRecord *rr;
 
@@ -3018,7 +3063,7 @@ static void handle_reconfirm_request(request_state *rstate)
     }
 
 // setup rstate to accept new reg/dereg requests
-static void reset_connected_rstate(request_state *rstate)
+mDNSlocal void reset_connected_rstate(request_state *rstate)
     {
     rstate->ts = t_morecoming;
     rstate->hdr_bytes = 0;
@@ -3031,7 +3076,7 @@ static void reset_connected_rstate(request_state *rstate)
 // returns a resource record (allocated w/ malloc) containing the data found in an IPC message
 // data must be in format flags, interfaceIndex, name, rrtype, rrclass, rdlen, rdata, (optional)ttl
 // (ttl only extracted/set if ttl argument is non-zero).  returns NULL for a bad-parameter error
-static AuthRecord *read_rr_from_ipc_msg(char *msgbuf, int GetTTL, int validate_flags)
+mDNSlocal AuthRecord *read_rr_from_ipc_msg(char *msgbuf, int GetTTL, int validate_flags)
     {
     char *rdata, name[256];
     AuthRecord *rr;
@@ -3092,7 +3137,7 @@ static AuthRecord *read_rr_from_ipc_msg(char *msgbuf, int GetTTL, int validate_f
 // identical callback signature.  on successful completion rep is set to point to a malloc'd reply_state struct,
 // and mStatus_NoError is returned.  otherwise the appropriate error is returned.
 
-static mStatus gen_rr_response(domainname *servicename, mDNSInterfaceID id, request_state *request, reply_state **rep)
+mDNSlocal mStatus gen_rr_response(domainname *servicename, mDNSInterfaceID id, request_state *request, reply_state **rep)
     {
     char *data;
     int len;
@@ -3133,7 +3178,7 @@ static mStatus gen_rr_response(domainname *servicename, mDNSInterfaceID id, requ
     return mStatus_NoError;
     }
 
-static int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain)
+mDNSlocal int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain)
     {
     domainlabel n;
     domainname d, t;
@@ -3146,7 +3191,7 @@ static int build_domainname_from_strings(domainname *srv, char *name, char *regt
     }
 
 // append a reply to the list in a request object
-static void append_reply(request_state *req, reply_state *rep)
+mDNSlocal void append_reply(request_state *req, reply_state *rep)
     {
     reply_state *ptr;
 
@@ -3163,7 +3208,7 @@ static void append_reply(request_state *req, reply_state *rep)
 // read_msg may be called any time when the transfer state (rs->ts) is t_morecoming.
 // returns the current state of the request (morecoming, error, complete, terminated.)
 // if there is no data on the socket, the socket will be closed and t_terminated will be returned
-static int read_msg(request_state *rs)
+mDNSlocal int read_msg(request_state *rs)
     {
     uint32_t nleft;
     int nread;
@@ -3266,7 +3311,7 @@ rerror:
     return t_error;
     }
 
-static int send_msg(reply_state *rs)
+mDNSlocal int send_msg(reply_state *rs)
     {
     ssize_t nwriten;
     
@@ -3318,12 +3363,11 @@ static int send_msg(reply_state *rs)
     return rs->ts;
     }
 
-static reply_state *create_reply(reply_op_t op, size_t datalen, request_state *request)
+mDNSlocal reply_state *create_reply(reply_op_t op, size_t datalen, request_state *request)
 {
     reply_state *reply;
     int totallen;
 
-    
     if ((unsigned)datalen < sizeof(reply_hdr))
         {
         LogMsg("ERROR: create_reply - data length less than lenght of required fields");
@@ -3350,7 +3394,7 @@ static reply_state *create_reply(reply_op_t op, size_t datalen, request_state *r
     return reply;
     }
 
-static int deliver_error(request_state *rstate, mStatus err)
+mDNSlocal int deliver_error(request_state *rstate, mStatus err)
        {
        int nwritten = -1;
        undelivered_error_t *undeliv;
@@ -3382,7 +3426,7 @@ static int deliver_error(request_state *rstate, mStatus err)
        }
 
 // returns 0 on success, -1 if send is incomplete, or on terminal failure (request is aborted)
-static transfer_state send_undelivered_error(request_state *rs)
+mDNSlocal transfer_state send_undelivered_error(request_state *rs)
        {
        int nwritten;
        
@@ -3410,7 +3454,7 @@ static transfer_state send_undelivered_error(request_state *rs)
 // send bogus data along with an error code to the app callback
 // returns 0 on success (linking reply into list of not fully delivered),
 // -1 on failure (request should be aborted)
-static int deliver_async_error(request_state *rs, reply_op_t op, mStatus err)
+mDNSlocal int deliver_async_error(request_state *rs, reply_op_t op, mStatus err)
     {
     int len;
     reply_state *reply;
@@ -3431,7 +3475,7 @@ static int deliver_async_error(request_state *rs, reply_op_t op, mStatus err)
     return 0;
     }
 
-static void abort_request(request_state *rs)
+mDNSlocal void abort_request(request_state *rs)
     {
     reply_state *rep, *ptr;
 
@@ -3439,7 +3483,10 @@ static void abort_request(request_state *rs)
     if (rs->msgbuf) freeL("abort_request", rs->msgbuf);
        LogOperation("%3d: Removing FD", rs->sd);
     udsSupportRemoveFDFromEventLoop(rs->sd);                                   // Note: This also closes file descriptor rs->sd for us
-    rs->sd = dnssd_InvalidSocket;
+
+       // Don't use dnssd_InvalidSocket (-1) because that's the sentinel value MACOSX_MDNS_MALLOC_DEBUGGING uses
+       // for detecting when the memory for an object is inadvertently freed while the object is still on some list
+    rs->sd = -2;
 
     // free pending replies
     rep = rs->replies;
@@ -3458,7 +3505,7 @@ static void abort_request(request_state *rs)
         }
     }
 
-static void unlink_request(request_state *rs)
+mDNSlocal void unlink_request(request_state *rs)
     {
     request_state *ptr;
     
@@ -3478,7 +3525,7 @@ static void unlink_request(request_state *rs)
     }
 
 //hack to search-replace perror's to LogMsg's
-static void my_perror(char *errmsg)
+mDNSlocal void my_perror(char *errmsg)
     {
     LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno()));
     }
@@ -3487,7 +3534,7 @@ static void my_perror(char *errmsg)
 // without overrunning it.
 // returns 0 on success, -1 on error.
 
-static int validate_message(request_state *rstate)
+mDNSlocal int validate_message(request_state *rstate)
     {
     uint32_t min_size;
     
@@ -3546,7 +3593,7 @@ static int validate_message(request_state *rstate)
     
     }
 
-static uint32_t dnssd_htonl(uint32_t l)
+mDNSlocal uint32_t dnssd_htonl(uint32_t l)
        {
        uint32_t        ret;
        char    *       data;
@@ -3560,7 +3607,7 @@ static uint32_t dnssd_htonl(uint32_t l)
 
 #if defined(_WIN32)
 
-static char * win32_strerror(int inErrorCode)
+mDNSlocal char * win32_strerror(int inErrorCode)
        {
        static char buffer[1024];
        DWORD       n;
index dc116b574cfec10b553e26261f53ea26e4dcd1e0..988a41cfe7f731a37247a2f76c11de83684bdb31 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * 
  * @APPLE_LICENSE_HEADER_END@
 
-       Contains:       mDNS platform plugin for VxWorks.
-
-       Copyright:  Copyright (C) 2002-2004 Apple Computer, Inc., All Rights Reserved.
-
-       Change History (most recent first):
+    Change History (most recent first):
 
 $Log: mDNSVxWorks.c,v $
-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 NATPMP 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 (1005) 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.
-
-       To Do:
+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.
 
-               - Add support for IPv6 (needs VxWorks IPv6 support).
 */
 
-// Set up the debug library to use the default category (see DebugServicesLite.h for details).
-
-#if( !TARGET_NON_APPLE )
-       #define DEBUG_USE_DEFAULT_CATEGORY              1
+#if 0
+#pragma mark == Configuration ==
 #endif
 
+//===========================================================================================================================
+//     Configuration
+//===========================================================================================================================
+
+#define        DEBUG_NAME                                                      "[mDNS] "
+#define        MDNS_AAAA_OVER_IPV4                                     1       // 1=Send AAAA & A records over IPv4 & IPv6, 0=Send AAAA over IPv6, A over IPv4.
+#define        MDNS_EXCLUDE_IPV4_ROUTABLE_IPV6         1       // 1=Don't use IPv6 socket if non-link-local IPv4 available on same interface.
+#define        MDNS_ENABLE_PPP                                         0       // 1=Enable Unicast DNS over PPP interfaces. 0=Don't enable it.
+#define MDNS_DEBUG_PACKETS                                     1       // 1=Enable debug output for packet send/recv if debug level high enough.
+#define MDNS_DEBUG_SHOW                                                1       // 1=Enable console show routines.
+#define        DEBUG_USE_DEFAULT_CATEGORY                      1       // Set up to use the default category (see DebugServices.h for details).
+
 #include       <stdarg.h>
 #include       <stddef.h>
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <string.h>
+#include       <time.h>
+
+#include       "vxWorks.h"
+#include       "config.h"
 
 #include       <sys/types.h>
+
 #include       <arpa/inet.h>
-#include       <fcntl.h>
+#include       <net/if.h>
+#include       <net/if_dl.h>
+#include       <net/if_types.h>
+#include       <net/ifaddrs.h>
+#include       <netinet6/in6_var.h>
 #include       <netinet/if_ether.h>
 #include       <netinet/in.h>
 #include       <netinet/ip.h>
@@ -151,7 +69,6 @@ mDNS platform plugin for VxWorks.
 #include       <sys/socket.h>
 #include       <unistd.h>
 
-#include       "vxWorks.h"
 #include       "ifLib.h"
 #include       "inetLib.h"
 #include       "pipeDrv.h"
@@ -162,30 +79,13 @@ mDNS platform plugin for VxWorks.
 #include       "taskLib.h"
 #include       "tickLib.h"
 
-#include       "config.h"
-
-#if( !TARGET_NON_APPLE )
-       #include        "ACP/ACPUtilities.h"
-       #include        "Support/DebugServicesLite.h"
-       #include        "Support/MiscUtilities.h"
-#endif
-
+#include       "CommonServices.h"
+#include       "DebugServices.h"
+#include       "DNSCommon.h"
 #include       "mDNSEmbeddedAPI.h"
 
 #include       "mDNSVxWorks.h"
 
-#if 0
-#pragma mark == Preprocessor ==
-#endif
-
-//===========================================================================================================================
-//     Preprocessor
-//===========================================================================================================================
-
-#if( !TARGET_NON_APPLE )
-       debug_log_new_default_category( mdns );
-#endif
-
 #if 0
 #pragma mark == Constants ==
 #endif
@@ -194,118 +94,49 @@ mDNS platform plugin for VxWorks.
 //     Constants
 //===========================================================================================================================
 
-#define        DEBUG_NAME                                              "[mDNS] "
-
-#define        kMDNSDefaultName                                "My-Device"
-
-#define        kMDNSTaskName                                   "tMDNS"
-#define        kMDNSTaskPriority                               102
-#define        kMDNSTaskStackSize                              49152
-
-#define        kMDNSPipeName                                   "/pipe/mDNS"
-#define        kMDNSPipeMessageQueueSize               32
-#define        kMDNSPipeMessageSize                    1
-
-#define        kInvalidSocketRef                               -1
-
 typedef uint8_t                MDNSPipeCommandCode;
-enum
-{
-       kMDNSPipeCommandCodeInvalid                     = 0, 
-       kMDNSPipeCommandCodeReschedule          = 1, 
-       kMDNSPipeCommandCodeReconfigure         = 2, 
-       kMDNSPipeCommandCodeQuit                        = 3
-};
-
-#if 0
-#pragma mark == Structures ==
-#endif
-
-//===========================================================================================================================
-//     Structures
-//===========================================================================================================================
 
-typedef int            MDNSSocketRef;
-
-struct MDNSInterfaceItem
-{
-       MDNSInterfaceItem *                     next;
-       char                                            name[ 32 ];
-       MDNSSocketRef                           multicastSocketRef;
-       MDNSSocketRef                           sendingSocketRef;
-       NetworkInterfaceInfo            hostSet;
-       mDNSBool                                        hostRegistered;
-       
-       int                                                     sendMulticastCounter;
-       int                                                     sendUnicastCounter;
-       int                                                     sendErrorCounter;
-       
-       int                                                     recvCounter;
-       int                                                     recvErrorCounter;
-       int                                                     recvLoopCounter;
-};
+#define kMDNSPipeCommandCodeInvalid                    0
+#define kMDNSPipeCommandCodeReschedule         1
+#define kMDNSPipeCommandCodeReconfigure                2
+#define kMDNSPipeCommandCodeQuit                       3
 
 #if 0
-#pragma mark == Macros ==
+#pragma mark == Prototypes ==
 #endif
 
 //===========================================================================================================================
-//     Macros
+//     Prototypes
 //===========================================================================================================================
 
-#if( TARGET_NON_APPLE )
-       
-       // Do-nothing versions of the debugging macros for non-Apple platforms.
-       
-       #define check(assertion)
-       #define check_string( assertion, cstring )
-       #define check_noerr(err)
-       #define check_noerr_string( error, cstring )
-       #define check_errno( assertion, errno_value )
-       #define debug_string( cstring )
-       #define require( assertion, label )                                             do { if( !(assertion) ) goto label; } while(0)
-       #define require_string( assertion, label, string )                                              require(assertion, label)
-       #define require_quiet( assertion, label )                                                               require( assertion, label )
-       #define require_noerr( error, label )                                                                   do { if( (error) != 0 ) goto label; } while(0)
-       #define require_noerr_quiet( assertion, label )                                                 require_noerr( assertion, label )
-       #define require_noerr_action( error, label, action )                                    do { if( (error) != 0 ) { {action;}; goto label; } } while(0)
-       #define require_noerr_action_quiet( assertion, label, action )                  require_noerr_action( assertion, label, action )
-       #define require_action( assertion, label, action )                                              do { if( !(assertion) ) { {action;}; goto label; } } while(0)
-       #define require_action_quiet( assertion, label, action )                                require_action( assertion, label, action )
-       #define require_action_string( assertion, label, action, cstring )              do { if( !(assertion) ) { {action;}; goto label; } } while(0)
-       #define require_errno( assertion, errno_value, label )                                  do { if( !(assertion) ) goto label; } while(0)
-       #define require_errno_action( assertion, errno_value, label, action )   do { if( !(assertion) ) { {action;}; goto label; } } while(0)
-       
-       #define dlog( ARGS... )
+#if( DEBUG )
+       mDNSlocal void  DebugMsg( DebugLevel inLevel, const char *inFormat, ... );
        
-       #define DEBUG_UNUSED( X )                       (void)( X )
+       #define dmsg( LEVEL, ARGS... )  DebugMsg( LEVEL, ## ARGS )
+#else
+       #define dmsg( LEVEL, ARGS... )
 #endif
 
-#if 0
-#pragma mark == Prototypes ==
+#if( DEBUG && MDNS_DEBUG_PACKETS )
+       #define dpkt( LEVEL, ARGS... )  DebugMsg( LEVEL, ## ARGS )
+#else
+       #define dpkt( LEVEL, ARGS... )
 #endif
 
-//===========================================================================================================================
-//     Prototypes
-//===========================================================================================================================
-
-// ifIndexToIfp is in net/if.c, but not exported by net/if.h so provide it here.
-
-extern struct ifnet * ifIndexToIfp(int ifIndex);
+#define        ForgetSem( X )          do { if( *( X ) ) { semDelete( ( *X ) ); *( X ) = 0; } } while( 0 )
+#define        ForgetSocket( X )       do { if( IsValidSocket( *( X ) ) ) { close_compat( *( X ) ); *( X ) = kInvalidSocketRef; } } while( 0 )
 
-// Platform Internals
+// Interfaces
 
-mDNSlocal void         SetupNames( mDNS * const inMDNS );
-mDNSlocal mStatus      SetupInterfaceList( mDNS * const inMDNS );
-mDNSlocal mStatus      TearDownInterfaceList( mDNS * const inMDNS );
-mDNSlocal mStatus      SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inAddr, MDNSInterfaceItem **outItem );
-mDNSlocal mStatus      TearDownInterface( mDNS * const inMDNS, MDNSInterfaceItem *inItem );
-mDNSlocal mStatus
-       SetupSocket( 
-               mDNS * const                    inMDNS, 
-               const struct ifaddrs *  inAddr, 
-               mDNSIPPort                              inPort, 
-               MDNSSocketRef *                 outSocketRef );
+mDNSlocal mStatus      UpdateInterfaceList( mDNS *const inMDNS, mDNSs32 inUTC );
+mDNSlocal NetworkInterfaceInfoVxWorks *        AddInterfaceToList( mDNS *const inMDNS, struct ifaddrs *inIFA, mDNSs32 inUTC );
+mDNSlocal int  SetupActiveInterfaces( mDNS *const inMDNS, mDNSs32 inUTC );
+mDNSlocal void MarkAllInterfacesInactive( mDNS *const inMDNS, mDNSs32 inUTC );
+mDNSlocal int  ClearInactiveInterfaces( mDNS *const inMDNS, mDNSs32 inUTC, mDNSBool inClosing );
+mDNSlocal NetworkInterfaceInfoVxWorks *        FindRoutableIPv4( mDNS *const inMDNS, mDNSu32 inScopeID );
+mDNSlocal NetworkInterfaceInfoVxWorks *        FindInterfaceByIndex( mDNS *const inMDNS, int inFamily, mDNSu32 inIndex );
+mDNSlocal mStatus      SetupSocket( mDNS *const inMDNS, const mDNSAddr *inAddr, mDNSBool inMcast, int inFamily, SocketSet *inSS );
+mDNSlocal mStatus      SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP );
 
 // Commands
 
@@ -313,26 +144,26 @@ mDNSlocal mStatus SetupCommandPipe( mDNS * const inMDNS );
 mDNSlocal mStatus      TearDownCommandPipe( mDNS * const inMDNS );
 mDNSlocal mStatus      SendCommand( const mDNS * const inMDNS, MDNSPipeCommandCode inCommandCode );
 mDNSlocal mStatus      ProcessCommand( mDNS * const inMDNS );
-mDNSlocal void         ProcessCommandReconfigure( mDNS *inMDNS );
 
 // Threads
 
-mDNSlocal mStatus      SetupTask( mDNS * const inMDNS );
-mDNSlocal mStatus      TearDownTask( mDNS * const inMDNS );
 mDNSlocal void         Task( mDNS *inMDNS );
 mDNSlocal mStatus      TaskInit( mDNS *inMDNS );
-mDNSlocal void         TaskSetupReadSet( mDNS *inMDNS, fd_set *outReadSet, int *outMaxSocket );
-mDNSlocal void         TaskSetupTimeout( mDNS *inMDNS, mDNSs32 inNextTaskTime, struct timeval *outTimeout );
-mDNSlocal void         TaskProcessPacket( mDNS *inMDNS, MDNSInterfaceItem *inItem, MDNSSocketRef inSocketRef );
-
-// Utilities
-
-#if( TARGET_NON_APPLE )
-       mDNSlocal void  GenerateUniqueHostName( char *outName, long *ioSeed );
-       mDNSlocal void  GenerateUniqueDNSName( char *outName, long *ioSeed );
-#endif
-
-// Platform Accessors
+mDNSlocal void         TaskTerm( mDNS *inMDNS );
+mDNSlocal void         TaskSetupSelect( mDNS *inMDNS, fd_set *outSet, int *outMaxFd, mDNSs32 inNextEvent, struct timeval *outTimeout );
+mDNSlocal void         TaskProcessPackets( mDNS *inMDNS, SocketSet *inSS, SocketRef inSock );
+mDNSlocal ssize_t
+       mDNSRecvMsg( 
+               SocketRef       inSock, 
+               void *          inBuffer, 
+               size_t          inBufferSize, 
+               void *          outFrom, 
+               size_t          inFromSize, 
+               size_t *        outFromSize, 
+               mDNSAddr *      outDstAddr, 
+               uint32_t *      outIndex );
+
+// DNSServices compatibility. When all clients move to DNS-SD, this section can be removed.
 
 #ifdef __cplusplus
        extern "C" {
@@ -360,17 +191,19 @@ mDNSexport mStatus        mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInter
 //     Globals
 //===========================================================================================================================
 
-mDNSlocal mDNS *                                       gMDNSPtr                                                        = NULL;
-mDNSlocal mDNS_PlatformSupport         gMDNSPlatformSupport;
-mDNSlocal mDNSs32                                      gMDNSTicksToMicrosecondsMultiplier      = 0;
-
-// Platform support
+debug_log_new_default_category( mdns );
 
-mDNSs32                                                                mDNSPlatformOneSecond;
+mDNSexport mDNSs32                                     mDNSPlatformOneSecond;
+mDNSlocal mDNSs32                                      gMDNSTicksToMicro               = 0;
+mDNSlocal mDNS *                                       gMDNSPtr                                = NULL;
+mDNSlocal mDNS_PlatformSupport         gMDNSPlatformSupport;
+mDNSlocal mDNSBool                                     gMDNSDeferIPv4                  = mDNSfalse;
+#if( DEBUG )
+       DebugLevel                                              gMDNSDebugOverrideLevel = kDebugLevelMax;
+#endif
 
 #if 0
 #pragma mark -
-#pragma mark == Public APIs ==
 #endif
 
 //===========================================================================================================================
@@ -378,18 +211,21 @@ mDNSs32                                                           mDNSPlatformOneSecond;
 //===========================================================================================================================
 
 void   mDNSReconfigure( void )
+{      
+       if( gMDNSPtr ) SendCommand( gMDNSPtr, kMDNSPipeCommandCodeReconfigure );
+}
+
+//===========================================================================================================================
+//     mDNSDeferIPv4
+//===========================================================================================================================
+
+void   mDNSDeferIPv4( mDNSBool inDefer )
 {
-       // Send a "reconfigure" command to the MDNS task.
-       
-       if( gMDNSPtr )
-       {
-               SendCommand( gMDNSPtr, kMDNSPipeCommandCodeReconfigure );
-       }
+       gMDNSDeferIPv4 = inDefer;
 }
 
 #if 0
 #pragma mark -
-#pragma mark == Platform Support ==
 #endif
 
 //===========================================================================================================================
@@ -399,51 +235,48 @@ void      mDNSReconfigure( void )
 mStatus        mDNSPlatformInit( mDNS * const inMDNS )
 {
        mStatus         err;
+       int                     id;
        
-       dlog( kDebugLevelInfo, DEBUG_NAME "platform init\n" );
+       mDNSPlatformOneSecond   = sysClkRateGet();
+       gMDNSTicksToMicro               = ( 1000000L / mDNSPlatformOneSecond );
        
-       // Initialize variables.
-
-       memset( &gMDNSPlatformSupport, 0, sizeof( gMDNSPlatformSupport ) );
-       inMDNS->p                                                       = &gMDNSPlatformSupport;
-       inMDNS->p->commandPipe                          = ERROR;
-       inMDNS->p->task                                         = ERROR;
-       inMDNS->p->rescheduled                          = 1;            // Default to rescheduled until fully initialized.
-       mDNSPlatformOneSecond                           = sysClkRateGet();
-       gMDNSTicksToMicrosecondsMultiplier      = ( 1000000L / mDNSPlatformOneSecond );
+       // Do minimal initialization to get the task started and so we can cleanup safely if an error occurs.
        
-       // Allocate semaphores.
+       memset( &gMDNSPlatformSupport, 0, sizeof( gMDNSPlatformSupport ) );
+       if( !inMDNS->p ) inMDNS->p      = &gMDNSPlatformSupport;
+       inMDNS->p->unicastSS.info       = NULL;
+       inMDNS->p->unicastSS.sockV4     = kInvalidSocketRef;
+       inMDNS->p->unicastSS.sockV6     = kInvalidSocketRef;
+       inMDNS->p->initErr                      = mStatus_NotInitializedErr;
+       inMDNS->p->commandPipe          = ERROR;
+       inMDNS->p->taskID                       = ERROR;
        
-       inMDNS->p->lockID = semMCreate( SEM_Q_FIFO );
-       require_action( inMDNS->p->lockID, exit, err = mStatus_NoMemoryErr );
+       inMDNS->p->lock = semMCreate( SEM_Q_FIFO );
+       require_action( inMDNS->p->lock, exit, err = mStatus_NoMemoryErr );
        
-       inMDNS->p->readyEvent = semBCreate( SEM_Q_FIFO, SEM_EMPTY );
-       require_action( inMDNS->p->readyEvent, exit, err = mStatus_NoMemoryErr );
+       inMDNS->p->initEvent = semBCreate( SEM_Q_FIFO, SEM_EMPTY );
+       require_action( inMDNS->p->initEvent, exit, err = mStatus_NoMemoryErr );
        
        inMDNS->p->quitEvent = semBCreate( SEM_Q_FIFO, SEM_EMPTY );
        require_action( inMDNS->p->quitEvent, exit, err = mStatus_NoMemoryErr );
        
-       gMDNSPtr = inMDNS;
-       
-       // Set up the task and wait for it to initialize. Initialization is done from the task instead of here to avoid 
-       // stack space issues. Some of the initialization may require a larger stack than the current task supports.
+       // Start the task and wait for it to initialize. The task does the full initialization from its own context
+       // to avoid potential issues with stack space and APIs that key off the current task (e.g. watchdog timers).
+       // We wait here until the init is complete because it needs to be ready to use as soon as this function returns.
        
-       err = SetupTask( inMDNS );
+       id = taskSpawn( "tMDNS", 102, 0, 16384, (FUNCPTR) Task, (int) inMDNS, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
+       err = translate_errno( id != ERROR, errno_compat(), mStatus_NoMemoryErr );
        require_noerr( err, exit );
        
-       err = semTake( inMDNS->p->readyEvent, WAIT_FOREVER );
-       require_noerr( err, exit );
-       err = inMDNS->p->taskInitErr;
+       err = semTake( inMDNS->p->initEvent, WAIT_FOREVER );
+       if( err == OK ) err = inMDNS->p->initErr;
        require_noerr( err, exit );
        
+       gMDNSPtr = inMDNS;
        mDNSCoreInitComplete( inMDNS, err );
        
 exit:
-       if( err )
-       {
-               mDNSPlatformClose( inMDNS );
-       }
-       dlog( kDebugLevelInfo, DEBUG_NAME "platform init done (err=%ld)\n", err );
+       if( err ) mDNSPlatformClose( inMDNS );
        return( err );
 }
 
@@ -455,41 +288,30 @@ void      mDNSPlatformClose( mDNS * const inMDNS )
 {
        mStatus         err;
        
-       dlog( kDebugLevelInfo, DEBUG_NAME "platform close\n" );
        check( inMDNS );
        
-       // Tear everything down.
-       
-       err = TearDownTask( inMDNS );
-       check_noerr( err );
-       
-       err = TearDownInterfaceList( inMDNS );
-       check_noerr( err );
-               
-       err = TearDownCommandPipe( inMDNS );
-       check_noerr( err );
-       
        gMDNSPtr = NULL;
        
-       // Release semaphores.
+       // Signal the task to quit and wait for it to signal back that it exited. Timeout in 10 seconds to handle a hung thread.
        
-       if( inMDNS->p->quitEvent )
-       {
-               semDelete( inMDNS->p->quitEvent );
-               inMDNS->p->quitEvent = 0;
-       }
-       if( inMDNS->p->readyEvent )
+       if( inMDNS->p->taskID != ERROR )
        {
-               semDelete( inMDNS->p->readyEvent );
-               inMDNS->p->readyEvent = 0;
-       }
-       if( inMDNS->p->lockID )
-       {
-               semDelete( inMDNS->p->lockID );
-               inMDNS->p->lockID = 0;
+               SendCommand( inMDNS, kMDNSPipeCommandCodeQuit );
+               if( inMDNS->p->quitEvent )
+               {
+                       err = semTake( inMDNS->p->quitEvent, sysClkRateGet() * 10 );
+                       check_noerr( err );
+               }
+               inMDNS->p->taskID = ERROR;
        }
        
-       dlog( kDebugLevelInfo, DEBUG_NAME "platform close done\n" );
+       // Clean up resources set up in mDNSPlatformInit. All other resources should have been cleaned up already by TaskTerm.
+       
+       ForgetSem( &inMDNS->p->quitEvent );
+       ForgetSem( &inMDNS->p->initEvent );
+       ForgetSem( &inMDNS->p->lock );
+       
+       dmsg( kDebugLevelNotice, DEBUG_NAME "CLOSED\n" );
 }
 
 //===========================================================================================================================
@@ -499,70 +321,89 @@ void      mDNSPlatformClose( mDNS * const inMDNS )
 mStatus
        mDNSPlatformSendUDP( 
                const mDNS * const                      inMDNS, 
-               const void * const              inMsg, 
-               const mDNSu8 * const            inMsgEnd, 
+               const void * const                      inMsg, 
+               const mDNSu8 * const            inEnd, 
                mDNSInterfaceID                         inInterfaceID, 
                const mDNSAddr *                        inDstIP, 
                mDNSIPPort                                      inDstPort )
 {
-       mStatus                                 err;
-       MDNSInterfaceItem *             item;
-       struct sockaddr_in              addr;
-       int                                             n;
-       
-       dlog( kDebugLevelChatty, DEBUG_NAME "platform send UDP\n" );
+       mStatus                                                         err;
+       NetworkInterfaceInfoVxWorks *           info;
+       SocketRef                                                       sock;
+       struct sockaddr_storage                         to;
+       int                                                                     n;
        
-       // Check parameters.
+       // Set up the sockaddr to sent to and the socket to send on.
        
-       check( inMDNS );
-       check( inMsg );
-       check( inMsgEnd );
-       check( inInterfaceID );
-       check( inDstIP );
-       if( inDstIP->type != mDNSAddrType_IPv4 )
+       info = (NetworkInterfaceInfoVxWorks *) inInterfaceID;
+       if( inDstIP->type == mDNSAddrType_IPv4 )
+       {
+               struct sockaddr_in *            sa4;
+               
+               sa4 = (struct sockaddr_in *) &to;
+               sa4->sin_len                    = sizeof( *sa4 );
+               sa4->sin_family                 = AF_INET;
+               sa4->sin_port                   = inDstPort.NotAnInteger;
+               sa4->sin_addr.s_addr    = inDstIP->ip.v4.NotAnInteger;
+               sock = info ? info->ss.sockV4 : inMDNS->p->unicastSS.sockV4;
+       }
+       else if( inDstIP->type == mDNSAddrType_IPv6 )
+       {
+               struct sockaddr_in6 *           sa6;
+               
+               sa6 = (struct sockaddr_in6 *) &to;
+               sa6->sin6_len           = sizeof( *sa6 );
+               sa6->sin6_family        = AF_INET6;
+               sa6->sin6_port          = inDstPort.NotAnInteger;
+               sa6->sin6_flowinfo      = 0;
+               sa6->sin6_addr          = *( (struct in6_addr *) &inDstIP->ip.v6 );
+               sa6->sin6_scope_id      = info ? info->scopeID : 0;
+               sock = info ? info->ss.sockV6 : inMDNS->p->unicastSS.sockV6;
+       }
+       else
        {
+               dmsg( kDebugLevelError, DEBUG_NAME "%s: ERROR! destination is not an IPv4 or IPv6 address\n", __ROUTINE__ );
                err = mStatus_BadParamErr;
                goto exit;
        }
-
-#if( DEBUG )
-       // Make sure the InterfaceID is valid.
        
-       for( item = inMDNS->p->interfaceList; item; item = item->next )
+       // Send the packet if we've got a valid socket of this type. Note: mDNSCore may ask us to send an IPv4 packet and then 
+       // an IPv6 multicast packet. If we don't have the corresponding type of socket available, quietly return an error.
+       
+       n = (int)( (mDNSu8 *) inEnd - (mDNSu8 *) inMsg );
+       if( !IsValidSocket( sock ) )
        {
-               if( item == (MDNSInterfaceItem *) inInterfaceID )
-               {
-                       break;
-               }
+               dpkt( kDebugLevelChatty - 1, 
+                       DEBUG_NAME "DROP: %4d bytes,                                                     DST=[%#39a]:%5hu, IF=%8s(%u) %#p\n", 
+                       n, inDstIP, mDNSVal16( inDstPort ), info ? info->ifinfo.ifname : "unicast", info ? info->scopeID : 0, info );
+               err = mStatus_Invalid;
+               goto exit;
        }
-       require_action( item, exit, err = mStatus_NoSuchNameErr );
-#endif
-
-       // Send the packet.
-       
-       item = (MDNSInterfaceItem *) inInterfaceID;
-       check( item->sendingSocketRef != kInvalidSocketRef );
-       
-       memset( &addr, 0, sizeof( addr ) );
-       addr.sin_family                 = AF_INET;
-       addr.sin_port                   = inDstPort.NotAnInteger;
-       addr.sin_addr.s_addr    = inDstIP->ip.v4.NotAnInteger;
-       
-       n = inMsgEnd - ( (const mDNSu8 * const) inMsg );
-       n = sendto( item->sendingSocketRef, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
-       check_errno( n, errno );
        
-       item->sendErrorCounter          += ( n < 0 );
-       item->sendMulticastCounter      += ( inDstPort.NotAnInteger == MulticastDNSPort.NotAnInteger );
-       item->sendUnicastCounter        += ( inDstPort.NotAnInteger != MulticastDNSPort.NotAnInteger );
+       dpkt( kDebugLevelChatty, 
+               DEBUG_NAME "SEND %4d bytes,                                                      DST=[%#39a]:%5hu, IF=%8s(%u) %#p\n", 
+               n, inDstIP, mDNSVal16( inDstPort ), info ? info->ifinfo.ifname : "unicast", info ? info->scopeID : 0, info );
        
-       dlog( kDebugLevelChatty, DEBUG_NAME "sent (to=%u.%u.%u.%u:%hu)\n", 
-                 inDstIP->ip.v4.b[ 0 ], inDstIP->ip.v4.b[ 1 ], inDstIP->ip.v4.b[ 2 ], inDstIP->ip.v4.b[ 3 ], 
-                 htons( inDstPort.NotAnInteger ) );
+       n = sendto( sock, (mDNSu8 *) inMsg, n, 0, (struct sockaddr *) &to, to.ss_len );
+       if( n < 0 )
+       {
+               // Don't warn about ARP failures or no route to host for unicast destinations.
+               
+               err = errno_compat();
+               if( ( ( err == EHOSTDOWN ) || ( err == ENETDOWN ) || ( err == EHOSTUNREACH ) ) && !mDNSAddressIsAllDNSLinkGroup( inDstIP ) )
+               {
+                       goto exit;
+               }
+               
+               dmsg( kDebugLevelError, "%s: ERROR! sendto failed on %8s(%u) to %#a:%d, sock %d, err %d, time %u\n",
+                       __ROUTINE__, info ? info->ifinfo.ifname : "unicast", info ? info->scopeID : 0, inDstIP, mDNSVal16( inDstPort ), 
+                       sock, err, (unsigned int) inMDNS->timenow );
+               if( err == 0 ) err = mStatus_UnknownErr;
+               goto exit;
+       }
        err = mStatus_NoError;
-
+       
 exit:
-       dlog( kDebugLevelChatty, DEBUG_NAME "platform send UDP done\n" );
        return( err );
 }
 
@@ -591,7 +432,7 @@ mDNSexport int mDNSPlatformReadTCP(int sd, void *buf, int buflen)
        {
        (void)sd;                       // Unused
        (void)buf;                      // Unused
-       (void)buflen;                   // Unused
+       (void)buflen;           // Unused
        return(0);
        }
 
@@ -609,16 +450,19 @@ mDNSexport int mDNSPlatformWriteTCP(int sd, const char *msg, int len)
 
 void   mDNSPlatformLock( const mDNS * const inMDNS )
 {
-       check( inMDNS->p->lockID );
+       check_string( inMDNS->p && ( inMDNS->p->taskID != ERROR ), "mDNS task not started" );
        
-       if( inMDNS->p->lockID )
+#if( DEBUG )
+       if( semTake( inMDNS->p->lock, 60 * sysClkRateGet() ) != OK )
        {
-               #if( TARGET_NON_APPLE )
-                       semTake( inMDNS->p->lockID, WAIT_FOREVER );
-               #else
-                       semTakeDeadlockDetect( inMDNS->p->lockID, WAIT_FOREVER );
-               #endif
+               dmsg( kDebugLevelTragic, "\n### DEADLOCK DETECTED ### (sem=%#p, task=%#p)\n\n", inMDNS->p->lock, taskIdSelf() );
+               debug_stack_trace();                    // 1) Print Stack Trace.
+               semShow( inMDNS->p->lock, 1 );  // 2) Print semaphore info, including which tasks are pending on it.
+               taskSuspend( 0 );                               // 3) Suspend task. Can be resumed from the console for debugging.
        }
+#else
+       semTake( inMDNS->p->lock, WAIT_FOREVER );
+#endif
 }
 
 //===========================================================================================================================
@@ -627,38 +471,23 @@ void      mDNSPlatformLock( const mDNS * const inMDNS )
 
 void   mDNSPlatformUnlock( const mDNS * const inMDNS )
 {
-       check( inMDNS );
-       check( inMDNS->p );
-       check( inMDNS->p->lockID );
-       check_string( inMDNS->p->task != ERROR, "mDNS task not started" );
-       
-       // When an API routine is called, "m->NextScheduledEvent" is reset to "timenow" before calling mDNSPlatformUnlock()
-       // Since our main mDNS_Execute() loop is on a different thread, we need to wake up that thread to:
-       // (a) handle immediate work (if any) resulting from this API call
-       // (b) calculate the next sleep time between now and the next interesting event
+       check_string( inMDNS->p && ( inMDNS->p->taskID != ERROR ), "mDNS task not started" );
        
-       if( ( mDNS_TimeNow(inMDNS) - inMDNS->NextScheduledEvent ) >= 0 )
-       {
-               // We only need to send the reschedule event 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. This avoids filling up the command queue.
-               
-               if( ( inMDNS->p->rescheduled++ == 0 ) && ( taskIdSelf() != inMDNS->p->task ) )
-               {
-                       SendCommand( inMDNS, kMDNSPipeCommandCodeReschedule );
-               }
-       }
+       // Wake up the mDNS task to handle any work initiated by an API call and to calculate the next event time.
+       // We only need to wake up if we're not already inside the task. This avoids filling up the command queue.
        
-       if( inMDNS->p->lockID )
+       if( taskIdSelf() != inMDNS->p->taskID )
        {
-               semGive( inMDNS->p->lockID );
+               SendCommand( inMDNS, kMDNSPipeCommandCodeReschedule );
        }
+       semGive( inMDNS->p->lock );
 }
 
 //===========================================================================================================================
 //     mDNSPlatformStrLen
 //===========================================================================================================================
 
-mDNSu32  mDNSPlatformStrLen( const void *inSrc )
+mDNSu32        mDNSPlatformStrLen( const void *inSrc )
 {
        check( inSrc );
        
@@ -735,15 +564,14 @@ mDNSexport void * mDNSPlatformMemAllocate( mDNSu32 inSize )
 mDNSexport void        mDNSPlatformMemFree( void *inMem )
 {
        check( inMem );
-       
-       free( inMem );
+       if( inMem ) free( inMem );
 }
 
 //===========================================================================================================================
 //     mDNSPlatformRandomSeed
 //===========================================================================================================================
 
-mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
+mDNSexport mDNSu32     mDNSPlatformRandomSeed( void )
 {
        return( tickGet() );
 }
@@ -752,9 +580,10 @@ mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
 //     mDNSPlatformTimeInit
 //===========================================================================================================================
 
-mDNSexport mStatus mDNSPlatformTimeInit( void )
+mDNSexport mStatus     mDNSPlatformTimeInit( void )
 {
        // No special setup is required on VxWorks -- we just use tickGet().
+       
        return( mStatus_NoError );
 }
 
@@ -773,102 +602,102 @@ mDNSs32 mDNSPlatformRawTime( void )
 
 mDNSexport mDNSs32     mDNSPlatformUTC( void )
 {
-       return( -1 );
+       return( (mDNSs32) time( NULL ) );
 }
 
 //===========================================================================================================================
-//     mDNSPlatformInterfaceNameToID
+//     mDNSPlatformInterfaceIDfromInterfaceIndex
 //===========================================================================================================================
 
-mStatus        mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID )
+mDNSexport mDNSInterfaceID     mDNSPlatformInterfaceIDfromInterfaceIndex( const mDNS *const inMDNS, mDNSu32 inIndex )
 {
-       mStatus                                 err;
-       MDNSInterfaceItem *             ifd;
+       NetworkInterfaceInfoVxWorks *           i;
        
-       check( inMDNS );
-       check( inMDNS->p );
-       check( inName );
-       
-       // Search for an interface with the specified name,
-       
-       for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
+       if( inIndex == (mDNSu32) -1 ) return( mDNSInterface_LocalOnly );
+       if( inIndex != 0 )
        {
-               if( strcmp( ifd->name, inName ) == 0 )
+               for( i = inMDNS->p->interfaceList; i; i = i->next )
                {
-                       break;
+                       // Don't get tricked by inactive interfaces with no InterfaceID set.
+                       
+                       if( i->ifinfo.InterfaceID && ( i->scopeID == inIndex ) ) return( i->ifinfo.InterfaceID );
                }
        }
-       if( !ifd )
-       {
-               err = mStatus_NoSuchNameErr;
-               goto exit;
-       }
-               
-       // Success!
+       return( NULL );
+}
+
+//===========================================================================================================================
+//     mDNSPlatformInterfaceIndexfromInterfaceID
+//===========================================================================================================================
+
+mDNSexport mDNSu32     mDNSPlatformInterfaceIndexfromInterfaceID( const mDNS *const inMDNS, mDNSInterfaceID inID )
+{
+       NetworkInterfaceInfoVxWorks *           i;
        
-       if( outID )
+       if( inID == mDNSInterface_LocalOnly ) return( (mDNSu32) -1 );
+       if( inID )
        {
-               *outID = (mDNSInterfaceID) ifd;
+               // Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces.
+               
+               for( i = inMDNS->p->interfaceList; i && ( (mDNSInterfaceID) i != inID ); i = i->next ) {}
+               if( i ) return( i->scopeID );
        }
-       err = mStatus_NoError;
-       
-exit:
-       return( err );
+       return( 0 );
 }
 
 //===========================================================================================================================
-//     mDNSPlatformInterfaceIDToInfo
+//     mDNSPlatformInterfaceNameToID
 //===========================================================================================================================
 
-mStatus        mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo )
+mStatus        mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID )
 {
-       mStatus                                 err;
-       MDNSInterfaceItem *             ifd;
-       
-       check( inMDNS );
-       check( inID );
-       check( outInfo );
-       
-       // Search for an interface with the specified ID,
+       NetworkInterfaceInfoVxWorks *           i;
        
-       for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
+       for( i = inMDNS->p->interfaceList; i; i = i->next )
        {
-               if( ifd == (MDNSInterfaceItem *) inID )
+               // Don't get tricked by inactive interfaces with no InterfaceID set.
+               
+               if( i->ifinfo.InterfaceID && ( strcmp( i->ifinfo.ifname, inName ) == 0 ) )
                {
-                       break;
+                       *outID = (mDNSInterfaceID) i;
+                       return( mStatus_NoError );
                }
        }
-       if( !ifd )
-       {
-               err = mStatus_NoSuchNameErr;
-               goto exit;
-       }
+       return( mStatus_NoSuchNameErr );
+}
+
+//===========================================================================================================================
+//     mDNSPlatformInterfaceIDToInfo
+//===========================================================================================================================
+
+mStatus        mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo )
+{
+       NetworkInterfaceInfoVxWorks *           i;
        
-       // Success!
+       // Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces.
        
-       outInfo->name   = ifd->name;
-       outInfo->ip     = ifd->hostSet.ip;
-       err                     = mStatus_NoError;
+       for( i = inMDNS->p->interfaceList; i && ( (mDNSInterfaceID) i != inID ); i = i->next ) {}
+       if( !i ) return( mStatus_NoSuchNameErr );
        
-exit:
-       return( err );
+       outInfo->name   = i->ifinfo.ifname;
+       outInfo->ip     = i->ifinfo.ip;
+       return( mStatus_NoError );
 }
 
 //===========================================================================================================================
 //     debugf_
 //===========================================================================================================================
 
-#if( MDNS_DEBUGMSGS )
-mDNSexport void debugf_( const char *format, ... )
+#if( MDNS_DEBUGMSGS > 0 )
+mDNSexport void        debugf_( const char *inFormat, ... )
 {
        char            buffer[ 512 ];
-    va_list            args;
-    mDNSu32            length;
-    
-       va_start( args, format );
-       length = mDNS_vsnprintf( buffer, sizeof( buffer ), format, args );
+       va_list         args;
+       
+       va_start( args, inFormat );
+       mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
        va_end( args );
-
+       
        dlog( kDebugLevelInfo, "%s\n", buffer );
 }
 #endif
@@ -878,14 +707,13 @@ mDNSexport void debugf_( const char *format, ... )
 //===========================================================================================================================
 
 #if( MDNS_DEBUGMSGS > 1 )
-mDNSexport void verbosedebugf_( const char *format, ... )
+mDNSexport void        verbosedebugf_( const char *inFormat, ... )
 {
        char            buffer[ 512 ];
-    va_list            args;
-    mDNSu32            length;
-    
-       va_start( args, format );
-       length = mDNS_vsnprintf( buffer, sizeof( buffer ), format, args );
+       va_list         args;
+       
+       va_start( args, inFormat );
+       mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
        va_end( args );
        
        dlog( kDebugLevelVerbose, "%s\n", buffer );
@@ -896,406 +724,769 @@ mDNSexport void verbosedebugf_( const char *format, ... )
 //     LogMsg
 //===========================================================================================================================
 
-void LogMsg( const char *inFormat, ... )
+mDNSexport void        LogMsg( const char *inFormat, ... )
 {
+#if( DEBUG )
        char            buffer[ 512 ];
-    va_list            args;
-    mDNSu32            length;
+       va_list         args;
        
        va_start( args, inFormat );
-       length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
+       mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
        va_end( args );
        
        dlog( kDebugLevelWarning, "%s\n", buffer );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == Platform Internals ==
+#else
+       DEBUG_UNUSED( inFormat );
 #endif
+}
 
+#if( DEBUG )
 //===========================================================================================================================
-//     SetupNames
+//     DebugMsg
 //===========================================================================================================================
 
-mDNSlocal void SetupNames( mDNS * const inMDNS )
+mDNSlocal void DebugMsg( DebugLevel inLevel, const char *inFormat, ... )
 {
-       char                    tempCString[ 128 ];
-       mDNSu8                  tempPString[ 128 ];
-       mDNSu8 *                namePtr;
-       
-       // Set up the host name.
-       
-       tempCString[ 0 ] = '\0';
-       GenerateUniqueHostName( tempCString, NULL );
-       check( tempCString[ 0 ] != '\0' );
-       if( tempCString[ 0 ] == '\0' )
-       {
-               // No name so use the default.
-               
-               strcpy( tempCString, kMDNSDefaultName );
-       }
-       inMDNS->nicelabel.c[ 0 ] = strlen( tempCString );
-       memcpy( &inMDNS->nicelabel.c[ 1 ], tempCString, inMDNS->nicelabel.c[ 0 ] );
-       check( inMDNS->nicelabel.c[ 0 ] > 0 );
-       
-       // Set up the DNS name.
+       char            buffer[ 512 ];
+       va_list         args;
        
-       tempCString[ 0 ] = '\0';
-       GenerateUniqueDNSName( tempCString, NULL );
-       if( tempCString[ 0 ] != '\0' )
-       {
-               tempPString[ 0 ] = strlen( tempCString );
-               memcpy( &tempPString[ 1 ], tempCString, tempPString[ 0 ] );
-               namePtr = tempPString;
-       }
-       else
-       {
-               // No DNS name so use the host name.
-               
-               namePtr = inMDNS->nicelabel.c;
-       }
-       ConvertUTF8PstringToRFC1034HostLabel( namePtr, &inMDNS->hostlabel );
-       if( inMDNS->hostlabel.c[ 0 ] == 0 )
-       {
-               // Nice name has no characters that are representable as an RFC 1034 name (e.g. Japanese) so use the default.
-               
-               MakeDomainLabelFromLiteralString( &inMDNS->hostlabel, kMDNSDefaultName );
-       }
-       check( inMDNS->hostlabel.c[ 0 ] > 0 );
-
-       mDNS_SetFQDN( inMDNS );
+       va_start( args, inFormat );
+       mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
+       va_end( args );
        
-       dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] );
-       dlog( kDebugLevelInfo, DEBUG_NAME "host name \"%.*s\"\n", inMDNS->hostlabel.c[ 0 ], &inMDNS->hostlabel.c[ 1 ] );
+       if( inLevel >= gMDNSDebugOverrideLevel ) inLevel = kDebugLevelMax;
+       dlog( inLevel, "%s", buffer );
 }
+#endif
+
+#if 0
+#pragma mark -
+#pragma mark == Interfaces ==
+#endif
 
 //===========================================================================================================================
-//     SetupInterfaceList
+//     UpdateInterfaceList
 //===========================================================================================================================
 
-mDNSlocal mStatus      SetupInterfaceList( mDNS * const inMDNS )
-{
-       mStatus                                         err;
-       struct ifaddrs *                        addrs;
-       struct ifaddrs *                        p;
-       uint32_t                                        flagMask;
-       uint32_t                                        flagTest;
-       MDNSInterfaceItem **            next;
-       MDNSInterfaceItem *                     item;
+#if( MDNS_ENABLE_PPP )
        
-       addrs = NULL;
-       
-       dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface list\n" );
-       check( inMDNS );
+       // Note: This includes PPP dial-in interfaces (pppXYZ), but not PPP dial-out interface (pppdXYZ).
        
-       // Tear down any existing interfaces that may be set up.
-       
-       TearDownInterfaceList( inMDNS );
-       inMDNS->p->interfaceList = NULL;
-       next = &inMDNS->p->interfaceList;
+       #define IsCompatibleInterface( IFA )                                                                                                                                            \
+               ( ( ( IFA )->ifa_flags & IFF_UP )                                                                                                                                       &&      \
+                 ( ( ( IFA )->ifa_addr->sa_family == AF_INET ) || ( ( IFA )->ifa_addr->sa_family == AF_INET6 ) )       &&      \
+                 ( ( IFA )->ifa_netmask && ( ( IFA )->ifa_addr->sa_family == ( IFA )->ifa_netmask->sa_family ) )       &&      \
+                 ( !( ( IFA )->ifa_flags & IFF_POINTOPOINT ) || ( strncmp( ( IFA )->ifa_name, "pppd", 4 ) != 0 ) ) )
+#else
+       #define IsCompatibleInterface( IFA )                                                                                                                                                            \
+               ( ( ( ( IFA )->ifa_flags & ( IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT ) ) == ( IFF_UP | IFF_MULTICAST ) )       &&      \
+                 ( ( ( IFA )->ifa_addr->sa_family == AF_INET ) || ( ( IFA )->ifa_addr->sa_family == AF_INET6 ) )                       &&      \
+                 ( ( IFA )->ifa_netmask && ( ( IFA )->ifa_addr->sa_family == ( IFA )->ifa_netmask->sa_family ) ) )
+#endif
+
+#define        IsLinkLocalSockAddr( SA )                                                                                                                                       \
+       ( ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET )                                                                 \
+         ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 0 ] == 169 ) &&   \
+                 ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 1 ] == 254 ) )        \
+         : IN6_IS_ADDR_LINKLOCAL( &( (const struct sockaddr_in6 *)( SA ) )->sin6_addr ) )
+
+#define        FamilyToString( X )                                     \
+       ( ( ( X ) == AF_INET )  ? "AF_INET"  :  \
+       ( ( ( X ) == AF_INET6 ) ? "AF_INET6" :  \
+       ( ( ( X ) == AF_LINK )  ? "AF_LINK"  :  \
+                                                         "UNKNOWN" ) ) )
+
+mDNSlocal mStatus      UpdateInterfaceList( mDNS *const inMDNS, mDNSs32 inUTC )
+{
+       mStatus                                                         err;
+       struct ifaddrs *                                        ifaList;
+       struct ifaddrs *                                        ifa;
+       int                                                                     family;
+       mDNSBool                                                        foundV4;
+       mDNSBool                                                        foundV6;
+       struct ifaddrs *                                        loopbackV4;
+       struct ifaddrs *                                        loopbackV6;
+       mDNSEthAddr                                                     primaryMAC;
+       SocketRef                                                       infoSock;
+       char                                                            defaultName[ 64 ];
+       NetworkInterfaceInfoVxWorks *           i;
+       domainlabel                                                     nicelabel;
+       domainlabel                                                     hostlabel;
+       domainlabel                                                     tmp;
+       
+       ifaList         = NULL; 
+       foundV4         = mDNSfalse;
+       foundV6         = mDNSfalse;
+       loopbackV4      = NULL;
+       loopbackV6      = NULL;
+       primaryMAC      = zeroEthAddr;
+       
+       // Set up an IPv6 socket so we can check the state of interfaces using SIOCGIFAFLAG_IN6.
+       
+       infoSock = socket( AF_INET6, SOCK_DGRAM, 0 );
+       check_translated_errno( IsValidSocket( infoSock ), errno_compat(), kUnknownErr );
+       
+       // Run through the entire list of interfaces.
+       
+       err = getifaddrs( &ifaList );
+       check_translated_errno( err == 0, errno_compat(), kUnknownErr );
+       
+       for( ifa = ifaList; ifa; ifa = ifa->ifa_next )
+       {
+               int             flags;
+               
+               family = ifa->ifa_addr->sa_family;
+               dmsg( kDebugLevelVerbose, DEBUG_NAME "%s: %8s(%d), Flags 0x%08X, Family %8s(%2d)\n", __ROUTINE__, 
+                       ifa->ifa_name, if_nametoindex( ifa->ifa_name ), ifa->ifa_flags, FamilyToString( family ), family );
+               
+               // Save off the MAC address of the first Ethernet-ish interface.
+               
+               if( family == AF_LINK )
+               {
+                       struct sockaddr_dl *            sdl;
+                       
+                       sdl = (struct sockaddr_dl *) ifa->ifa_addr;
+                       if( ( sdl->sdl_type == IFT_ETHER ) && ( sdl->sdl_alen == sizeof( primaryMAC ) && 
+                               mDNSSameEthAddress( &primaryMAC, &zeroEthAddr ) ) )
+                       {
+                               memcpy( primaryMAC.b, sdl->sdl_data + sdl->sdl_nlen, 6 );
+                       }
+               }
+               
+               if( !IsCompatibleInterface( ifa ) ) continue;
+               
+               // If this is a link-local address and there's a non-link-local address on this interface, skip this alias.
+               
+               if( IsLinkLocalSockAddr( ifa->ifa_addr ) )
+               {
+                       struct ifaddrs *                ifaLL;
+                       
+                       for( ifaLL = ifaList; ifaLL; ifaLL = ifaLL->ifa_next )
+                       {
+                               if( ifaLL->ifa_addr->sa_family != family )                      continue;
+                               if( !IsCompatibleInterface( ifaLL ) )                           continue;
+                               if( strcmp( ifaLL->ifa_name, ifa->ifa_name ) != 0 )     continue;
+                               if( !IsLinkLocalSockAddr( ifaLL->ifa_addr ) )           break;
+                       }
+                       if( ifaLL )
+                       {
+                               dmsg( kDebugLevelInfo, DEBUG_NAME "%s: %8s(%d) skipping link-local alias\n", __ROUTINE__, 
+                                       ifa->ifa_name, if_nametoindex( ifa->ifa_name ) );
+                               continue;
+                       }
+               }
+               
+               // If this is an IPv6 interface, perform additional checks to make sure it is really ready for use.
+               // If this is a loopback interface, save it off since we may add it later if there are no other interfaces.
+               // Otherwise, add the interface to the list.
+               
+               flags = 0;
+               if( ( family == AF_INET6 ) && IsValidSocket( infoSock ) )
+               {
+                       struct sockaddr_in6 *           sa6;
+                       struct in6_ifreq                        ifr6;
+                       
+                       sa6 = (struct sockaddr_in6 *) ifa->ifa_addr;
+                       memset( &ifr6, 0, sizeof( ifr6 ) );
+                       strcpy( ifr6.ifr_name, ifa->ifa_name );
+                       ifr6.ifr_addr = *sa6;
+                       if( ioctl( infoSock, SIOCGIFAFLAG_IN6, (int) &ifr6 ) != -1 )
+                       {
+                               flags = ifr6.ifr_ifru.ifru_flags6;
+                       }
+               }
+
+               // HACK: This excludes interfaces with IN6_IFF_DUPLICATED set instead of using IN6_IFF_NOTREADY (which is
+               // HACK: IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED) because we currently do not get a notification when an
+               // HACK: interface goes from the tentative state to the fully ready state. So as a short-term workaround, 
+               // HACK: this allows tentative interfaces to be registered. We should revisit if we get notification hooks.
+               
+               if( flags & ( IN6_IFF_DUPLICATED | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY ) )
+               {
+                       dmsg( kDebugLevelNotice, DEBUG_NAME "%s: %8s(%d), SIOCGIFAFLAG_IN6 not ready yet (0x%X)\n", __ROUTINE__, 
+                               ifa->ifa_name, if_nametoindex( ifa->ifa_name ), flags );
+                       continue;
+               }
+               if( ifa->ifa_flags & IFF_LOOPBACK )
+               {
+                       if( family == AF_INET ) loopbackV4 = ifa;
+                       else                                    loopbackV6 = ifa;
+               }
+               else
+               {
+                       if( ( family == AF_INET ) && gMDNSDeferIPv4 && IsLinkLocalSockAddr( ifa->ifa_addr ) ) continue;
+                       i = AddInterfaceToList( inMDNS, ifa, inUTC );
+                       if( i && i->multicast )
+                       {
+                               if( family == AF_INET ) foundV4 = mDNStrue;
+                               else                                    foundV6 = mDNStrue;
+                       }
+               }
+       }
        
-       // Set up each interface that is active, multicast-capable, and not the loopback interface or point-to-point.
+       // For efficiency, we don't register a loopback interface when other interfaces of that family are available.
        
-       flagMask = IFF_UP | IFF_MULTICAST | IFF_LOOPBACK | IFF_POINTOPOINT;
-       flagTest = IFF_UP | IFF_MULTICAST;
+       if( !foundV4 && loopbackV4 ) AddInterfaceToList( inMDNS, loopbackV4, inUTC );
+       if( !foundV6 && loopbackV6 ) AddInterfaceToList( inMDNS, loopbackV6, inUTC );
+       freeifaddrs( ifaList );
+       if( IsValidSocket( infoSock ) ) close_compat( infoSock );
        
-       err = getifaddrs( &addrs );
-       require_noerr( err, exit );
+       // The list is complete. Set the McastTxRx setting for each interface. We always send and receive using IPv4.
+       // To reduce traffic, we send and receive using IPv6 only on interfaces that have no routable IPv4 address.
+       // Having a routable IPv4 address assigned is a reasonable indicator of being on a large, configured network,
+       // which means there's a good chance that most or all the other devices on that network should also have v4.
+       // By doing this we lose the ability to talk to true v6-only devices on that link, but we cut the packet rate in half.
+       // At this time, reducing the packet rate is more important than v6-only devices on a large configured network,
+       // so we are willing to make that sacrifice.
        
-       for( p = addrs; p; p = p->ifa_next )
+       for( i = inMDNS->p->interfaceList; i; i = i->next )
        {
-               if( ( p->ifa_flags & flagMask ) == flagTest )
+               if( i->exists )
                {
-                       err = SetupInterface( inMDNS, p, &item );
-                       require_noerr( err, exit );
+                       mDNSBool        txrx;
                        
-                       *next = item;
-                       next = &item->next;
+                       txrx = i->multicast && ( ( i->ifinfo.ip.type == mDNSAddrType_IPv4 ) || !FindRoutableIPv4( inMDNS, i->scopeID ) );
+                       if( i->ifinfo.McastTxRx != txrx )
+                       {
+                               i->ifinfo.McastTxRx = txrx;
+                               i->exists                       = 2;    // 2=state change; need to de-register and re-register this interface.
+                       }
                }
        }
-       err = mStatus_NoError;
        
-exit:
-       if( addrs )
+       // Set up the user-specified, friendly name, which is allowed to be full UTF-8.
+       
+       mDNS_snprintf( defaultName, sizeof( defaultName ), "Device-%02X:%02X:%02X:%02X:%02X:%02X",
+               primaryMAC.b[ 0 ], primaryMAC.b[ 1 ], primaryMAC.b[ 2 ], primaryMAC.b[ 3 ], primaryMAC.b[ 4 ], primaryMAC.b[ 5 ] );
+       
+       MakeDomainLabelFromLiteralString( &nicelabel, "Put Nice Name Here" ); // $$$ Implementers: Fill in nice name of device.
+       if( nicelabel.c[ 0 ] == 0 ) MakeDomainLabelFromLiteralString( &nicelabel, defaultName );
+       
+       // Set up the RFC 1034-compliant label. If not set or it is not RFC 1034 compliant, try the user-specified nice name.
+       
+       MakeDomainLabelFromLiteralString( &tmp, "Put-DNS-Name-Here" ); // $$$ Implementers: Fill in DNS name of device.
+       ConvertUTF8PstringToRFC1034HostLabel( tmp.c, &hostlabel );
+       if( hostlabel.c[ 0 ] == 0 ) ConvertUTF8PstringToRFC1034HostLabel( nicelabel.c, &hostlabel );
+       if( hostlabel.c[ 0 ] == 0 ) MakeDomainLabelFromLiteralString( &hostlabel, defaultName );
+       
+       // Update our globals and mDNS with the new labels.
+       
+       if( !SameDomainLabel( inMDNS->p->userNiceLabel.c, nicelabel.c ) )
        {
-               freeifaddrs( addrs );
+               dmsg( kDebugLevelInfo, DEBUG_NAME "Updating nicelabel to \"%#s\"\n", nicelabel.c );
+               inMDNS->p->userNiceLabel        = nicelabel;
+               inMDNS->nicelabel                       = nicelabel;
        }
-       if( err )
+       if( !SameDomainLabel( inMDNS->p->userHostLabel.c, hostlabel.c ) )
        {
-               TearDownInterfaceList( inMDNS );
+               dmsg( kDebugLevelInfo, DEBUG_NAME "Updating hostlabel to \"%#s\"\n", hostlabel.c );
+               inMDNS->p->userHostLabel        = hostlabel;
+               inMDNS->hostlabel                       = hostlabel;
+               mDNS_SetFQDN( inMDNS );
        }
-       dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface list done (err=%ld)\n", err );
-       return( err );
+       return( mStatus_NoError );
 }
 
 //===========================================================================================================================
-//     TearDownInterfaceList
+//     AddInterfaceToList
 //===========================================================================================================================
 
-mDNSlocal mStatus      TearDownInterfaceList( mDNS * const inMDNS )
+mDNSlocal NetworkInterfaceInfoVxWorks *        AddInterfaceToList( mDNS *const inMDNS, struct ifaddrs *inIFA, mDNSs32 inUTC )
 {
-       dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down interface list\n" );
-       check( inMDNS );
+       mStatus                                                         err;
+       mDNSAddr                                                        ip;
+       mDNSAddr                                                        mask;
+       mDNSu32                                                         scopeID;
+       NetworkInterfaceInfoVxWorks **          p;
+       NetworkInterfaceInfoVxWorks *           i;
+               
+       i = NULL;
+       
+       err = SockAddrToMDNSAddr( inIFA->ifa_addr, &ip );
+       require_noerr( err, exit );
        
-       // Tear down all the interfaces.
+       err = SockAddrToMDNSAddr( inIFA->ifa_netmask, &mask );
+       require_noerr( err, exit );
+       
+       // Search for an existing interface with the same info. If found, just return that one.
        
-       while( inMDNS->p->interfaceList )
+       scopeID = if_nametoindex( inIFA->ifa_name );
+       check( scopeID );
+       for( p = &inMDNS->p->interfaceList; *p; p = &( *p )->next )
        {
-               MDNSInterfaceItem *             item;
-               
-               item = inMDNS->p->interfaceList;
-               inMDNS->p->interfaceList = item->next;
-               
-               TearDownInterface( inMDNS, item );
+               if( ( scopeID == ( *p )->scopeID ) && mDNSSameAddress( &ip, &( *p )->ifinfo.ip ) )
+               {
+                       dmsg( kDebugLevelInfo, DEBUG_NAME "%s: Found existing interface %u with address %#a at %#p\n", __ROUTINE__, 
+                               scopeID, &ip, *p );
+                       ( *p )->exists = mDNStrue;
+                       i = *p;
+                       goto exit;
+               }
        }
        
-       dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down interface list done\n" );
-       return( mStatus_NoError );
+       // Allocate the new interface info and fill it out.
+       
+       i = (NetworkInterfaceInfoVxWorks *) calloc( 1, sizeof( *i ) );
+       require( i, exit );
+       
+       dmsg( kDebugLevelInfo, DEBUG_NAME "%s: Making   new   interface %u with address %#a at %#p\n", __ROUTINE__, scopeID, &ip, i );
+       strncpy( i->ifinfo.ifname, inIFA->ifa_name, sizeof( i->ifinfo.ifname ) );       
+       i->ifinfo.ifname[ sizeof( i->ifinfo.ifname ) - 1 ] = '\0';
+       i->ifinfo.InterfaceID   = NULL;
+       i->ifinfo.ip                    = ip;
+       i->ifinfo.mask                  = mask;
+       i->ifinfo.Advertise             = inMDNS->AdvertiseLocalAddresses;
+       i->ifinfo.McastTxRx             = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList.
+       
+       i->next                                 = NULL;
+       i->exists                               = mDNStrue;
+       i->lastSeen                             = inUTC;
+       i->scopeID                              = scopeID;
+       i->family                               = inIFA->ifa_addr->sa_family;
+       i->multicast                    = ( inIFA->ifa_flags & IFF_MULTICAST ) && !( inIFA->ifa_flags & IFF_POINTOPOINT );
+       
+       i->ss.info                              = i;
+       i->ss.sockV4                    = kInvalidSocketRef;
+       i->ss.sockV6                    = kInvalidSocketRef;
+       *p = i;
+       
+exit:
+       return( i );
 }
 
 //===========================================================================================================================
-//     SetupInterface
+//     SetupActiveInterfaces
+//
+//     Returns a count of non-link local IPv4 addresses registered.
 //===========================================================================================================================
 
-mDNSlocal mStatus      SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inAddr, MDNSInterfaceItem **outItem )
+#define        mDNSAddressIsNonLinkLocalIPv4( X )      \
+       ( ( ( X )->type == mDNSAddrType_IPv4 ) && ( ( ( X )->ip.v4.b[ 0 ] != 169 ) || ( ( X )->ip.v4.b[ 1 ] != 254 ) ) )
+
+mDNSlocal int  SetupActiveInterfaces( mDNS *const inMDNS, mDNSs32 inUTC )
 {
-       mStatus                                                 err;
-       MDNSInterfaceItem *                             item;
-       MDNSSocketRef                                   socketRef;
-       const struct sockaddr_in *              ipv4, *mask;
-       
-       dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface (name=%s)\n", inAddr->ifa_name );
-       check( inMDNS );
-       check( inAddr );
-       check( inAddr->ifa_addr );
-       ipv4 = (const struct sockaddr_in *) inAddr->ifa_addr;
-       mask = (const struct sockaddr_in *) inAddr->ifa_netmask;
-       check( outItem );
-       
-       // Allocate memory for the info item.
+       int                                                                     count;
+       NetworkInterfaceInfoVxWorks *           i;
        
-       item = (MDNSInterfaceItem *) calloc( 1, sizeof( *item ) );
-       require_action( item, exit, err = mStatus_NoMemoryErr );
-       strcpy( item->name, inAddr->ifa_name );
-       item->multicastSocketRef        = kInvalidSocketRef;
-       item->sendingSocketRef          = kInvalidSocketRef;
-       
-       // Set up the multicast DNS (port 5353) socket for this interface.
-       
-       err = SetupSocket( inMDNS, inAddr, MulticastDNSPort, &socketRef );
-       require_noerr( err, exit );
-       item->multicastSocketRef = socketRef;
+       count = 0;
+       for( i = inMDNS->p->interfaceList; i; i = i->next )
+       {
+               NetworkInterfaceInfo *                          n;
+               NetworkInterfaceInfoVxWorks *           primary;
                
-       // Set up the sending socket for this interface.
-       
-       err = SetupSocket( inMDNS, inAddr, zeroIPPort, &socketRef );
-       require_noerr( err, exit );
-       item->sendingSocketRef = socketRef;
-       
-       // Register this interface with mDNS.
-       
-       item->hostSet.InterfaceID             = (mDNSInterfaceID) item;
-       item->hostSet.ip  .type               = mDNSAddrType_IPv4;
-       item->hostSet.ip  .ip.v4.NotAnInteger = ipv4->sin_addr.s_addr;
-       item->hostSet.mask.type               = mDNSAddrType_IPv4;
-       item->hostSet.mask.ip.v4.NotAnInteger = mask->sin_addr.s_addr;
-       item->hostSet.ifname[0]               = 0;
-       item->hostSet.Advertise               = inMDNS->AdvertiseLocalAddresses;
-       item->hostSet.McastTxRx               = mDNStrue;
+               if( !i->exists ) continue;
+               
+               // Search for the primary interface and sanity check it.
+               
+               n = &i->ifinfo;
+               primary = FindInterfaceByIndex( inMDNS, i->family, i->scopeID );
+               if( !primary )
+               {
+                       dmsg( kDebugLevelError, DEBUG_NAME "%s: ERROR! didn't find %s(%u)\n", __ROUTINE__, i->ifinfo.ifname, i->scopeID );
+                       continue;
+               }
+               if( n->InterfaceID && ( n->InterfaceID != (mDNSInterfaceID) primary ) )
+               {
+                       dmsg( kDebugLevelError, DEBUG_NAME "%s: ERROR! n->InterfaceID %#p != primary %#p\n", __ROUTINE__, 
+                               n->InterfaceID, primary );
+                       n->InterfaceID = NULL;
+               }
+               
+               // If n->InterfaceID is set, it means we've already called mDNS_RegisterInterface() for this interface.
+               // so we don't need to call it again. Otherwise, register the interface with mDNS.
+               
+               if( !n->InterfaceID )
+               {
+                       mDNSBool                flapping;
+                       
+                       n->InterfaceID = (mDNSInterfaceID) primary;
+                       
+                       // If lastSeen == inUTC, then this is a brand-new interface, or an interface that never went away.
+                       // If lastSeen != inUTC, then this is an old interface, that went away for (inUTC - lastSeen) seconds.
+                       // If it's is an old one that went away and came back in less than a minute, we're in a flapping scenario.
+                       
+                       flapping = ( ( inUTC - i->lastSeen ) > 0 ) && ( ( inUTC - i->lastSeen ) < 60 );
+                       mDNS_RegisterInterface( inMDNS, n, flapping ? mDNSPlatformOneSecond * 5 : 0 );
+                       if( mDNSAddressIsNonLinkLocalIPv4( &i->ifinfo.ip ) ) ++count;
+                       
+                       dmsg( kDebugLevelInfo, DEBUG_NAME "%s:   Registered    %8s(%u) InterfaceID %#p %#a%s%s\n", __ROUTINE__, 
+                               i->ifinfo.ifname, i->scopeID, primary, &n->ip, 
+                               flapping                        ? " (Flapping)" : "", 
+                               n->InterfaceActive      ? " (Primary)"  : "" );
+               }
+               
+               // Set up a socket if it's not already set up. If multicast is not enabled on this interface then we 
+               // don't need a socket since unicast traffic will be handled on the unicast socket.
+               
+               if( n->McastTxRx )
+               {
+                       mStatus         err;
+                       
+                       if( ( ( i->family == AF_INET  ) && !IsValidSocket( primary->ss.sockV4 ) ) || 
+                               ( ( i->family == AF_INET6 ) && !IsValidSocket( primary->ss.sockV6 ) ) )
+                       {
+                               err = SetupSocket( inMDNS, &i->ifinfo.ip, mDNStrue, i->family, &primary->ss );
+                               check_noerr( err );
+                       }
+               }
+               else
+               {
+                       dmsg( kDebugLevelInfo, DEBUG_NAME "%s:   No Tx/Rx on   %8s(%u) InterfaceID %#p %#a\n", __ROUTINE__, 
+                               i->ifinfo.ifname, i->scopeID, primary, &n->ip );
+               }
+       }
+       return( count );
+}
 
-       err = mDNS_RegisterInterface( inMDNS, &item->hostSet, 0 );
-       require_noerr( err, exit );
-       item->hostRegistered = mDNStrue;
-       
-       dlog( kDebugLevelInfo, DEBUG_NAME "Registered IP address: %u.%u.%u.%u\n", 
-                 item->hostSet.ip.ip.v4.b[ 0 ], item->hostSet.ip.ip.v4.b[ 1 ], 
-                 item->hostSet.ip.ip.v4.b[ 2 ], item->hostSet.ip.ip.v4.b[ 3 ] );
-       
-       // Success!
-       
-       *outItem = item;
-       item = NULL;
+//===========================================================================================================================
+//     MarkAllInterfacesInactive
+//===========================================================================================================================
+
+mDNSlocal void MarkAllInterfacesInactive( mDNS *const inMDNS, mDNSs32 inUTC )
+{
+       NetworkInterfaceInfoVxWorks *           i;
        
-exit:
-       if( item )
+       for( i = inMDNS->p->interfaceList; i; i = i->next )
        {
-               TearDownInterface( inMDNS, item );
+               if( !i->exists ) continue;
+               i->lastSeen = inUTC;
+               i->exists       = mDNSfalse;
        }
-       dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface done (name=%s, err=%ld)\n", inAddr->ifa_name, err );
-       return( err );
 }
 
 //===========================================================================================================================
-//     TearDownInterface
+//     ClearInactiveInterfaces
+//
+//     Returns count of non-link local IPv4 addresses de-registered.
 //===========================================================================================================================
 
-mDNSlocal mStatus      TearDownInterface( mDNS * const inMDNS, MDNSInterfaceItem *inItem )
+mDNSlocal int  ClearInactiveInterfaces( mDNS *const inMDNS, mDNSs32 inUTC, mDNSBool inClosing )
 {
-       MDNSSocketRef           socketRef;
-       
-       check( inMDNS );
-       check( inItem );
-       
-       // Deregister this interface with mDNS.
-       
-       dlog( kDebugLevelInfo, DEBUG_NAME "Deregistering IP address: %u.%u.%u.%u\n", 
-                 inItem->hostSet.ip.ip.v4.b[ 0 ], inItem->hostSet.ip.ip.v4.b[ 1 ], 
-                 inItem->hostSet.ip.ip.v4.b[ 2 ], inItem->hostSet.ip.ip.v4.b[ 3 ] );
-       
-       if( inItem->hostRegistered )
+       int                                                                     count;
+       NetworkInterfaceInfoVxWorks *           i;
+       NetworkInterfaceInfoVxWorks **          p;
+       
+       // First pass:
+       // If an interface is going away, then de-register it from mDNSCore.
+       // We also have to de-register it if the primary interface that it's using for its InterfaceID is going away.
+       // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
+       // it refers to has gone away, we'll crash. Don't actually close the sockets or free the memory yet though: 
+       // When the last representative of an interface goes away mDNSCore may want to send goodbye packets on that 
+       // interface. (Not yet implemented, but a good idea anyway.).
+       
+       count = 0;
+       for( i = inMDNS->p->interfaceList; i; i = i->next )
        {
-               inItem->hostRegistered = mDNSfalse;
-               mDNS_DeregisterInterface( inMDNS, &inItem->hostSet );
+               NetworkInterfaceInfoVxWorks *           primary;
+               
+               // 1. If this interface is no longer active, or its InterfaceID is changing, de-register it.
+               
+               if( !i->ifinfo.InterfaceID ) continue;
+               primary = FindInterfaceByIndex( inMDNS, i->family, i->scopeID );
+               if( ( i->exists == 0 ) || ( i->exists == 2 ) || ( i->ifinfo.InterfaceID != (mDNSInterfaceID) primary ) )
+               {
+                       dmsg( kDebugLevelInfo, DEBUG_NAME "%s: Deregistering %8s(%u) InterfaceID %#p %#a%s\n", __ROUTINE__, 
+                               i->ifinfo.ifname, i->scopeID, i->ifinfo.InterfaceID, &i->ifinfo.ip, 
+                               i->ifinfo.InterfaceActive ? " (Primary)" : "" );
+                       
+                       mDNS_DeregisterInterface( inMDNS, &i->ifinfo );
+                       i->ifinfo.InterfaceID = NULL;
+                       if( mDNSAddressIsNonLinkLocalIPv4( &i->ifinfo.ip ) ) ++count;
+               }
        }
        
-       // Close the multicast socket.
+       // Second pass:
+       // Now that everything that's going to de-register has done so, we can close sockets and free the memory.
        
-       socketRef = inItem->multicastSocketRef;
-       inItem->multicastSocketRef = kInvalidSocketRef;
-       if( socketRef != kInvalidSocketRef )
+       p = &inMDNS->p->interfaceList;
+       while( *p )
        {
-               dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down multicast socket %d\n", socketRef );
-               close( socketRef );
-       }
+               i = *p;
+               
+               // 2. Close all our sockets. We'll recreate them later as needed.
+               // (We may have previously had both v4 and v6, and we may not need both any more.).
                
-       // Close the sending socket.
+               ForgetSocket( &i->ss.sockV4 );
+               ForgetSocket( &i->ss.sockV6 );
+               
+               // 3. If no longer active, remove the interface from the list and free its memory.
+               
+               if( !i->exists )
+               {
+                       mDNSBool                deleteIt;
+                       
+                       if( inClosing )
+                       {
+                               check_string( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) i ) == 0, "closing with in-use records!" );
+                               deleteIt = mDNStrue;
+                       }
+                       else
+                       {
+                               if( i->lastSeen == inUTC ) i->lastSeen = inUTC - 1;
+                               deleteIt = ( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) i ) == 0 ) && ( ( inUTC - i->lastSeen ) >= 60 );
+                       }
+                       dmsg( kDebugLevelInfo, DEBUG_NAME "%s: %-13s %8s(%u) InterfaceID %#p %#a Age %d%s\n", __ROUTINE__, 
+                               deleteIt ? "Deleting" : "Holding", i->ifinfo.ifname, i->scopeID, i->ifinfo.InterfaceID, &i->ifinfo.ip, 
+                               inUTC - i->lastSeen, i->ifinfo.InterfaceActive ? " (Primary)" : "" );
+                       if( deleteIt )
+                       {
+                               *p = i->next;
+                               free( i );
+                               continue;
+                       }
+               }
+               p = &i->next;
+       }
+       return( count );
+}
+
+//===========================================================================================================================
+//     FindRoutableIPv4
+//===========================================================================================================================
+
+mDNSlocal NetworkInterfaceInfoVxWorks *        FindRoutableIPv4( mDNS *const inMDNS, mDNSu32 inScopeID )
+{
+#if( MDNS_EXCLUDE_IPV4_ROUTABLE_IPV6 )
+       NetworkInterfaceInfoVxWorks *           i;
        
-       socketRef = inItem->sendingSocketRef;
-       inItem->sendingSocketRef = kInvalidSocketRef;
-       if( socketRef != kInvalidSocketRef )
+       for( i = inMDNS->p->interfaceList; i; i = i->next )
        {
-               dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down sending socket %d\n", socketRef );
-               close( socketRef );
+               if( i->exists && ( i->scopeID == inScopeID ) && mDNSAddressIsNonLinkLocalIPv4( &i->ifinfo.ip ) )
+               {
+                       break;
+               }
        }
+       return( i );
+#else
+       DEBUG_UNUSED( inMDNS );
+       DEBUG_UNUSED( inScopeID );
+       
+       return( NULL );
+#endif
+}
+
+//===========================================================================================================================
+//     FindInterfaceByIndex
+//===========================================================================================================================
+
+mDNSlocal NetworkInterfaceInfoVxWorks *        FindInterfaceByIndex( mDNS *const inMDNS, int inFamily, mDNSu32 inIndex )
+{
+       NetworkInterfaceInfoVxWorks *           i;
        
-       // Free the memory used by the interface info.
+       check( inIndex != 0 );
        
-       free( inItem ); 
-       return( mStatus_NoError );
+       for( i = inMDNS->p->interfaceList; i; i = i->next )
+       {
+               if( i->exists && ( i->scopeID == inIndex ) &&
+                       ( MDNS_AAAA_OVER_IPV4                                                                                                                   ||
+                         ( ( inFamily == AF_INET  ) && ( i->ifinfo.ip.type == mDNSAddrType_IPv4 ) )    ||
+                         ( ( inFamily == AF_INET6 ) && ( i->ifinfo.ip.type == mDNSAddrType_IPv6 ) ) ) )
+               {
+                       return( i );
+               }
+       }
+       return( NULL );
 }
 
 //===========================================================================================================================
 //     SetupSocket
 //===========================================================================================================================
 
-mDNSlocal mStatus
-       SetupSocket( 
-               mDNS * const                    inMDNS, 
-               const struct ifaddrs *  inAddr, 
-               mDNSIPPort                              inPort, 
-               MDNSSocketRef *                 outSocketRef  )
+mDNSlocal mStatus      SetupSocket( mDNS *const inMDNS, const mDNSAddr *inAddr, mDNSBool inMcast, int inFamily, SocketSet *inSS )
 {
-       mStatus                                                 err;
-       MDNSSocketRef                                   socketRef;
-       int                                                             option;
-       unsigned char                                   optionByte;
-       struct ip_mreq                                  mreq;
-       const struct sockaddr_in *              ipv4;
-       struct sockaddr_in                              addr;
-       mDNSv4Addr                                              ip;
-       
-       dlog( kDebugLevelVerbose, DEBUG_NAME "setting up socket done\n" );
-       check( inMDNS );
+       mStatus                 err;
+       SocketRef *             sockPtr;
+       mDNSIPPort              port;
+       SocketRef               sock;
+       const int               on = 1;
+               
        check( inAddr );
-       check( inAddr->ifa_addr );
-       ipv4 = (const struct sockaddr_in *) inAddr->ifa_addr;
-       check( outSocketRef );
+       check( inSS );
        
-       // Set up a UDP socket for multicast DNS. 
+       sockPtr = ( inFamily == AF_INET ) ? &inSS->sockV4 : &inSS->sockV6;
+       port    = ( inMcast || inMDNS->CanReceiveUnicastOn5353 ) ? MulticastDNSPort : zeroIPPort;
        
-       socketRef = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
-       require_errno_action( socketRef, errno, exit, err = mStatus_UnknownErr );
-               
-       // A port of zero means this socket is for sending and should be set up for sending. Otherwise, it is for receiving 
-       // and should be set up for receiving. The reason for separate sending vs receiving sockets is to workaround problems
-       // with VxWorks IP stack when using dynamic IP configuration such as DHCP (problems binding to wildcard IP when the
-       // IP address later changes). Since we have to bind the Multicast DNS address to workaround these issues we have to
-       // use a separate sending socket since it is illegal to send a packet with a multicast source address (RFC 1122).
+       sock = socket( inFamily, SOCK_DGRAM, IPPROTO_UDP );
+       err = translate_errno( IsValidSocket( sock ), errno_compat(), mStatus_UnknownErr );
+       require_noerr( err, exit );
        
-       if( inPort.NotAnInteger != zeroIPPort.NotAnInteger )
+       // Allow multiple listeners if this is a multicast port.
+       
+       if( port.NotAnInteger )
        {       
-               // Turn on reuse port option so multiple servers can listen for Multicast DNS packets.
+               err = setsockopt( sock, SOL_SOCKET, SO_REUSEPORT, (char *) &on, sizeof( on ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
+       }
+       
+       // Set up the socket based on the family (IPv4 or IPv6).
+       
+       if( inFamily == AF_INET )
+       {
+               const int                               ttlV4           = 255;
+               const u_char                    ttlV4Mcast      = 255;
+               struct sockaddr_in              sa4;
                
-               option = 1;
-               err = setsockopt( socketRef, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
-               check_errno( err, errno );
+               // Receive destination addresses so we know which address the packet was sent to.
                
-               // Join the all-DNS multicast group so we receive Multicast DNS packets.
+               err = setsockopt( sock, IPPROTO_IP, IP_RECVDSTADDR, (char *) &on, sizeof( on ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
                
-               ip.NotAnInteger                         = ipv4->sin_addr.s_addr;
-               mreq.imr_multiaddr.s_addr       = AllDNSLinkGroupv4.NotAnInteger;
-               mreq.imr_interface.s_addr       = ip.NotAnInteger;
-               err = setsockopt( socketRef, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof( mreq ) );
-               check_errno( err, errno );
+               // Receive interface indexes so we know which interface received the packet.
                
-               // Bind to the multicast DNS address and port 5353.
+               err = setsockopt( sock, IPPROTO_IP, IP_RECVIF, (char *) &on, sizeof( on ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
                
-               memset( &addr, 0, sizeof( addr ) );
-               addr.sin_family                 = AF_INET;
-               addr.sin_port                   = inPort.NotAnInteger;
-               addr.sin_addr.s_addr    = AllDNSLinkGroupv4.NotAnInteger;
-               err = bind( socketRef, (struct sockaddr *) &addr, sizeof( addr ) );
-               check_errno( err, errno );
+               // Join the multicast group on this interface and specify the outgoing interface, if it's for multicast receiving.
                
-               dlog( kDebugLevelVerbose, DEBUG_NAME "setting up socket done (%s, %u.%u.%u.%u:%u, %d)\n", 
-                         inAddr->ifa_name, ip.b[ 0 ], ip.b[ 1 ], ip.b[ 2 ], ip.b[ 3 ], ntohs( inPort.NotAnInteger ), socketRef );
+               if( inMcast )
+               {
+                       struct in_addr          addrV4;
+                       struct ip_mreq          mreqV4;
+                       
+                       addrV4.s_addr                           = inAddr->ip.v4.NotAnInteger;
+                       mreqV4.imr_multiaddr.s_addr = AllDNSLinkGroupv4.NotAnInteger;
+                       mreqV4.imr_interface            = addrV4;
+                       err = setsockopt( sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreqV4, sizeof( mreqV4 ) );
+                       check_translated_errno( err == 0, errno_compat(), kOptionErr );
+                       
+                       err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_IF, (char *) &addrV4, sizeof( addrV4 ) );
+                       check_translated_errno( err == 0, errno_compat(), kOptionErr );
+               }
+               
+               // Send unicast packets with TTL 255 (helps against spoofing).
+               
+               err = setsockopt( sock, IPPROTO_IP, IP_TTL, (char *) &ttlV4, sizeof( ttlV4 ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
+               
+               // Send multicast packets with TTL 255 (helps against spoofing).
+               
+               err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &ttlV4Mcast, sizeof( ttlV4Mcast ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
+               
+               // Start listening for packets.
+               
+               memset( &sa4, 0, sizeof( sa4 ) );
+               sa4.sin_len                     = sizeof( sa4 );
+               sa4.sin_family          = AF_INET;
+               sa4.sin_port            = port.NotAnInteger;
+               sa4.sin_addr.s_addr     = htonl( INADDR_ANY ); // We want to receive multicasts AND unicasts on this socket.
+               err = bind( sock, (struct sockaddr *) &sa4, sizeof( sa4 ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
        }
-       else
+       else if( inFamily == AF_INET6 )
        {
-               // Bind to the interface address and multicast DNS port.
+               struct sockaddr_in6             sa6;
+               const int                               ttlV6 = 255;
                
-               ip.NotAnInteger                 = ipv4->sin_addr.s_addr;
-               memset( &addr, 0, sizeof( addr ) );
-               addr.sin_family                 = AF_INET;
-               addr.sin_port                   = MulticastDNSPort.NotAnInteger;
-               addr.sin_addr.s_addr    = ip.NotAnInteger;
-               err = bind( socketRef, (struct sockaddr *) &addr, sizeof( addr ) );
-               check_errno( err, errno );
+               // Receive destination addresses and interface index so we know where the packet was received and intended.
                
-               // Direct multicast packets to the specified interface.
+               err = setsockopt( sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *) &on, sizeof( on ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
                
-               addr.sin_addr.s_addr = ip.NotAnInteger;
-               err = setsockopt( socketRef, IPPROTO_IP, IP_MULTICAST_IF, (char *) &addr.sin_addr, sizeof( addr.sin_addr ) );
-               check_errno( err, errno );
+               // Receive only IPv6 packets because otherwise, we may get IPv4 addresses as IPv4-mapped IPv6 addresses.
                
-               // Set the TTL of outgoing unicast packets to 255 (helps against spoofing).
+               err = setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on, sizeof( on ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
                
-               option = 255;
-               err = setsockopt( socketRef, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) );
-               check_errno( err, errno );
+               // Join the multicast group on this interface and specify the outgoing interface, if it's for multicast receiving.
                
-               // Set the TTL of outgoing multicast packets to 255 (helps against spoofing).
+               if( inMcast )
+               {
+                       u_int                                   ifindex;
+                       struct ipv6_mreq                mreqV6;
+                       
+                       ifindex                                 = inSS->info->scopeID;
+                       mreqV6.ipv6mr_interface = ifindex;
+                       mreqV6.ipv6mr_multiaddr = *( (struct in6_addr * ) &AllDNSLinkGroupv6 );
+                       err = setsockopt( sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreqV6, sizeof( mreqV6 ) );
+                       check_translated_errno( err == 0, errno_compat(), kOptionErr );
+                       
+                       err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &ifindex, sizeof( ifindex ) );
+                       check_translated_errno( err == 0, errno_compat(), kOptionErr );
+               }
                
-               optionByte = 255;
-               err = setsockopt( socketRef, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &optionByte, sizeof( optionByte ) );
-               check_errno( err, errno );
+               // Send unicast packets with TTL 255 (helps against spoofing).
                
-               // WARNING: Setting this option causes unicast responses to be routed to the wrong interface so they are 
-               // WARNING: disabled. These options were only hints to improve 802.11 performance (and not implemented) anyway.
+               err = setsockopt( sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *) &ttlV6, sizeof( ttlV6 ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
                
-#if 0
-               // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to maximize 802.11 multicast rate.
+               // Send multicast packets with TTL 255 (helps against spoofing).
                
-               option = IPTOS_LOWDELAY | IPTOS_THROUGHPUT;
-               err = setsockopt( socketRef, IPPROTO_IP, IP_TOS, (char *) &option, sizeof( option ) );
-               check_errno( err, errno );
-#endif
-       
-               dlog( kDebugLevelVerbose, DEBUG_NAME "setting up sending socket done (%s, %u.%u.%u.%u, %d)\n", 
-                         inAddr->ifa_name, ip.b[ 0 ], ip.b[ 1 ], ip.b[ 2 ], ip.b[ 3 ], socketRef );
+               err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &ttlV6, sizeof( ttlV6 ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
+               
+               // Receive our own packets for same-machine operation.
+               
+               err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &on, sizeof( on ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
+               
+               // Start listening for packets.
+               
+               memset( &sa6, 0, sizeof( sa6 ) );
+               sa6.sin6_len            = sizeof( sa6 );
+               sa6.sin6_family         = AF_INET6;
+               sa6.sin6_port           = port.NotAnInteger;
+               sa6.sin6_flowinfo       = 0;
+               sa6.sin6_addr           = in6addr_any; // We want to receive multicasts AND unicasts on this socket.
+               sa6.sin6_scope_id       = 0;
+               err = bind( sock, (struct sockaddr *) &sa6, sizeof( sa6 ) );
+               check_translated_errno( err == 0, errno_compat(), kOptionErr );
+       }
+       else
+       {
+               dmsg( kDebugLevelError, DEBUG_NAME "%s: unsupport socket family (%d)\n", __ROUTINE__, inFamily );
+               err = kUnsupportedErr;
+               goto exit;
        }
        
-       // Success!
+       // Make the socket non-blocking so we can potentially get multiple packets per select call.
        
-       *outSocketRef = socketRef;
-       socketRef = kInvalidSocketRef;
+       err = ioctl( sock, FIONBIO, (int) &on );
+       check_translated_errno( err == 0, errno_compat(), kOptionErr );
+       
+       *sockPtr = sock;
+       sock = kInvalidSocketRef;
        err = mStatus_NoError;
        
 exit:
-       if( socketRef != kInvalidSocketRef )
+       if( IsValidSocket( sock ) ) close_compat( sock );
+       return( err );
+}
+
+//===========================================================================================================================
+//     SockAddrToMDNSAddr
+//===========================================================================================================================
+
+mDNSlocal mStatus      SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP )
+{
+       mStatus         err;
+       
+       check( inSA );
+       check( outIP );
+       
+       if( inSA->sa_family == AF_INET )
+       {
+               struct sockaddr_in *            sa4;
+               
+               sa4 = (struct sockaddr_in *) inSA;
+               outIP->type                             = mDNSAddrType_IPv4;
+               outIP->ip.v4.NotAnInteger       = sa4->sin_addr.s_addr;
+               err = mStatus_NoError;
+       }
+       else if( inSA->sa_family == AF_INET6 )
+       {
+               struct sockaddr_in6 *           sa6;
+               
+               sa6 = (struct sockaddr_in6 *) inSA;
+               outIP->type     = mDNSAddrType_IPv6;
+               outIP->ip.v6    = *( (mDNSv6Addr *) &sa6->sin6_addr );
+               if( IN6_IS_ADDR_LINKLOCAL( &sa6->sin6_addr ) ) outIP->ip.v6.w[ 1 ] = 0;
+               err = mStatus_NoError;
+       }
+       else
        {
-               close( socketRef );
+               dmsg( kDebugLevelError, DEBUG_NAME "%s: invalid sa_family (%d)\n", __ROUTINE__, inSA->sa_family );
+               err = mStatus_BadParamErr;
        }
        return( err );
 }
@@ -1312,19 +1503,13 @@ exit:
 mDNSlocal mStatus      SetupCommandPipe( mDNS * const inMDNS )
 {
        mStatus         err;
+               
+       err = pipeDevCreate( "/pipe/mDNS", 32, 1 );
+       check_translated_errno( err == 0, errno_compat(), kUnknownErr );
        
-       // Clean up any leftover command pipe.
-       
-       TearDownCommandPipe( inMDNS );
-       
-       // Create the pipe device and open it.
-       
-       pipeDevCreate( kMDNSPipeName, kMDNSPipeMessageQueueSize, kMDNSPipeMessageSize );
-       
-       inMDNS->p->commandPipe = open( kMDNSPipeName, O_RDWR, 0 );
-       require_errno_action( inMDNS->p->commandPipe, errno, exit, err = mStatus_UnsupportedErr );
-       
-       err = mStatus_NoError;
+       inMDNS->p->commandPipe = open( "/pipe/mDNS", O_RDWR, 0 );
+       err = translate_errno( inMDNS->p->commandPipe != ERROR, errno_compat(), mStatus_UnsupportedErr );
+       require_noerr( err, exit );
        
 exit:
        return( err );
@@ -1336,15 +1521,17 @@ exit:
 
 mDNSlocal mStatus      TearDownCommandPipe( mDNS * const inMDNS )
 {
+       mStatus         err;
+       
        if( inMDNS->p->commandPipe != ERROR )
        {
-               close( inMDNS->p->commandPipe );
-#ifdef _WRS_VXWORKS_5_X
-               // pipeDevDelete is not defined in older versions of VxWorks
-               pipeDevDelete( kMDNSPipeName, FALSE );
-#endif
+               err = close( inMDNS->p->commandPipe );
+               check_translated_errno( err == 0, errno_compat(), kUnknownErr );
                inMDNS->p->commandPipe = ERROR;
-       }       
+               
+               err = pipeDevDelete( "/pipe/mDNS", FALSE );
+               check_translated_errno( err == 0, errno_compat(), kUnknownErr );
+       }
        return( mStatus_NoError );
 }
 
@@ -1356,12 +1543,11 @@ mDNSlocal mStatus       SendCommand( const mDNS * const inMDNS, MDNSPipeCommandCode in
 {
        mStatus         err;
        
-       require_action( inMDNS->p->commandPipe != ERROR, exit, err = mStatus_NotInitializedErr );
+       require_action_quiet( inMDNS->p->commandPipe != ERROR, exit, err = mStatus_NotInitializedErr );
        
        err = write( inMDNS->p->commandPipe, &inCommandCode, sizeof( inCommandCode ) );
-       require_errno( err, errno, exit );
-       
-       err = mStatus_NoError;
+       err = translate_errno( err >= 0, errno_compat(), kWriteErr );
+       require_noerr( err, exit );
        
 exit:
        return( err );
@@ -1374,241 +1560,129 @@ exit:
 mDNSlocal mStatus      ProcessCommand( mDNS * const inMDNS )
 {
        mStatus                                 err;
-       MDNSPipeCommandCode             commandCode;
-       
-       require_action( inMDNS->p->commandPipe != ERROR, exit, err = mStatus_NotInitializedErr );
-       
-       // Read the command code from the pipe and dispatch it.
-       
-       err = read( inMDNS->p->commandPipe, &commandCode, sizeof( commandCode ) );
-       require_errno( err, errno, exit );
+       MDNSPipeCommandCode             cmd;
+       mDNSs32                                 utc;
+               
+       err = read( inMDNS->p->commandPipe, &cmd, sizeof( cmd ) );
+       err = translate_errno( err >= 0, errno_compat(), kReadErr );
+       require_noerr( err, exit );
        
-       switch( commandCode )
+       switch( cmd )
        {
-               case kMDNSPipeCommandCodeReschedule:
-                       
-                       // Reschedule event. Do nothing here, but this will cause mDNS_Execute to run before waiting again.
-                       
-                       dlog( kDebugLevelChatty, DEBUG_NAME "reschedule\n" );
-                       break;
-               
-               case kMDNSPipeCommandCodeReconfigure:
-                       ProcessCommandReconfigure( inMDNS );
+               case kMDNSPipeCommandCodeReschedule:    // Reschedule: just break out to re-run mDNS_Execute.
                        break;
                
-               case kMDNSPipeCommandCodeQuit:
-               
-                       // Quit requested. Set quit flag and bump the config ID to let the thread exit normally.
+               case kMDNSPipeCommandCodeReconfigure:   // Reconfigure: rebuild the interface list after a config change.
+                       dmsg( kDebugLevelInfo, DEBUG_NAME "***   NETWORK CONFIGURATION CHANGE   ***\n" );
+                       mDNSPlatformLock( inMDNS );
                        
-                       dlog( kDebugLevelVerbose, DEBUG_NAME "processing pipe quit command\n" );
-                       inMDNS->p->quit = mDNStrue;
-                       ++inMDNS->p->configID;
-                       break;
-                               
-               default:
-                       dlog( kDebugLevelError, DEBUG_NAME "unknown pipe command code (code=0x%08X)\n", commandCode );
-                       err = mStatus_BadParamErr;
-                       goto exit;
+                       utc = mDNSPlatformUTC();
+                       MarkAllInterfacesInactive( inMDNS, utc );
+                       UpdateInterfaceList( inMDNS, utc );
+                       ClearInactiveInterfaces( inMDNS, utc, mDNSfalse );
+                       SetupActiveInterfaces( inMDNS, utc );
+                       
+                       mDNSPlatformUnlock( inMDNS );
+                       if( inMDNS->MainCallback ) inMDNS->MainCallback( inMDNS, mStatus_ConfigChanged );       
                        break;
+               
+               case kMDNSPipeCommandCodeQuit:                  // Quit: just set a flag so the task exits cleanly.
+                       inMDNS->p->quit = mDNStrue;
+                       break;
+               
+               default:
+                       dmsg( kDebugLevelError, DEBUG_NAME "unknown pipe command (%d)\n", cmd );
+                       err = mStatus_BadParamErr;
+                       goto exit;
        }
-       err = mStatus_NoError;
-
-exit:
-       return( err );
-}
-
-//===========================================================================================================================
-//     ProcessCommandReconfigure
-//===========================================================================================================================
-
-mDNSlocal void ProcessCommandReconfigure( mDNS *inMDNS )
-{
-       mStatus         err;
-       
-       dlog( kDebugLevelVerbose, DEBUG_NAME "processing pipe reconfigure command\n" );
-       
-       // Tear down the existing interfaces and set up new ones using the new IP info.
-       
-       mDNSPlatformLock( inMDNS );
-       
-       err = TearDownInterfaceList( inMDNS );
-       check_noerr( err );
-       
-       err = SetupInterfaceList( inMDNS );
-       check_noerr( err );
-       
-       mDNSPlatformUnlock( inMDNS );
-       
-       // Inform clients of the change.
-       
-       if( inMDNS->MainCallback )
-       {
-               inMDNS->MainCallback( inMDNS, mStatus_ConfigChanged );
-       }
-       
-       // Force mDNS to update.
-       
-       mDNSCoreMachineSleep( inMDNS, mDNSfalse );
-       
-       // Bump the config ID so the main processing loop detects the configuration change.
-       
-       ++inMDNS->p->configID;
-}
-
-#if 0
-#pragma mark -
-#pragma mark == Threads ==
-#endif
-
-//===========================================================================================================================
-//     SetupTask
-//===========================================================================================================================
-
-mDNSlocal mStatus      SetupTask( mDNS * const inMDNS )
-{
-       mStatus         err;
-       int                     task;
-       
-       dlog( kDebugLevelVerbose, DEBUG_NAME "setting up thread\n" );
-       check( inMDNS );
-       
-       // Create our main thread. Note: The task will save off its ID in the globals. We cannot do it here because the 
-       // task invokes code that needs it and the task may begin execution before taskSpawn returns the task ID.
-       // This also means code in this thread context cannot rely on the task ID until the task has fully initialized.
-       
-       task = taskSpawn( kMDNSTaskName, kMDNSTaskPriority, 0, kMDNSTaskStackSize, (FUNCPTR) Task, 
-                                         (int) inMDNS, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
-       require_action( task != ERROR, exit, err = mStatus_NoMemoryErr );
-       
-       err = mStatus_NoError;
-       
-exit:
-       dlog( kDebugLevelVerbose, DEBUG_NAME "setting up thread done (err=%ld, id=%d)\n", err, task );
-       return( err );
-}
-
-//===========================================================================================================================
-//     TearDownTask
-//===========================================================================================================================
-
-mDNSlocal mStatus      TearDownTask( mDNS * const inMDNS )
-{
-       mStatus         err;
-       
-       dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down thread\n" );
-       check( inMDNS );
-       
-       // Send a quit command to cause the thread to exit.
-       
-       SendCommand( inMDNS, kMDNSPipeCommandCodeQuit );
-       
-       // Wait for the thread to signal it has exited. Timeout in 10 seconds to handle a hung thread.
-       
-       if( inMDNS->p->quitEvent )
-       {
-               err = semTake( inMDNS->p->quitEvent, sysClkRateGet() * 10 );
-               check_noerr( err );
-       }
-       err = mStatus_NoError;
        
-       dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down thread done (err=%ld)\n", err );
+exit:
        return( err );
 }
 
+#if 0
+#pragma mark -
+#pragma mark == Threads ==
+#endif
+
 //===========================================================================================================================
 //     Task
 //===========================================================================================================================
 
 mDNSlocal void Task( mDNS *inMDNS )
 {
-       mStatus                                 err;
-       fd_set                                  allReadSet;
-       MDNSInterfaceItem *             item;
-       int                                             maxSocket;
-       long                                    configID;
-       struct timeval                  timeout;
+       mStatus                                                         err;
+       mDNSs32                                                         nextEvent;
+       fd_set                                                          readSet;
+       int                                                                     maxFd;
+       struct timeval                                          timeout;
+       NetworkInterfaceInfoVxWorks *           i;
+       int                                                                     fd;
+       int                                                                     n;
        
-       dlog( kDebugLevelVerbose, DEBUG_NAME "task starting\n" );
        check( inMDNS );
        
-       // Set up everything up.
-       
        err = TaskInit( inMDNS );
        require_noerr( err, exit );
        
-       // Main Processing Loop.
-       
        while( !inMDNS->p->quit )
        {
-               // Set up the read set here to avoid the overhead of setting it up each iteration of the main processing loop. 
-               // If the configuration changes, the server ID will be bumped, causing this code to set up the read set again.
+               // Let mDNSCore do its work then wait for an event. On idle timeouts (n == 0), just loop back to mDNS_Exceute.
                
-               TaskSetupReadSet( inMDNS, &allReadSet, &maxSocket );
-               configID = inMDNS->p->configID;
-               dlog( kDebugLevelVerbose, DEBUG_NAME "task starting processing loop (configID=%ld)\n", configID );
+               nextEvent = mDNS_Execute( inMDNS );
+               TaskSetupSelect( inMDNS, &readSet, &maxFd, nextEvent, &timeout );                       
+               n = select( maxFd + 1, &readSet, NULL, NULL, &timeout );
+               check_translated_errno( n >= 0, errno_compat(), kUnknownErr );
+               if( n == 0 ) continue;
                
-               while( configID == inMDNS->p->configID )
+               // Process interface-specific sockets with pending data.
+               
+               n = 0;
+               for( i = inMDNS->p->interfaceList; i; i = i->next )
                {
-                       mDNSs32         nextTaskTime;
-                       fd_set          readSet;
-                       int                     n;
-                       
-                       // Give the mDNS core a chance to do its work. Reset the rescheduled flag before calling mDNS_Execute
-                       // so anything that needs processing during or after causes a re-schedule to wake up the thread. The
-                       // reschedule flag is set to 1 after processing a waking up to prevent redundant reschedules while
-                       // processing packets. This introduces a window for a race condition because the thread wake-up and
-                       // reschedule set are not atomic, but this would be benign. Even if the reschedule flag is "corrupted"
-                       // like this, it would only result in a redundant reschedule since it will loop back to mDNS_Execute.
-                       
-                       inMDNS->p->rescheduled = 0;
-                       nextTaskTime = mDNS_Execute( inMDNS );
-                       TaskSetupTimeout( inMDNS, nextTaskTime, &timeout );
-                       
-                       // Wait until something occurs (e.g. command, incoming packet, or timeout).
-                       
-                       readSet = allReadSet;
-                       n = select( maxSocket + 1, &readSet, NULL, NULL, &timeout );
-                       inMDNS->p->rescheduled = 1;
-                       check_errno( n, errno );
-                       dlog( kDebugLevelChatty - 1, DEBUG_NAME "task select result = %d\n", n );
-                       if( n == 0 )
-                       {
-                               // Next task timeout occurred. Loop back up to give mDNS core a chance to work.
-                               
-                               dlog( kDebugLevelChatty, DEBUG_NAME "next task timeout occurred (%ld)\n", mDNS_TimeNow(inMDNS) );
-                               continue;
-                       }
-                       
-                       // Scan the read set to determine if any sockets have something pending and process them.
-                       
-                       n = 0;
-                       for( item = inMDNS->p->interfaceList; item; item = item->next )
+                       fd = i->ss.sockV4;
+                       if( IsValidSocket( fd ) && FD_ISSET( fd, &readSet ) )
                        {
-                               if( FD_ISSET( item->multicastSocketRef, &readSet ) )
-                               {
-                                       TaskProcessPacket( inMDNS, item, item->multicastSocketRef );
-                                       ++n;
-                               }
+                               TaskProcessPackets( inMDNS, &i->ss, fd );
+                               ++n;
                        }
-                       
-                       // Check for a pending command and process it.
-                       
-                       if( FD_ISSET( inMDNS->p->commandPipe, &readSet ) )
+                       fd = i->ss.sockV6;
+                       if( IsValidSocket( fd ) && FD_ISSET( fd, &readSet ) )
                        {
-                               ProcessCommand( inMDNS );
+                               TaskProcessPackets( inMDNS, &i->ss, fd );
                                ++n;
                        }
-                       check( n > 0 );
                }
+               
+               // Process unicast sockets with pending data.
+               
+               fd = inMDNS->p->unicastSS.sockV4;
+               if( IsValidSocket( fd ) && FD_ISSET( fd, &readSet ) )
+               {
+                       TaskProcessPackets( inMDNS, &inMDNS->p->unicastSS, fd );
+                       ++n;
+               }
+               fd = inMDNS->p->unicastSS.sockV6;
+               if( IsValidSocket( fd ) && FD_ISSET( fd, &readSet ) )
+               {
+                       TaskProcessPackets( inMDNS, &inMDNS->p->unicastSS, fd );
+                       ++n;
+               }
+               
+               // Processing pending commands.
+               
+               fd = inMDNS->p->commandPipe;
+               check( fd >= 0 );
+               if( FD_ISSET( fd, &readSet ) )
+               {
+                       ProcessCommand( inMDNS );
+                       ++n;
+               }
+               check_string( n > 0, "select said something was readable, but nothing was" );
        }
 
 exit:
-       // Signal we've quit.
-       
-       check( inMDNS->p->quitEvent );
-       semGive( inMDNS->p->quitEvent );
-       
-       dlog( kDebugLevelInfo, DEBUG_NAME "task ended\n" );
+       TaskTerm( inMDNS );
 }
 
 //===========================================================================================================================
@@ -1617,86 +1691,155 @@ exit:
 
 mDNSlocal mStatus      TaskInit( mDNS *inMDNS )
 {
-       mStatus         err;
-       
-       dlog( kDebugLevelVerbose, DEBUG_NAME "task init\n" );
-       check( inMDNS->p->readyEvent );
+       mStatus                 err;
+       mDNSs32                 utc;
+       socklen_t               len;
        
-       inMDNS->p->task = taskIdSelf();
+       inMDNS->p->taskID = taskIdSelf();
        
        err = SetupCommandPipe( inMDNS );
        require_noerr( err, exit );
        
-       SetupNames( inMDNS );
+       inMDNS->CanReceiveUnicastOn5353 = mDNStrue;
        
-       err = SetupInterfaceList( inMDNS );
-       require_noerr( err, exit );
+       // Set up the HINFO string using the description property (e.g. "Device V1.0").
+       
+       inMDNS->HIHardware.c[ 0 ] = 11;
+       memcpy( &inMDNS->HIHardware.c[ 1 ], "Device V1.0", inMDNS->HIHardware.c[ 0 ] ); // $$$ Implementers: Fill in real info.
+       
+       // Set up the unicast sockets.
+       
+       err = SetupSocket( inMDNS, &zeroAddr, mDNSfalse, AF_INET, &inMDNS->p->unicastSS );
+       check_noerr( err );
+       if( err == mStatus_NoError )
+       {
+               struct sockaddr_in              sa4;
+               
+               len = sizeof( sa4 );
+               err = getsockname( inMDNS->p->unicastSS.sockV4, (struct sockaddr *) &sa4, &len );
+               check_translated_errno( err == 0, errno_compat(), kUnknownErr );
+               if( err == 0 ) inMDNS->UnicastPort4.NotAnInteger = sa4.sin_port;
+       }
+       
+       err = SetupSocket( inMDNS, &zeroAddr, mDNSfalse, AF_INET6, &inMDNS->p->unicastSS );
+       check_noerr( err );
+       if( err == mStatus_NoError )
+       {
+               struct sockaddr_in6             sa6;
+               
+               len = sizeof( sa6 );
+               err = getsockname( inMDNS->p->unicastSS.sockV6, (struct sockaddr *) &sa6, &len );
+               check_translated_errno( err == 0, errno_compat(), kUnknownErr );
+               if( err == 0 ) inMDNS->UnicastPort6.NotAnInteger = sa6.sin6_port;
+       }
+       
+       // Set up the interfaces.
+       
+       utc = mDNSPlatformUTC();
+       UpdateInterfaceList( inMDNS, utc );
+       SetupActiveInterfaces( inMDNS, utc );
+       err = mStatus_NoError;
        
 exit:
        // Signal the "ready" semaphore to indicate the task initialization code has completed (success or not).
        
-       inMDNS->p->taskInitErr = err;
-       semGive( inMDNS->p->readyEvent );
-
-       dlog( kDebugLevelVerbose, DEBUG_NAME "task init done (err=%ld)\n", err );
+       inMDNS->p->initErr = err;
+       semGive( inMDNS->p->initEvent );
        return( err );
 }
 
 //===========================================================================================================================
-//     TaskSetupReadSet
+//     TaskTerm
 //===========================================================================================================================
 
-mDNSlocal void TaskSetupReadSet( mDNS *inMDNS, fd_set *outReadSet, int *outMaxSocket )
+mDNSlocal void TaskTerm( mDNS *inMDNS )
 {
-       MDNSInterfaceItem *             item;
-       int                                             maxSocket;
+       mStatus         err;
+       mDNSs32         utc;
        
-       dlog( kDebugLevelVerbose, DEBUG_NAME "task setting up read set\n" );
-       check( inMDNS );
-       check( outReadSet );
-       check( outMaxSocket );
+       // Tear down all interfaces.
+       
+       utc = mDNSPlatformUTC();
+       MarkAllInterfacesInactive( inMDNS, utc );
+       ClearInactiveInterfaces( inMDNS, utc, mDNStrue );
+       check_string( !inMDNS->p->interfaceList, "LEAK: closing without deleting all interfaces" );
+       
+       // Close unicast sockets.
+       
+       ForgetSocket( &inMDNS->p->unicastSS.sockV4);
+       ForgetSocket( &inMDNS->p->unicastSS.sockV6 );
+       
+       // Tear down everything else that was set up in TaskInit then signal back that we're done.
+       
+       err = TearDownCommandPipe( inMDNS );
+       check_noerr( err );
        
-       // Initialize the read set. Default the max socket to -1 so "maxSocket + 1" (as needed by select) is zero. This 
-       // should never happen since we should always have at least one interface, but it's just to be safe.
+       err = semGive( inMDNS->p->quitEvent );
+       check_translated_errno( err == 0, errno_compat(), kUnknownErr );
+}
+
+//===========================================================================================================================
+//     TaskSetupSelect
+//===========================================================================================================================
+
+mDNSlocal void TaskSetupSelect( mDNS *inMDNS, fd_set *outSet, int *outMaxFd, mDNSs32 inNextEvent, struct timeval *outTimeout )
+{
+       NetworkInterfaceInfoVxWorks *           i;
+       int                                                                     maxFd;
+       int                                                                     fd;
+       mDNSs32                                                         delta;
        
-       FD_ZERO( outReadSet );
-       maxSocket = -1;
+       FD_ZERO( outSet );
+       maxFd = -1;
        
-       // Add all the receiving sockets to the read set.
+       // Add the interface-specific sockets.
        
-       for( item = inMDNS->p->interfaceList; item; item = item->next )
+       for( i = inMDNS->p->interfaceList; i; i = i->next )
        {
-               FD_SET( item->multicastSocketRef, outReadSet );
-               if( item->multicastSocketRef > maxSocket )
+               fd = i->ss.sockV4;
+               if( IsValidSocket( fd ) )
+               {
+                       FD_SET( fd, outSet );
+                       if( fd > maxFd ) maxFd = fd;
+               }
+               
+               fd = i->ss.sockV6;
+               if( IsValidSocket( fd ) )
                {
-                       maxSocket = item->multicastSocketRef;
+                       FD_SET( fd, outSet );
+                       if( fd > maxFd ) maxFd = fd;
                }
        }
        
-       // Add the command pipe to the read set.
+       // Add the unicast sockets.
        
-       FD_SET( inMDNS->p->commandPipe, outReadSet );
-       if( inMDNS->p->commandPipe > maxSocket )
+       fd = inMDNS->p->unicastSS.sockV4;
+       if( IsValidSocket( fd ) )
        {
-               maxSocket = inMDNS->p->commandPipe;
+               FD_SET( fd, outSet );
+               if( fd > maxFd ) maxFd = fd;
        }
-       check( maxSocket > 0 );
-       *outMaxSocket = maxSocket;
        
-       dlog( kDebugLevelVerbose, DEBUG_NAME "task setting up read set done (maxSocket=%d)\n", maxSocket );
-}
-
-//===========================================================================================================================
-//     TaskSetupTimeout
-//===========================================================================================================================
-
-mDNSlocal void TaskSetupTimeout( mDNS *inMDNS, mDNSs32 inNextTaskTime, struct timeval *outTimeout )
-{
-       mDNSs32         delta;
+       fd = inMDNS->p->unicastSS.sockV6;
+       if( IsValidSocket( fd ) )
+       {
+               FD_SET( fd, outSet );
+               if( fd > maxFd ) maxFd = fd;
+       }
+       
+       // Add the command pipe.
+       
+       fd = inMDNS->p->commandPipe;
+       check( fd >= 0 );
+       FD_SET( fd, outSet );
+       if( fd > maxFd ) maxFd = fd;
+       
+       check( maxFd > 0 );
+       *outMaxFd = maxFd;
        
        // Calculate how long to wait before performing idle processing.
        
-       delta = inNextTaskTime - mDNS_TimeNow(inMDNS);
+       delta = inNextEvent - mDNS_TimeNow( inMDNS );
        if( delta <= 0 )
        {
                // The next task time is now or in the past. Set the timeout to fire immediately.
@@ -1709,345 +1852,195 @@ mDNSlocal void        TaskSetupTimeout( mDNS *inMDNS, mDNSs32 inNextTaskTime, struct ti
                // Calculate the seconds and microseconds until the timeout should occur. Add one to the ticks remainder 
                // before multiplying to account for integer rounding error and avoid firing the timeout too early.
                
-               outTimeout->tv_sec  = delta / mDNSPlatformOneSecond;
-               outTimeout->tv_usec = ( ( delta % mDNSPlatformOneSecond ) + 1 ) * gMDNSTicksToMicrosecondsMultiplier;
-               
-               // Check if the microseconds is more than 1 second. If so, bump the seconds instead.
-               
+               outTimeout->tv_sec      = delta / mDNSPlatformOneSecond;
+               outTimeout->tv_usec     = ( ( delta % mDNSPlatformOneSecond ) + 1 ) * gMDNSTicksToMicro;
                if( outTimeout->tv_usec >= 1000000L )
                {
                        outTimeout->tv_sec += 1;
                        outTimeout->tv_usec = 0;
                }
        }
-       
-       dlog( kDebugLevelChatty, DEBUG_NAME "next task in %ld:%ld seconds (%ld)\n", 
-                 outTimeout->tv_sec, outTimeout->tv_usec, inNextTaskTime );
-}
-//===========================================================================================================================
-//     TaskProcessPacket
-//===========================================================================================================================
-
-mDNSlocal void TaskProcessPacket( mDNS *inMDNS, MDNSInterfaceItem *inItem, MDNSSocketRef inSocketRef )
-{
-       int                                             n;
-       DNSMessage                              packet;
-       struct sockaddr_in              addr;
-       int                                             addrSize;
-       mDNSu8 *                                packetEndPtr;
-       mDNSAddr                                srcAddr;
-       mDNSIPPort                              srcPort;
-       mDNSAddr                                dstAddr;
-       mDNSIPPort                              dstPort;
-               
-       // Receive the packet.
-       
-       addrSize = sizeof( addr );
-       n = recvfrom( inSocketRef, (char *) &packet, sizeof( packet ), 0, (struct sockaddr *) &addr, &addrSize );
-       check( n >= 0 );
-       if( n >= 0 )
-       {
-               // Set up the src/dst/interface info.
-               
-               srcAddr.type                            = mDNSAddrType_IPv4;
-               srcAddr.ip.v4.NotAnInteger      = addr.sin_addr.s_addr;
-               srcPort.NotAnInteger            = addr.sin_port;
-               dstAddr.type                            = mDNSAddrType_IPv4;
-               dstAddr.ip.v4                           = AllDNSLinkGroupv4;
-               dstPort                                         = MulticastDNSPort;
-               
-               dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" );
-               dlog( kDebugLevelChatty, DEBUG_NAME "    size      = %d\n", n );
-               dlog( kDebugLevelChatty, DEBUG_NAME "    src       = %u.%u.%u.%u:%hu\n", 
-                         srcAddr.ip.v4.b[ 0 ], srcAddr.ip.v4.b[ 1 ], srcAddr.ip.v4.b[ 2 ], srcAddr.ip.v4.b[ 3 ], 
-                         ntohs( srcPort.NotAnInteger ) );
-               dlog( kDebugLevelChatty, DEBUG_NAME "    dst       = %u.%u.%u.%u:%hu\n", 
-                         dstAddr.ip.v4.b[ 0 ], dstAddr.ip.v4.b[ 1 ], dstAddr.ip.v4.b[ 2 ], dstAddr.ip.v4.b[ 3 ], 
-                         ntohs( dstPort.NotAnInteger ) );
-               dlog( kDebugLevelChatty, DEBUG_NAME "    interface = 0x%08X\n", (int) inItem->hostSet.InterfaceID );
-               dlog( kDebugLevelChatty, DEBUG_NAME "--\n" );
-               
-               // Dispatch the packet to mDNS.
-               
-               packetEndPtr = ( (mDNSu8 *) &packet ) + n;
-               mDNSCoreReceive( inMDNS, &packet, packetEndPtr, &srcAddr, srcPort, &dstAddr, dstPort, inItem->hostSet.InterfaceID );
-       }
-       
-       // Update counters.
-       
-       inItem->recvCounter                     += 1;
-       inItem->recvErrorCounter        += ( n < 0 );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == Utilities ==
-#endif
-
-#if( TARGET_NON_APPLE )
-//===========================================================================================================================
-//     GenerateUniqueHostName
-//
-//     Non-Apple platform stub routine to generate a unique name for the device. Should be implemented to return a unique name.
-//===========================================================================================================================
-
-mDNSlocal void GenerateUniqueHostName( char *outName, long *ioSeed )
-{
-       DEBUG_UNUSED( ioSeed );
-       
-       // $$$ Non-Apple Platforms: Fill in appropriate name for device.
-       
-       mDNSPlatformStrCopy( kMDNSDefaultName, outName );
-}
-
-//===========================================================================================================================
-//     GenerateUniqueDNSName
-//
-//     Non-Apple platform stub routine to generate a unique RFC 1034-compatible DNS name for the device. Should be 
-//     implemented to return a unique name.
-//===========================================================================================================================
-
-mDNSlocal void GenerateUniqueDNSName( char *outName, long *ioSeed )
-{
-       DEBUG_UNUSED( ioSeed );
-       
-       // $$$ Non-Apple Platforms: Fill in appropriate DNS name for device.
-       
-       mDNSPlatformStrCopy( kMDNSDefaultName, outName );
 }
-#endif
-
-#if 0
-#pragma mark -
-#endif
 
 //===========================================================================================================================
-//     getifaddrs
+//     TaskProcessPackets
 //===========================================================================================================================
 
-int    getifaddrs( struct ifaddrs **outAddrs )
+mDNSlocal void TaskProcessPackets( mDNS *inMDNS, SocketSet *inSS, SocketRef inSock )
 {
-       int                                             err;
-       struct ifaddrs *                head;
-       struct ifaddrs **               next;
-       struct ifaddrs *                ifa;
-       int                                             i;
-       struct ifnet *                  ifp;
-       char                                    ipString[ INET_ADDR_LEN ];
-       int                                             n;
-       
-       head = NULL;
-       next = &head;
-       
-       i = 1;
+       mDNSu32                                         ifindex;
+       ssize_t                                         n;
+       mDNSu8 *                                        buf;
+       size_t                                          size;
+       struct sockaddr_storage         from;
+       size_t                                          fromSize;
+       mDNSAddr                                        destAddr;
+       mDNSAddr                                        senderAddr;
+       mDNSIPPort                                      senderPort;
+       mDNSInterfaceID                         id;
+       
+       buf  = (mDNSu8 *) &inMDNS->imsg;
+       size = sizeof( inMDNS->imsg );
        for( ;; )
        {
-               ifp = ifIndexToIfp( i );
-               if( !ifp )
-               {
-                       break;
-               }
-               ++i;
-               
-               // Allocate and initialize the ifaddrs structure and attach it to the linked list.
-               
-               ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
-               require_action( ifa, exit, err = ENOMEM );
-               
-               *next = ifa;
-               next  = &ifa->ifa_next;
-               
-               // Fetch the name.
-               
-               ifa->ifa_name = (char *) malloc( 16 );
-               require_action( ifa->ifa_name, exit, err = ENOMEM );
-               
-               n = sprintf( ifa->ifa_name, "%s%d", ifp->if_name, ifp->if_unit );
-               require_action( n < 16, exit, err = ENOBUFS );
-               
-               // Fetch the address.
-               
-               ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( struct sockaddr_in ) );
-               require_action( ifa->ifa_addr, exit, err = ENOMEM );
-               
-               ipString[ 0 ] = '\0';
-               #if( TARGET_NON_APPLE )
-                       err = ifAddrGet( ifa->ifa_name, ipString );
-                       require_noerr( err, exit );
-               #else
-                       err = ifAddrGetNonAlias( ifa->ifa_name, ipString );
-                       require_noerr( err, exit );
-               #endif
-               
-               err = sock_pton( ipString, AF_INET, ifa->ifa_addr, 0, NULL );
-               require_noerr( err, exit );
-               
-               // Fetch flags.
-               
-               ifa->ifa_flags = ifp->if_flags;
-       }
-       
-       // Success!
-       
-       if( outAddrs )
-       {
-               *outAddrs = head;
-               head = NULL;
-       }
-       err = 0;
-
-exit:
-       if( head )
-       {
-               freeifaddrs( head );
-       }
-       return( err );
-}
-
-//===========================================================================================================================
-//     freeifaddrs
-//===========================================================================================================================
-
-void   freeifaddrs( struct ifaddrs *inAddrs )
-{
-       struct ifaddrs *                p;
-       struct ifaddrs *                q;
-       
-       // Free each piece of the structure. Set to null after freeing to handle macro-aliased fields.
-       
-       for( p = inAddrs; p; p = q )
-       {
-               q = p->ifa_next;
-               
-               if( p->ifa_name )
+               ifindex = 0;
+               n = mDNSRecvMsg( inSock, buf, size, &from, sizeof( from ), &fromSize, &destAddr, &ifindex );            
+               if( n < 0 ) break;
+               if( from.ss_family == AF_INET )
                {
-                       free( p->ifa_name );
-                       p->ifa_name = NULL;
+                       struct sockaddr_in *            sa4;
+                       
+                       sa4 = (struct sockaddr_in *) &from;
+                       senderAddr.type                                 = mDNSAddrType_IPv4;
+                       senderAddr.ip.v4.NotAnInteger   = sa4->sin_addr.s_addr;
+                       senderPort.NotAnInteger                 = sa4->sin_port;
                }
-               if( p->ifa_addr )
+               else if( from.ss_family == AF_INET6 )
                {
-                       free( p->ifa_addr );
-                       p->ifa_addr = NULL;
+                       struct sockaddr_in6 *           sa6;
+                       
+                       sa6 = (struct sockaddr_in6 *) &from;
+                       senderAddr.type                 = mDNSAddrType_IPv6;
+                       senderAddr.ip.v6                = *( (mDNSv6Addr *) &sa6->sin6_addr );
+                       senderPort.NotAnInteger = sa6->sin6_port;
                }
-               if( p->ifa_netmask )
+               else
                {
-                       free( p->ifa_netmask );
-                       p->ifa_netmask = NULL;
+                       dmsg( kDebugLevelWarning, DEBUG_NAME "%s: WARNING! from addr unknown family %d\n", __ROUTINE__, from.ss_family );
+                       continue;
                }
-               if( p->ifa_dstaddr )
+               
+               // Even though we indicated a specific interface when joining the multicast group, a weirdness of the 
+               // sockets API means that even though this socket has only officially joined the multicast group
+               // on one specific interface, the kernel will still deliver multicast packets to it no matter which
+               // interface they arrive on. According to the official Unix Powers That Be, this is Not A Bug.
+               // To work around this weirdness, we use the IP_RECVIF/IPV6_PKTINFO options to find the interface
+               // on which the packet arrived, and ignore the packet if it really arrived on some other interface.
+               
+               if( mDNSAddrIsDNSMulticast( &destAddr ) )
                {
-                       free( p->ifa_dstaddr );
-                       p->ifa_dstaddr = NULL;
+                       if( !inSS->info || !inSS->info->exists )
+                       {
+                               dpkt( kDebugLevelChatty - 3, DEBUG_NAME "  ignored mcast, src=[%#39a],       dst=[%#39a],       if= unicast socket %d\n", 
+                                       &senderAddr, &destAddr, inSock );
+                               continue;
+                       }
+                       if( ifindex != inSS->info->scopeID )
+                       {
+                               #if( DEBUG && MDNS_DEBUG_PACKETS )
+                                       char            ifname[ IF_NAMESIZE ];
+                               #endif
+                               
+                               dpkt( kDebugLevelChatty - 3, 
+                                       DEBUG_NAME "  ignored mcast, src=[%#39a]        dst=[%#39a],       if=%8s(%u) -- really for %8s(%u)\n", 
+                                       &senderAddr, &destAddr, inSS->info->ifinfo.ifname, inSS->info->scopeID, 
+                                       if_indextoname( ifindex, ifname ), ifindex );
+                               continue;
+                       }
+                       
+                       id = inSS->info->ifinfo.InterfaceID;
+                       dpkt( kDebugLevelChatty - 2, DEBUG_NAME "recv %4d bytes, src=[%#39a]:%5hu, dst=[%#39a],       if=%8s(%u) %#p\n", 
+                               n, &senderAddr, mDNSVal16( senderPort ), &destAddr, inSS->info->ifinfo.ifname, inSS->info->scopeID, id );
                }
-               if( p->ifa_data )
+               else
                {
-                       free( p->ifa_data );
-                       p->ifa_data = NULL;
+                       NetworkInterfaceInfoVxWorks *           i;
+                       
+                       // For unicast packets, try to find the matching interface.
+                       
+                       for( i = inMDNS->p->interfaceList; i && ( i->scopeID != ifindex ); i = i->next ) {}
+                       if( i ) id = i->ifinfo.InterfaceID;
+                       else    id = NULL;
                }
-               free( p );
+               mDNSCoreReceive( inMDNS, buf, buf + n, &senderAddr, senderPort, &destAddr, MulticastDNSPort, id );
        }
 }
 
 //===========================================================================================================================
-//     sock_pton
+//     mDNSRecvMsg
 //===========================================================================================================================
 
-int    sock_pton( const char *inString, int inFamily, void *outAddr, size_t inAddrSize, size_t *outAddrSize )
+mDNSlocal ssize_t
+       mDNSRecvMsg( 
+               SocketRef       inSock, 
+               void *          inBuffer, 
+               size_t          inBufferSize, 
+               void *          outFrom, 
+               size_t          inFromSize, 
+               size_t *        outFromSize, 
+               mDNSAddr *      outDstAddr, 
+               uint32_t *      outIndex )
 {
-       int             err;
+       struct msghdr                   msg;
+       struct iovec                    iov;
+       ssize_t                                 n;
+       char                                    ancillary[ 1024 ];
+       struct cmsghdr *                cmPtr;
+       int                                             err;
        
-       if( inFamily == AF_INET )
+       // Read a packet and any ancillary data. Note: EWOULDBLOCK errors are expected when we've read all pending packets.
+       
+       iov.iov_base            = (char *) inBuffer;
+       iov.iov_len                     = inBufferSize;
+       msg.msg_name            = (caddr_t) outFrom;
+       msg.msg_namelen         = inFromSize;
+       msg.msg_iov                     = &iov;
+       msg.msg_iovlen          = 1;
+       msg.msg_control         = (caddr_t) &ancillary;
+       msg.msg_controllen      = sizeof( ancillary );
+       msg.msg_flags           = 0;
+       n = recvmsg( inSock, &msg, 0 );
+       if( n < 0 )
        {
-               struct sockaddr_in *            ipv4;
-               
-               if( inAddrSize == 0 )
-               {
-                       inAddrSize = sizeof( struct sockaddr_in );
-               }
-               if( inAddrSize < sizeof( struct sockaddr_in ) )
-               {
-                       err = EINVAL;
-                       goto exit;
-               }
-               
-               ipv4 = (struct sockaddr_in *) outAddr;
-               err = inet_aton( (char *) inString, &ipv4->sin_addr );
-               if( err == 0 )
-               {
-                       ipv4->sin_family = AF_INET;
-                       if( outAddrSize )
-                       {
-                               *outAddrSize = sizeof( struct sockaddr_in );
-                       }
-               }
+               err = errno_compat();
+               if( err != EWOULDBLOCK ) dmsg( kDebugLevelWarning, DEBUG_NAME "%s: recvmsg(%d) returned %d, errno %d\n", 
+                       __ROUTINE__, inSock, n, err );
+               goto exit;
        }
-#if( defined( AF_INET6 ) )
-       else if( inFamily == AF_INET6 )         // $$$ TO DO: Add IPv6 support.
+       if( msg.msg_controllen < sizeof( struct cmsghdr ) )
        {
-               err = EAFNOSUPPORT;
+               dmsg( kDebugLevelWarning, DEBUG_NAME "%s: recvmsg(%d) msg_controllen %d < sizeof( struct cmsghdr ) %u\n", 
+                       __ROUTINE__, inSock, msg.msg_controllen, sizeof( struct cmsghdr ) );
+               n = mStatus_UnknownErr;
                goto exit;
        }
-#endif
-       else
+       if( msg.msg_flags & MSG_CTRUNC )
        {
-               err = EAFNOSUPPORT;
+               dmsg( kDebugLevelWarning, DEBUG_NAME "%s: recvmsg(%d) MSG_CTRUNC (%d recv'd)\n", __ROUTINE__, inSock, n );
+               n = mStatus_BadFlagsErr;
                goto exit;
        }
-
-exit:
-       return( err );
-}
-
-//===========================================================================================================================
-//     sock_ntop
-//===========================================================================================================================
-
-char * sock_ntop( const void *inAddr, size_t inAddrSize, char *inBuffer, size_t inBufferSize )
-{
-       const struct sockaddr *         addr;
+       *outFromSize = msg.msg_namelen;
        
-       addr = (const struct sockaddr *) inAddr;
-       if( addr->sa_family == AF_INET )
+       // Parse each option out of the ancillary data.
+       
+       for( cmPtr = CMSG_FIRSTHDR( &msg ); cmPtr; cmPtr = CMSG_NXTHDR( &msg, cmPtr ) )
        {
-               struct sockaddr_in *            ipv4;
-               
-               if( inAddrSize == 0 )
+               if( ( cmPtr->cmsg_level == IPPROTO_IP ) && ( cmPtr->cmsg_type == IP_RECVDSTADDR ) )
                {
-                       inAddrSize = sizeof( struct sockaddr_in );
+                       outDstAddr->type                                = mDNSAddrType_IPv4;
+                       outDstAddr->ip.v4.NotAnInteger  = *( (mDNSu32 *) CMSG_DATA( cmPtr ) );
                }
-               if( inAddrSize < sizeof( struct sockaddr_in ) )
+               else if( ( cmPtr->cmsg_level == IPPROTO_IP ) && ( cmPtr->cmsg_type == IP_RECVIF ) )
                {
-                       errno = EINVAL;
-                       inBuffer = NULL;
-                       goto exit;
+                       struct sockaddr_dl *            sdl;
+                       
+                       sdl = (struct sockaddr_dl *) CMSG_DATA( cmPtr );
+                       *outIndex = sdl->sdl_index;
                }
-               if( inBufferSize < 16 )
+               else if( ( cmPtr->cmsg_level == IPPROTO_IPV6 ) && ( cmPtr->cmsg_type == IPV6_PKTINFO ) )
                {
-                       errno = ENOBUFS;
-                       inBuffer = NULL;
-                       goto exit;
+                       struct in6_pktinfo *            pi6;
+                       
+                       pi6 = (struct in6_pktinfo *) CMSG_DATA( cmPtr );
+                       outDstAddr->type        = mDNSAddrType_IPv6;
+                       outDstAddr->ip.v6       = *( (mDNSv6Addr *) &pi6->ipi6_addr );
+                       *outIndex                       = pi6->ipi6_ifindex;
                }
-               
-               ipv4 = (struct sockaddr_in *) addr;
-               inet_ntoa_b( ipv4->sin_addr, inBuffer );
-       }
-#if( defined( AF_INET6 ) )
-       else if( addr->sa_family == AF_INET6 )  // $$$ TO DO: Add IPv6 support.
-       {               
-               errno = EAFNOSUPPORT;
-               inBuffer = NULL;
-               goto exit;
-       }
-#endif
-       else
-       {
-               errno = EAFNOSUPPORT;
-               inBuffer = NULL;
-               goto exit;
        }
        
 exit:
-       return( inBuffer );
+       return( n );
 }
 
 #if 0
@@ -2055,139 +2048,113 @@ exit:
 #pragma mark == Debugging ==
 #endif
 
-#if( DEBUG )
-
-void   mDNSShow( BOOL inShowRecords );
-void   mDNSShowRecords( void );
-void   mDNSShowTXT( const void *inTXT, size_t inTXTSize );
-
+#if( DEBUG && MDNS_DEBUG_SHOW )
 //===========================================================================================================================
 //     mDNSShow
 //===========================================================================================================================
 
-void   mDNSShow( BOOL inShowRecords )
+void   mDNSShow( void );
+
+void   mDNSShow( void )
 {
-       MDNSInterfaceItem *             item;
-       mDNSAddr                                ip;
-       int                                             n;
+       NetworkInterfaceInfoVxWorks *           i;
+       int                                                                     num;
+       AuthRecord *                                            r;
+       mDNSs32                                                         utc;
        
+       // Globals
+       
+       dmsg( kDebugLevelMax, "\n-- mDNS globals --\n" );
+       dmsg( kDebugLevelMax, "    sizeof( mDNS )           = %d\n", (int) sizeof( mDNS ) );
+       dmsg( kDebugLevelMax, "    sizeof( ResourceRecord ) = %d\n", (int) sizeof( ResourceRecord ) );
+       dmsg( kDebugLevelMax, "    sizeof( AuthRecord )     = %d\n", (int) sizeof( AuthRecord ) );
+       dmsg( kDebugLevelMax, "    sizeof( CacheRecord )    = %d\n", (int) sizeof( CacheRecord ) );
+       dmsg( kDebugLevelMax, "    mDNSPlatformOneSecond    = %ld\n", mDNSPlatformOneSecond );
+       dmsg( kDebugLevelMax, "    gMDNSTicksToMicro        = %ld\n", gMDNSTicksToMicro );
+       dmsg( kDebugLevelMax, "    gMDNSPtr                 = %#p\n", gMDNSPtr );
        if( !gMDNSPtr )
        {
-               printf( "### mDNS not initialized\n" );
+               dmsg( kDebugLevelMax, "### mDNS not initialized\n" );
                return;
        }
-       
-       // Globals
-       
-       printf( "\n-- mDNS globals --\n" );
-       printf( "    sizeof( mDNS )                     = %d\n", (int) sizeof( mDNS ) );
-       printf( "    sizeof( ResourceRecord )           = %d\n", (int) sizeof( ResourceRecord ) );
-       printf( "    sizeof( AuthRecord )               = %d\n", (int) sizeof( AuthRecord ) );
-       printf( "    sizeof( CacheRecord )              = %d\n", (int) sizeof( CacheRecord ) );
-       printf( "    gMDNSPtr                           = 0x%08lX\n", (unsigned long) gMDNSPtr );
-       printf( "    gMDNSTicksToMicrosecondsMultiplier = %ld\n", gMDNSTicksToMicrosecondsMultiplier );
-       printf( "    lockID                             = 0x%08lX\n", (unsigned long) gMDNSPtr->p->lockID );
-       printf( "    readyEvent                         = 0x%08lX\n", (unsigned long) gMDNSPtr->p->readyEvent );
-       printf( "    taskInitErr                        = %ld\n", gMDNSPtr->p->taskInitErr );
-       printf( "    quitEvent                          = 0x%08lX\n", (unsigned long) gMDNSPtr->p->quitEvent );
-       printf( "    commandPipe                        = %d\n", gMDNSPtr->p->commandPipe );
-       printf( "    task                               = 0x%08lX\n", (unsigned long) gMDNSPtr->p->task );
-       printf( "    quit                               = %d\n", gMDNSPtr->p->quit );
-       printf( "    configID                           = %ld\n", gMDNSPtr->p->configID );
-       printf( "    rescheduled                        = %d\n", gMDNSPtr->p->rescheduled );
-       printf( "    nicelabel                          = \"%.*s\"\n", gMDNSPtr->nicelabel.c[ 0 ], (char *) &gMDNSPtr->nicelabel.c[ 1 ] );
-       printf( "    hostLabel                          = \"%.*s\"\n", gMDNSPtr->hostlabel.c[ 0 ], (char *) &gMDNSPtr->hostlabel.c[ 1 ] );
-       printf( "\n");
+       dmsg( kDebugLevelMax, "    nicelabel                = \"%#s\"\n", gMDNSPtr->nicelabel.c );
+       dmsg( kDebugLevelMax, "    hostLabel                = \"%#s\"\n", gMDNSPtr->hostlabel.c );
+       dmsg( kDebugLevelMax, "    MulticastHostname        = \"%##s\"\n", gMDNSPtr->MulticastHostname.c );
+       dmsg( kDebugLevelMax, "    HIHardware               = \"%#s\"\n", gMDNSPtr->HIHardware.c );
+       dmsg( kDebugLevelMax, "    HISoftware               = \"%#s\"\n", gMDNSPtr->HISoftware.c );
+       dmsg( kDebugLevelMax, "    UnicastPort4/6           = %d/%d\n", 
+               mDNSVal16( gMDNSPtr->UnicastPort4 ), mDNSVal16( gMDNSPtr->UnicastPort6 ) );
+       dmsg( kDebugLevelMax, "    unicastSS.sockV4/V6      = %d/%d\n", 
+               gMDNSPtr->p->unicastSS.sockV4, gMDNSPtr->p->unicastSS.sockV6 );
+       dmsg( kDebugLevelMax, "    lock                     = %#p\n", gMDNSPtr->p->lock );
+       dmsg( kDebugLevelMax, "    initEvent                = %#p\n", gMDNSPtr->p->initEvent );
+       dmsg( kDebugLevelMax, "    initErr                  = %ld\n", gMDNSPtr->p->initErr );
+       dmsg( kDebugLevelMax, "    quitEvent                = %#p\n", gMDNSPtr->p->quitEvent );
+       dmsg( kDebugLevelMax, "    commandPipe              = %d\n", gMDNSPtr->p->commandPipe );
+       dmsg( kDebugLevelMax, "    taskID                   = %#p\n", gMDNSPtr->p->taskID );
+       dmsg( kDebugLevelMax, "\n" );
        
        // Interfaces
        
-       printf( "\n-- mDNS interfaces --\n" );
-       n = 1;
-       for( item = gMDNSPtr->p->interfaceList; item; item = item->next )
+       utc = mDNSPlatformUTC();
+       dmsg( kDebugLevelMax, "-- mDNS interfaces --\n" );
+       num = 0;
+       for( i = gMDNSPtr->p->interfaceList; i; i = i->next )
        {
-               printf( "    -- interface %u --\n", n );
-               printf( "        name                           = \"%s\"\n", item->name );
-               printf( "        multicastSocketRef             = %d\n", item->multicastSocketRef );
-               printf( "        sendingSocketRef               = %d\n", item->sendingSocketRef );
-               ip = item->hostSet.ip;
-               printf( "        hostSet.ip                     = %u.%u.%u.%u\n", ip.ip.v4.b[ 0 ], ip.ip.v4.b[ 1 ], 
-                                                                                                                                                 ip.ip.v4.b[ 2 ], ip.ip.v4.b[ 3 ] );
-               printf( "        hostSet.advertise              = %s\n", item->hostSet.Advertise ? "YES" : "NO" );
-               printf( "        hostRegistered                 = %s\n", item->hostRegistered ? "YES" : "NO" );
-               printf( "        --\n" );
-               printf( "        sendMulticastCounter           = %d\n", item->sendMulticastCounter );
-               printf( "        sendUnicastCounter             = %d\n", item->sendUnicastCounter );
-               printf( "        sendErrorCounter               = %d\n", item->sendErrorCounter );
-               printf( "        recvCounter                    = %d\n", item->recvCounter );
-               printf( "        recvErrorCounter               = %d\n", item->recvErrorCounter );
-               printf( "        recvLoopCounter                = %d\n", item->recvLoopCounter );
-               printf( "\n" );
-               ++n;
+               dmsg( kDebugLevelMax, "    interface %2d %8s(%u) [%#39a] %s, sockV4 %2d, sockV6 %2d, Age %d\n", 
+                       num, i->ifinfo.ifname, i->scopeID, &i->ifinfo.ip, 
+                       i->ifinfo.InterfaceID ? "      REGISTERED" : "*NOT* registered", 
+                       i->ss.sockV4, i->ss.sockV6, utc - i->lastSeen );
+               ++num;
        }
+       dmsg( kDebugLevelMax, "\n" );
        
        // Resource Records
        
-       if( inShowRecords )
-       {
-               mDNSShowRecords();
-       }
-}
-
-//===========================================================================================================================
-//     mDNSShowRecords
-//===========================================================================================================================
-
-void   mDNSShowRecords( void )
-{
-       MDNSInterfaceItem *             item;
-       int                                             n;
-       AuthRecord *                    record;
-       char                                    name[ MAX_ESCAPED_DOMAIN_NAME ];
-       
-       printf( "\n-- mDNS resource records --\n" );
-       n = 1;
-       for( record = gMDNSPtr->ResourceRecords; record; record = record->next )
-       {
-               item = (MDNSInterfaceItem *) record->resrec.InterfaceID;
-               ConvertDomainNameToCString( &record->resrec.name, name );
-               printf( "    -- record %d --\n", n );
-               printf( "        interface = 0x%08X (%s)\n", (int) item, item ? item->name : "<any>" );
-               printf( "        name      = \"%s\"\n", name );
-               printf( "\n" );
-               ++n;
-       }
-       printf( "\n");
-}
-
-//===========================================================================================================================
-//     mDNSShowTXT
-//===========================================================================================================================
-
-void   mDNSShowTXT( const void *inTXT, size_t inTXTSize )
-{
-       const mDNSu8 *          p;
-       const mDNSu8 *          end;
-       int                                     i;
-       mDNSu8                          size;
-       
-       printf( "\nTXT record (%u bytes):\n\n", inTXTSize );
-       
-       p       = (const mDNSu8 *) inTXT;
-       end = p + inTXTSize;
-       i       = 0;
-       
-       while( p < end )
+       dmsg( kDebugLevelMax, "-- mDNS resource records --\n" );
+       num = 0;
+       for( r = gMDNSPtr->ResourceRecords; r; r = r->next )
        {
-               size = *p++;
-               if( ( p + size ) > end )
+               i = (NetworkInterfaceInfoVxWorks *) r->resrec.InterfaceID;
+               if( r->resrec.rrtype == kDNSType_TXT )
                {
-                       printf( "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" );
-                       break;
+                       RDataBody *                     rd;
+                       const mDNSu8 *          txt;
+                       const mDNSu8 *          end;
+                       mDNSu8                          size;
+                       int                                     nEntries;
+                                               
+                       rd = &r->resrec.rdata->u;
+                       dmsg( kDebugLevelMax, "    record %2d: %#p %8s(%u): %4d %##s %s:\n", num, i, 
+                               i ? i->ifinfo.ifname    : "<any>", 
+                               i ? i->scopeID                  : 0, 
+                               r->resrec.rdlength, r->resrec.name->c, DNSTypeName( r->resrec.rrtype ) );
+                       
+                       nEntries = 0;
+                       txt = rd->txt.c;
+                       end = txt + r->resrec.rdlength;
+                       while( txt < end )
+                       {
+                               size = *txt++;
+                               if( ( txt + size ) > end )
+                               {
+                                       dmsg( kDebugLevelMax, "        ### ERROR! txt length byte too big (%u, %u max)\n", size, end - txt );
+                                       break;
+                               }
+                               dmsg( kDebugLevelMax, "        string %2d (%3d bytes): \"%.*s\"\n", nEntries, size, size, txt );
+                               txt += size;
+                               ++nEntries;
+                       }
+               }
+               else
+               {
+                       dmsg( kDebugLevelMax, "    record %2d: %#p %8s(%u): %s\n", num, i, 
+                               i ? i->ifinfo.ifname    : "<any>", 
+                               i ? i->scopeID                  : 0, 
+                               ARDisplayString( gMDNSPtr, r ) );
                }
-               printf( "%2d (%3d bytes): \"%.*s\"\n", i, size, size, p );
-               p += size;
-               ++i;
+               ++num;
        }
-       printf( "\n" );
+       dmsg( kDebugLevelMax, "\n");
 }
-#endif // DEBUG
+#endif // DEBUG && MDNS_DEBUG_SHOW
index 9526ae5f6999a669b3393befb71331ec0d7d91a5..50552f3962aa519577b0856889127592501da875 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * 
  * @APPLE_LICENSE_HEADER_END@
 
-       Contains:       mDNS platform plugin for VxWorks.
-
-       Copyright:  Copyright (C) 2002-2003 Apple Computer, Inc., All Rights Reserved.
-
-       Change History (most recent first):
+    Change History (most recent first):
 
 $Log: mDNSVxWorks.h,v $
-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.
+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__
-#define        __MDNS_VXWORKS__
+#ifndef        __MDNS_VXWORKS_H__
+#define        __MDNS_VXWORKS_H__
 
 #include       "vxWorks.h"
+#include       "config.h"
+
 #include       "semLib.h"
 
-#include       "mDNSEmbeddedAPI.h"
+#include       "CommonServices.h"
+#include       "DebugServices.h"
 
 #ifdef __cplusplus
        extern "C" {
@@ -55,96 +45,91 @@ mDNS platform plugin for VxWorks.
 
 // Forward Declarations
 
-typedef struct MDNSInterfaceItem       MDNSInterfaceItem;
+typedef struct NetworkInterfaceInfoVxWorks             NetworkInterfaceInfoVxWorks;
 
 //---------------------------------------------------------------------------------------------------------------------------
-/*!    @struct         mDNS_PlatformSupport_struct
+/*!    @struct         SocketSet
 
-       @abstract       Structure containing platform-specific data.
+       @abstract       Data for IPv4 and IPv6 sockets.
 */
 
-struct mDNS_PlatformSupport_struct
+typedef struct SocketSet       SocketSet;
+struct SocketSet
 {
-       SEM_ID                                  lockID;
-       SEM_ID                                  readyEvent;
-       mStatus                                 taskInitErr;
-       SEM_ID                                  quitEvent;
-       MDNSInterfaceItem *             interfaceList;
-       int                                             commandPipe;
-       int                                             task;
-       mDNSBool                                quit;
-       long                                    configID;
-       int                                             rescheduled;
+       NetworkInterfaceInfoVxWorks *           info;
+       SocketRef                                                       sockV4;
+       SocketRef                                                       sockV6;
 };
 
 //---------------------------------------------------------------------------------------------------------------------------
-/*!    @function       mDNSReconfigure
-       
-       @abstract       Tell mDNS that the configuration has changed. Call when IP address changes, link goes up after being down, etc.
-       
-       @discussion
-       
-       VxWorks does not provide a generic mechanism for getting notified when network interfaces change so this routines
-       provides a way for BSP-specific code to signal mDNS that something has changed and it should re-build its interfaces.
-*/
-
-void   mDNSReconfigure( void );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!    @struct         ifaddrs
+/*!    @struct         NetworkInterfaceInfoVxWorks
 
-       @abstract       Interface information
+       @abstract       Interface info for VxWorks.
 */
 
-struct ifaddrs
+struct NetworkInterfaceInfoVxWorks
 {
-       struct ifaddrs *        ifa_next;
-       char *                          ifa_name;
-       u_int                           ifa_flags;
-       struct sockaddr *       ifa_addr;
-       struct sockaddr *       ifa_netmask;
-       struct sockaddr *       ifa_dstaddr;
-       void *                          ifa_data;
+       NetworkInterfaceInfo                            ifinfo;         // MUST be the first element in this structure.
+       NetworkInterfaceInfoVxWorks *           next;
+       mDNSu32                                                         exists;         // 1 = currently exists in getifaddrs list; 0 = doesn't.
+                                                                                                       // 2 = exists, but McastTxRx state changed.
+       mDNSs32                                                         lastSeen;       // If exists == 0, last time this interface appeared in getifaddrs list.
+       mDNSu32                                                         scopeID;        // Interface index / IPv6 scope ID.
+       int                                                                     family;         // Socket address family of the primary socket.
+       mDNSBool                                                        multicast;
+       SocketSet                                                       ss;
 };
 
 //---------------------------------------------------------------------------------------------------------------------------
-/*!    @function       getifaddrs
-
-       @abstract       Builds a linked list of interfaces. Caller must free using freeifaddrs if successful.
-*/
-
-int    getifaddrs( struct ifaddrs **outAddrs );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!    @function       freeifaddrs
+/*!    @struct         mDNS_PlatformSupport_struct
 
-       @abstract       Frees a linked list of interfaces built with getifaddrs.
+       @abstract       Data for mDNS platform plugin.
 */
 
-void   freeifaddrs( struct ifaddrs *inAddrs );
+struct mDNS_PlatformSupport_struct
+{
+       NetworkInterfaceInfoVxWorks *           interfaceList;
+       SocketSet                                                       unicastSS;
+       domainlabel                                                     userNiceLabel;
+       domainlabel                                                     userHostLabel;
+       
+       SEM_ID                                                          lock;
+       SEM_ID                                                          initEvent;
+       mStatus                                                         initErr;
+       SEM_ID                                                          quitEvent;      
+       int                                                                     commandPipe;
+       int                                                                     taskID;
+       mDNSBool                                                        quit;
+};
 
 //---------------------------------------------------------------------------------------------------------------------------
-/*!    @function       sock_pton
-
-       @abstract       Converts a 'p'resentation address string into a 'n'umeric sockaddr structure.
+/*!    @function       mDNSReconfigure
        
-       @result         0 if successful or an error code on failure.
+       @abstract       Tell mDNS that the configuration has changed. Call when IP address changes, link goes up after being down, etc.
+       
+       @discussion
+       
+       VxWorks does not provide a generic mechanism for getting notified when network interfaces change so this routines
+       provides a way for BSP-specific code to signal mDNS that something has changed and it should re-build its interfaces.
 */
 
-int    sock_pton( const char *inString, int inFamily, void *outAddr, size_t inAddrSize, size_t *outAddrSize );
+void   mDNSReconfigure( void );
 
 //---------------------------------------------------------------------------------------------------------------------------
-/*!    @function       sock_ntop
-
-       @abstract       Converts a 'n'umeric sockaddr structure into a 'p'resentation address string.
+/*!    @function       mDNSDeferIPv4
+       
+       @abstract       Tells mDNS whether to defer advertising of IPv4 interfaces.
+       
+       @discussion
        
-       @result         Ptr to 'p'resentation address string buffer if successful or NULL on failure.
+       To workaround problems with clients getting a link-local IPv4 address before a DHCP address is acquired, this allows
+       external code to defer advertising of IPv4 addresses until a DHCP lease has been acquired (or it times out).
 */
 
-char * sock_ntop( const void *inAddr, size_t inAddrSize, char *inBuffer, size_t inBufferSize );
+void   mDNSDeferIPv4( mDNSBool inDefer );
 
 #ifdef __cplusplus
        }
 #endif
 
-#endif // __MDNS_VXWORKS__
+#endif // __MDNS_VXWORKS_H__
index 07160cf0761cfd6a339f4c38758f383f565ee39e..c9a41238160ac76aaf1bb7c4148670e2e53ad33d 100755 (executable)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: ConfigPropertySheet.cpp,v $
+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
 
@@ -268,7 +271,7 @@ CConfigPropertySheet::SetupRegistryNotifications()
        check( m_threadExited == NULL );
        check( m_thread == NULL );
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\State\\Hostnames", &m_statusKey );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\State\\Hostnames", &m_statusKey );
        require_noerr( err, exit );
        
        m_threadExited = CreateEvent( NULL, FALSE, FALSE, NULL );
index c44dc2007bb4a34571f54c38d794b357454571f1..3111c3e8acc31d5f3c59a1bdbf8b39d504badcf6 100644 (file)
@@ -60,7 +60,6 @@ BEGIN
     END
 END
 
-
 #ifdef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -120,13 +119,13 @@ 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,7,19,248,28
-    LTEXT           "Hostname:",IDC_STATIC,15,55,35,8
-    EDITTEXT        IDC_EDIT1,52,53,187,14,ES_AUTOHSCROLL
-    PUSHBUTTON      "Password...",IDC_BUTTON1,52,72,67,14
-    ICON            IDI_FAILURE,IDC_FAILURE,240,50,21,20,SS_CENTERIMAGE | 
+                    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,21,20,SS_CENTERIMAGE | 
+    ICON            IDI_SUCCESS,IDC_SUCCESS,240,50,20,20,SS_CENTERIMAGE | 
                     SS_REALSIZEIMAGE | NOT WS_VISIBLE
 END
 
@@ -136,12 +135,12 @@ CAPTION "Registration"
 FONT 8, "MS Sans Serif", 0, 0, 0x0
 BEGIN
     CONTROL         "Domain:",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,13,54,42,10
-    COMBOBOX        IDC_COMBO2,59,53,189,46,CBS_DROPDOWN | CBS_SORT | 
+                    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,59,72,65,14
+    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,14,20,233,23
+                    IDC_STATIC,10,19,233,23
 END
 
 IDR_SECRET DIALOGEX 0, 0, 251, 90
@@ -153,9 +152,9 @@ 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_SECRET_NAME,36,26,208,14,ES_AUTOHSCROLL
-    LTEXT           "Secret:",IDC_STATIC,9,44,24,8
-    EDITTEXT        IDC_SECRET,36,42,208,14,ES_PASSWORD | ES_AUTOHSCROLL
+    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
@@ -182,7 +181,7 @@ 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,30,CBS_DROPDOWN | CBS_SORT | 
+    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.",
index e322593f1f0331283c6be4959a8f7b97f52c1ac0..19bdcc1c10295c1364a7628fe2023210013e1b86 100755 (executable)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="ControlPanel"\r
        SccProjectName=""\r
        SccLocalPath=""\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
                        <File\r
                                RelativePath="SharedSecret.cpp">\r
                        </File>\r
-                       <File\r
-                               RelativePath="ThirdPage.cpp">\r
-                       </File>\r
                        <File\r
                                RelativePath="stdafx.cpp">\r
                                <FileConfiguration\r
                                                UsePrecompiledHeader="0"/>\r
                                </FileConfiguration>\r
                        </File>\r
+                       <File\r
+                               RelativePath="ThirdPage.cpp">\r
+                       </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                                RelativePath="SharedSecret.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="ThirdPage.h">\r
+                               RelativePath="stdafx.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="stdafx.h">\r
+                               RelativePath="ThirdPage.h">\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
                        Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">\r
                        <File\r
-                               RelativePath="ControlPanel.rc">\r
+                               RelativePath="res\configurator.ico">\r
                        </File>\r
                        <File\r
-                               RelativePath="res\ControlPanel.rc2">\r
+                               RelativePath="res\controlpanel.ico">\r
                        </File>\r
                        <File\r
-                               RelativePath="res\configurator.ico">\r
+                               RelativePath="ControlPanel.rc">\r
                        </File>\r
                        <File\r
-                               RelativePath="res\controlpanel.ico">\r
+                               RelativePath="res\ControlPanel.rc2">\r
                        </File>\r
                        <File\r
                                RelativePath="res\failure.ico">\r
                                RelativePath="..\DebugServices.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\WinServices.cpp">\r
+                               RelativePath="..\..\mDNSShared\dns_sd.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\WinServices.h">\r
+                               RelativePath="..\WinServices.cpp">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dns_sd.h">\r
+                               RelativePath="..\WinServices.h">\r
                        </File>\r
                </Filter>\r
        </Files>\r
index 9dfe4017c8ec20a17e9f18cbf2012ba57d2b51ca..375d0f44167a8293013ce17b391e7b78a27813e9 100755 (executable)
     Change History (most recent first):
 
 $Log: FirstPage.cpp,v $
+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
 
@@ -51,17 +57,18 @@ CFirstPage::CFirstPage()
 :
        CPropertyPage(CFirstPage::IDD),
        m_ignoreHostnameChange( false ),
-       m_statusKey( NULL )
+       m_statusKey( NULL ),
+       m_setupKey( NULL )
 {
        //{{AFX_DATA_INIT(CFirstPage)
        //}}AFX_DATA_INIT
 
        OSStatus err;
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\State\\Hostnames", &m_statusKey );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\State\\Hostnames", &m_statusKey );
        check_noerr( err );
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\Hostnames", &m_setupKey );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\Hostnames", &m_setupKey );
        check_noerr( err );
 }
 
@@ -128,12 +135,33 @@ void CFirstPage::OnBnClickedSharedSecret()
 
        CSharedSecret dlg;
 
-       dlg.m_secretName = name;
+       dlg.m_key = name;
 
        if ( dlg.DoModal() == IDOK )
        {
-               dlg.Commit();
+               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;
 }
 
 
index a330e84f4287104110c2f806a2e4e7c840d9227b..83058b3fc2aa9232c16be2507d95f284c97ee324 100755 (executable)
     Change History (most recent first):
 
 $Log: SecondPage.cpp,v $
+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
 
@@ -46,10 +55,16 @@ IMPLEMENT_DYNCREATE(CSecondPage, CPropertyPage)
 
 CSecondPage::CSecondPage()
 :
-       CPropertyPage(CSecondPage::IDD)
+       CPropertyPage(CSecondPage::IDD),
+       m_setupKey( NULL )
 {
        //{{AFX_DATA_INIT(CSecondPage)
        //}}AFX_DATA_INIT
+
+       OSStatus err;
+
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &m_setupKey );
+       check_noerr( err );
 }
 
 
@@ -59,6 +74,11 @@ CSecondPage::CSecondPage()
 
 CSecondPage::~CSecondPage()
 {
+       if ( m_setupKey )
+       {
+               RegCloseKey( m_setupKey );
+               m_setupKey = NULL;
+       }
 }
 
 
@@ -109,7 +129,6 @@ BOOL
 CSecondPage::OnSetActive()
 {
        CConfigPropertySheet    *       psheet;
-       HKEY                                            key = NULL;
        DWORD                                           dwSize;
        DWORD                                           enabled;
        DWORD                                           err;
@@ -126,20 +145,15 @@ CSecondPage::OnSetActive()
 
        // Now populate the registration domain box
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key );
-       require_noerr( err, exit );
-
-       err = Populate( m_regDomainsBox, key, psheet->m_regDomains );
+       err = Populate( m_regDomainsBox, m_setupKey, psheet->m_regDomains );
        check_noerr( err );
 
        dwSize = sizeof( DWORD );
-       err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+       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 ) );
 
-       RegCloseKey( key );
-
 exit:
 
        return b;
@@ -168,20 +182,12 @@ CSecondPage::OnOK()
 void
 CSecondPage::Commit()
 {
-       HKEY            key = NULL;
-       DWORD           err;
-
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key );
-       require_noerr( err, exit );
-
-       err = Commit( m_regDomainsBox, key, m_advertiseServicesButton.GetCheck() == BST_CHECKED );
-       check_noerr( err );
-       
-exit:
+       DWORD err;
 
-       if ( key )
+       if ( m_setupKey != NULL )
        {
-               RegCloseKey( key );
+               err = Commit( m_regDomainsBox, m_setupKey, m_advertiseServicesButton.GetCheck() == BST_CHECKED );
+               check_noerr( err );
        }
 }
 
@@ -244,15 +250,39 @@ CSecondPage::Commit( CComboBox & box, HKEY key, DWORD enabled )
 
 void CSecondPage::OnBnClickedSharedSecret()
 {
-       CString string;
+       CString name;
 
-       m_regDomainsBox.GetWindowText( string );
+       m_regDomainsBox.GetWindowText( name );
 
        CSharedSecret dlg;
 
-       dlg.m_secretName = string;
+       dlg.m_key = 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:
 
-       dlg.DoModal();
+       return;
 }
 
 
@@ -470,6 +500,7 @@ CSecondPage::RegQueryString( HKEY key, CString valueName, CString & value )
 
                string = (TCHAR*) malloc( stringLen );
                require_action( string, exit, err = kUnknownErr );
+               *string = '\0';
 
                err = RegQueryValueEx( key, valueName, 0, NULL, (LPBYTE) string, &stringLen );
 
index a8d1f09a0a866c63bd22eaed670bd1b1da312bf0..917608edad7806ae6aec3b1c84fd8df12b4c9427 100755 (executable)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: SecondPage.h,v $
+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
 
@@ -113,6 +116,7 @@ private:
        CButton                 m_advertiseServicesButton;
        CButton                 m_sharedSecretButton;
        BOOL                    m_modified;
+       HKEY                    m_setupKey;
 
 public:
        afx_msg void OnCbnSelChange();
index e690b4979464a80d928bf94a540087bc7b702e28..7ba6a2a63464e3f676518865944be14639cc4962 100644 (file)
     Change History (most recent first):
 
 $Log: SharedSecret.cpp,v $
+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
 
@@ -61,8 +67,8 @@ IMPLEMENT_DYNAMIC(CSharedSecret, CDialog)
 
 CSharedSecret::CSharedSecret(CWnd* pParent /*=NULL*/)
        : CDialog(CSharedSecret::IDD, pParent)
+       , m_key(_T(""))
        , m_secret(_T(""))
-       , m_secretName(_T(""))
 {
 }
 
@@ -83,8 +89,8 @@ CSharedSecret::~CSharedSecret()
 void CSharedSecret::DoDataExchange(CDataExchange* pDX)
 {
        CDialog::DoDataExchange(pDX);
-       DDX_Text(pDX, IDC_SECRET, m_secret);
-       DDX_Text(pDX, IDC_SECRET_NAME, m_secretName);
+       DDX_Text(pDX, IDC_KEY, m_key );
+       DDX_Text(pDX, IDC_SECRET, m_secret );
 }
 
 
@@ -98,27 +104,41 @@ END_MESSAGE_MAP()
 //---------------------------------------------------------------------------------------------------------------------------
 
 void
-CSharedSecret::Commit()
+CSharedSecret::Commit( CString zone )
 {
        LSA_OBJECT_ATTRIBUTES   attrs;
        LSA_HANDLE                              handle = NULL;
        NTSTATUS                                res;
+       LSA_UNICODE_STRING              lucZoneName;
        LSA_UNICODE_STRING              lucKeyName;
-       LSA_UNICODE_STRING              lucPrivateData;
+       LSA_UNICODE_STRING              lucSecretName;
        BOOL                                    ok;
        OSStatus                                err;
 
        // If there isn't a trailing dot, add one because the mDNSResponder
        // presents names with the trailing dot.
 
-       if ( m_secretName.ReverseFind( '.' ) != m_secretName.GetLength() )
+       if ( zone.ReverseFind( '.' ) != zone.GetLength() )
+       {
+               zone += '.';
+       }
+
+       if ( m_key.ReverseFind( '.' ) != m_key.GetLength() )
        {
-               m_secretName += '.';
+               m_key += '.';
        }
 
+       // <rdar://problem/4192119>
+       //
+       // Prepend "$" to the key name, so that there will
+       // be no conflict between the zone name and the key
+       // name
+
+       m_key.Insert( 0, L"$" );
+
        // attrs are reserved, so initialize to zeroes.
 
-       ZeroMemory(&attrs, sizeof( attrs ) );
+       ZeroMemory( &attrs, sizeof( attrs ) );
 
        // Get a handle to the Policy object on the local system
 
@@ -128,17 +148,25 @@ CSharedSecret::Commit()
 
        // Intializing PLSA_UNICODE_STRING structures
 
-       ok = InitLsaString( &lucKeyName, m_secretName );
+       ok = InitLsaString( &lucZoneName, zone );
+       err = translate_errno( ok, errno_compat(), kUnknownErr );
+       require_noerr( err, exit );
+       ok = InitLsaString( &lucKeyName, m_key );
        err = translate_errno( ok, errno_compat(), kUnknownErr );
        require_noerr( err, exit );
 
-       ok = InitLsaString( &lucPrivateData, m_secret );
+       ok = InitLsaString( &lucSecretName, m_secret );
        err = translate_errno( ok, errno_compat(), kUnknownErr );
        require_noerr( err, exit );
 
        // Store the private data.
 
-       res = LsaStorePrivateData( handle, &lucKeyName, &lucPrivateData );
+       res = LsaStorePrivateData( handle, &lucZoneName, &lucKeyName );
+       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+       require_noerr( err, exit );
+
+       res = LsaStorePrivateData( handle, &lucKeyName, &lucSecretName );
        err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
        require_noerr( err, exit );
 
index 9982d785ef1763dfeffaee4eca9241093654ee15..c757df9c0f84ac97cfe4c74616d0d046b3873af7 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: SharedSecret.h,v $
+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
 
@@ -51,7 +54,7 @@ public:
        enum { IDD = IDR_SECRET };
 
        void
-       Commit();
+       Commit( CString zone );
 
 protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
@@ -59,6 +62,7 @@ protected:
        DECLARE_MESSAGE_MAP()
 
 public:
+
+       CString m_key;
        CString m_secret;
-       CString m_secretName;
 };
index bfb56bd7dd08a34a76b9f4d60b61cb6dfc448abd..b8cef51e9072df63812ac44ba368663955306c99 100755 (executable)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: ThirdPage.cpp,v $
+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
 
@@ -40,7 +43,7 @@ Revision 1.2  2005/03/03 19:55:22  shersche
 
 #include <WinServices.h>
     
-#define MAX_KEY_LENGTH 255\r
+#define MAX_KEY_LENGTH 255
 
 
 IMPLEMENT_DYNCREATE(CThirdPage, CPropertyPage)
@@ -79,16 +82,16 @@ void CThirdPage::DoDataExchange(CDataExchange* pDX)
        CPropertyPage::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CThirdPage)
        //}}AFX_DATA_MAP
-       DDX_Control(pDX, IDC_BROWSE_LIST, m_browseListCtrl);\r
-       DDX_Control(pDX, IDC_REMOVE_BROWSE_DOMAIN, m_removeButton);\r
+       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)\r
-       ON_BN_CLICKED(IDC_REMOVE_BROWSE_DOMAIN, OnBnClickedRemoveBrowseDomain)\r
-       ON_NOTIFY(LVN_ITEMCHANGED, IDC_BROWSE_LIST, OnLvnItemchangedBrowseList)\r
+       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()
 
 
@@ -117,11 +120,11 @@ CThirdPage::OnSetActive()
        DWORD                                           dwSize;
        DWORD                                           enabled;
        DWORD                                           err;
-       TCHAR                                           subKeyName[MAX_KEY_LENGTH];\r
-       DWORD                                           cSubKeys = 0;\r
-       DWORD                                           cbMaxSubKey;\r
-       DWORD                                           cchMaxClass;\r
-       int                                                     nIndex;\r
+       TCHAR                                           subKeyName[MAX_KEY_LENGTH];
+       DWORD                                           cSubKeys = 0;
+       DWORD                                           cbMaxSubKey;
+       DWORD                                           cchMaxClass;
+       int                                                     nIndex;
     DWORD                                              i; 
        BOOL                                            b = CPropertyPage::OnSetActive();
 
@@ -148,39 +151,39 @@ CThirdPage::OnSetActive()
 
        // Now populate the browse domain box
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key );
        require_noerr( err, exit );
 
-       // Get information about this node\r
-\r
-    err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       \r
+       // Get information about this node
+
+    err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
        require_noerr( err, exit );
-\r
-       for ( i = 0; i < cSubKeys; i++)\r
-       {       \r
-               dwSize = MAX_KEY_LENGTH;\r
-            \r
-               err = RegEnumKeyEx( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );\r
-               require_noerr( err, exit );\r
-\r
-               err = RegOpenKey( key, subKeyName, &subKey );\r
-               require_noerr( err, exit );\r
-\r
-               dwSize = sizeof( DWORD );\r
-               err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );\r
-               require_noerr( err, exit );\r
-\r
+
+       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 );\r
-               m_browseListCtrl.SetCheck( nIndex, enabled );\r
-\r
-               RegCloseKey( subKey );\r
-               subKey = NULL;\r
-    }\r
-\r
-       m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );\r
-\r
-       m_removeButton.EnableWindow( FALSE );\r
+               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:
 
@@ -198,8 +201,8 @@ exit:
 
        return b;
 }
-\r
\r
+
 
 //---------------------------------------------------------------------------------------------------------------------------
 //     CThirdPage::OnOK
@@ -225,31 +228,31 @@ CThirdPage::Commit()
 {
        HKEY            key             = NULL;
        HKEY            subKey  = NULL;
-       TCHAR           subKeyName[MAX_KEY_LENGTH];\r
-       DWORD           cSubKeys = 0;\r
-       DWORD           cbMaxSubKey;\r
+       TCHAR           subKeyName[MAX_KEY_LENGTH];
+       DWORD           cSubKeys = 0;
+       DWORD           cbMaxSubKey;
        DWORD           cchMaxClass;
        DWORD           dwSize;
        int                     i;
        DWORD           err;
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key );
        require_noerr( err, exit );
 
-       // First, remove all the entries that are there\r
-\r
-    err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       \r
+       // 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 );
-\r
-       for ( i = 0; i < (int) cSubKeys; i++ )\r
-       {       \r
-               dwSize = MAX_KEY_LENGTH;\r
-            \r
-               err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );\r
-               require_noerr( err, exit );\r
-                       \r
-               err = RegDeleteKey( key, subKeyName );\r
-               require_noerr( err, exit );\r
+
+       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
@@ -297,9 +300,9 @@ CThirdPage::OnBnClickedAddBrowseDomain()
                int nIndex;
 
                nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L"");
-               m_browseListCtrl.SetItemText( nIndex, 1, dlg.m_text );\r
-               m_browseListCtrl.SetCheck( nIndex, 1 );\r
-\r
+               m_browseListCtrl.SetItemText( nIndex, 1, dlg.m_text );
+               m_browseListCtrl.SetCheck( nIndex, 1 );
+
                m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );
 
                m_browseListCtrl.Invalidate();
@@ -316,141 +319,141 @@ CThirdPage::OnBnClickedAddBrowseDomain()
 void
 CThirdPage::OnBnClickedRemoveBrowseDomain()
 {
-       UINT    selectedCount = m_browseListCtrl.GetSelectedCount();\r
-       int             nItem = -1;\r
-       UINT    i;\r
-\r
-       // Update all of the selected items.\r
-\r
-       for ( i = 0; i < selectedCount; i++ )\r
-       {\r
-               nItem = m_browseListCtrl.GetNextItem( -1, LVNI_SELECTED );\r
-               check( nItem != -1 );\r
-\r
-               m_browseListCtrl.DeleteItem( nItem );\r
-\r
-               SetModified( TRUE );\r
-       }\r
-\r
-       m_removeButton.EnableWindow( FALSE );\r
+       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\r
-CThirdPage::OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)\r
-{\r
-       if ( m_browseListCtrl.GetSelectedCount() )\r
-       {\r
-               m_removeButton.EnableWindow( TRUE );\r
-       }\r
-\r
-       if ( m_initialized )\r
-       {\r
-               NM_LISTVIEW * pNMListView = (NM_LISTVIEW*)pNMHDR; \r
-        \r
-               BOOL bPrevState = (BOOL) ( ( ( pNMListView->uOldState & LVIS_STATEIMAGEMASK ) >> 12 ) - 1 ); \r
-        \r
-               if ( bPrevState < 0 )\r
-               {\r
-                       bPrevState = 0;\r
-               }\r
-\r
-\r
-               BOOL bChecked = ( BOOL ) ( ( ( pNMListView->uNewState & LVIS_STATEIMAGEMASK ) >> 12) - 1 ); \r
-        \r
-               if ( bChecked < 0 )\r
-               {\r
-                       bChecked = 0;\r
-               }\r
-\r
-               if ( bPrevState != bChecked )\r
-               {\r
-                       SetModified( TRUE );\r
-               }\r
-       }\r
-\r
-       *pResult = 0;\r
+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 \r
-CThirdPage::SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)\r
-{\r
-       CString str1;\r
-       CString str2;\r
-       int             ret = 0;\r
-\r
+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 );
-\r
-       str1 = self->m_browseListCtrl.GetItemText( (int) lParam1, 1 );\r
-       str2 = self->m_browseListCtrl.GetItemText( (int) lParam2, 1 );\r
-\r
-       ret = str1.Compare( str2 );\r
-\r
-exit:\r
-\r
-       return ret;\r
+
+       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);
 }
-\r
-\r
-// CAddBrowseDomain dialog\r
-\r
-IMPLEMENT_DYNAMIC(CAddBrowseDomain, CDialog)\r
-CAddBrowseDomain::CAddBrowseDomain(CWnd* pParent /*=NULL*/)\r
-       : CDialog(CAddBrowseDomain::IDD, pParent)\r
-{\r
-}\r
-\r
-CAddBrowseDomain::~CAddBrowseDomain()\r
-{\r
-}\r
-\r
-void CAddBrowseDomain::DoDataExchange(CDataExchange* pDX)\r
-{\r
-       CDialog::DoDataExchange(pDX);\r
-       DDX_Control(pDX, IDC_COMBO1, m_comboBox);\r
-}\r
-\r
-\r
-BOOL\r
-CAddBrowseDomain::OnInitDialog()\r
-{\r
-       CConfigPropertySheet    *       psheet;\r
-       CConfigPropertySheet::StringList::iterator              it;\r
-       \r
-       BOOL b = CDialog::OnInitDialog();\r
-\r
+
+
+BOOL
+CAddBrowseDomain::OnInitDialog()
+{
+       CConfigPropertySheet    *       psheet;
+       CConfigPropertySheet::StringList::iterator              it;
+       
+       BOOL b = CDialog::OnInitDialog();
+
        psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
-       require_quiet( psheet, exit );\r
-\r
-       for ( it = psheet->m_browseDomains.begin(); it != psheet->m_browseDomains.end(); it++ )\r
-       {\r
-               CString text = *it;\r
-\r
+       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 );
-               }\r
-       }\r
-\r
-exit:\r
-\r
-       return b;\r
-}\r
-\r
-\r
-void\r
-CAddBrowseDomain::OnOK()\r
-{\r
-       m_comboBox.GetWindowText( m_text );\r
-\r
-       CDialog::OnOK();\r
-}\r
-\r
-\r
-\r
-BEGIN_MESSAGE_MAP(CAddBrowseDomain, CDialog)\r
-END_MESSAGE_MAP()\r
-\r
+               }
+       }
+
+exit:
+
+       return b;
+}
+
+
+void
+CAddBrowseDomain::OnOK()
+{
+       m_comboBox.GetWindowText( m_text );
+
+       CDialog::OnOK();
+}
+
+
+
+BEGIN_MESSAGE_MAP(CAddBrowseDomain, CDialog)
+END_MESSAGE_MAP()
+
index 9baf23cb6f7fbe658e5e97bf76d6bfccca0a9c9d..3a0fec7e98cf86369157085f2c7137562351db5c 100644 (file)
@@ -23,6 +23,8 @@
 #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
index 6bdeb9288c9b7fa1374d42da00156a0faa908022..7e63ac4c495712b330bc7a21004cf8f09c0a352a 100755 (executable)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: stdafx.h,v $
+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
 
@@ -59,6 +62,10 @@ Revision 1.2  2005/03/03 19:55:21  shersche
 // turns off MFC's hiding of some common and often safely ignored warning messages
 #define _AFX_ALL_WARNINGS
 
+#if !defined(_WSPIAPI_COUNTOF)
+#      define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#endif
+
 #include <afxwin.h>         // MFC core and standard components
 #include <afxext.h>         // MFC extensions
 #include <afxdisp.h>        // MFC Automation classes
index 7eeb488cd454bb41ebe87f61fbaca556aa8ab718..00a0820544383b61015937943b20addac4875f89 100755 (executable)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: Stdafx.h,v $
+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)
 
@@ -40,6 +43,10 @@ Initial revision
 
 #pragma once
 
+#if !defined(_WSPIAPI_COUNTOF)
+#      define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#endif
+
 #using <mscorlib.dll>
 #using <System.dll>
 
index 719de8dfa19c33b2f953133493fdf9fe2d24dc06..d857d4c0c7b3614c2bed2d4e87b4f51239f4e413 100755 (executable)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="DLL.NET"\r
        ProjectGUID="{9C6701E2-82B7-44B7-9B5E-3897D9153F79}"\r
        Keyword="ManagedCProj">\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
                                RelativePath=".\AssemblyInfo.cpp">\r
                        </File>\r
                        <File\r
-                               RelativePath=".\Stdafx.cpp">\r
+                               RelativePath=".\dnssd_NET.cpp">\r
                        </File>\r
                        <File\r
-                               RelativePath=".\dnssd_NET.cpp">\r
+                               RelativePath=".\Stdafx.cpp">\r
                        </File>\r
                </Filter>\r
                <Filter\r
                        Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
                        UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
                        <File\r
-                               RelativePath="PString.h">\r
+                               RelativePath=".\dnssd_NET.h">\r
                        </File>\r
                        <File\r
-                               RelativePath=".\Stdafx.h">\r
+                               RelativePath="PString.h">\r
                        </File>\r
                        <File\r
-                               RelativePath=".\dnssd_NET.h">\r
+                               RelativePath=".\resource.h">\r
                        </File>\r
                        <File\r
-                               RelativePath=".\resource.h">\r
+                               RelativePath=".\Stdafx.h">\r
                        </File>\r
                </Filter>\r
                <Filter\r
index a15aedf3542b9c44f3726c2cd4b564044e584c6a..6dd9e97f7cd3def5481a060165f972fda098a3dc 100644 (file)
     Change History (most recent first):
     
 $Log: dllmain.c,v $
+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.
 
@@ -32,6 +38,7 @@ DLL wrapper for DNS-SD API.
 */
 
 #include <windows.h>
+#include <DebugServices.h>
 
 BOOL APIENTRY  DllMain( HANDLE inModule, DWORD inReason, LPVOID inReserved )
 {
@@ -48,3 +55,80 @@ BOOL APIENTRY        DllMain( HANDLE inModule, DWORD inReason, LPVOID inReserved )
        }
     return( TRUE );
 }
+
+
+BOOL
+IsSystemServiceDisabled()
+{
+       ENUM_SERVICE_STATUS     *       lpService = NULL;
+       SC_HANDLE                                       sc;
+       BOOL                                                    ret = FALSE;
+       BOOL                                                    ok;
+       DWORD                                                   bytesNeeded = 0;
+       DWORD                                                   srvCount;
+       DWORD                                                   resumeHandle = 0;
+       DWORD                                                   srvType;
+       DWORD                                                   srvState;
+       DWORD                                                   dwBytes = 0;
+       DWORD                                                   i;
+       OSStatus                                                err;
+
+       sc = OpenSCManager( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE );
+       err = translate_errno( sc, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       srvType         =       SERVICE_WIN32;
+       srvState                =       SERVICE_STATE_ALL;
+
+       for ( ;; )
+       {
+               // Call EnumServicesStatus using the handle returned by OpenSCManager
+
+               ok = EnumServicesStatus ( sc, srvType, srvState, lpService, dwBytes, &bytesNeeded, &srvCount, &resumeHandle );
+
+               if ( ok || ( GetLastError() != ERROR_MORE_DATA ) )
+               {
+                       break;
+               }
+
+               if ( lpService )
+               {
+                       free( lpService );
+               }
+
+               dwBytes = bytesNeeded;
+
+               lpService = ( ENUM_SERVICE_STATUS* ) malloc( dwBytes );
+               require_action( lpService, exit, ret = FALSE );
+       }
+
+       err = translate_errno( ok, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       for ( i = 0; i < srvCount; i++ )
+       {
+               if ( strcmp( lpService[i].lpServiceName, "Bonjour Service" ) == 0 )
+               {
+                       if ( ( lpService[i].ServiceStatus.dwCurrentState == SERVICE_PAUSED ) || ( lpService[i].ServiceStatus.dwCurrentState == SERVICE_STOPPED ) )
+                       {
+                               ret = TRUE;
+                       }
+
+                       break;
+               }
+       }
+
+exit:
+
+       if ( lpService )
+       {
+               free( lpService );
+       }
+
+       if ( sc )
+       {
+               CloseServiceHandle ( sc );
+       }
+
+       return ret;
+}
index 39750483b70ec739f0b909c6de49b10890c6e080..383a90aabd1bc6b66a2d05ae9d505b588ecd4994 100644 (file)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="DLL"\r
        ProjectGUID="{AB581101-18F0-46F6-B56A-83A6B1EA657E}"\r
        Keyword="Win32Proj">\r
@@ -33,7 +33,8 @@
                                Detect64BitPortabilityProblems="TRUE"\r
                                DebugInformationFormat="4"\r
                                CallingConvention="2"\r
-                               CompileAs="0"/>\r
+                               CompileAs="0"\r
+                               DisableSpecificWarnings="4127;4204"/>\r
                        <Tool\r
                                Name="VCCustomBuildTool"/>\r
                        <Tool\r
@@ -45,6 +46,7 @@
                                GenerateDebugInformation="TRUE"\r
                                ProgramDatabaseFile="$(OutDir)/dnssd.pdb"\r
                                SubSystem="2"\r
+                               BaseAddress="0x16000000"\r
                                ImportLibrary="$(IntDir)\dnssd.lib"\r
                                TargetMachine="1"/>\r
                        <Tool\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
+                       OutputDirectory=".\Release"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="2"\r
                        CharacterSet="2">\r
@@ -79,7 +87,8 @@
                                Detect64BitPortabilityProblems="TRUE"\r
                                DebugInformationFormat="3"\r
                                CallingConvention="2"\r
-                               CompileAs="0"/>\r
+                               CompileAs="0"\r
+                               DisableSpecificWarnings="4127;4204"/>\r
                        <Tool\r
                                Name="VCCustomBuildTool"/>\r
                        <Tool\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               BaseAddress="0x16000000"\r
                                ImportLibrary=".\Release\dnssd.lib"\r
                                TargetMachine="1"/>\r
                        <Tool\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
                        <File\r
                                RelativePath="..\DebugServices.c">\r
                        </File>\r
-                       <File\r
-                               RelativePath="..\..\mDNSShared\GenLinkedList.c">\r
-                       </File>\r
                        <File\r
                                RelativePath=".\dllmain.c">\r
                        </File>\r
                        <File\r
                                RelativePath="..\..\mDNSShared\dnssd_ipc.c">\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\GenLinkedList.c">\r
+                       </File>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                        <File\r
                                RelativePath="..\DebugServices.h">\r
                        </File>\r
-                       <File\r
-                               RelativePath="..\..\mDNSShared\GenLinkedList.h">\r
-                       </File>\r
                        <File\r
                                RelativePath="..\..\mDNSShared\dns_sd.h">\r
                        </File>\r
                        <File\r
                                RelativePath="..\..\mDNSShared\dnssd_sock.h">\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\mDNSShared\GenLinkedList.h">\r
+                       </File>\r
                        <File\r
                                RelativePath=".\resource.h">\r
                        </File>\r
diff --git a/mDNSWindows/Installer/Main.ism b/mDNSWindows/Installer/Main.ism
deleted file mode 100644 (file)
index c430d40..0000000
Binary files a/mDNSWindows/Installer/Main.ism and /dev/null differ
diff --git a/mDNSWindows/Installer/SDK.ism b/mDNSWindows/Installer/SDK.ism
deleted file mode 100644 (file)
index e63bde7..0000000
Binary files a/mDNSWindows/Installer/SDK.ism and /dev/null differ
diff --git a/mDNSWindows/Java/Java.vcproj b/mDNSWindows/Java/Java.vcproj
new file mode 100755 (executable)
index 0000000..a846ec9
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="Java"\r
+       ProjectGUID="{9CE2568A-3170-41C6-9F20-A0188A9EC114}"\r
+       Keyword="MakeFileProj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="Debug"\r
+                       IntermediateDirectory="Debug"\r
+                       ConfigurationType="0">\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
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="Release"\r
+                       IntermediateDirectory="Release"\r
+                       ConfigurationType="0">\r
+                       <Tool\r
+                               Name="VCNMakeTool"\r
+                               BuildCommandLine="nmake /f makefile"\r
+                               ReBuildCommandLine="nmake /f makefile"\r
+                               CleanCommandLine="nmake /f makefile clean"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
index b590e307f49897ba5b8de91fbade93a02a2126c3..8a115ee238c5812a6ac824500c5cee12231b505a 100644 (file)
@@ -20,6 +20,9 @@
 # @APPLE_LICENSE_HEADER_END@
 #
 # $Log: makefile,v $
+# 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
 #
@@ -64,7 +67,7 @@
 COREDIR = ..\..\mDNSCore
 SHAREDDIR = ..\..\mDNSShared
 
-JDK = \javasdk
+JDK = $(JAVA_HOME)
 
 CC = cl
 RC = rc
index 7b3fc0efcde4e0c58e5edfb8c474ae90f2a19e59..8253f1054bdfa95fa39ff7e112d8835c309af7b6 100644 (file)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="NSPTool"\r
        ProjectGUID="{208B3A9F-1CA0-4D1D-9D6C-C61616F94705}"\r
        Keyword="Win32Proj">\r
                                AdditionalIncludeDirectories="..\"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\InstallTools"\r
+                       OutputDirectory=".\Release"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="1"\r
                        CharacterSet="2">\r
                                AdditionalIncludeDirectories="..\"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r
index 5a02c2f50c95b9238a3286e0e8d4dd35c1e05339..dc94ba9a2f26974e671af40c2a386b1a3d896c91 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: RegNames.h,v $
+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
 
@@ -35,6 +38,7 @@ Consolidates all registry key names and can safely be included in any component
 
 #if defined(UNICODE)
 
+#      define kServiceParametersNode                           L"SOFTWARE\\Apple Computer, Inc.\\Bonjour"
 #      define kServiceName                                                     L"Bonjour Service"
 #      define kServiceDynDNSBrowseDomains                      L"BrowseDomains"
 #      define kServiceDynDNSHostNames                          L"HostNames"
@@ -48,6 +52,7 @@ Consolidates all registry key names and can safely be included in any component
 
 # else
 
+#      define kServiceParametersNode                           "SOFTWARE\\Apple Computer, Inc.\\Bonjour"
 #      define kServiceName                                                     "Bonjour Service"
 #      define kServiceDynDNSBrowseDomains                      "BrowseDomains"
 #      define kServiceDynDNSHostNames                          "HostNames"
index 15eb7f8c127aaffd78f4b2151cee14bb40b7cd89..ba235c8ebe861da768f476f7fc0491801b9edca8 100755 (executable)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: Firewall.cpp,v $
+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
 
@@ -32,7 +35,16 @@ Wrapper for Windows Firewall API code
 
 */
 
-#define _WIN32_DCOM 
+// <rdar://problem/4278931> Doesn't compile correctly with latest Platform SDK
+
+#if !defined(_WIN32_DCOM)
+#      define _WIN32_DCOM 
+#endif
+
+
+#if !defined(_WSPIAPI_COUNTOF)
+#      define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#endif
 
 #include "Firewall.h"
 #include <windows.h>
index 451c239ce0b7b8b2eb348eeef9445d348d9b7727..768b589ab8a06ce83c537a1b7c4cea38dfe247d2 100644 (file)
     Change History (most recent first):
     
 $Log: Service.c,v $
+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
 
@@ -169,8 +196,9 @@ mDNSResponder Windows Service. Provides global Bonjour support with an IPC inter
 
 #define        DEBUG_NAME                                                      "[Server] "
 #define kServiceFirewallName                           L"Bonjour"
-#define        kServiceDependencies                            TEXT("Tcpip\0winmgmt\0\0")
+#define        kServiceDependencies                            TEXT("Tcpip\0\0")
 #define        kDNSServiceCacheEntryCountDefault       512
+#define kRetryFirewallPeriod                           30 * 1000
 
 #define RR_CACHE_SIZE 500
 static CacheEntity gRRCache[RR_CACHE_SIZE];
@@ -257,8 +285,9 @@ static mDNSs32              udsIdle(mDNS * const inMDNS, mDNSs32 interval);
 static void                    CoreCallback(mDNS * const inMDNS, mStatus result);
 static void                    HostDescriptionChanged(mDNS * const inMDNS);
 static OSStatus                GetRouteDestination(DWORD * ifIndex, DWORD * address);
-static bool                    HaveLLRoute(PMIB_IPFORWARDROW rowExtant);
-static OSStatus                SetLLRoute();
+static OSStatus                SetLLRoute( mDNS * const inMDNS );
+static bool                    HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr );
+static bool                    IsValidAddress( const char * addr );
 
 #if defined(UNICODE)
 #      define StrLen(X)        wcslen(X)
@@ -301,6 +330,7 @@ DEBUG_LOCAL HANDLE                                  *       gWaitList                               = NULL;
 DEBUG_LOCAL HANDLE                                             gStopEvent                              = NULL;
 DEBUG_LOCAL CRITICAL_SECTION                   gEventSourceLock;
 DEBUG_LOCAL GenLinkedList                              gEventSources;
+DEBUG_LOCAL BOOL                                               gRetryFirewall                  = FALSE;
 
 
 #if 0
@@ -478,7 +508,7 @@ static OSStatus     InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR i
        
        // Get a full path to the executable since a relative path may have been specified.
        
-       size = GetFullPathName( inPath, sizeof( fullPath ), fullPath, &namePtr );
+       size = GetFullPathName( inPath, MAX_PATH, fullPath, &namePtr );
        err = translate_errno( size > 0, (OSStatus) GetLastError(), kPathErr );
        require_noerr( err, exit );
        
@@ -589,7 +619,6 @@ static OSStatus SetServiceParameters()
        DWORD                   value;
        DWORD                   valueLen = sizeof(DWORD);
        DWORD                   type;
-       LPCTSTR                 s;
        OSStatus                err;
        HKEY                    key;
 
@@ -598,8 +627,7 @@ static OSStatus SetServiceParameters()
        //
        // Add/Open Parameters section under service entry in registry
        //
-       s = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters");
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode, &key );
        require_noerr( err, exit );
        
        //
@@ -636,7 +664,6 @@ static OSStatus GetServiceParameters()
        DWORD                   value;
        DWORD                   valueLen;
        DWORD                   type;
-       LPCTSTR                 s;
        OSStatus                err;
        HKEY                    key;
 
@@ -645,8 +672,7 @@ static OSStatus GetServiceParameters()
        //
        // Add/Open Parameters section under service entry in registry
        //
-       s = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters");
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode, &key );
        require_noerr( err, exit );
        
        valueLen = sizeof(DWORD);
@@ -680,21 +706,80 @@ exit:
 
 static OSStatus CheckFirewall()
 {
-       DWORD                   value;
-       DWORD                   valueLen;
-       DWORD                   type;
-       LPCTSTR                 s;
-       HKEY                    key = NULL;
-       OSStatus                err = kUnknownErr;
-       
+       DWORD                                   value;
+       DWORD                                   valueLen;
+       DWORD                                   type;
+       ENUM_SERVICE_STATUS     *       lpService = NULL;
+       SC_HANDLE                               sc = NULL;
+       HKEY                                    key = NULL;
+       BOOL                                    ok;
+       DWORD                                   bytesNeeded = 0;
+       DWORD                                   srvCount;
+       DWORD                                   resumeHandle = 0;
+       DWORD                                   srvType;
+       DWORD                                   srvState;
+       DWORD                                   dwBytes = 0;
+       DWORD                                   i;
+       BOOL                                    isRunning = FALSE;
+       OSStatus                                err = kUnknownErr;
+       
+       // Check to see if the firewall service is running.  If it isn't, then
+       // we want to return immediately
+
+       sc = OpenSCManager( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE );
+       err = translate_errno( sc, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       srvType         =       SERVICE_WIN32;
+       srvState        =       SERVICE_STATE_ALL;
+
+       for ( ;; )
+       {
+               // Call EnumServicesStatus using the handle returned by OpenSCManager
+
+               ok = EnumServicesStatus ( sc, srvType, srvState, lpService, dwBytes, &bytesNeeded, &srvCount, &resumeHandle );
+
+               if ( ok || ( GetLastError() != ERROR_MORE_DATA ) )
+               {
+                       break;
+               }
+
+               if ( lpService )
+               {
+                       free( lpService );
+               }
+
+               dwBytes = bytesNeeded;
+
+               lpService = ( ENUM_SERVICE_STATUS* ) malloc( dwBytes );
+               require_action( lpService, exit, err = mStatus_NoMemoryErr );
+       }
+
+       err = translate_errno( ok, GetLastError(), kUnknownErr );
+       require_noerr( err, exit );
+
+       for ( i = 0; i < srvCount; i++ )
+       {
+               if ( wcscmp( lpService[i].lpServiceName, L"SharedAccess" ) == 0 )
+               {
+                       if ( lpService[i].ServiceStatus.dwCurrentState == SERVICE_RUNNING )
+                       {
+                               isRunning = TRUE;
+                       }
+
+                       break;
+               }
+       }
+
+       require_action( isRunning, exit, err = kUnknownErr );
+
        // Check to see if we've managed the firewall.
        // This package might have been installed, then
        // the OS was upgraded to SP2 or above.  If that's
        // the case, then we need to manipulate the firewall
        // so networking works correctly.
 
-       s = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters");
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode, &key );
        require_noerr( err, exit );
 
        valueLen = sizeof(DWORD);
@@ -725,6 +810,16 @@ exit:
        {
                RegCloseKey( key );
        }
+       
+       if ( lpService )
+       {
+               free( lpService );
+       }
+
+       if ( sc )
+       {
+               CloseServiceHandle ( sc );
+       }
 
        return( err );
 }
@@ -889,7 +984,6 @@ static void WINAPI ServiceMain( DWORD argc, LPTSTR argv[] )
 {
        OSStatus                err;
        BOOL                    ok;
-       TCHAR                   desc[ 256 ];
        
        err = ServiceSetupEventLogging();
        check_noerr( err );
@@ -911,13 +1005,6 @@ static void WINAPI ServiceMain( DWORD argc, LPTSTR argv[] )
        err = translate_errno( gServiceStatusHandle, (OSStatus) GetLastError(), kInUseErr );
        require_noerr( err, exit );
        
-       // Setup the description. This should be done by the installer, but it doesn't support that yet.
-                       
-       desc[ 0 ] = '\0';
-       LoadString( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) );
-       err = SetServiceInfo( NULL, kServiceName, desc );
-       check_noerr( err );
-       
        // Mark the service as starting.
 
        gServiceStatus.dwCurrentState   = SERVICE_START_PENDING;
@@ -1083,6 +1170,11 @@ static OSStatus  ServiceRun( int argc, LPTSTR argv[] )
        
        err = CheckFirewall();
        check_noerr( err );
+
+       if ( err )
+       {
+               gRetryFirewall = TRUE;
+       }
        
        // Run the service-specific stuff. This does not return until the service quits or is stopped.
        
@@ -1158,11 +1250,14 @@ static OSStatus ServiceSpecificInitialize( int argc, LPTSTR argv[] )
        require_noerr( err, exit);
 
        //
-       // set a route to link local addresses (169.254.0.0)
+       // <rdar://problem/4096464> Don't call SetLLRoute on loopback
+       // 
+       // Otherwise, set a route to link local addresses (169.254.0.0)
        //
-       if (gServiceManageLLRouting == true)
+
+       if ( gServiceManageLLRouting && !gPlatformStorage.registeredLoopback4 )
        {
-               SetLLRoute();
+               SetLLRoute( &gMDNSRecord );
        }
 
 exit:
@@ -1179,16 +1274,32 @@ exit:
 
 static OSStatus        ServiceSpecificRun( int argc, LPTSTR argv[] )
 {
+       DWORD   timeout;
        DWORD result;
        
        DEBUG_UNUSED( argc );
        DEBUG_UNUSED( argv );
 
        // Main event loop. Process connection requests and state changes (i.e. quit).
-       while( (result = WaitForSingleObject(gStopEvent, INFINITE)) != WAIT_OBJECT_0 )
+
+       timeout = ( gRetryFirewall ) ? kRetryFirewallPeriod : INFINITE;
+
+       while( (result = WaitForSingleObject( gStopEvent, timeout ) ) != WAIT_OBJECT_0 )
        {
-               // Unexpected wait result.
-               dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, result );
+               if ( result == WAIT_TIMEOUT )
+               {
+                       OSStatus err;
+
+                       err = CheckFirewall();
+                       check_noerr( err );
+
+                       timeout = INFINITE;
+               }
+               else
+               {
+                       // Unexpected wait result.
+                       dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, result );
+               }
        }
 
        return kNoErr;
@@ -1246,13 +1357,17 @@ static void     ServiceSpecificFinalize( int argc, LPTSTR argv[] )
 static void
 CoreCallback(mDNS * const inMDNS, mStatus status)
 {
-       DEBUG_UNUSED( inMDNS );
-
        if (status == mStatus_ConfigChanged)
        {
-               if (gServiceManageLLRouting == true)
+               //
+               // <rdar://problem/4096464> Don't call SetLLRoute on loopback
+               // 
+               // Otherwise, set a route to link local addresses (169.254.0.0)
+               //
+
+               if ( gServiceManageLLRouting && !inMDNS->p->registeredLoopback4 )
                {
-                       SetLLRoute();
+                       SetLLRoute( inMDNS );
                }
        }
 }
@@ -1658,11 +1773,11 @@ EventSourceUnlock()
 
 
 //===========================================================================================================================
-//     HaveLLRoute
+//     HaveRoute
 //===========================================================================================================================
 
 static bool
-HaveLLRoute(PMIB_IPFORWARDROW rowExtant)
+HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr )
 {
        PMIB_IPFORWARDTABLE     pIpForwardTable = NULL;
        DWORD                           dwSize                  = 0;
@@ -1694,7 +1809,7 @@ HaveLLRoute(PMIB_IPFORWARDROW rowExtant)
        //
        for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
        {
-               if (pIpForwardTable->table[i].dwForwardDest == inet_addr(kLLNetworkAddr))
+               if ( pIpForwardTable->table[i].dwForwardDest == addr )
                {
                        memcpy( rowExtant, &(pIpForwardTable->table[i]), sizeof(*rowExtant) );
                        found = true;
@@ -1713,12 +1828,23 @@ exit:
 }
 
 
+//===========================================================================================================================
+//     IsValidAddress
+//===========================================================================================================================
+
+static bool
+IsValidAddress( const char * addr )
+{
+       return ( addr && ( strcmp( addr, "0.0.0.0" ) != 0 ) ) ? true : false;
+}      
+
+
 //===========================================================================================================================
 //     SetLLRoute
 //===========================================================================================================================
 
 static OSStatus
-SetLLRoute()
+SetLLRoute( mDNS * const inMDNS )
 {
        DWORD                           ifIndex;
        MIB_IPFORWARDROW        rowExtant;
@@ -1748,7 +1874,7 @@ SetLLRoute()
        //
        // check to make sure we don't already have a route
        //
-       if (HaveLLRoute(&rowExtant))
+       if ( HaveRoute( &rowExtant, inet_addr( kLLNetworkAddr ) ) )
        {
                //
                // set the age to 0 so that we can do a memcmp.
@@ -1782,13 +1908,32 @@ SetLLRoute()
        }
 
        //
-       // see if this address is a link local address
+       // Now we want to see if we should install a default route for this interface.
+       // We want to do this if the following are true:
        //
-       if ((row.dwForwardNextHop & 0xFFFF) == row.dwForwardDest)
+       // 1. This interface has a link-local address
+       // 2. This is the only IPv4 interface
+       //
+
+       if ( ( row.dwForwardNextHop & 0xFFFF ) == row.dwForwardDest )
        {
-               //
-               // if so, set up a route to ARP everything
-               //
+               mDNSInterfaceData       *       ifd;
+               int                                             numLinkLocalInterfaces  = 0;
+               int                                             numInterfaces                   = 0;
+       
+               for ( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
+               {
+                       if ( ifd->defaultAddr.type == mDNSAddrType_IPv4 )
+                       {
+                               numInterfaces++;
+
+                               if ( ( ifd->interfaceInfo.ip.ip.v4.b[0] == 169 ) && ( ifd->interfaceInfo.ip.ip.v4.b[1] == 254 ) )
+                               {
+                                       numLinkLocalInterfaces++;
+                               }
+                       }
+               }
+
                row.dwForwardDest               = 0;
                row.dwForwardIfIndex    = ifIndex;
                row.dwForwardMask               = 0;
@@ -1796,16 +1941,26 @@ SetLLRoute()
                row.dwForwardProto              = MIB_IPPROTO_NETMGMT;
                row.dwForwardAge                = 0;
                row.dwForwardPolicy             = 0;
-               row.dwForwardMetric1    = 1;
+               row.dwForwardMetric1    = 20;
                row.dwForwardMetric2    = (DWORD) - 1;
                row.dwForwardMetric3    = (DWORD) - 1;
                row.dwForwardMetric4    = (DWORD) - 1;
                row.dwForwardMetric5    = (DWORD) - 1;
-
-               err = CreateIpForwardEntry(&row);
-
-               require_noerr( err, exit );
+               
+               if ( numInterfaces == numLinkLocalInterfaces )
+               {
+                       if ( !HaveRoute( &row, 0 ) )
+                       {
+                               err = CreateIpForwardEntry(&row);
+                               require_noerr( err, exit );
+                       }
+               }
+               else
+               {
+                       DeleteIpForwardEntry( &row );
+               }
        }
+
 exit:
 
        return ( err );
@@ -1823,6 +1978,7 @@ GetRouteDestination(DWORD * ifIndex, DWORD * address)
        IP_ADAPTER_INFO *       pAdapterInfo    =       NULL;
        IP_ADAPTER_INFO *       pAdapter                =       NULL;
        ULONG                           bufLen;
+       mDNSBool                        done                    =       mDNSfalse;
        OSStatus                        err;
 
        //
@@ -1882,24 +2038,41 @@ GetRouteDestination(DWORD * ifIndex, DWORD * address)
                pAdapter = pAdapter->Next;
        }
 
-       pAdapter        =       pAdapterInfo;
-       err                     =       kUnknownErr;
-
-       while (pAdapter)
+       while ( !done )
        {
-               //
-               // if we don't have an interface selected, choose the first one
-               //
-               if ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) && (!(*ifIndex) || (pAdapter->Index == (*ifIndex))))
+               pAdapter        =       pAdapterInfo;
+               err                     =       kUnknownErr;
+
+               while (pAdapter)
                {
-                       *address =      inet_addr( pAdapter->IpAddressList.IpAddress.String );
-                       *ifIndex =  pAdapter->Index;
-                       err              =      kNoErr;
-                       break;
+                       // If we don't have an interface selected, choose the first one that is of type ethernet and
+                       // has a valid IP Address
+
+                       if ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) && ( IsValidAddress( pAdapter->IpAddressList.IpAddress.String ) ) && (!(*ifIndex) || (pAdapter->Index == (*ifIndex))))
+                       {
+                               *address =      inet_addr( pAdapter->IpAddressList.IpAddress.String );
+                               *ifIndex =  pAdapter->Index;
+                               err              =      kNoErr;
+                               break;
+                       }
+               
+                       pAdapter = pAdapter->Next;
                }
-       
-               pAdapter = pAdapter->Next;
-       }
+
+               // If we found the right interface, or we weren't trying to find a specific interface then we're done
+
+               if ( !err || !( *ifIndex) )
+               {
+                       done = mDNStrue;
+               }
+
+               // Otherwise, try again by wildcarding the interface
+
+               else
+               {
+                       *ifIndex = 0;
+               }
+       } 
 
 exit:
 
@@ -1910,4 +2083,3 @@ exit:
 
        return( err );
 }
-
index cbc4e1441cf35b62a91ee941cced97165c6e908d..f77394ee1f0ff054a8a3ed6ce9441e1643f79e01 100644 (file)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="mDNSResponder"\r
        ProjectGUID="{C1D98254-BA27-4427-A3BE-A68CA2CC5F69}"\r
        Keyword="Win32Proj">\r
@@ -19,8 +19,8 @@
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;&quot;C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include&quot;"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;DEBUG=1;MDNS_DEBUGMSGS=0;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0500;DEBUG=1;MDNS_DEBUGMSGS=0;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE"\r
                                StringPooling="TRUE"\r
                                MinimalRebuild="TRUE"\r
                                ExceptionHandling="FALSE"\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
+                       OutputDirectory=".\Release"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="1"\r
                        CharacterSet="2">\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;&quot;C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include&quot;"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE"\r
+                               AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0500;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE"\r
                                RuntimeLibrary="0"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="4"\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\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;asmx"\r
                        UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\DNSCommon.c">\r
-                       </File>\r
-                       <File\r
-                               RelativePath="..\..\mDNSCore\DNSDigest.c">\r
+                               RelativePath="..\dDNS.c">\r
                        </File>\r
                        <File\r
                                RelativePath="..\DebugServices.c">\r
                        </File>\r
                        <File\r
-                               RelativePath="Firewall.cpp">\r
+                               RelativePath="..\..\mDNSCore\DNSCommon.c">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\GenLinkedList.c">\r
+                               RelativePath="..\..\mDNSCore\DNSDigest.c">\r
                        </File>\r
                        <File\r
-                               RelativePath=".\Service.c">\r
+                               RelativePath="..\..\mDNSShared\dnssd_ipc.c">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\dDNS.c">\r
+                               RelativePath="Firewall.cpp">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dnssd_ipc.c">\r
+                               RelativePath="..\..\mDNSShared\GenLinkedList.c">\r
                        </File>\r
                        <File\r
                                RelativePath="..\..\mDNSCore\mDNS.c">\r
                        <File\r
                                RelativePath="..\mDNSWin32.c">\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\VPCDetect.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\Service.c">\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\mDNSCore\uDNS.c">\r
                        </File>\r
                                RelativePath="..\CommonServices.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSCore\DNSCommon.h">\r
+                               RelativePath="..\dDNS.h">\r
                        </File>\r
                        <File\r
                                RelativePath="..\DebugServices.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\GenLinkedList.h">\r
-                       </File>\r
-                       <File\r
-                               RelativePath=".\Resource.h">\r
+                               RelativePath="..\..\mDNSCore\DNSCommon.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\dDNS.h">\r
+                               RelativePath="..\..\mDNSShared\dnssd_ipc.h">\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\mDNSShared\dnssd_ipc.h">\r
+                               RelativePath="..\..\mDNSShared\GenLinkedList.h">\r
                        </File>\r
                        <File\r
                                RelativePath="..\..\mDNSCore\mDNSDebug.h">\r
                        <File\r
                                RelativePath="..\mDNSWin32.h">\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\VPCDetect.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\Resource.h">\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\mDNSCore\uDNS.h">\r
                        </File>\r
diff --git a/mDNSWindows/SystemServiceTest/Prefix.h b/mDNSWindows/SystemServiceTest/Prefix.h
deleted file mode 100644 (file)
index 53fb893..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
-
-    Change History (most recent first):
-
-$Log: Prefix.h,v $
-Revision 1.1  2004/06/18 04:17:43  rpantos
-Move up one level.
-
-Revision 1.1  2004/01/30 02:58:57  bradley
-Test tool for the mDNSResponder Windows service.
-                                       
-*/
-
-#ifndef __PREFIX__
-#define __PREFIX__
-
-#if( defined( _DEBUG ) )
-       #define DEBUG                                   1
-       #define MDNS_DEBUGMSGS                  1
-#else
-       #define DEBUG                                   0
-#endif
-
-#define        DNS_SD_DIRECT_ENABLED           0
-#define        DNS_SD_CLIENT_ENABLED           1
-
-#endif // __PREFIX__
diff --git a/mDNSWindows/SystemServiceTest/Tool.c b/mDNSWindows/SystemServiceTest/Tool.c
deleted file mode 100644 (file)
index f4d675a..0000000
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
-
-    Change History (most recent first):
-       
-$Log: Tool.c,v $
-Revision 1.2  2004/07/13 21:24:28  rpantos
-Fix for <rdar://problem/3701120>.
-
-Revision 1.1  2004/06/18 04:17:43  rpantos
-Move up one level.
-
-Revision 1.3  2004/04/09 21:03:15  bradley
-Changed port numbers to use network byte order for consistency with other platforms.
-
-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 02:58:57  bradley
-Test tool for the mDNSResponder Windows service.
-
-*/
-
-#include       <stdio.h>
-#include       <stdlib.h>
-
-#include       "CommonServices.h"
-#include       "DebugServices.h"
-#include       "DNSSD.h"
-
-//===========================================================================================================================
-//     Structures
-//===========================================================================================================================
-
-#define MAX_DOMAIN_LABEL 63
-#define MAX_DOMAIN_NAME 255
-
-typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
-
-typedef struct { u_char c[ 64]; } domainlabel;
-typedef struct { u_char c[256]; } domainname;
-
-typedef struct 
-    { 
-    uint16_t priority; 
-    uint16_t weight; 
-    uint16_t port; 
-    domainname target;
-    } srv_rdata;
-
-//===========================================================================================================================
-//     Prototypes
-//===========================================================================================================================
-
-int                            main( int argc, char* argv[] );
-static void                    Usage( void );
-static int                     ProcessArgs( int argc, char* argv[] );
-
-#if( defined( WINVER ) )
-       static BOOL WINAPI      ConsoleControlHandler( DWORD inControlEvent );
-#endif
-
-static void CALLBACK_COMPAT
-       EnumerateDomainsCallBack(
-               DNSServiceRef           inRef,
-               DNSServiceFlags         inFlags,
-               uint32_t                        inInterfaceIndex,
-               DNSServiceErrorType     inErrorCode,
-               const char *            inDomain,  
-               void *                          inContext );
-
-static void CALLBACK_COMPAT
-       BrowseCallBack(
-               DNSServiceRef           inRef,
-               DNSServiceFlags         inFlags,
-               uint32_t                        inInterfaceIndex,
-               DNSServiceErrorType     inErrorCode,
-               const char *            inName,  
-               const char *            inType,  
-               const char *            inDomain,  
-               void *                          inContext );
-
-static void CALLBACK_COMPAT
-       ResolveCallBack(
-               DNSServiceRef           inRef,
-               DNSServiceFlags         inFlags,
-               uint32_t                        inInterfaceIndex,
-               DNSServiceErrorType     inErrorCode,
-               const char *            inFullName,  
-               const char *            inHostName,  
-               uint16_t                        inPort, 
-               uint16_t                        inTXTSize, 
-               const char *            inTXT, 
-               void *                          inContext );
-
-static void CALLBACK_COMPAT
-       RegisterCallBack(
-               DNSServiceRef           inRef,
-               DNSServiceFlags         inFlags,
-               DNSServiceErrorType     inErrorCode,
-               const char *            inName,  
-               const char *            inType,  
-               const char *            inDomain,  
-               void *                          inContext );
-
-static void CALLBACK_COMPAT
-       RecordCallBack( 
-               DNSServiceRef                   inRef, 
-               DNSRecordRef                    inRecordRef, 
-               DNSServiceFlags                 inFlags, 
-               DNSServiceErrorType     inErrorCode, 
-               void *                                  inContext );
-
-static void CALLBACK_COMPAT
-       QueryCallBack( 
-               const DNSServiceRef             inRef, 
-               const DNSServiceFlags           inFlags, 
-               const uint32_t                          inInterfaceIndex, 
-               const DNSServiceErrorType       inErrorCode, 
-               const char *                            inName, 
-               const uint16_t                          inRRType, 
-               const uint16_t                          inRRClass, 
-               const uint16_t                          inRDataSize, 
-               const void *                            inRData, 
-               const uint32_t                          inTTL, 
-               void *                                          inContext );
-
-static void    PrintRData( uint16_t inRRType, size_t inRDataSize, const uint8_t *inRData );
-
-static char *ConvertDomainLabelToCString_withescape(const domainlabel *const label, char *ptr, char esc);
-static char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc);
-
-//===========================================================================================================================
-//     Globals
-//===========================================================================================================================
-
-#if( defined( WINVER ) )
-       static volatile int             gQuit = 0;
-#endif
-
-//===========================================================================================================================
-//     main
-//===========================================================================================================================
-
-int main( int argc, char *argv[] )
-{
-       OSStatus                err;
-       
-       debug_initialize( kDebugOutputTypeMetaConsole );
-       debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
-
-       SetConsoleCtrlHandler( ConsoleControlHandler, TRUE );
-       err = ProcessArgs( argc, argv );
-       return( (int) err );
-}
-
-//===========================================================================================================================
-//     Usage
-//===========================================================================================================================
-
-static void    Usage( void )
-{
-       fprintf( stderr, "\n" );
-       fprintf( stderr, "DNSServiceTest 1.0d1\n" );
-       fprintf( stderr, "\n" );
-       fprintf( stderr, "  -server <IP>                                      Set Remote Server\n" );
-       fprintf( stderr, "  -cv                                               Check Version\n" );
-       fprintf( stderr, "  -bd                                               Browse for Browse Domains\n" );
-       fprintf( stderr, "  -bs <type> <domain>                               Browse for Services\n" );
-       fprintf( stderr, "  -rsi <name> <type> <domain>                       Resolve Service Instance\n" );
-       fprintf( stderr, "  -rs <name> <type> <domain> <host> <port> <txt>    Register Service\n" );
-       fprintf( stderr, "  -rr                                               Register Records\n" );
-       fprintf( stderr, "  -qr <name> <type> <domain> <rrType>               Query Record\n" );
-       fprintf( stderr, "  -cr <name> <type> <domain> <rrType>               Reconfirm Record\n" );
-       fprintf( stderr, "  -cp <code>                                        Copy Property\n" );
-       fprintf( stderr, "  -h[elp]                                           Help\n" );
-       fprintf( stderr, "\n" );
-}
-
-DEBUG_LOCAL DNSServiceRef              gRef            = NULL;
-DEBUG_LOCAL DNSRecordRef               gRecordRef      = NULL;
-DEBUG_LOCAL const char *               gServer         = NULL;
-
-//===========================================================================================================================
-//     ProcessArgs
-//===========================================================================================================================
-
-static int ProcessArgs( int argc, char* argv[] )
-{      
-       OSStatus                        err;
-       int                                     i;
-       const char *            name;
-       const char *            type;
-       const char *            domain;
-       uint16_t                        port;
-       const char *            host;
-       const char *            txt;
-       uint16_t                        txtSize;
-       uint8_t                         txtStorage[ 256 ];
-       uint32_t                        ipv4;
-       char                            s[ 256 ];
-       DNSRecordRef            records[ 10 ];
-       char                            fullName[ kDNSServiceMaxDomainName ];
-       uint16_t                        rrType;
-       
-       err = DNSServiceInitialize( kDNSServiceInitializeFlagsNoServerCheck, 0 );
-       require_noerr( err, exit );
-       
-       // Parse the command line arguments (ignore first argument since it's just the program name).
-       
-       if( argc <= 1 )
-       {
-               Usage();
-               err = 0;
-               goto exit;
-       }
-       for( i = 1; i < argc; ++i )
-       {
-               if( strcmp( argv[ i ], "-server" ) == 0 )
-               {
-                       require_action( argc > ( i + 1 ), exit, err = kParamErr );
-                       gServer = argv[ ++i ];
-                       
-                       printf( "Server set to \"%s\"\n", gServer );
-               }
-               else if( strcmp( argv[ i ], "-cv" ) == 0 )
-               {
-                       // Check Version
-                                               
-                       err = DNSServiceCheckVersion();
-                       printf( "CheckVersion: %ld\n", err );
-                       err = kNoErr;
-                       goto exit;
-               }
-               else if( strcmp( argv[ i ], "-bd" ) == 0 )
-               {
-                       err = DNSServiceEnumerateDomains( &gRef, kDNSServiceFlagsBrowseDomains, 0, 
-                               EnumerateDomainsCallBack, NULL );
-                       require_noerr( err, exit );
-               }
-               else if( strcmp( argv[ i ], "-bs" ) == 0 )
-               {
-                       // Browse service <type> <domain>
-                                               
-                       if( argc > ( i + 2 ) )
-                       {
-                               type    = argv[ ++i ];
-                               domain  = argv[ ++i ];
-                       }
-                       else
-                       {
-                               type    = "_http._tcp";
-                               domain  = "";
-                       }
-                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
-                       {
-                               domain = "local.";
-                       }
-                       
-                       err = DNSServiceBrowse( &gRef, 0, 0, type, domain, BrowseCallBack, NULL );
-                       require_noerr( err, exit );
-               }
-               else if( strcmp( argv[ i ], "-rsi" ) == 0 )
-               {
-                       // Resolve Service Instance <name> <type> <domain>
-                                               
-                       if( argc > ( i + 3 ) )
-                       {
-                               name    = argv[ ++i ];
-                               type    = argv[ ++i ];
-                               domain  = argv[ ++i ];
-                       }
-                       else
-                       {
-                               name    = "test service";
-                               type    = "_http._tcp";
-                               domain  = "";
-                       }
-                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
-                       {
-                               domain = "local.";
-                       }
-                       
-                       err = DNSServiceResolve( &gRef, 0, 0, name, type, domain, ResolveCallBack, NULL );
-                       require_noerr( err, exit );
-               }
-               else if( strcmp( argv[ i ], "-rs" ) == 0 )
-               {
-                       // Register Service <name> <type> <domain> <host> <port> <txt>
-                       
-                       if( argc > ( i + 6 ) )
-                       {
-                               name    = argv[ ++i ];
-                               type    = argv[ ++i ];
-                               domain  = argv[ ++i ];
-                               host    = argv[ ++i ];
-                               port    = (uint16_t) atoi( argv[ ++i ] );
-                               txt     = argv[ ++i ];
-                       }
-                       else
-                       {
-                               name    = "test service";
-                               type    = "_http._tcp";
-                               domain  = "";
-                               host    = "";
-                               port    = 80;
-                               txt             = "My TXT Record";
-                       }
-                       if( *txt != '\0' )
-                       {
-                               txtStorage[ 0 ] = (uint8_t) strlen( txt );
-                               memcpy( &txtStorage[ 1 ], txt, txtStorage[ 0 ] );
-                               txtSize = (uint16_t)( 1 + txtStorage[ 0 ] );
-                               txt = (const char *) txtStorage;
-                       }
-                       else
-                       {
-                               txt = NULL;
-                               txtSize = 0;
-                       }
-                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
-                       {
-                               domain = "local.";
-                       }
-                       
-                       err = DNSServiceRegister( &gRef, 0, 0, name, type, domain, host, htons( port ), txtSize, txt, 
-                               RegisterCallBack, NULL );
-                       require_noerr( err, exit );
-                       
-                       #if( TEST_SERVICE_RECORDS )
-                               ipv4 = 0x11223344;
-                               err = DNSServiceAddRecord( gRef, &gRecordRef, 0, kDNSServiceDNSType_A, kDNSServiceDNSClass_IN, &ipv4, 60 );
-                               require_noerr( err, exit );
-                               
-                               Sleep( 10000 );
-                               
-                               ipv4 = 0x22334455;
-                               err = DNSServiceUpdateRecord( gRef, gRecordRef, 0, 4, &ipv4, 60 );
-                               require_noerr( err, exit );
-                               
-                               Sleep( 10000 );
-                               
-                               err = DNSServiceRemoveRecord( gRef, gRecordRef, 0 );
-                               require_noerr( err, exit );
-                               gRecordRef = NULL;
-                               
-                               Sleep( 10000 );
-                       #endif
-               }
-               else if( strcmp( argv[ i ], "-rr" ) == 0 )
-               {
-                       // Register Records
-                       
-                       err = DNSServiceCreateConnection( &gRef );
-                       require_noerr( err, exit );
-                                               
-                       printf( "registering 10 address records...\n" );
-                       ipv4 = 0x11223310;
-                       for( i = 0; i < 10; ++i )
-                       {
-                               sprintf( s, "testhost-%d.local.", i );
-                               ++ipv4;
-                               err = DNSServiceRegisterRecord( gRef, &records[ i ], kDNSServiceFlagsUnique, 0, s, 
-                                       kDNSServiceDNSType_A, kDNSServiceDNSClass_IN, 4, &ipv4, 60, RecordCallBack, NULL );
-                               check_noerr( err );
-                       }
-                       Sleep( 10000 );
-                       
-                       printf( "deregistering half of the records\n" );
-                       for( i = 0; i < 10; ++i )
-                       {
-                               if( i % 2 )
-                               {
-                                       err = DNSServiceRemoveRecord( gRef, records[ i ], 0 );
-                                       check_noerr( err );
-                                       records[ i ] = NULL;
-                               }
-                       }
-                       Sleep( 10000 );
-                       
-                       printf( "updating the remaining records\n" );
-                       for( i = 0; i < 10; ++i )
-                       {
-                               if( records[ i ] )
-                               {
-                                       ++ipv4;
-                                       err = DNSServiceUpdateRecord( gRef, records[ i ], 0, 4, &ipv4, 60 );
-                                       check_noerr( err );
-                               }
-                       }
-                       Sleep( 10000 );
-                       
-                       printf( "deregistering all remaining records\n" );
-               DNSServiceRefDeallocate( gRef );
-               
-               Sleep( 5000 );
-               }
-               else if( strcmp( argv[ i ], "-qr" ) == 0 )
-               {
-                       // Query Record <name> <type> <domain> <rrType>
-                                               
-                       if( argc > ( i + 4 ) )
-                       {
-                               name    = argv[ ++i ];
-                               type    = argv[ ++i ];
-                               domain  = argv[ ++i ];
-                               rrType  = (uint16_t) atoi( argv[ ++i ] );
-                       }
-                       else
-                       {
-                               name    = "test";
-                               type    = "";
-                               domain  = "";
-                               rrType  = 1;    // Address
-                       }
-                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
-                       {
-                               domain = "local.";
-                       }
-                       err = DNSServiceConstructFullName( fullName, name, type, domain );
-                       require_noerr( err, exit );
-                       
-                       printf( "resolving fullname %s type %d\n", fullName, rrType );
-                       err = DNSServiceQueryRecord( &gRef, 0, 0, fullName, rrType, kDNSServiceDNSClass_IN, QueryCallBack, NULL );
-                       require_noerr( err, exit );
-               }
-               else if( strcmp( argv[ i ], "-cr" ) == 0 )
-               {
-                       // Reconfirm Record <name> <type> <domain> <rrType>
-                       
-                       if( argc > ( i + 4 ) )
-                       {
-                               name    = argv[ ++i ];
-                               type    = argv[ ++i ];
-                               domain  = argv[ ++i ];
-                               rrType  = (uint16_t) atoi( argv[ ++i ] );
-                       }
-                       else
-                       {
-                               name    = "test";
-                               type    = "";
-                               domain  = "";
-                               rrType  = 1;    // Address
-                       }
-                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
-                       {
-                               domain = "local.";
-                       }
-                       err = DNSServiceConstructFullName( fullName, name, type, domain );
-                       require_noerr( err, exit );
-                       
-                       printf( "reconfirming record fullname %s type %d\n", fullName, rrType );
-                       ipv4 = 0x11223310;
-                       DNSServiceReconfirmRecord( 0, 0, fullName, rrType, kDNSServiceDNSClass_IN, 4, &ipv4 );
-               }
-               else if( strcmp( argv[ i ], "-cp" ) == 0 )
-               {
-                       DNSPropertyCode         code;
-                       DNSPropertyData         data;
-                       
-                       // Copy Property <code>
-                                               
-                       if( argc > ( i + 1 ) )
-                       {
-                               name = argv[ ++i ];
-                               require_action( strlen( name ) == 4, exit, err = kParamErr );
-                               
-                               code  = (DNSPropertyCode)( name[ 0 ] << 24 );
-                               code |= (DNSPropertyCode)( name[ 1 ] << 16 );
-                               code |= (DNSPropertyCode)( name[ 2 ] <<  8 );
-                               code |= (DNSPropertyCode)  name[ 3 ];
-                       }
-                       else
-                       {
-                               code = kDNSPropertyCodeVersion;
-                               name = "vers";
-                       }
-                       
-                       err = DNSServiceCopyProperty( code, &data );
-                       require_noerr( err, exit );
-                       
-                       printf( "'%s' property:\n", name );
-                       if( code == kDNSPropertyCodeVersion )
-                       {
-                               printf( "    clientCurrentVersion:      0x%08X\n", data.u.version.clientCurrentVersion );
-                               printf( "    clientOldestServerVersion: 0x%08X\n", data.u.version.clientOldestServerVersion );
-                               printf( "    serverCurrentVersion:      0x%08X\n", data.u.version.serverCurrentVersion );
-                               printf( "    serverOldestClientVersion: 0x%08X\n", data.u.version.serverOldestClientVersion );
-                       }
-               }
-               else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || ( strcmp( argv[ i ], "-h" ) == 0 ) )
-               {
-                       // Help
-                       
-                       Usage();
-                       err = 0;
-                       goto exit;
-               }
-               else
-               {
-                       // Unknown parameter.
-                       
-                       dlog( kDebugLevelError, "unknown parameter (%s)\n", argv[ i ] );
-                       err = kParamErr;
-                       goto exit;
-               }
-       }
-       
-       // Run until control-C'd.
-       
-       while( !gQuit )
-       {
-               Sleep( 100 );
-       }
-       err = kNoErr;
-       
-exit:
-       DNSServiceFinalize();
-       if( err )
-       {
-               Usage();
-       }
-       return( err );
-}
-
-//===========================================================================================================================
-//     ConsoleControlHandler
-//===========================================================================================================================
-
-static BOOL WINAPI     ConsoleControlHandler( DWORD inControlEvent )
-{
-       BOOL            handled;
-       
-       handled = 0;
-       switch( inControlEvent )
-       {
-               case CTRL_C_EVENT:
-               case CTRL_BREAK_EVENT:
-               case CTRL_CLOSE_EVENT:
-               case CTRL_LOGOFF_EVENT:
-               case CTRL_SHUTDOWN_EVENT:
-                       gQuit = 1;
-                       handled = 1;
-                       break;
-               
-               default:
-                       break;
-       }
-       return( handled );
-}
-
-//===========================================================================================================================
-//     EnumerateDomainsCallBack
-//===========================================================================================================================
-
-static void CALLBACK_COMPAT
-       EnumerateDomainsCallBack(
-               DNSServiceRef           inRef,
-               DNSServiceFlags         inFlags,
-               uint32_t                        inInterfaceIndex,
-               DNSServiceErrorType     inErrorCode,
-               const char *            inDomain,  
-               void *                          inContext )
-{
-       printf( "inRef:            0x%08X\n", (uintptr_t) inRef );
-       printf( "inFlags:          0x%08X\n", (int) inFlags );
-       printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex );
-       printf( "inErrorCode:      %ld\n", inErrorCode );
-       printf( "inDomain:         \"%s\"\n", inDomain ? inDomain : "<null>" );
-       printf( "inContext:        0x%08X\n", (uintptr_t) inContext );
-       printf( "\n" );
-}
-
-//===========================================================================================================================
-//     BrowseCallBack
-//===========================================================================================================================
-
-static void CALLBACK_COMPAT
-       BrowseCallBack(
-               DNSServiceRef           inRef,
-               DNSServiceFlags         inFlags,
-               uint32_t                        inInterfaceIndex,
-               DNSServiceErrorType     inErrorCode,
-               const char *            inName,  
-               const char *            inType,  
-               const char *            inDomain,  
-               void *                          inContext )
-{
-       printf( "inRef:            0x%08X\n", (uintptr_t) inRef );
-       printf( "inFlags:          0x%08X\n", (int) inFlags );
-       printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex );
-       printf( "inErrorCode:      %ld\n", inErrorCode );
-       printf( "inName:           \"%s\"\n", inName ? inName : "<null>" );
-       printf( "inType:           \"%s\"\n", inType ? inType : "<null>" );
-       printf( "inDomain:         \"%s\"\n", inDomain ? inDomain : "<null>" );
-       printf( "inContext:        0x%08X\n", (uintptr_t) inContext );
-       printf( "\n" );
-}
-
-//===========================================================================================================================
-//     ResolveCallBack
-//===========================================================================================================================
-
-static void CALLBACK_COMPAT
-       ResolveCallBack(
-               DNSServiceRef           inRef,
-               DNSServiceFlags         inFlags,
-               uint32_t                        inInterfaceIndex,
-               DNSServiceErrorType     inErrorCode,
-               const char *            inFullName,  
-               const char *            inHostName,  
-               uint16_t                        inPort, 
-               uint16_t                        inTXTSize, 
-               const char *            inTXT, 
-               void *                          inContext )
-{
-       printf( "inRef:            0x%08X\n", (uintptr_t) inRef );
-       printf( "inFlags:          0x%08X\n", (int) inFlags );
-       printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex );
-       printf( "inErrorCode:      %ld\n", inErrorCode );
-       printf( "inFullName:       \"%s\"\n", inFullName ? inFullName : "<null>" );
-       printf( "inHostName:       \"%s\"\n", inHostName ? inHostName : "<null>" );
-       printf( "inPort:           %d\n", ntohs( inPort ) );
-       printf( "inTXTSize:        %ld\n", inTXTSize );
-       printf( "inTXT:            0x%08X\n", (uintptr_t) inTXT );
-       printf( "inContext:        0x%08X\n", (uintptr_t) inContext );
-       printf( "\n" );
-}
-
-//===========================================================================================================================
-//     RegisterCallBack
-//===========================================================================================================================
-
-static void CALLBACK_COMPAT
-       RegisterCallBack(
-               DNSServiceRef           inRef,
-               DNSServiceFlags         inFlags,
-               DNSServiceErrorType     inErrorCode,
-               const char *            inName,  
-               const char *            inType,  
-               const char *            inDomain,  
-               void *                          inContext )
-{
-       printf( "inRef:            0x%08X\n", (uintptr_t) inRef );
-       printf( "inFlags:          0x%08X\n", (int) inFlags );
-       printf( "inErrorCode:      %ld\n", inErrorCode );
-       printf( "inName:           \"%s\"\n", inName ? inName : "<null>" );
-       printf( "inType:           \"%s\"\n", inType ? inType : "<null>" );
-       printf( "inDomain:         \"%s\"\n", inDomain ? inDomain : "<null>" );
-       printf( "inContext:        0x%08X\n", (uintptr_t) inContext );
-       printf( "\n" );
-}
-
-//===========================================================================================================================
-//     RecordCallBack
-//===========================================================================================================================
-
-static void CALLBACK_COMPAT
-       RecordCallBack( 
-               DNSServiceRef                   inRef, 
-               DNSRecordRef                    inRecordRef, 
-               DNSServiceFlags                 inFlags, 
-               DNSServiceErrorType     inErrorCode, 
-               void *                                  inContext )
-{
-       DEBUG_UNUSED( inRef );
-       DEBUG_UNUSED( inRecordRef );
-       DEBUG_UNUSED( inFlags );
-       DEBUG_UNUSED( inContext );
-       
-       if( inErrorCode == kDNSServiceErr_NoError )
-       {
-               printf( "RecordCallBack: no errors\n" );
-       }
-       else
-       {
-               printf( "RecordCallBack: %ld error\n", inErrorCode );
-       }
-}
-
-//===========================================================================================================================
-//     QueryCallBack
-//===========================================================================================================================
-
-static void CALLBACK_COMPAT
-       QueryCallBack( 
-               const DNSServiceRef             inRef, 
-               const DNSServiceFlags           inFlags, 
-               const uint32_t                          inInterfaceIndex, 
-               const DNSServiceErrorType       inErrorCode, 
-               const char *                            inName, 
-               const uint16_t                          inRRType, 
-               const uint16_t                          inRRClass, 
-               const uint16_t                          inRDataSize, 
-               const void *                            inRData, 
-               const uint32_t                          inTTL, 
-               void *                                          inContext )
-{
-       DEBUG_UNUSED( inRef );
-       DEBUG_UNUSED( inRRClass );
-       DEBUG_UNUSED( inTTL );
-       DEBUG_UNUSED( inContext );
-       
-       if( inErrorCode == kDNSServiceErr_NoError )
-       {
-               if( inFlags & kDNSServiceFlagsAdd )
-               {
-                       printf( "Add" );
-               }
-               else
-               {
-                       printf( "Rmv" );
-               }
-               if( inFlags & kDNSServiceFlagsMoreComing )
-               {
-                       printf( "+" );
-               }
-               else
-               {
-                       printf( " " );
-               }
-               printf(" 0x%04X %d %s rdata ", inFlags, inInterfaceIndex, inName );
-               PrintRData( inRRType, (size_t) inRDataSize, (const uint8_t *) inRData );
-       }
-       else
-       {
-               printf( "QueryCallback: %ld error\n", inErrorCode );
-       }
-}
-
-//===========================================================================================================================
-//     PrintRData
-//===========================================================================================================================
-
-static void    PrintRData( uint16_t inRRType, size_t inRDataSize, const uint8_t *inRData )
-{
-       size_t                          i;
-       srv_rdata *                     srv;
-       char                            s[ 1005 ];
-       struct in_addr          in;
-       
-       switch( inRRType )
-       {
-               case kDNSServiceDNSType_TXT:
-                       
-                       // Print all the alphanumeric and punctuation characters
-                       
-                       for( i = 0; i < inRDataSize; ++i )
-                       {
-                               if( ( inRData[ i ] >= 32 ) && ( inRData[ i ] <= 127 ) )
-                               {
-                                       printf( "%c", inRData[ i ] );
-                               }
-                       }
-                       printf( "\n" );
-                       break;
-                       
-               case kDNSServiceDNSType_SRV:
-                       srv = (srv_rdata *)inRData;
-                       ConvertDomainNameToCString_withescape(&srv->target, s, 0);
-                       printf("pri=%d, w=%d, port=%d, target=%s\n", srv->priority, srv->weight, srv->port, s);
-                       break;
-                       
-               case kDNSServiceDNSType_A:
-                       check( inRDataSize == 4 );
-                       memcpy( &in, inRData, sizeof( in ) );
-                       printf( "%s\n", inet_ntoa( in ) );
-                       break;
-                       
-               case kDNSServiceDNSType_PTR:
-                       ConvertDomainNameToCString_withescape( (domainname *) inRData, s, 0 );
-                       break;
-               
-               case kDNSServiceDNSType_AAAA:
-                       check( inRDataSize == 16 );
-                       printf( "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\n",
-                                       inRData[0], inRData[1], inRData[2], inRData[3], inRData[4], inRData[5], inRData[6], inRData[7], inRData[8], 
-                                       inRData[9], inRData[10], inRData[11], inRData[12], inRData[13], inRData[14], inRData[15] );
-                       break;
-               
-               default:
-                       printf( "ERROR: I dont know how to print inRData of type %d\n", inRRType );
-                       return;
-       }
-}
-
-static char *ConvertDomainLabelToCString_withescape(const domainlabel *const label, char *ptr, char esc)
-    {
-    const unsigned char *      src = label->c;                         // Domain label we're reading
-    const unsigned char        len = *src++;                           // Read length of this (non-null) label
-    const unsigned char *const end = src + len;                        // Work out where the label ends
-    if (len > 63) return(NULL);           // If illegal label, abort
-    while (src < end)                                           // While we have characters in the label
-        {
-        unsigned char c = *src++;
-        if (esc)
-            {
-            if (c == '.')                                       // If character is a dot,
-                *ptr++ = esc;                                   // Output escape character
-            else if (c <= ' ')                                  // If non-printing ascii,
-                {                                                   // Output decimal escape sequence
-                *ptr++ = esc;
-                *ptr++ = (char)  ('0' + (c / 100)     );
-                *ptr++ = (char)  ('0' + (c /  10) % 10);
-                c      = (unsigned char)('0' + (c      ) % 10);
-                }
-            }
-        *ptr++ = (char)c;                                       // Copy the character
-        }
-    *ptr = 0;                                                   // Null-terminate the string
-    return(ptr);                                                // and return
-    }
-
-static char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc)
-    {
-    const unsigned char *src         = name->c;                        // Domain name we're reading
-    const unsigned char *const max   = name->c + MAX_DOMAIN_NAME;      // Maximum that's valid
-
-    if (*src == 0) *ptr++ = '.';                                // Special case: For root, just write a dot
-
-    while (*src)                                                                                                        // While more characters in the domain name
-        {
-        if (src + 1 + *src >= max) return(NULL);
-        ptr = ConvertDomainLabelToCString_withescape((const domainlabel *)src, ptr, esc);
-        if (!ptr) return(NULL);
-        src += 1 + *src;
-        *ptr++ = '.';                                           // Write the dot after the label
-        }
-
-    *ptr++ = 0;                                                 // Null-terminate the string
-    return(ptr);                                                // and return
-    }
diff --git a/mDNSWindows/SystemServiceTest/Tool.mcp b/mDNSWindows/SystemServiceTest/Tool.mcp
deleted file mode 100644 (file)
index 2f38283..0000000
Binary files a/mDNSWindows/SystemServiceTest/Tool.mcp and /dev/null differ
diff --git a/mDNSWindows/SystemServiceTest/Tool2002.vcproj b/mDNSWindows/SystemServiceTest/Tool2002.vcproj
deleted file mode 100644 (file)
index 0afc4b3..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
-       ProjectType="Visual C++"
-       Version="7.00"
-       Name="mDNSResponderTest"
-       ProjectGUID="{F66EFE7E-50A6-44D4-87C7-742B303BA852}"
-       Keyword="Win32Proj">
-       <Platforms>
-               <Platform
-                       Name="Win32"/>
-       </Platforms>
-       <Configurations>
-               <Configuration
-                       Name="Debug|Win32"
-                       OutputDirectory="Debug"
-                       IntermediateDirectory="Debug"
-                       ConfigurationType="1"
-                       CharacterSet="2">
-                       <Tool
-                               Name="VCCLCompilerTool"
-                               Optimization="0"
-                               AdditionalIncludeDirectories="..\..\..\mDNSCore;..\..\..\mDNSWindows"
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;DEBUG=1"
-                               StringPooling="TRUE"
-                               MinimalRebuild="TRUE"
-                               ExceptionHandling="FALSE"
-                               BasicRuntimeChecks="3"
-                               SmallerTypeCheck="FALSE"
-                               RuntimeLibrary="1"
-                               BufferSecurityCheck="TRUE"
-                               ForceConformanceInForLoopScope="TRUE"
-                               UsePrecompiledHeader="2"
-                               BrowseInformation="1"
-                               WarningLevel="4"
-                               WarnAsError="TRUE"
-                               Detect64BitPortabilityProblems="TRUE"
-                               DebugInformationFormat="3"/>
-                       <Tool
-                               Name="VCCustomBuildTool"/>
-                       <Tool
-                               Name="VCLinkerTool"
-                               AdditionalDependencies="ws2_32.lib"
-                               OutputFile="$(ProjectName)Debug.exe"
-                               LinkIncremental="1"
-                               SuppressStartupBanner="TRUE"
-                               GenerateDebugInformation="TRUE"
-                               SubSystem="1"
-                               TargetMachine="1"/>
-                       <Tool
-                               Name="VCMIDLTool"/>
-                       <Tool
-                               Name="VCPostBuildEventTool"/>
-                       <Tool
-                               Name="VCPreBuildEventTool"/>
-                       <Tool
-                               Name="VCPreLinkEventTool"/>
-                       <Tool
-                               Name="VCResourceCompilerTool"/>
-                       <Tool
-                               Name="VCWebServiceProxyGeneratorTool"/>
-                       <Tool
-                               Name="VCWebDeploymentTool"/>
-               </Configuration>
-               <Configuration
-                       Name="Release|Win32"
-                       OutputDirectory="Release"
-                       IntermediateDirectory="Release"
-                       ConfigurationType="1"
-                       CharacterSet="2"
-                       WholeProgramOptimization="FALSE">
-                       <Tool
-                               Name="VCCLCompilerTool"
-                               Optimization="2"
-                               InlineFunctionExpansion="2"
-                               FavorSizeOrSpeed="2"
-                               OmitFramePointers="TRUE"
-                               AdditionalIncludeDirectories="..\..\..\mDNSCore;..\..\..\mDNSWindows"
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
-                               StringPooling="TRUE"
-                               ExceptionHandling="FALSE"
-                               RuntimeLibrary="0"
-                               BufferSecurityCheck="FALSE"
-                               EnableFunctionLevelLinking="FALSE"
-                               DisableLanguageExtensions="FALSE"
-                               ForceConformanceInForLoopScope="TRUE"
-                               UsePrecompiledHeader="2"
-                               WarningLevel="4"
-                               WarnAsError="TRUE"
-                               Detect64BitPortabilityProblems="TRUE"
-                               DebugInformationFormat="3"
-                               CompileAs="1"/>
-                       <Tool
-                               Name="VCCustomBuildTool"/>
-                       <Tool
-                               Name="VCLinkerTool"
-                               AdditionalDependencies="ws2_32.lib"
-                               OutputFile="$(ProjectName).exe"
-                               LinkIncremental="1"
-                               SuppressStartupBanner="TRUE"
-                               GenerateDebugInformation="TRUE"
-                               SubSystem="1"
-                               OptimizeReferences="2"
-                               EnableCOMDATFolding="2"
-                               TargetMachine="1"/>
-                       <Tool
-                               Name="VCMIDLTool"/>
-                       <Tool
-                               Name="VCPostBuildEventTool"/>
-                       <Tool
-                               Name="VCPreBuildEventTool"/>
-                       <Tool
-                               Name="VCPreLinkEventTool"/>
-                       <Tool
-                               Name="VCResourceCompilerTool"/>
-                       <Tool
-                               Name="VCWebServiceProxyGeneratorTool"/>
-                       <Tool
-                               Name="VCWebDeploymentTool"/>
-               </Configuration>
-       </Configurations>
-       <Files>
-               <File
-                       RelativePath="..\..\CommonServices.h">
-               </File>
-               <File
-                       RelativePath="..\..\..\mDNSCore\DNSCommon.c">
-               </File>
-               <File
-                       RelativePath="..\..\..\mDNSCore\DNSCommon.h">
-               </File>
-               <File
-                       RelativePath="..\..\..\mDNSCore\DNSDigest.c">
-               </File>
-               <File
-                       RelativePath="..\..\DNSSD.c">
-               </File>
-               <File
-                       RelativePath="..\..\DNSSD.h">
-               </File>
-               <File
-                       RelativePath="..\..\DNSSDDirect.c">
-               </File>
-               <File
-                       RelativePath="..\..\DNSSDDirect.h">
-               </File>
-               <File
-                       RelativePath="..\..\DebugServices.c">
-               </File>
-               <File
-                       RelativePath="..\..\DebugServices.h">
-               </File>
-               <File
-                       RelativePath="..\..\RMxClient.c">
-               </File>
-               <File
-                       RelativePath="..\..\RMxClient.h">
-               </File>
-               <File
-                       RelativePath="..\..\RMxCommon.c">
-               </File>
-               <File
-                       RelativePath="..\..\RMxCommon.h">
-               </File>
-               <File
-                       RelativePath="Tool.c">
-               </File>
-               <File
-                       RelativePath="..\..\..\mDNSCore\mDNS.c">
-               </File>
-               <File
-                       RelativePath="..\..\..\mDNSCore\mDNSClientAPI.h">
-               </File>
-               <File
-                       RelativePath="..\..\..\mDNSCore\mDNSDebug.h">
-               </File>
-               <File
-                       RelativePath="..\..\mDNSWin32.c">
-               </File>
-               <File
-                       RelativePath="..\..\mDNSWin32.h">
-               </File>
-               <File
-                       RelativePath="..\..\..\mDNSCore\uDNS.c">
-               </File>
-               <File
-                       RelativePath="..\..\..\mDNSCore\uDNS.h">
-               </File>
-       </Files>
-       <Globals>
-       </Globals>
-</VisualStudioProject>
diff --git a/mDNSWindows/VPCDetect.cpp b/mDNSWindows/VPCDetect.cpp
new file mode 100755 (executable)
index 0000000..a572306
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+
+    Change History (most recent first):
+    
+$Log: VPCDetect.cpp,v $
+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"
+#include "DebugServices.h"
+#include <comdef.h>
+#include <Wbemidl.h>
+
+# pragma comment(lib, "wbemuuid.lib")
+
+static BOOL g_doneCheck = FALSE;
+static BOOL g_isVPC            = FALSE;
+
+
+BOOL
+IsVPCRunning()
+{
+       IWbemLocator                    *       pLoc            = 0;
+       IWbemServices                   *       pSvc            = 0;
+    IEnumWbemClassObject       *       pEnumerator = NULL;
+       bool                                            coInit          = false;
+       HRESULT                                         hres;
+
+       // Short circuit if we've already done this
+
+       require_action_quiet( !g_doneCheck, exit, g_doneCheck = TRUE );
+
+    // Initialize COM.
+
+       hres = CoInitializeEx(0, COINIT_MULTITHREADED);
+       require_action( SUCCEEDED( hres ), exit, g_isVPC = false );
+       coInit = true;
+
+       // Initialize Security
+
+       hres =  CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL );
+       require_action( SUCCEEDED( hres ), exit, g_isVPC = false );
+
+                      
+    // Obtain the initial locator to Windows Management on a particular host computer.
+
+    hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc );
+       require_action( SUCCEEDED( hres ), exit, g_isVPC = false );
+    // Connect to the root\cimv2 namespace with the
+    // current user and obtain pointer pSvc
+    // to make IWbemServices calls.
+
+       hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc );
+       require_action( SUCCEEDED( hres ), exit, g_isVPC = false );
+    
+    // Set the IWbemServices proxy so that impersonation
+    // of the user (client) occurs.
+
+       hres = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
+       require_action( SUCCEEDED( hres ), exit, g_isVPC = false );
+
+    // Use the IWbemServices pointer to make requests of WMI. 
+    // Make requests here:
+
+       hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * from Win32_BaseBoard"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
+    
+       require_action( SUCCEEDED( hres ), exit, g_isVPC = false );
+
+       do
+       {
+               IWbemClassObject* pInstance = NULL;
+               ULONG dwCount = NULL;
+
+               hres = pEnumerator->Next( WBEM_INFINITE, 1, &pInstance, &dwCount);
+
+               if ( pInstance )
+               {
+                       VARIANT v;
+                       BSTR strClassProp = SysAllocString(L"Manufacturer");
+                       HRESULT hr;
+
+                       hr = pInstance->Get(strClassProp, 0, &v, 0, 0);
+                       SysFreeString(strClassProp);
+
+                       // check the HRESULT to see if the action succeeded.
+
+                       if (SUCCEEDED(hr) && (V_VT(&v) == VT_BSTR))
+                       {
+                               wchar_t * wstring = wcslwr( V_BSTR( &v ) );
+
+                               if (wcscmp( wstring, L"microsoft corporation" ) == 0 )
+                               {
+                                       g_isVPC = true;
+                               }
+                       }
+               
+                       VariantClear(&v);
+               }
+       } while (hres == WBEM_S_NO_ERROR);
+         
+exit:
+       if ( pSvc != NULL )
+       {
+       pSvc->Release();
+       }
+
+       if ( pLoc != NULL )
+       {
+       pLoc->Release();     
+       }
+
+       if ( coInit )
+       {
+       CoUninitialize();
+       }
+
+       if ( !g_doneCheck )
+       {
+               g_doneCheck = TRUE;
+
+               if ( g_isVPC )
+               {
+                       dlog( kDebugLevelTrace, "Virtual PC detected" );
+               }
+       }
+
+       return g_isVPC;
+}
diff --git a/mDNSWindows/VPCDetect.h b/mDNSWindows/VPCDetect.h
new file mode 100644 (file)
index 0000000..ed709ac
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+
+    Change History (most recent first):
+    
+$Log: VPCDetect.h,v $
+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
+
+#include <windows.h>
+
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+
+extern BOOL
+IsVPCRunning();
+
+
+#if defined(__cplusplus)
+}
+#endif
index 884d661f10b7956767aa35e4367e4be7ef466cbe..8256ddf7c38adecc54aad5a360702f03b8741a2f 100644 (file)
     Change History (most recent first):
 
 $Log: WinVersRes.h,v $
+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
 
@@ -121,10 +184,10 @@ First checked in.
 #define MASTER_PROD_NAME       "Bonjour"
 
 // Define the product version for mDNSResponder on Windows
-#define MASTER_PROD_VERS               1,0,0,58
-#define MASTER_PROD_VERS_STR   "1,0,0,58"
-#define MASTER_PROD_VERS_STR2  "1.0.0.58"
-#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.0.58"
+#define MASTER_PROD_VERS               1,0,2,9
+#define MASTER_PROD_VERS_STR   "1,0,2,9"
+#define MASTER_PROD_VERS_STR2  "1.0.2.9"
+#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.2.9"
 
 // Define the legal copyright
 #define MASTER_LEGAL_COPYRIGHT "Copyright (C) 2003-2005 Apple Computer, Inc."
index 08cbc886949ddb99b82645964fa04d83c8ca413a..0435517fb7d74c53e807628942681f614a20f7b3 100755 (executable)
 
     Change History (most recent first):
 
+$Log: dDNS.c,v $
+Revision 1.8  2005/09/12 07:13:33  herscher
+<rdar://problem/4248878> Workaround for router crash.  Lazily call RegisterSearchDomains rather than call it always at startup.
+
+Revision 1.7  2005/08/10 01:43:23  herscher
+Pass NULL in for the IPv6 paramter to mDNS_SetPrimaryInterfaceInfo to get this code to compile on Windows.
+
+Revision 1.6  2005/03/23 05:54:48  cheshire
+<rdar://problem/4021486> Fix build warnings
+Fix %s where it should be %##s in debugf & LogMsg calls
+
 */
 
 #include "dDNS.h"
 #include "DNSCommon.h"
+#include "uds_daemon.h"
 #include <winsock2.h>
 #include <iphlpapi.h>
 #include <ws2tcpip.h>
@@ -52,7 +64,11 @@ static ARListElem *SCPrefBrowseDomains = mDNSNULL; // manually generated local-o
 static domainname                      dDNSRegDomain;             // Default wide-area zone for service registration
 static DNameListElem   *       dDNSBrowseDomains;         // Default wide-area zone for legacy ("empty string") browses
 static domainname                      dDNSHostname;
+static mDNSBool                                dDNSRegisterSearchDomains = mDNSfalse;
 
+mDNSlocal mStatus RegisterNameServers( mDNS *const m );
+mDNSlocal mStatus RegisterSearchDomains( mDNS *const m );
+       
 
 mStatus dDNS_SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
        {
@@ -81,8 +97,20 @@ mStatus dDNS_SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
 
        LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
        return(mStatus_Invalid);
+       } 
+
+
+mStatus dDNS_RegisterSearchDomains( mDNS * const m )
+       {
+       mStatus err = mStatus_NoError;
+
+       dDNSRegisterSearchDomains = mDNStrue;
+       RegisterSearchDomains( m );
+
+       return err;
        }
 
+
 mDNSlocal void MarkSearchListElem(domainname *domain)
        {
        SearchListElem *new, *ptr;
@@ -166,7 +194,7 @@ mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceR
                        {
                        if (SameDomainName(&ptr->ar.resrec.rdata->u.name, &answer->rdata->u.name))
                                {
-                               debugf("Deregistering PTR %s -> %s", ptr->ar.resrec.name->c, ptr->ar.resrec.rdata->u.name.c);
+                               debugf("Deregistering PTR %##s -> %##s", ptr->ar.resrec.name->c, ptr->ar.resrec.rdata->u.name.c);
                 dereg = &ptr->ar;
                                if (prev) prev->next = ptr->next;
                                else slElem->AuthRecs = ptr->next;
@@ -271,7 +299,7 @@ mDNSlocal void FoundDefBrowseDomain(mDNS *const m, DNSQuestion *question, const
                        prev = ptr;
                        ptr = ptr->next;
                        }
-               LogMsg("FoundDefBrowseDomain: Got remove event for domain %s not in list", answer->rdata->u.name.c);
+               LogMsg("FoundDefBrowseDomain: Got remove event for domain %##s not in list", answer->rdata->u.name.c);
                }
        }
 
@@ -359,7 +387,7 @@ mDNSlocal mStatus RegisterSearchDomains( mDNS *const m )
                                {
                                AuthRecord *dereg = &arList->ar;
                                arList = arList->next;
-                               debugf("Deregistering PTR %s -> %s", dereg->resrec.name->c, dereg->resrec.rdata->u.name.c);
+                               debugf("Deregistering PTR %##s -> %##s", dereg->resrec.name->c, dereg->resrec.rdata->u.name.c);
                                err = mDNS_Deregister(m, dereg);
                                if (err) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err);
                                }
@@ -471,7 +499,7 @@ mDNSlocal void SetSCPrefsBrowseDomains(mDNS *m, DNameListElem * browseDomains, m
                {
                        if ( !browseDomain->name.c[0] )
                                {
-                               LogMsg("SetSCPrefsBrowseDomains bad DDNS browse domain: %s", browseDomain->name.c[0] ? browseDomain->name.c : "(unknown)");
+                               LogMsg("SetSCPrefsBrowseDomains bad DDNS browse domain: %##s", browseDomain->name.c[0] ? (char*) browseDomain->name.c : "(unknown)");
                                }
                        else
                                {
@@ -554,9 +582,13 @@ mStatus dDNS_Setup( mDNS *const m )
        // YO CFRelease(key);
 
        // handle any changes to search domains and DNS server addresses
+
        if ( dDNSPlatformRegisterSplitDNS(m) != mStatus_NoError)
                if (dict) RegisterNameServers( m );  // fall back to non-split DNS aware configuration on failure
-       RegisterSearchDomains( m );  // note that we register name servers *before* search domains
+
+       if ( dDNSRegisterSearchDomains == mDNStrue )
+               dDNS_RegisterSearchDomains( m );  // note that we register name servers *before* search domains
+
        // if (dict) CFRelease(dict);
 
        // get IPv4 settings
@@ -588,7 +620,10 @@ mStatus dDNS_Setup( mDNS *const m )
        
        if ( dDNSPlatformGetPrimaryInterface( m, &ip, &r ) == mStatus_NoError )
                {
-               mDNS_SetPrimaryInterfaceInfo(m, &ip, r.ip.v4.NotAnInteger ? &r : mDNSNULL);
+               // For now, we're going to pass NULL for the IPv6 parameter so that the Windows code compiles. What needs
+               // to happen is that the implementation of dDNSPlatformGetPrimaryInterface() needs to call the
+               // IPv6 aware "GetAdaptersAddresses" rather than GetAdaptersInfo().
+               mDNS_SetPrimaryInterfaceInfo(m, &ip, NULL, r.ip.v4.NotAnInteger ? &r : mDNSNULL);
                }
 
        return mStatus_NoError;
@@ -608,14 +643,28 @@ mStatus dDNS_Setup( mDNS *const m )
 mStatus dDNS_InitDNSConfig(mDNS *const m)
        {
        mStatus err;
+       static AuthRecord LocalRegPTR;
 
        // start query for domains to be used in default (empty string domain) browses
        err = mDNS_GetDomains(m, &LegacyBrowseDomainQ, mDNS_DomainTypeBrowseLegacy, NULL, mDNSInterface_LocalOnly, FoundDefBrowseDomain, NULL);
 
        // provide .local automatically
        SetSCPrefsBrowseDomain(m, &localdomain, mDNStrue);
+
+       // <rdar://problem/4055653> dns-sd -E does not return "local."
+       // register registration domain "local"
+       mDNS_SetupResourceRecord(&LocalRegPTR, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, NULL, NULL);
+       MakeDomainNameFromDNSNameString(LocalRegPTR.resrec.name, mDNS_DomainTypeNames[mDNS_DomainTypeRegistration]);
+       AppendDNSNameString            (LocalRegPTR.resrec.name, "local");
+       AssignDomainName(&LocalRegPTR.resrec.rdata->u.name, &localdomain);
+       err = mDNS_Register(m, &LocalRegPTR);
+       if (err)
+               {
+               LogMsg("ERROR: dDNS_InitDNSConfig - mDNS_Register returned error %d", err);
+               }
+
     return mStatus_NoError;
-}
+       }
 
 void
 dDNS_FreeIPAddrList(IPAddrListElem * list)
index e1b148e5d8569ce916c27a060c2bcf4702f20807..12c56da3930761ca9d9cdb509ab5d36a124b2e9b 100755 (executable)
 #pragma mark - DynDNS structures
 #endif
 
+#if WIN32
+// named type definition in parentheses \r
+#      pragma warning( disable: 4115 ) \r
+#endif\r
+
 typedef struct IPAddrListElem
        {
        mDNSAddr addr;
index 7a90e66bca5cc4fac1b12cbe2da4efa632d938f2..7084d16b2a0dc1e86bc27e534a2d78c5d405cbfe 100755 (executable)
@@ -72,7 +72,7 @@ static int _getISOCode(LANGID wLangID, char *isoLangCode, int codeLen) {
                int startIndex = i * MODULO_ISOCODES;
                
                langCode = (ISOCODES[startIndex] << 8);
-               langCode += ( (unsigned short) (ISOCODES[startIndex + 1]) );
+               langCode = langCode + ( (unsigned short) (ISOCODES[startIndex + 1]) );
 
                if (langCode == wLangID) {
                        char *langStr = (char *)&(ISOCODES[startIndex+2]);
@@ -118,6 +118,7 @@ int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locF
        if ( !strcmp( appPathNameA, "" ) )
        {
                char   folder[MAX_PATH];
+               char * ext;
                char * app;
 
                GetModuleFileNameA( module, folder, MAX_PATH );
@@ -126,10 +127,16 @@ int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locF
                
                app = strrchr( folder, '\\' );
                require_action( app, exit, ret = 0 );
-
                *app++ = '\0';
 
-               snprintf( appPathNameA, MAX_PATH, "%s\\Resources\\%s", folder, app );
+               // Strip the extension
+
+               if ( ( ( ext = strstr( app, ".exe" ) ) != NULL ) || ( ( ext = strstr( app, ".dll" ) ) != NULL ) )
+               {
+                       *ext = '\0';
+               }
+
+               snprintf( appPathNameA, MAX_PATH, "%s\\%s", folder, app );
        }
 
        ret = PathForResourceWithPathA (appPathNameA, name, locFile, locFileLen);
@@ -149,6 +156,7 @@ int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, in
        {
                wchar_t   folder[MAX_PATH];
                wchar_t * app;
+               wchar_t * ext;
 
                GetModuleFileNameW( module, folder, MAX_PATH);
 
@@ -156,10 +164,16 @@ int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, in
                
                app = wcsrchr( folder, '\\' );
                require_action( app, exit, ret = 0 );
-
                *app++ = '\0';
 
-               swprintf( appPathNameW, MAX_PATH, L"%ls\\Resources\\%ls", folder, app );
+               // Strip the extension
+
+               if ( ( ( ext = wcsstr( app, L".exe" ) ) != NULL ) || ( ( ext = wcsstr( app, L".dll" ) ) != NULL ) )
+               {
+                       *ext = '\0';
+               }
+
+               swprintf( appPathNameW, MAX_PATH, L"%ls\\%ls", folder, app );
        }
 
        ret = PathForResourceWithPathW (appPathNameW, name, locFile, locFileLen);
index 6e7bb361389c072d68ab8155142b0994c62bd8d5..93a14a71eb991e3888d4de3d788262f13fc590a0 100755 (executable)
     Change History (most recent first):
     
 $Log: mDNSWin32.c,v $
+Revision 1.105  2005/11/27 20:21:16  herscher
+<rdar://problem/4210580> Workaround Virtual PC bug that incorrectly modifies incoming mDNS packets
+
+Revision 1.104  2005/10/19 19:42:59  herscher
+<rdar://problem/4295946> Use the registry to determine the domain name, rather than using GetNetworkParams().  GetNetworkParams() does not reliably return domain information for the current network configuration.
+
+Revision 1.103  2005/10/18 06:13:20  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.102  2005/10/05 20:55:14  herscher
+<rdar://problem/4096464> Don't call SetLLRoute on loopback interface
+
+Revision 1.101  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.100  2005/09/29 06:36:00  herscher
+Change check( err ) to check( !err ).  This was a typo that was introduced in a previous checkin.
+
+Revision 1.99  2005/09/29 06:31:46  herscher
+<rdar://problem/4278934> Fall back to calling getifaddrs_ipv4 if getifaddrs_ipv6 fails
+
+Revision 1.98  2005/09/24 01:11:56  cheshire
+Add comment about GetWindowsVersionString
+
+Revision 1.97  2005/09/22 07:10:44  herscher
+<rdar://problem/4263713> Don't send domain enumeration query if domain is empty string or "."
+
+Revision 1.96  2005/09/22 07:06:06  herscher
+<rdar://problem/4252581> Don't loop uncontrollably upon detection of error in main event loop
+
+Revision 1.95  2005/09/11 22:51:40  herscher
+<rdar://problem/4249284> Obtain Hostname by using GetComputerNameEx, rather than gethostname.
+
+Revision 1.94  2005/09/11 21:43:15  herscher
+<rdar://problem/4245949> Don't create HINFO records on Windows
+
+Revision 1.93  2005/07/15 06:06:40  shersche
+<rdar://problem/4165134> Change all WinSock allocation loops to bail out after 100 tries to eliminate the possibility of any infinite loops
+
+Revision 1.92  2005/07/11 20:32:17  shersche
+<rdar://problem/4175515> Fix crash when logging into Cisco VPN
+
+Revision 1.91  2005/04/25 21:34:28  shersche
+<rdar://problem/4096465> Wide-Area services don't disappear when interface goes away
+
+Revision 1.90  2005/04/25 21:18:08  shersche
+<rdar://problem/4097314> mDNSResponder crash when interface goes away.  This error seems to be caused by the Windows platform code not returning mStatus_TransientErr when there is a problem with a udp unicast send.
+
+Revision 1.89  2005/04/22 07:32:24  shersche
+<rdar://problem/4092108> PPP connection disables Bonjour .local lookups
+<rdar://problem/4093944> mDNSResponder ignores Point-to-Point interfaces
+
+Revision 1.88  2005/04/05 03:53:03  shersche
+<rdar://problem/4066485> Registering with shared secret key doesn't work.
+
+Revision 1.87  2005/04/03 08:03:12  shersche
+<rdar://problem/4076478> mDNSResponder won't start on Windows 2000.
+
+Revision 1.86  2005/03/30 07:37:14  shersche
+Use prefix to compute IPv4 subnet mask, falling back to calling AddressToIndexAndMask only if prefix is zero.
+
+Revision 1.85  2005/03/30 07:34:52  shersche
+<rdar://problem/4045657> Interface index being returned is 512
+
+Revision 1.84  2005/03/29 19:19:47  shersche
+<rdar://problem/4055599> Windows is not accepting unicast responses.  This bug was a result of an error in obtaining the subnet mask for IPv4 interfaces.
+
 Revision 1.83  2005/03/07 18:27:42  shersche
 <rdar://problem/4037940> Fix problem when ControlPanel commits changes to the browse domain list
 
@@ -333,6 +400,7 @@ Multicast DNS platform plugin for Win32
 
 #include       "CommonServices.h"
 #include       "DebugServices.h"
+#include       "VPCDetect.h"
 #include       "RegNames.h"
 #include       <dns_sd.h>
 
@@ -361,6 +429,7 @@ Multicast DNS platform plugin for Win32
 #define        MDNS_WINDOWS_ENABLE_IPV4                                        1
 #define        MDNS_WINDOWS_ENABLE_IPV6                                        1
 #define        MDNS_FIX_IPHLPAPI_PREFIX_BUG                            1
+#define MDNS_SET_HINFO_STRINGS                                         0
 
 #define        kMDNSDefaultName                                                        "My Computer"
 
@@ -381,6 +450,8 @@ Multicast DNS platform plugin for Win32
        static GUID                                                                             kWSARecvMsgGUID = WSAID_WSARECVMSG;
 #endif
 
+#define kIPv6IfIndexBase                                                       (10000000L)
+
 
 #if 0
 #pragma mark == Prototypes ==
@@ -446,6 +517,16 @@ mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInter
 
 // Utilities
 
+typedef struct PolyString PolyString;
+
+struct PolyString
+{
+       domainname                      m_dname;
+       char                            m_utf8[256];
+       PLSA_UNICODE_STRING     m_lsa;
+};
+
+
 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
        mDNSlocal int   getifaddrs_ipv6( struct ifaddrs **outAddrs );
 #endif
@@ -458,15 +539,18 @@ mDNSexport mStatus        mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInter
        mDNSlocal int   getifaddrs_ce( struct ifaddrs **outAddrs );
 #endif
 
-mDNSlocal mDNSBool     CanReceiveUnicast( void );
+mDNSlocal DWORD                                GetPrimaryInterface();
+mDNSlocal mStatus                      AddressToIndexAndMask( struct sockaddr * address, uint32_t * index, struct sockaddr * mask );
+mDNSlocal mDNSBool                     CanReceiveUnicast( void );
+mDNSlocal mDNSBool                     IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr );
 
 mDNSlocal mStatus                      StringToAddress( mDNSAddr * ip, LPSTR string );
 mDNSlocal mStatus                      RegQueryString( HKEY key, LPCSTR param, LPSTR * string, DWORD * stringLen, DWORD * enabled );
 mDNSlocal struct ifaddrs*      myGetIfAddrs(int refresh);
 mDNSlocal OSStatus                     TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize );
 mDNSlocal OSStatus                     WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize );
-mDNSlocal OSStatus                     ConvertUTF8ToLsaString( const char * input, PLSA_UNICODE_STRING output );
-mDNSlocal OSStatus                     ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char ** output );
+mDNSlocal OSStatus                     MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input );
+mDNSlocal OSStatus                     MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input );
 mDNSlocal void                         FreeTCPConnectionData( mDNSTCPConnectionData * data );
 
 #ifdef __cplusplus
@@ -543,8 +627,11 @@ mStatus    mDNSPlatformInit( mDNS * const inMDNS )
        
        // 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 ] );
        dlog( kDebugLevelInfo, DEBUG_NAME "HIHardware: %#s\n", inMDNS->HIHardware.c );
        
@@ -552,6 +639,7 @@ mStatus     mDNSPlatformInit( mDNS * const inMDNS )
                "mDNSResponder (%s %s)", __DATE__, __TIME__ );
        inMDNS->HISoftware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HISoftware.c[ 1 ] );
        dlog( kDebugLevelInfo, DEBUG_NAME "HISoftware: %#s\n", inMDNS->HISoftware.c );
+#endif
        
        // Set up the IPv4 unicast socket
 
@@ -578,10 +666,18 @@ mStatus   mDNSPlatformInit( mDNS * const inMDNS )
        {
                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 );
+               // If we are running inside VPC, then we won't use WSARecvMsg because it will give us bogus information due to
+               // a bug in VPC itself.
+
+               err = IsVPCRunning();
+
+               if ( !err )
+               {
+                       err = WSAIoctl( inMDNS->p->unicastSock4, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, 
+                                                       sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock4RecvMsgPtr, sizeof( inMDNS->p->unicastSock4RecvMsgPtr ), &size, NULL, NULL );
+               }
                
-               if ( err != 0 )
+               if ( err )
                {
                        inMDNS->p->unicastSock4RecvMsgPtr = NULL;
                }
@@ -793,7 +889,20 @@ mStatus
        {
                n = sendto( sendingsocket, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
                err = translate_errno( n > 0, errno_compat(), kWriteErr );
-               require_noerr( err, exit );
+
+               if ( err )
+               {
+                       // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
+
+                       if ( !mDNSAddressIsAllDNSLinkGroup( inDstIP ) && ( WSAGetLastError() == WSAEHOSTDOWN || WSAGetLastError() == WSAENETDOWN || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAENETUNREACH ) )
+                       {
+                               err = mStatus_TransientErr;
+                       }
+                       else
+                       {
+                               require_noerr( err, exit );
+                       }
+               }
        }
        
 exit:
@@ -960,7 +1069,7 @@ mDNSs32    mDNSPlatformRawTime( void )
 
 mDNSexport mDNSs32     mDNSPlatformUTC( void )
 {
-       return( -1 );
+       return ( mDNSs32 ) time( NULL );
 }
 
 //===========================================================================================================================
@@ -1305,7 +1414,7 @@ dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, DNam
 
        *browseDomains = NULL;
        
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup\\") kServiceDynDNSHostNames, &key );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSHostNames, &key );
        require_noerr( err, exit );
 
        err = RegQueryString( key, "", &name, &dwSize, &enabled );
@@ -1329,7 +1438,7 @@ dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, DNam
                name = NULL;
        }
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains, &key );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains, &key );
        require_noerr( err, exit );
 
        // Get information about this node
@@ -1382,7 +1491,7 @@ dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, DNam
                key = NULL;
        }
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains, &key );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains, &key );
        require_noerr( err, exit );
        
        err = RegQueryString( key, "", &name, &dwSize, &enabled );
@@ -1438,7 +1547,7 @@ dDNSPlatformSetNameStatus(domainname *const dname, mStatus status)
        }
 
        check( strlen( p ) <= MAX_ESCAPED_DOMAIN_NAME );
-       name = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\State\\HostNames");
+       name = kServiceParametersNode TEXT("\\DynDNS\\State\\HostNames");
        err = RegCreateKey( HKEY_LOCAL_MACHINE, name, &key );
        require_noerr( err, exit );
 
@@ -1462,36 +1571,38 @@ exit:
 //===========================================================================================================================
 
 void
-dDNSPlatformSetSecretForDomain( mDNS *m, const domainname * domain )
+dDNSPlatformSetSecretForDomain( mDNS *m, const domainname * inDomain )
 {
-       char                                    dstring[MAX_ESCAPED_DOMAIN_NAME];
-       domainname                      *       d;
-       domainname                              canon;
+       PolyString                              domain;
+       PolyString                              key;
+       PolyString                              secret;
        size_t                                  i;
        size_t                                  dlen;
        LSA_OBJECT_ATTRIBUTES   attrs;
        LSA_HANDLE                              handle = NULL;
-       LSA_UNICODE_STRING              keyName = { 0, 0, NULL };
-       LSA_UNICODE_STRING      *       secret = NULL;
-       char                            *       converted = NULL;
        NTSTATUS                                res;
        OSStatus                                err;
 
+       // Initialize PolyStrings
+
+       domain.m_lsa    = NULL;
+       key.m_lsa               = NULL;
+       secret.m_lsa    = NULL;
+
        // canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
        
-       ConvertDomainNameToCString(domain, dstring);
-       dlen = strlen(dstring);
-       for (i = 0; i < dlen; i++)
+       ConvertDomainNameToCString( inDomain, domain.m_utf8 );
+       dlen = strlen( domain.m_utf8 );
+       for ( i = 0; i < dlen; i++ )
        {
-               dstring[i] = (char) tolower(dstring[i]);  // canonicalize -> lower case
+               domain.m_utf8[i] = (char) tolower( domain.m_utf8[i] );  // canonicalize -> lower case
        }
 
-       MakeDomainNameFromDNSNameString(&canon, dstring);
-       d = &canon;
+       MakeDomainNameFromDNSNameString( &domain.m_dname, domain.m_utf8 );
 
        // attrs are reserved, so initialize to zeroes.
 
-       ZeroMemory(&attrs, sizeof( attrs ) );
+       ZeroMemory( &attrs, sizeof( attrs ) );
 
        // Get a handle to the Policy object on the local system
 
@@ -1501,38 +1612,63 @@ dDNSPlatformSetSecretForDomain( mDNS *m, const domainname * domain )
 
        // Get the encrypted data
 
-       err = ConvertUTF8ToLsaString( dstring, &keyName );
+       domain.m_lsa = ( PLSA_UNICODE_STRING) malloc( sizeof( LSA_UNICODE_STRING ) );
+       require_action( domain.m_lsa != NULL, exit, err = mStatus_NoMemoryErr );
+       err = MakeLsaStringFromUTF8String( domain.m_lsa, domain.m_utf8 );
        require_noerr( err, exit );
 
-       res = LsaRetrievePrivateData( handle, &keyName, &secret );
+       // Retrieve the key
+
+       res = LsaRetrievePrivateData( handle, domain.m_lsa, &key.m_lsa );
        err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
        require_noerr_quiet( err, exit );
 
-       // Convert the unicode to string to 8 bit
+       // <rdar://problem/4192119> Lsa secrets use a flat naming space.  Therefore, we will prepend "$" to the keyname to
+       // make sure it doesn't conflict with a zone name.
+       
+       // Convert the key to a domainname.  Strip off the "$" prefix.
 
-       err = ConvertLsaStringToUTF8( secret, &converted );
+       err = MakeUTF8StringFromLsaString( key.m_utf8, sizeof( key.m_utf8 ), key.m_lsa );
        require_noerr( err, exit );
+       require_action( key.m_utf8[0] == '$', exit, err = kUnknownErr );
+       MakeDomainNameFromDNSNameString( &key.m_dname, key.m_utf8 + 1 );
+
+       // Retrieve the secret
 
-       mDNS_SetSecretForZone( m, d, d, converted );
+       res = LsaRetrievePrivateData( handle, key.m_lsa, &secret.m_lsa );
+       err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+       require_noerr_quiet( err, exit );
+       
+       // Convert the secret to UTF8 string
+
+       err = MakeUTF8StringFromLsaString( secret.m_utf8, sizeof( secret.m_utf8 ), secret.m_lsa );
+       require_noerr( err, exit );
+
+       // And finally, tell the core about this secret
+
+       debugf("Setting shared secret for zone %s with key %##s", domain.m_utf8, key.m_dname.c);
+       mDNS_SetSecretForZone( m, &domain.m_dname, &key.m_dname, secret.m_utf8 );
 
 exit:
 
-       if ( converted )
+       if ( domain.m_lsa != NULL )
        {
-               free( converted );
-               converted = NULL;
+               if ( domain.m_lsa->Buffer != NULL )
+               {
+                       free( domain.m_lsa->Buffer );
+               }
+
+               free( domain.m_lsa );
        }
 
-       if ( secret )
+       if ( key.m_lsa != NULL )
        {
-               LsaFreeMemory( secret );
-               secret = NULL;
+               LsaFreeMemory( key.m_lsa );
        }
 
-       if ( keyName.Buffer )
+       if ( secret.m_lsa != NULL )
        {
-               free( keyName.Buffer );
-               keyName.Buffer = NULL;
+               LsaFreeMemory( secret.m_lsa );
        }
 
        if ( handle )
@@ -1569,26 +1705,29 @@ dDNSPlatformGetSearchDomainList( void )
        tok = strtok( searchList, "," );
        while ( tok )
        {
-               domainname domain;
-
-               if ( MakeDomainNameFromDNSNameString( &domain, tok ) )
+               if ( ( strcmp( tok, "" ) != 0 ) && ( strcmp( tok, "." ) != 0 ) )
                {
-                       DNameListElem * last = current;
+                       domainname domain;
 
-                       current = (DNameListElem*) malloc( sizeof( DNameListElem ) );
-                       require_action( current, exit, err = mStatus_NoMemoryErr );
-
-                       AssignDomainName( &current->name, &domain );
-                       current->next = NULL;
-                       
-                       if ( !head )
+                       if ( MakeDomainNameFromDNSNameString( &domain, tok ) )
                        {
-                               head = current;
-                       }
+                               DNameListElem * last = current;
+       
+                               current = (DNameListElem*) malloc( sizeof( DNameListElem ) );
+                               require_action( current, exit, err = mStatus_NoMemoryErr );
+       
+                               AssignDomainName( &current->name, &domain );
+                               current->next = NULL;
+                               
+                               if ( !head )
+                               {
+                                       head = current;
+                               }
 
-                       if ( last )
-                       {
-                               last->next = current;
+                               if ( last )
+                               {
+                                       last->next = current;
+                               }
                        }
                }
 
@@ -1680,35 +1819,74 @@ exit:
 IPAddrListElem*
 dDNSPlatformGetDNSServers( void )
 {
-       FIXED_INFO              *       fixedInfo       = NULL;
-       ULONG                           bufLen          = sizeof( FIXED_INFO ); 
-       IP_ADDR_STRING  *       ipAddr;
-       IPAddrListElem  *       head            = NULL;
-       IPAddrListElem  *       current         = NULL;
-       int                                     i                       = 0;
-       mStatus                         err;
+       PIP_PER_ADAPTER_INFO    pAdapterInfo    =       NULL;
+       FIXED_INFO                      *       fixedInfo       = NULL;
+       ULONG                                   bufLen          = 0;    
+       IP_ADDR_STRING          *       dnsServerList;
+       IP_ADDR_STRING          *       ipAddr;
+       IPAddrListElem          *       head            = NULL;
+       IPAddrListElem          *       current         = NULL;
+       DWORD                                   index;
+       int                                             i                       = 0;
+       mStatus                                 err                     = kUnknownErr;
+
+       // Get the primary interface.
 
-       while ( 1 )
+       index = GetPrimaryInterface();
+
+       // This should have the interface index of the primary index.  Fall back in cases where
+       // it can't be determined.
+
+       if ( index )
        {
-               if ( fixedInfo )
+               bufLen = 0;
+
+               for ( i = 0; i < 100; i++ )
                {
-                       GlobalFree( fixedInfo );
-                       fixedInfo = NULL;
+                       err = GetPerAdapterInfo( index, pAdapterInfo, &bufLen );
+
+                       if ( err != ERROR_BUFFER_OVERFLOW )
+                       {
+                               break;
+                       }
+
+                       pAdapterInfo = (PIP_PER_ADAPTER_INFO) realloc( pAdapterInfo, bufLen );
+                       require_action( pAdapterInfo, exit, err = mStatus_NoMemoryErr );
                }
 
-               fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
-   
-               err = GetNetworkParams( fixedInfo, &bufLen );
+               require_noerr( err, exit );
+
+               dnsServerList = &pAdapterInfo->DnsServerList;
+       }
+       else
+       {
+               bufLen = sizeof( FIXED_INFO );
 
-               if ( ( err != ERROR_BUFFER_OVERFLOW ) || ( i++ == 100 ) )
+               for ( i = 0; i < 100; i++ )
                {
-                       break;
+                       if ( fixedInfo )
+                       {
+                               GlobalFree( fixedInfo );
+                               fixedInfo = NULL;
+                       }
+
+                       fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
+                       require_action( fixedInfo, exit, err = mStatus_NoMemoryErr );
+          
+                       err = GetNetworkParams( fixedInfo, &bufLen );
+
+                       if ( err != ERROR_BUFFER_OVERFLOW )
+                       {
+                               break;
+                       }
                }
-       }
 
-       require_noerr( err, exit );
+               require_noerr( err, exit );
 
-       for ( ipAddr = &fixedInfo->DnsServerList; ipAddr; ipAddr = ipAddr->Next )
+               dnsServerList = &fixedInfo->DnsServerList;
+       }
+
+       for ( ipAddr = dnsServerList; ipAddr; ipAddr = ipAddr->Next )
        {
                mDNSAddr                        addr;
                IPAddrListElem  *       last = current;
@@ -1739,6 +1917,11 @@ dDNSPlatformGetDNSServers( void )
 
 exit:
 
+       if ( pAdapterInfo )
+       {
+               free( pAdapterInfo );
+       }
+
        if ( fixedInfo )
        {
                GlobalFree( fixedInfo );
@@ -1755,55 +1938,97 @@ exit:
 DNameListElem*
 dDNSPlatformGetDomainName( void )
 {
-       FIXED_INFO              *       fixedInfo       = NULL;
-       ULONG                           bufLen          = sizeof( FIXED_INFO ); 
        DNameListElem   *       head            = NULL;
        int                                     i                       = 0;
-       mStatus                         err;
+       IP_ADAPTER_INFO *       pAdapterInfo;
+       IP_ADAPTER_INFO *       pAdapter;
+       DWORD                           bufLen;
+       DWORD                           index;
+       HKEY                            key = NULL;
+       LPSTR                           domain = NULL;
+       domainname                      dname;
+       DWORD                           dwSize;
+       mStatus                         err = mStatus_NoError;
 
-       while ( 1 )
+       pAdapterInfo    = NULL;
+       
+       for ( i = 0; i < 100; i++ )
        {
-               if ( fixedInfo )
-               {
-                       GlobalFree( fixedInfo );
-                       fixedInfo = NULL;
-               }
-
-               fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
-   
-               err = GetNetworkParams( fixedInfo, &bufLen );
+               err = GetAdaptersInfo( pAdapterInfo, &bufLen);
 
-               if ( ( err != ERROR_BUFFER_OVERFLOW ) || ( i++ == 100 ) )
+               if ( err != ERROR_BUFFER_OVERFLOW )
                {
                        break;
                }
+
+               pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
+               require_action( pAdapterInfo, exit, err = kNoMemoryErr );
        }
 
        require_noerr( err, exit );
 
-       if ( fixedInfo->DomainName )
-       {
-               domainname dname;
+       index = GetPrimaryInterface();
 
-               if ( MakeDomainNameFromDNSNameString( &dname, fixedInfo->DomainName ) || !dname.c[0] )
+       for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
+       {
+               if ( pAdapter->IpAddressList.IpAddress.String &&
+                    pAdapter->IpAddressList.IpAddress.String[0] &&
+                    pAdapter->GatewayList.IpAddress.String &&
+                    pAdapter->GatewayList.IpAddress.String[0] &&
+                    ( !index || ( pAdapter->Index == index ) ) )
                {
-                       head = (DNameListElem*) malloc( sizeof( DNameListElem ) );
-                       require_action( head, exit, err = mStatus_NoMemoryErr );
+                       // Found one that will work
 
-                       AssignDomainName( &head->name, &dname );
-                       head->next = NULL;
-               }
-               else
-               {
-                       dlog( kDebugLevelError, "bad DDNS host name from domain name: %s", fixedInfo->DomainName );
+                       char keyName[1024];
+
+                       _snprintf( keyName, 1024, "%s%s", "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\", pAdapter->AdapterName );
+
+                       err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyName, &key );
+                       require_noerr( err, exit );
+
+                       err = RegQueryString( key, "Domain", &domain, &dwSize, NULL );
+                       check_noerr( err );
+
+                       if ( !domain || !domain[0] )
+                       {
+                               if ( domain )
+                               {
+                                       free( domain );
+                                       domain = NULL;
+                               }
+
+                               err = RegQueryString( key, "DhcpDomain", &domain, &dwSize, NULL );
+                               check_noerr( err );
+                       }
+
+                       if ( domain && domain[0] && ( MakeDomainNameFromDNSNameString( &dname, domain ) || !dname.c[0] ) )
+                       {
+                               head = (DNameListElem*) malloc( sizeof( DNameListElem ) );
+                               require_action( head, exit, err = mStatus_NoMemoryErr );
+
+                               AssignDomainName( &head->name, &dname );
+                               head->next = NULL;
+                       }
+
+                       break;
                }
        }
 
 exit:
 
-       if ( fixedInfo )
+       if ( pAdapterInfo )
        {
-               GlobalFree( fixedInfo );
+               free( pAdapterInfo );
+       }
+
+       if ( domain )
+       {
+               free( domain );
+       }
+
+       if ( key )
+       {
+               RegCloseKey( key );
        }
 
        return head;
@@ -1830,41 +2055,36 @@ dDNSPlatformRegisterSplitDNS( mDNS * m )
 mStatus
 dDNSPlatformGetPrimaryInterface( mDNS * m, mDNSAddr * primary, mDNSAddr * router )
 {
-       IP_ADAPTER_INFO *       pAdapterInfo = NULL;
+       IP_ADAPTER_INFO *       pAdapterInfo;
        IP_ADAPTER_INFO *       pAdapter;
-       DWORD                           bufLen          = sizeof( IP_ADAPTER_INFO );
+       DWORD                           bufLen;
        int                                     i;
        BOOL                            found;
+       DWORD                           index;
        mStatus                         err = mStatus_NoError;
 
        DEBUG_UNUSED( m );
 
-       pAdapterInfo = NULL;
-       found = FALSE;
+       pAdapterInfo    = NULL;
+       bufLen                  = 0;
+       found                   = FALSE;
 
        for ( i = 0; i < 100; i++ )
        {
-               if ( pAdapterInfo )
-               {
-                       free( pAdapterInfo );
-                       pAdapterInfo = NULL;
-               }
-
-               pAdapterInfo = (IP_ADAPTER_INFO*) malloc( bufLen );
-               require_action( pAdapterInfo, exit, err = kNoMemoryErr );
-
                err = GetAdaptersInfo( pAdapterInfo, &bufLen);
 
                if ( err != ERROR_BUFFER_OVERFLOW )
                {
                        break;
                }
+
+               pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
+               require_action( pAdapterInfo, exit, err = kNoMemoryErr );
        }
 
-       // Windows doesn't really have a concept of a primary adapter,
-       // so we're just going to iterate through all the adapters and
-       // pick the first one that has an IP address assigned and
-       // a gateway assigned
+       require_noerr( err, exit );
+
+       index = GetPrimaryInterface();
 
        for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
        {
@@ -1873,7 +2093,8 @@ dDNSPlatformGetPrimaryInterface( mDNS * m, mDNSAddr * primary, mDNSAddr * router
                     pAdapter->GatewayList.IpAddress.String &&
                     pAdapter->GatewayList.IpAddress.String[0] &&
                     ( StringToAddress( primary, pAdapter->IpAddressList.IpAddress.String ) == mStatus_NoError ) &&
-                    ( StringToAddress( router, pAdapter->GatewayList.IpAddress.String ) == mStatus_NoError ) )
+                    ( StringToAddress( router, pAdapter->GatewayList.IpAddress.String ) == mStatus_NoError ) &&
+                    ( !index || ( pAdapter->Index == index ) ) )
                {
                        // Found one that will work
 
@@ -1882,16 +2103,6 @@ dDNSPlatformGetPrimaryInterface( mDNS * m, mDNSAddr * primary, mDNSAddr * router
                }
        }
 
-       if ( !found )
-       {
-               // If we couldn't find one, then let's try the first one in the list
-
-               err = StringToAddress( primary, pAdapter->IpAddressList.IpAddress.String );
-               require_noerr( err, exit );
-
-               found = TRUE;
-       }
-
 exit:
 
        if ( pAdapterInfo )
@@ -2119,8 +2330,12 @@ mDNSlocal mStatus        SetupNiceName( mDNS * const inMDNS )
        // if we can't find it in the registry, then use the hostname of the machine
        if ( err || ( utf8[ 0 ] == '\0' ) )
        {
-               err = gethostname( tempString, sizeof( tempString ) - 1 );
-               check_translated_errno( err == 0, errno_compat(), kNameErr );
+               DWORD tempStringLen = sizeof( tempString );
+               BOOL  ok;
+
+               ok = GetComputerNameExA( ComputerNamePhysicalDnsHostname, tempString, &tempStringLen );
+               err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
+               check_noerr( err );
                
                if( !err )
                {
@@ -2159,7 +2374,9 @@ mDNSlocal mStatus SetupHostName( mDNS * const inMDNS )
 {
        mStatus         err = 0;
        char            tempString[ 256 ];
+       DWORD           tempStringLen;
        domainlabel tempLabel;
+       BOOL            ok;
        
        check( inMDNS );
 
@@ -2167,8 +2384,10 @@ mDNSlocal mStatus        SetupHostName( mDNS * const inMDNS )
        tempString[ 0 ] = '\0';
 
        // use the hostname of the machine
-       err = gethostname( tempString, sizeof( tempString ) - 1 );
-       check_translated_errno( err == 0, errno_compat(), kNameErr );
+       tempStringLen = sizeof( tempString );
+       ok = GetComputerNameExA( ComputerNamePhysicalDnsHostname, tempString, &tempStringLen );
+       err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
+       check_noerr( err );
 
        // if we can't get the hostname
        if( err || ( tempString[ 0 ] == '\0' ) )
@@ -2232,19 +2451,25 @@ mDNSlocal mStatus       SetupInterfaceList( mDNS * const inMDNS )
        mDNSInterfaceData *                     ifd;
        struct ifaddrs *                        addrs;
        struct ifaddrs *                        p;
-       struct ifaddrs *                        loopback;
+       struct ifaddrs *                        loopbackv4;
+       struct ifaddrs *                        loopbackv6;
        u_int                                           flagMask;
        u_int                                           flagTest;
-       BOOL                                            foundUnicastSock4DestAddr;
-       BOOL                                            foundUnicastSock6DestAddr;
+       mDNSBool                                        foundv4;
+       mDNSBool                                        foundv6;
+       mDNSBool                                        foundUnicastSock4DestAddr;
+       mDNSBool                                        foundUnicastSock6DestAddr;
        
        dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list\n" );
        check( inMDNS );
        check( inMDNS->p );
        
-       addrs                                           = NULL;
-       foundUnicastSock4DestAddr       = FALSE;
-       foundUnicastSock6DestAddr       = FALSE;
+       inMDNS->p->registeredLoopback4  = mDNSfalse;
+       addrs                                                   = NULL;
+       foundv4                                                 = mDNSfalse;
+       foundv6                                                 = mDNSfalse;
+       foundUnicastSock4DestAddr               = mDNSfalse;
+       foundUnicastSock6DestAddr               = mDNSfalse;
        
        // Tear down any existing interfaces that may be set up.
        
@@ -2266,10 +2491,11 @@ mDNSlocal mStatus       SetupInterfaceList( mDNS * const inMDNS )
        err = getifaddrs( &addrs );
        require_noerr( err, exit );
        
-       loopback        = NULL;
+       loopbackv4      = NULL;
+       loopbackv6      = NULL;
        next            = &inMDNS->p->interfaceList;
-       
-       flagMask = IFF_UP | IFF_MULTICAST | IFF_POINTTOPOINT;
+
+       flagMask = IFF_UP | IFF_MULTICAST;
        flagTest = IFF_UP | IFF_MULTICAST;
        
 #if( MDNS_WINDOWS_ENABLE_IPV4 )
@@ -2281,9 +2507,9 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS )
                }
                if( p->ifa_flags & IFF_LOOPBACK )
                {
-                       if( !loopback )
+                       if( !loopbackv4 )
                        {
-                               loopback = p;
+                               loopbackv4 = p;
                        }
                        continue;
                }
@@ -2292,7 +2518,16 @@ mDNSlocal mStatus        SetupInterfaceList( mDNS * const inMDNS )
                
                err = SetupInterface( inMDNS, p, &ifd );
                require_noerr( err, exit );
-               
+
+               // If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
+               // register him, but we also want to note that we haven't found a v4 interface
+               // so that we register loopback so same host operations work
+               
+               if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
+               {
+                       foundv4 = mDNStrue;
+               }
+
                // If we're on a platform that doesn't have WSARecvMsg(), there's no way
                // of determing the destination address of a packet that is sent to us.
                // For multicast packets, that's easy to determine.  But for the unicast
@@ -2308,8 +2543,6 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS )
                *next = ifd;
                next  = &ifd->next;
                ++inMDNS->p->interfaceCount;
-
-               
        }
 #endif
        
@@ -2324,9 +2557,9 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS )
                }
                if( p->ifa_flags & IFF_LOOPBACK )
                {
-                       if( !loopback )
+                       if( !loopbackv6 )
                        {
-                               loopback = p;
+                               loopbackv6 = p;
                        }
                        continue;
                }
@@ -2336,6 +2569,15 @@ mDNSlocal mStatus        SetupInterfaceList( mDNS * const inMDNS )
                err = SetupInterface( inMDNS, p, &ifd );
                require_noerr( err, exit );
                                
+               // If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
+               // register him, but we also want to note that we haven't found a v4 interface
+               // so that we register loopback so same host operations work
+               
+               if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
+               {
+                       foundv6 = mDNStrue;
+               }
+
                // If we're on a platform that doesn't have WSARecvMsg(), there's no way
                // of determing the destination address of a packet that is sent to us.
                // For multicast packets, that's easy to determine.  But for the unicast
@@ -2371,19 +2613,22 @@ mDNSlocal mStatus       SetupInterfaceList( mDNS * const inMDNS )
                {
                        continue;
                }
-               loopback = p;
+               
+               v4loopback = p;
                break;
        }
        
 #endif
        
-       if( !inMDNS->p->interfaceList && loopback )
+       if ( !foundv4 && loopbackv4 )
        {
                dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
-                       loopback->ifa_name ? loopback->ifa_name : "<null>", loopback->ifa_extra.index, loopback->ifa_addr );
+                       loopbackv4->ifa_name ? loopbackv4->ifa_name : "<null>", loopbackv4->ifa_extra.index, loopbackv4->ifa_addr );
                
-               err = SetupInterface( inMDNS, loopback, &ifd );
+               err = SetupInterface( inMDNS, loopbackv4, &ifd );
                require_noerr( err, exit );
+
+               inMDNS->p->registeredLoopback4 = mDNStrue;
                
 #if( MDNS_WINDOWS_ENABLE_IPV4 )
 
@@ -2497,7 +2742,6 @@ mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI
        ifd->sock               = kInvalidSocketRef;
        ifd->index              = inIFA->ifa_extra.index;
        ifd->scopeID    = inIFA->ifa_extra.index;
-       
        check( strlen( inIFA->ifa_name ) < sizeof( ifd->name ) );
        strncpy( ifd->name, inIFA->ifa_name, sizeof( ifd->name ) - 1 );
        ifd->name[ sizeof( ifd->name ) - 1 ] = '\0';
@@ -2512,7 +2756,7 @@ mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI
        // but we cut the packet rate in half. At this time, reducing the packet rate is more important than v6-only 
        // devices on a large configured network, so we are willing to make that sacrifice.
        
-       ifd->interfaceInfo.McastTxRx   = mDNStrue;
+       ifd->interfaceInfo.McastTxRx   = ( ( inIFA->ifa_flags & IFF_MULTICAST ) && !( inIFA->ifa_flags & IFF_POINTTOPOINT ) ) ? mDNStrue : mDNSfalse;
        ifd->interfaceInfo.InterfaceID = NULL;
 
        for( p = inMDNS->p->interfaceList; p; p = p->next )
@@ -2521,7 +2765,6 @@ mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI
                {
                        if (!ifd->interfaceInfo.InterfaceID)
                        {
-                               p->scopeID                                              = ifd->scopeID;
                                ifd->interfaceInfo.InterfaceID  = (mDNSInterfaceID) p;
                        }
 
@@ -2556,9 +2799,18 @@ mDNSlocal mStatus        SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI
                {
                        DWORD           size;
 
-                       err = WSAIoctl( sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ),
-                               &ifd->wsaRecvMsgFunctionPtr, sizeof( ifd->wsaRecvMsgFunctionPtr ), &size, NULL, NULL );
-                       if( err != 0 )
+                       // If we are running inside VPC, then we won't use WSARecvMsg because it will give us bogus information due to
+                       // a bug in VPC itself.
+                       
+                       err = IsVPCRunning();
+
+                       if ( !err )
+                       {
+                               err = WSAIoctl( sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ),
+                                       &ifd->wsaRecvMsgFunctionPtr, sizeof( ifd->wsaRecvMsgFunctionPtr ), &size, NULL, NULL );
+                       }
+
+                       if ( err )
                        {
                                ifd->wsaRecvMsgFunctionPtr = NULL;
                        }
@@ -2964,7 +3216,7 @@ mDNSlocal mStatus SetupNotifications( mDNS * const inMDNS )
        err = translate_errno( inMDNS->p->ddnsChangedEvent, (mStatus) GetLastError(), kUnknownErr );
        require_noerr( err, exit );
 
-       err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup"), &inMDNS->p->ddnsKey );
+       err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup"), &inMDNS->p->ddnsKey );
        require_noerr( err, exit );
 
        err = RegNotifyChangeKeyValue(inMDNS->p->ddnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->ddnsChangedEvent, TRUE);
@@ -3116,7 +3368,7 @@ mDNSlocal unsigned WINAPI ProcessingThread( LPVOID inParam )
                
        m = (mDNS *) inParam;
        err = ProcessingThreadInitialize( m );
-       require_noerr( err, exit );
+       check( !err );
        
        done = 0;
        while( !done )
@@ -3154,131 +3406,143 @@ mDNSlocal unsigned WINAPI     ProcessingThread( LPVOID inParam )
                        // Wait until something occurs (e.g. cancel, incoming packet, or timeout).
                                                
                        result = WaitForMultipleObjects( (DWORD) waitListCount, waitList, FALSE, (DWORD) interval );
-                       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 )
-                       {
-                               // Cancel event. Set the done flag and break to exit.
-                               
-                               dlog( kDebugLevelVerbose, DEBUG_NAME "canceling...\n" );
-                               done = 1;
-                               break;
-                       }
-                       else if( result == kWaitListInterfaceListChangedEvent )
-                       {
-                               // 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
+                       check( result != WAIT_FAILED );
+
+                       if ( result != WAIT_FAILED )
                        {
-                               int             waitItemIndex;
-                               
-                               // Socket data available event. Determine which socket and process the packet.
-                               
-                               waitItemIndex = (int)( ( (int) result ) - WAIT_OBJECT_0 );
-                               dlog( kDebugLevelChatty, DEBUG_NAME "socket data available on socket index %d\n", waitItemIndex );
-                               check( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) );
-                               if( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) )
+                               if( result == WAIT_TIMEOUT )
                                {
-                                       HANDLE                                  signaledObject;
-                                       int                                             n = 0;
-                                       mDNSInterfaceData               *       ifd;
-                                       mDNSTCPConnectionData   *       tcd;
+                                       // Next task timeout occurred. Loop back up to give mDNS core a chance to work.
                                        
-                                       signaledObject = waitList[ waitItemIndex ];
-
-#if ( MDNS_WINDOWS_ENABLE_IPV4 )
-                                       if ( m->p->unicastSock4ReadEvent == signaledObject )
+                                       dlog( kDebugLevelChatty - 1, DEBUG_NAME "timeout\n" );
+                                       continue;
+                               }
+                               else if( result == kWaitListCancelEvent )
+                               {
+                                       // Cancel event. Set the done flag and break to exit.
+                                       
+                                       dlog( kDebugLevelVerbose, DEBUG_NAME "canceling...\n" );
+                                       done = 1;
+                                       break;
+                               }
+                               else if( result == kWaitListInterfaceListChangedEvent )
+                               {
+                                       // 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
+                               {
+                                       int             waitItemIndex;
+                                       
+                                       // Socket data available event. Determine which socket and process the packet.
+                                       
+                                       waitItemIndex = (int)( ( (int) result ) - WAIT_OBJECT_0 );
+                                       dlog( kDebugLevelChatty, DEBUG_NAME "socket data available on socket index %d\n", waitItemIndex );
+                                       check( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) );
+                                       if( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) )
                                        {
-                                               ProcessingThreadProcessPacket( m, NULL, m->p->unicastSock4 );
-                                               ++n;
-                                       }
+                                               HANDLE                                  signaledObject;
+                                               int                                             n = 0;
+                                               mDNSInterfaceData               *       ifd;
+                                               mDNSTCPConnectionData   *       tcd;
+                                               
+                                               signaledObject = waitList[ waitItemIndex ];
+       
+#if ( MDNS_WINDOWS_ENABLE_IPV4 )
+                                               if ( m->p->unicastSock4ReadEvent == signaledObject )
+                                               {
+                                                       ProcessingThreadProcessPacket( m, NULL, m->p->unicastSock4 );
+                                                       ++n;
+                                               }
 #endif
-                                       
+                                               
 #if ( MDNS_WINDOWS_ENABLE_IPV6 )
-                                       if ( m->p->unicastSock6ReadEvent == signaledObject )
-                                       {
-                                               ProcessingThreadProcessPacket( m, NULL, m->p->unicastSock6 );
-                                               ++n;
-                                       }
+                                               if ( m->p->unicastSock6ReadEvent == signaledObject )
+                                               {
+                                                       ProcessingThreadProcessPacket( m, NULL, m->p->unicastSock6 );
+                                                       ++n;
+                                               }
 #endif
                                        
-                                       for( ifd = m->p->interfaceList; ifd; ifd = ifd->next )
-                                       {
-                                               if( ifd->readPendingEvent == signaledObject )
+                                               for( ifd = m->p->interfaceList; ifd; ifd = ifd->next )
                                                {
-                                                       ProcessingThreadProcessPacket( m, ifd, ifd->sock );
-                                                       ++n;
+                                                       if( ifd->readPendingEvent == signaledObject )
+                                                       {
+                                                               ProcessingThreadProcessPacket( m, ifd, ifd->sock );
+                                                               ++n;
+                                                       }
                                                }
-                                       }
-
-                                       for ( tcd = gTCPConnectionList; tcd; tcd = tcd->next )
-                                       {
-                                               if ( tcd->pendingEvent == signaledObject )
+       
+                                               for ( tcd = gTCPConnectionList; tcd; tcd = tcd->next )
                                                {
-                                                       mDNSBool connect = FALSE;
-
-                                                       if ( !tcd->connected )
+                                                       if ( tcd->pendingEvent == signaledObject )
                                                        {
-                                                               tcd->connected  = mDNStrue;
-                                                               connect                 = mDNStrue;
+                                                               mDNSBool connect = FALSE;
+       
+                                                               if ( !tcd->connected )
+                                                               {
+                                                                       tcd->connected  = mDNStrue;
+                                                                       connect                 = mDNStrue;
+                                                               }
+       
+                                                               tcd->callback( ( int ) tcd->sock, tcd->context, connect );
+       
+                                                               ++n;
+       
+                                                               break;
                                                        }
-
-                                                       tcd->callback( ( int ) tcd->sock, tcd->context, connect );
-
-                                                       ++n;
-
-                                                       break;
                                                }
+       
+                                               check( n > 0 );
+                                       }
+                                       else
+                                       {
+                                               // Unexpected wait result.
+                                       
+                                               dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, result );
                                        }
-
-                                       check( n > 0 );
-                               }
-                               else
-                               {
-                                       // Unexpected wait result.
-                               
-                                       dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, result );
                                }
                        }
+                       else
+                       {
+                               Sleep( 3 * 1000 );
+                               err = ProcessingThreadInitialize( m );
+                               check( err );
+                               break;
+                       }
                }
                
                // Release the wait list.
@@ -3496,7 +3760,7 @@ mDNSlocal void    ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *i
 
                                if ( inIFD )
                                {
-                                       require_action( ipv4PacketInfo->ipi_ifindex == ( inIFD->index >> 8 ), exit, err = kMismatchErr );
+                                       require_action( ipv4PacketInfo->ipi_ifindex == inIFD->index, exit, err = kMismatchErr );
                                }
 
                                dstAddr.type                            = mDNSAddrType_IPv4;
@@ -3510,7 +3774,7 @@ mDNSlocal void    ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *i
 
                                if ( inIFD )
                                {
-                                       require_action( ipv6PacketInfo->ipi6_ifindex == inIFD->index, exit, err = kMismatchErr );
+                                       require_action( ipv6PacketInfo->ipi6_ifindex == ( inIFD->index - kIPv6IfIndexBase), exit, err = kMismatchErr );
                                }
 
                                dstAddr.type    = mDNSAddrType_IPv6;
@@ -3577,6 +3841,13 @@ mDNSlocal void   ProcessingThreadInterfaceListChanged( mDNS *inMDNS )
        err = SetupInterfaceList( inMDNS );
        check_noerr( err );
                
+       err = dDNS_Setup( inMDNS );
+       check_noerr( err );
+
+       // so that LLQs are restarted against the up to date name servers
+
+       mDNS_UpdateLLQs( inMDNS );
+
        mDNSPlatformUnlock( inMDNS );
        
        // Inform clients of the change.
@@ -3638,6 +3909,10 @@ mDNSlocal void ProcessingThreadTCPIPConfigChanged( mDNS * inMDNS )
        err = dDNS_Setup( inMDNS );
        check_noerr( err );
 
+       // so that LLQs are restarted against the up to date name servers
+
+       mDNS_UpdateLLQs( inMDNS );
+
        // and reset the event handler
 
        if ( ( inMDNS->p->tcpipKey != NULL ) && ( inMDNS->p->tcpipChangedEvent ) )
@@ -3665,6 +3940,10 @@ mDNSlocal void   ProcessingThreadDynDNSConfigChanged( mDNS *inMDNS )
        err = dDNS_Setup( inMDNS );
        check_noerr( err );
 
+       // so that LLQs are restarted against the up to date name servers
+
+       mDNS_UpdateLLQs( inMDNS );
+
        // and reset the event handler
 
        if ((inMDNS->p->ddnsKey != NULL) && (inMDNS->p->ddnsChangedEvent))
@@ -3714,13 +3993,9 @@ int      getifaddrs( struct ifaddrs **outAddrs )
        }
        
        // Use the new IPv6-capable routine if supported. Otherwise, fall back to the old and compatible IPv4-only code.
+       // <rdar://problem/4278934>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 fails
        
-       if( gGetAdaptersAddressesFunctionPtr )
-       {
-               err = getifaddrs_ipv6( outAddrs );
-               require_noerr( err, exit );
-       }
-       else
+       if( !gGetAdaptersAddressesFunctionPtr || ( ( err = getifaddrs_ipv6( outAddrs ) ) != mStatus_NoError ) )
        {
                err = getifaddrs_ipv4( outAddrs );
                require_noerr( err, exit );
@@ -3770,7 +4045,7 @@ mDNSlocal int     getifaddrs_ipv6( struct ifaddrs **outAddrs )
        // This loops to handle the case where the interface changes in the window after getting the size, but before the
        // second call completes. A limit of 100 retries is enforced to prevent infinite loops if something else is wrong.
        
-       flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
+       flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
        i = 0;
        for( ;; )
        {
@@ -3868,16 +4143,27 @@ mDNSlocal int   getifaddrs_ipv6( struct ifaddrs **outAddrs )
                        ifa->ifa_flags = 0;
                        if( iaa->OperStatus == IfOperStatusUp )                 ifa->ifa_flags |= IFF_UP;
                        if( iaa->IfType == IF_TYPE_SOFTWARE_LOOPBACK )  ifa->ifa_flags |= IFF_LOOPBACK;
+                       else if ( IsPointToPoint( addr ) )                              ifa->ifa_flags |= IFF_POINTTOPOINT;
                        if( !( iaa->Flags & IP_ADAPTER_NO_MULTICAST ) ) ifa->ifa_flags |= IFF_MULTICAST;
+
                        
-                       // Get the interface index. Windows does not have a uniform scheme for IPv4 and IPv6 interface indexes
-                       // so the following is a hack to put IPv4 interface indexes in the upper 24-bits and IPv6 interface indexes
-                       // in the lower 8-bits. This allows the IPv6 interface index to be usable as an IPv6 scope ID directly.
+                       // <rdar://problem/4045657> Interface index being returned is 512
+                       //
+                       // Windows does not have a uniform scheme for IPv4 and IPv6 interface indexes.
+                       // This code used to shift the IPv4 index up to ensure uniqueness between
+                       // it and IPv6 indexes.  Although this worked, it was somewhat confusing to developers, who
+                       // then see interface indexes passed back that don't correspond to anything
+                       // that is seen in Win32 APIs or command line tools like "route".  As a relatively
+                       // small percentage of developers are actively using IPv6, it seems to 
+                       // make sense to make our use of IPv4 as confusion free as possible.
+                       // So now, IPv6 interface indexes will be shifted up by a
+                       // constant value which will serve to uniquely identify them, and we will
+                       // leave IPv4 interface indexes unmodified.
                        
                        switch( family )
                        {
-                               case AF_INET:  ifa->ifa_extra.index = iaa->IfIndex << 8; break;
-                               case AF_INET6: ifa->ifa_extra.index = ipv6IfIndex;       break;
+                               case AF_INET:  ifa->ifa_extra.index = iaa->IfIndex; break;
+                               case AF_INET6: ifa->ifa_extra.index = ipv6IfIndex + kIPv6IfIndexBase;    break;
                                default: break;
                        }
                        
@@ -3913,7 +4199,7 @@ mDNSlocal int     getifaddrs_ipv6( struct ifaddrs **outAddrs )
                        {
                                case AF_INET:
                                {
-                                       struct sockaddr_in *            sa4;
+                                       struct sockaddr_in * sa4;
                                        
                                        require_action( prefixLength <= 32, exit, err = ERROR_INVALID_DATA );
                                        
@@ -3921,12 +4207,21 @@ mDNSlocal int   getifaddrs_ipv6( struct ifaddrs **outAddrs )
                                        require_action( sa4, exit, err = WSAENOBUFS );
                                        
                                        sa4->sin_family = AF_INET;
-                                       if( prefixLength == 0 )
+                                       
+                                       if ( prefixLength != 0 )
                                        {
-                                               dlog( kDebugLevelWarning, DEBUG_NAME "%s: IPv4 netmask 0, defaulting to 255.255.255.255\n", __ROUTINE__ );
-                                               prefixLength = 32;
+                                               sa4->sin_addr.s_addr = htonl( 0xFFFFFFFFU << ( 32 - prefixLength ) );
                                        }
-                                       sa4->sin_addr.s_addr = htonl( 0xFFFFFFFFU << ( 32 - prefixLength ) );
+                                       else
+                                       {
+                                               uint32_t index;
+
+                                               dlog( kDebugLevelWarning, DEBUG_NAME "%s: IPv4 prefixLength is 0\n", __ROUTINE__ );
+                                               err = AddressToIndexAndMask( ifa->ifa_addr, &index, (struct sockaddr*) sa4 );
+                                               require_noerr( err, exit );
+                                       }
+
+                                       dlog( kDebugLevelInfo, DEBUG_NAME "%s: IPv4 mask = %s\n", __ROUTINE__, inet_ntoa( sa4->sin_addr ) );
                                        ifa->ifa_netmask = (struct sockaddr *) sa4;
                                        break;
                                }
@@ -4073,32 +4368,31 @@ mDNSlocal int   getifaddrs_ipv4( struct ifaddrs **outAddrs )
                
                // Get addresses.
                
-               switch( ifInfo->iiAddress.Address.sa_family )
+               if ( ifInfo->iiAddress.Address.sa_family == AF_INET )
                {
-                       case 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 ) );
+                       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 ) );
 
-                               sa4 = &ifInfo->iiNetmask.AddressIn;
-                               ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) );
-                               require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
-                               memcpy( ifa->ifa_netmask, sa4, sizeof( *sa4 ) );
+                       ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) );
 
-                               break;
-                       }
-                       
-                       default:
-                               break;
+                       // <rdar://problem/4076478> Service won't start on Win2K. The address
+                       // family field was not being initialized.
+
+                       ifa->ifa_netmask->sa_family = AF_INET;
+                       require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
+                       err = AddressToIndexAndMask( ifa->ifa_addr, &ifa->ifa_extra.index, ifa->ifa_netmask );
+                       require_noerr( err, exit );
                }
+               else
+               {
+                       // Emulate an interface index.
                
-               // Emulate an interface index.
-               
-               ifa->ifa_extra.index = (uint32_t)( i + 1 );
+                       ifa->ifa_extra.index = (uint32_t)( i + 1 );
+               }
        }
        
        // Success!
@@ -4297,6 +4591,127 @@ void    freeifaddrs( struct ifaddrs *inIFAs )
        }
 }
 
+
+//===========================================================================================================================
+//     GetPrimaryInterface
+//===========================================================================================================================
+
+mDNSlocal DWORD
+GetPrimaryInterface()
+{
+       PMIB_IPFORWARDTABLE     pIpForwardTable = NULL;
+       DWORD                           dwSize                  = 0;
+       BOOL                            bOrder                  = FALSE;
+       OSStatus                        err;
+       DWORD                           index                   = 0;
+       DWORD                           metric                  = 0;
+       unsigned long int       i;
+
+       // Find out how big our buffer needs to be.
+
+       err = GetIpForwardTable(NULL, &dwSize, bOrder);
+       require_action( err == ERROR_INSUFFICIENT_BUFFER, exit, err = kUnknownErr );
+
+       // Allocate the memory for the table
+
+       pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc( dwSize );
+       require_action( pIpForwardTable, exit, err = kNoMemoryErr );
+  
+       // Now get the table.
+
+       err = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
+       require_noerr( err, exit );
+
+
+       // Search for the row in the table we want.
+
+       for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
+       {
+               // Look for a default route
+
+               if ( pIpForwardTable->table[i].dwForwardDest == 0 )
+               {
+                       if ( index && ( pIpForwardTable->table[i].dwForwardMetric1 >= metric ) )
+                       {
+                               continue;
+                       }
+
+                       index   = pIpForwardTable->table[i].dwForwardIfIndex;
+                       metric  = pIpForwardTable->table[i].dwForwardMetric1;
+               }
+       }
+
+exit:
+
+       if ( pIpForwardTable != NULL )
+       {
+               free( pIpForwardTable );
+       }
+
+       return index;
+}
+
+
+//===========================================================================================================================
+//     AddressToIndexAndMask
+//===========================================================================================================================
+
+mDNSlocal mStatus
+AddressToIndexAndMask( struct sockaddr * addr, uint32_t * ifIndex, struct sockaddr * mask  )
+{
+       // Before calling AddIPAddress we use GetIpAddrTable to get
+       // an adapter to which we can add the IP.
+       
+       PMIB_IPADDRTABLE        pIPAddrTable    = NULL;
+       DWORD                           dwSize                  = 0;
+       mStatus                         err                             = mStatus_UnknownErr;
+       DWORD                           i;
+
+       // For now, this is only for IPv4 addresses.  That is why we can safely cast
+       // addr's to sockaddr_in.
+
+       require_action( addr->sa_family == AF_INET, exit, err = mStatus_UnknownErr );
+
+       // Make an initial call to GetIpAddrTable to get the
+       // necessary size into the dwSize variable
+
+       for ( i = 0; i < 100; i++ )
+       {
+               err = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
+
+               if ( err != ERROR_INSUFFICIENT_BUFFER )
+               {
+                       break;
+               }
+
+               pIPAddrTable = (MIB_IPADDRTABLE *) realloc( pIPAddrTable, dwSize );
+               require_action( pIPAddrTable, exit, err = WSAENOBUFS );
+       }
+
+       require_noerr( err, exit );
+
+       for ( i = 0; i < pIPAddrTable->dwNumEntries; i++ )
+       {
+               if ( ( ( struct sockaddr_in* ) addr )->sin_addr.s_addr == pIPAddrTable->table[i].dwAddr )
+               {
+                       *ifIndex                                                                                        = pIPAddrTable->table[i].dwIndex;
+                       ( ( struct sockaddr_in*) mask )->sin_addr.s_addr        = pIPAddrTable->table[i].dwMask;
+                       err                                                                                                     = mStatus_NoError;
+                       break;
+               }
+       }
+
+exit:
+
+       if ( pIPAddrTable )
+       {
+               free( pIPAddrTable );
+       }
+
+       return err;
+}
+
+
 //===========================================================================================================================
 //     CanReceiveUnicast
 //===========================================================================================================================
@@ -4327,6 +4742,49 @@ mDNSlocal mDNSBool       CanReceiveUnicast( void )
        return( ok );
 }
 
+
+//===========================================================================================================================
+//     IsPointToPoint
+//===========================================================================================================================
+
+mDNSlocal mDNSBool IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr )
+{
+       struct ifaddrs  *       addrs   =       NULL;
+       struct ifaddrs  *       p               =       NULL;
+       OSStatus                        err;
+       mDNSBool                        ret             =       mDNSfalse;
+
+       // For now, only works for IPv4 interfaces
+
+       if ( addr->Address.lpSockaddr->sa_family == AF_INET )
+       {
+               // The getifaddrs_ipv4 call will give us correct information regarding IFF_POINTTOPOINT flags.
+
+               err = getifaddrs_ipv4( &addrs );
+               require_noerr( err, exit );
+
+               for ( p = addrs; p; p = p->ifa_next )
+               {
+                       if ( ( addr->Address.lpSockaddr->sa_family == p->ifa_addr->sa_family ) &&
+                            ( ( ( struct sockaddr_in* ) addr->Address.lpSockaddr )->sin_addr.s_addr == ( ( struct sockaddr_in* ) p->ifa_addr )->sin_addr.s_addr ) )
+                       {
+                               ret = ( p->ifa_flags & IFF_POINTTOPOINT ) ? mDNStrue : mDNSfalse;
+                               break;
+                       }
+               }
+       }
+
+exit:
+
+       if ( addrs )
+       {
+               freeifaddrs( addrs );
+       }
+
+       return ret;
+}
+
+
 //===========================================================================================================================
 //     GetWindowsVersionString
 //===========================================================================================================================
@@ -4504,6 +4962,7 @@ static mStatus StringToAddress( mDNSAddr * ip, LPSTR string )
                dwSize = sizeof( sa4 );
 
                err = WSAStringToAddressA( string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize );
+               err = translate_errno( err == 0, WSAGetLastError(), kUnknownErr );
                require_noerr( err, exit );
                        
                err = dDNS_SetupAddr( ip, (struct sockaddr*) &sa4 );
@@ -4606,7 +5065,7 @@ exit:
 //===========================================================================================================================
 
 mDNSlocal OSStatus
-ConvertUTF8ToLsaString( const char * input, PLSA_UNICODE_STRING output )
+MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input )
 {
        int                     size;
        OSStatus        err;
@@ -4650,41 +5109,36 @@ exit:
 //===========================================================================================================================
 
 static OSStatus
-ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char ** output )
+MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input )
 {
-       int                     size;
+       size_t          size;
        OSStatus        err = kNoErr;
 
        // The Length field of this structure holds the number of bytes,
        // but WideCharToMultiByte expects the number of wchar_t's. So
        // we divide by sizeof(wchar_t) to get the correct number.
 
-       size = WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), NULL, 0, NULL, NULL);
+       size = (size_t) WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), NULL, 0, NULL, NULL);
        err = translate_errno( size != 0, GetLastError(), kUnknownErr );
        require_noerr( err, exit );
        
-       // Add one for trailing '\0'
+       // Ensure that we have enough space (Add one for trailing '\0')
+
+       require_action( ( size + 1 ) <= len, exit, err = mStatus_NoMemoryErr );
 
-       *output = (char*) malloc( size + 1 );
-       require_action( *output, exit, err = mStatus_NoMemoryErr );
+       // Convert the string
 
-       size = WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), *output, size, NULL, NULL);        
+       size = (size_t) WideCharToMultiByte( CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), output, (int) size, NULL, NULL); 
        err = translate_errno( size != 0, GetLastError(), kUnknownErr );
        require_noerr( err, exit );
 
        // have to add the trailing 0 because WideCharToMultiByte doesn't do it,
        // although it does return the correct size
 
-       (*output)[size] = '\0';
+       output[size] = '\0';
 
 exit:
 
-       if ( err && *output )
-       {
-               free( *output );
-               *output = NULL;
-       }
-
        return err;
 }
 
index f5c9c26e1d02304870529e252538c55bb687bcc3..1a9755debfac1546e647f73ee795cba4c133c381 100755 (executable)
@@ -23,6 +23,9 @@
     Change History (most recent first):
     
 $Log: mDNSWin32.h,v $
+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
 
@@ -199,6 +202,7 @@ struct      mDNS_PlatformSupport_struct
        HKEY                                            tcpipKey;
        HKEY                                            ddnsKey;
        mStatus                                         initStatus;
+       mDNSBool                                        registeredLoopback4;
        SocketRef                                       interfaceListChangedSocket;
        int                                                     interfaceCount;
        mDNSInterfaceData *                     interfaceList;
index c690459adcf8b1f708ae50ae0230e0c97849471f..f0937f5e1429c054dabd8e347106236e2f12dacc 100644 (file)
     Change History (most recent first):
     
 $Log: mdnsNSP.c,v $
+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
 
@@ -66,6 +90,7 @@ mDNS NameSpace Provider (NSP). Hooks into the Windows name resolution system to
 
 */
 
+
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <string.h>
@@ -73,11 +98,22 @@ mDNS NameSpace Provider (NSP). Hooks into the Windows name resolution system to
 #include       "CommonServices.h"
 #include       "DebugServices.h"
 
+#include       <iphlpapi.h>
 #include       <guiddef.h>
 #include       <ws2spi.h>
+#include       <shlwapi.h>
+
+
 
 #include       "dns_sd.h"
 
+#pragma comment(lib, "DelayImp.lib")
+
+#ifdef _MSC_VER
+#define swprintf _snwprintf
+#define snprintf _snprintf
+#endif
+
 #if 0
 #pragma mark == Structures ==
 #endif
@@ -95,15 +131,21 @@ struct     Query
        DWORD                           querySetFlags;
        WSAQUERYSETW *          querySet;
        size_t                          querySetSize;
-       HANDLE                          dataEvent;
+       HANDLE                          data4Event;
+       HANDLE                          data6Event;
        HANDLE                          cancelEvent;
-       HANDLE                          waitHandles[ 2 ];
+       HANDLE                          waitHandles[ 3 ];
        DWORD                           waitCount;
-       DNSServiceRef           resolver;
+       DNSServiceRef           resolver4;
+       DNSServiceRef           resolver6;
        char                            name[ kDNSServiceMaxDomainName ];
        size_t                          nameSize;
-       uint32_t                        addr;
-       bool                            addrValid;
+       uint8_t                         numValidAddrs;
+       uint32_t                        addr4;
+       bool                            addr4Valid;
+       uint8_t                         addr6[16];
+       u_long                          addr6ScopeId;
+       bool                            addr6Valid;
 };
 
 #define BUFFER_INITIAL_SIZE            4192
@@ -182,7 +224,21 @@ DEBUG_LOCAL OSStatus       QueryRetain( QueryRef inRef );
 DEBUG_LOCAL OSStatus   QueryRelease( QueryRef inRef );
 
 DEBUG_LOCAL void CALLBACK_COMPAT
-       QueryRecordCallback(
+       QueryRecordCallback4(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               uint32_t                        inInterfaceIndex,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inName,    
+               uint16_t                        inRRType,
+               uint16_t                        inRRClass,
+               uint16_t                        inRDataSize,
+               const void *            inRData,
+               uint32_t                        inTTL,
+               void *                          inContext );
+
+DEBUG_LOCAL void CALLBACK_COMPAT
+       QueryRecordCallback6(
                DNSServiceRef           inRef,
                DNSServiceFlags         inFlags,
                uint32_t                        inInterfaceIndex,
@@ -227,6 +283,12 @@ DEBUG_LOCAL OSStatus       HostsFileOpen( HostsFile ** self, const char * fname );
 DEBUG_LOCAL OSStatus   HostsFileClose( HostsFile * self );
 DEBUG_LOCAL void               HostsFileInfoFree( HostsFileInfo * info );
 DEBUG_LOCAL OSStatus   HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo );
+DEBUG_LOCAL const char * GetNextLabel( const char *cstr, char label[64] );
+DEBUG_LOCAL DWORD              GetScopeId( DWORD ifIndex );
+
+#ifdef ENABLE_REVERSE_LOOKUP
+DEBUG_LOCAL OSStatus   IsReverseLookup( LPCWSTR name, size_t size );
+#endif
 
 
 #if 0
@@ -244,9 +306,20 @@ DEBUG_LOCAL GUID                                   gNSPGUID                        = { 0xb600e6e9, 0x553b, 0x4a19, { 0x86, 0x96, 0x
 DEBUG_LOCAL LONG                                       gRefCount                       = 0;
 DEBUG_LOCAL CRITICAL_SECTION           gLock;
 DEBUG_LOCAL bool                                       gLockInitialized        = false;
-DEBUG_LOCAL bool                                       gDNSSDInitialized       = false;
 DEBUG_LOCAL QueryRef                           gQueryList                      = NULL;
 DEBUG_LOCAL HostsFileInfo              *       gHostsFileInfo          = NULL;
+typedef DWORD
+       ( WINAPI * GetAdaptersAddressesFunctionPtr )( 
+                       ULONG                                   inFamily, 
+                       DWORD                                   inFlags, 
+                       PVOID                                   inReserved, 
+                       PIP_ADAPTER_ADDRESSES   inAdapter, 
+                       PULONG                                  outBufferSize );
+
+DEBUG_LOCAL HMODULE                                                            gIPHelperLibraryInstance                        = NULL;
+DEBUG_LOCAL GetAdaptersAddressesFunctionPtr            gGetAdaptersAddressesFunctionPtr        = NULL;
+
+
 
 #if 0
 #pragma mark -
@@ -260,16 +333,17 @@ BOOL APIENTRY     DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved )
 {
        DEBUG_USE_ONLY( inInstance );
        DEBUG_UNUSED( inReserved );
-       
+
        switch( inReason )
        {
                case DLL_PROCESS_ATTACH:                        
                        gInstance = inInstance;         
                        gHostsFileInfo  = NULL;
                        debug_initialize( kDebugOutputTypeWindowsEventLog, "mDNS NSP", inInstance );
-                       debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelInfo );
+                       debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelNotice );
                        dlog( kDebugLevelTrace, "\n" );
                        dlog( kDebugLevelVerbose, "%s: process attach\n", __ROUTINE__ );
+
                        break;
                
                case DLL_PROCESS_DETACH:
@@ -290,6 +364,7 @@ BOOL APIENTRY       DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved )
                        dlog( kDebugLevelNotice, "%s: unknown reason code (%d)\n", __ROUTINE__, inReason );
                        break;
        }
+
        return( TRUE );
 }
 
@@ -395,6 +470,18 @@ int WSPAPI NSPStartup( LPGUID inProviderID, LPNSP_ROUTINE outRoutines )
        outRoutines->NSPRemoveServiceClass      = NSPRemoveServiceClass;
        outRoutines->NSPGetServiceClassInfo     = NSPGetServiceClassInfo;
        
+       // See if we can get the address for the GetAdaptersAddresses() API.  This is only in XP, but we want our
+       // code to run on older versions of Windows
+
+       if ( !gIPHelperLibraryInstance )
+       {
+               gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
+               if( gIPHelperLibraryInstance )
+               {
+                       gGetAdaptersAddressesFunctionPtr = (GetAdaptersAddressesFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetAdaptersAddresses" );
+               }
+       }
+
        err = NO_ERROR;
        
 exit:
@@ -444,17 +531,20 @@ int       WSPAPI  NSPCleanup( LPGUID inProviderID )
                NSPUnlock();
        }
        
-       // Shut down DNS-SD and release our resources.
-       
-       if( gDNSSDInitialized )
-       {
-               gDNSSDInitialized = false;
-       }
        if( gLockInitialized )
        {
                gLockInitialized = false;
                DeleteCriticalSection( &gLock );
        }
+
+       if( gIPHelperLibraryInstance )
+       {
+               BOOL ok;
+                               
+               ok = FreeLibrary( gIPHelperLibraryInstance );
+               check_translated_errno( ok, GetLastError(), kUnknownErr );
+               gIPHelperLibraryInstance = NULL;
+       }
        
 exit:
        dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
@@ -545,80 +635,55 @@ DEBUG_LOCAL int WSPAPI
                ( ( p[ 4 ] != 'A' ) && ( p[ 4 ] != 'a' ) )      ||
                ( ( p[ 5 ] != 'L' ) && ( p[ 5 ] != 'l' ) ) ) )
        {
-               require_action_quiet( size > sizeof_string( ".0.8.e.f.ip6.arpa" ), exit, err = WSASERVICE_NOT_FOUND );
-               p = name + ( size - 1 );
-               p = ( *p == '.' ) ? ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) : ( ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) + 1 );
-       
-               if      ( ( ( p[ 0 ] != '.' )                                                   ||
-                       ( ( p[ 1 ] != '0' ) )                                                   ||
-                       ( ( p[ 2 ] != '.' ) )                                                   ||
-                       ( ( p[ 3 ] != '8' ) )                                                   ||
-                       ( ( p[ 4 ] != '.' ) )                                                   ||
-                       ( ( p[ 5 ] != 'E' ) && ( p[ 5 ] != 'e' ) )              ||
-                       ( ( p[ 6 ] != '.' ) )                                                   ||
-                       ( ( p[ 7 ] != 'F' ) && ( p[ 7 ] != 'f' ) )              ||
-                       ( ( p[ 8 ] != '.' ) )                                                   ||
-                       ( ( p[ 9 ] != 'I' ) && ( p[ 9 ] != 'i' ) )              ||
-                       ( ( p[ 10 ] != 'P' ) && ( p[ 10 ] != 'p' ) )    ||      
-                       ( ( p[ 11 ] != '6' ) )                                                  ||
-                       ( ( p[ 12 ] != '.' ) )                                                  ||
-                       ( ( p[ 13 ] != 'A' ) && ( p[ 13 ] != 'a' ) )    ||
-                       ( ( p[ 14 ] != 'R' ) && ( p[ 14 ] != 'r' ) )    ||
-                       ( ( p[ 15 ] != 'P' ) && ( p[ 15 ] != 'p' ) )    ||
-                       ( ( p[ 16 ] != 'A' ) && ( p[ 16 ] != 'a' ) ) ) )
-               {
-                       require_action_quiet( size > sizeof_string( ".254.169.in-addr.arpa" ), exit, err = WSASERVICE_NOT_FOUND );
-                       p = name + ( size - 1 );
-                       p = ( *p == '.' ) ? ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) : ( ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) + 1 );
-       
-       require_action_quiet( ( ( p[ 0 ] == '.' )                                                &&
-                                                                       ( ( p[ 1 ] == '2' ) )                                                   &&
-                                                                       ( ( p[ 2 ] == '5' ) )                                                   &&
-                                                                       ( ( p[ 3 ] == '4' ) )                                                   &&
-                                                                       ( ( p[ 4 ] == '.' ) )                                                   &&
-                                                                       ( ( p[ 5 ] == '1' ) )                                                   &&
-                                                                       ( ( p[ 6 ] == '6' ) )                                                   &&
-                                                                       ( ( p[ 7 ] == '9' ) )                                                   &&
-                                                                       ( ( p[ 8 ] == '.' ) )                                                   &&
-                                                                       ( ( p[ 9 ] == 'I' ) || ( p[ 9 ] == 'i' ) )              &&
-                                                                       ( ( p[ 10 ] == 'N' ) || ( p[ 10 ] == 'n' ) )    &&      
-                                                                       ( ( p[ 11 ] == '-' ) )                                                  &&
-                                                                       ( ( p[ 12 ] == 'A' ) || ( p[ 12 ] == 'a' ) )    &&
-                                                                       ( ( p[ 13 ] == 'D' ) || ( p[ 13 ] == 'd' ) )    &&
-                                                                       ( ( p[ 14 ] == 'D' ) || ( p[ 14 ] == 'd' ) )    &&
-                                                                       ( ( p[ 15 ] == 'R' ) || ( p[ 15 ] == 'r' ) )    &&
-                                                                       ( ( p[ 16 ] == '.' ) )                                                  &&
-                                                                       ( ( p[ 17 ] == 'A' ) || ( p[ 17 ] == 'a' ) )    &&
-                                                                       ( ( p[ 18 ] == 'R' ) || ( p[ 18 ] == 'r' ) )    &&
-                                                                       ( ( p[ 19 ] == 'P' ) || ( p[ 19 ] == 'p' ) )    &&
-                                                                       ( ( p[ 20 ] == 'A' ) || ( p[ 20 ] == 'a' ) ) ),
-                                                                       exit, err = WSASERVICE_NOT_FOUND );
-               }
+#ifdef ENABLE_REVERSE_LOOKUP
+
+               err = IsReverseLookup( name, size );
+
+#else
+
+               err = WSASERVICE_NOT_FOUND;
+
+#endif
+
+               require_noerr( err, exit );
        }
        else
        {
+               const char      *       replyDomain;
+               char                    translated[ kDNSServiceMaxDomainName ];
+               int                             n;
+               int                             labels          = 0;
+               const char      *       label[128];
+               char                    text[64];
+
+               n = WideCharToMultiByte( CP_UTF8, 0, name, -1, translated, sizeof( translated ), NULL, NULL );
+               require_action( n > 0, exit, err = WSASERVICE_NOT_FOUND );
+
+               // <rdar://problem/4050633>
+
+               // Don't resolve multi-label name
+
+               replyDomain = translated;
+
+               while ( *replyDomain )
+               {
+                       label[labels++] = replyDomain;
+                       replyDomain             = GetNextLabel(replyDomain, text);
+               }
+
+               require_action( labels == 2, exit, err = WSASERVICE_NOT_FOUND );
+
                // <rdar://problem/3936771>
                //
                // Check to see if the name of this host is in the hosts table. If so,
                // don't try and resolve it
                
-               char    translated[ kDNSServiceMaxDomainName ];
-               int             n;
-
-               n = WideCharToMultiByte( CP_UTF8, 0, name, -1, translated, sizeof( translated ), NULL, NULL );
-               require_action( n > 0, exit, err = WSASERVICE_NOT_FOUND );
                require_action( InHostsTable( translated ) == FALSE, exit, err = WSASERVICE_NOT_FOUND );
        }
 
        // The name ends in .local ( and isn't in the hosts table ), .0.8.e.f.ip6.arpa, or .254.169.in-addr.arpa so start the resolve operation. Lazy initialize DNS-SD if needed.
                
        NSPLock();
-       if( !gDNSSDInitialized )
-       {
-               gDNSSDInitialized = true;
-       }
        
        err = QueryCreate( inQuerySet, inFlags, &obj );
        NSPUnlock();
@@ -651,6 +716,8 @@ DEBUG_LOCAL int WSPAPI
                LPDWORD                 ioSize,
                LPWSAQUERYSETW  outResults )
 {
+       BOOL                    data4;
+       BOOL                    data6;
        OSStatus                err;
        QueryRef                obj;
        DWORD                   waitResult;
@@ -660,6 +727,8 @@ DEBUG_LOCAL int WSPAPI
        
        dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
        
+       data4 = FALSE;
+       data6 = FALSE;
        obj = NULL;
        NSPLock();
        err = QueryRetain( (QueryRef) inLookup );
@@ -675,12 +744,56 @@ DEBUG_LOCAL int WSPAPI
        NSPUnlock();
        waitResult = WaitForMultipleObjects( obj->waitCount, obj->waitHandles, FALSE, 2 * 1000 );
        NSPLock();
-       require_action_quiet( waitResult != ( WAIT_OBJECT_0 + 1 ), exit, err = WSA_E_CANCELLED );
-       err = translate_errno( waitResult == WAIT_OBJECT_0, (OSStatus) GetLastError(), WSASERVICE_NOT_FOUND );
+       require_action_quiet( waitResult != ( WAIT_OBJECT_0 ), exit, err = WSA_E_CANCELLED );
+       err = translate_errno( ( waitResult == WAIT_OBJECT_0 + 1 ) || ( waitResult == WAIT_OBJECT_0 + 2 ), (OSStatus) GetLastError(), WSASERVICE_NOT_FOUND );
        require_noerr_quiet( err, exit );
-       DNSServiceProcessResult(obj->resolver);
-       require_action_quiet( obj->addrValid, exit, err = WSA_E_NO_MORE );
-       
+
+       // If we've received an IPv4 reply, then hang out briefly for an IPv6 reply
+
+       if ( waitResult == WAIT_OBJECT_0 + 1 )
+       {
+               data4 = TRUE;
+               data6 = WaitForSingleObject( obj->data6Event, 100 ) == WAIT_OBJECT_0 ? TRUE : FALSE;
+       }
+
+       // Else we've received an IPv6 reply, so hang out briefly for an IPv4 reply
+
+       else if ( waitResult == WAIT_OBJECT_0 + 2 )
+       {
+               data4 = WaitForSingleObject( obj->data4Event, 100 ) == WAIT_OBJECT_0 ? TRUE : FALSE;
+               data6 = TRUE;
+       }
+
+       if ( data4 )
+       {
+               __try
+               {
+                       err = DNSServiceProcessResult(obj->resolver4);
+               }
+               __except( EXCEPTION_EXECUTE_HANDLER )
+               {
+                       err = kUnknownErr;
+               }
+
+               require_noerr( err, exit );
+       }
+
+       if ( data6 )
+       {
+               __try
+               {
+                       err = DNSServiceProcessResult( obj->resolver6 );
+               }
+               __except( EXCEPTION_EXECUTE_HANDLER )
+               {
+                       err = kUnknownErr;
+               }
+
+               require_noerr( err, exit );
+       }
+
+       require_action_quiet( obj->addr4Valid || obj->addr6Valid, exit, err = WSA_E_NO_MORE );
+
        // Copy the externalized query results to the callers buffer (if it fits).
        
        size = QueryCopyQuerySetSize( obj, obj->querySet, obj->querySetFlags );
@@ -688,8 +801,9 @@ DEBUG_LOCAL int WSPAPI
        
        QueryCopyQuerySetTo( obj, obj->querySet, obj->querySetFlags, outResults );
        outResults->dwOutputFlags = RESULT_IS_ADDED;
-       obj->addrValid = false;
-       
+       obj->addr4Valid = false;
+       obj->addr6Valid = false;
+
 exit:
        if( obj )
        {
@@ -851,7 +965,9 @@ DEBUG_LOCAL OSStatus        QueryCreate( const WSAQUERYSETW *inQuerySet, DWORD inQueryS
        char                    name[ kDNSServiceMaxDomainName ];
        int                             n;
        QueryRef *              p;
-       
+       SOCKET                  s4;
+       SOCKET                  s6;
+
        obj = NULL;
        check( inQuerySet );
        check( inQuerySet->lpszServiceInstanceName );
@@ -873,27 +989,84 @@ DEBUG_LOCAL OSStatus      QueryCreate( const WSAQUERYSETW *inQuerySet, DWORD inQueryS
        for( p = &gQueryList; *p; p = &( *p )->next ) {}        // Find the end of the list.
        *p = obj;
        
-       // Set up events to signal when data is ready and when cancelling.
-       
-       obj->dataEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
-       require_action( obj->dataEvent, exit, err = WSA_NOT_ENOUGH_MEMORY );
-       
+       // Set up cancel event
+
        obj->cancelEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
        require_action( obj->cancelEvent, exit, err = WSA_NOT_ENOUGH_MEMORY );
+
+       // Set up events to signal when A record data is ready
        
-       // Start the query.
+       obj->data4Event = CreateEvent( NULL, TRUE, FALSE, NULL );
+       require_action( obj->data4Event, exit, err = WSA_NOT_ENOUGH_MEMORY );
+       
+       // Start the query.  Handle delay loaded DLL errors.
+
+       __try
+       {
+               err = DNSServiceQueryRecord( &obj->resolver4, 0, 0, name, kDNSServiceType_A, kDNSServiceClass_IN, QueryRecordCallback4, obj );
+       }
+       __except( EXCEPTION_EXECUTE_HANDLER )
+       {
+               err = kUnknownErr;
+       }
 
-       err = DNSServiceQueryRecord( &obj->resolver, 0, 0, name, kDNSServiceType_A, kDNSServiceClass_IN, 
-               QueryRecordCallback, obj );
        require_noerr( err, exit );
 
        // Attach the socket to the event
 
-       WSAEventSelect(DNSServiceRefSockFD(obj->resolver), obj->dataEvent, FD_READ|FD_CLOSE);
+       __try
+       {
+               s4 = DNSServiceRefSockFD(obj->resolver4);
+       }
+       __except( EXCEPTION_EXECUTE_HANDLER )
+       {
+               s4 = INVALID_SOCKET;
+       }
+
+       err = translate_errno( s4 != INVALID_SOCKET, errno_compat(), kUnknownErr );
+       require_noerr( err, exit );
+
+       WSAEventSelect(s4, obj->data4Event, FD_READ|FD_CLOSE);
+       
+       // Set up events to signal when AAAA record data is ready
+       
+       obj->data6Event = CreateEvent( NULL, TRUE, FALSE, NULL );
+       require_action( obj->data6Event, exit, err = WSA_NOT_ENOUGH_MEMORY );
        
+       // Start the query.  Handle delay loaded DLL errors.
+
+       __try
+       {
+               err = DNSServiceQueryRecord( &obj->resolver6, 0, 0, name, kDNSServiceType_AAAA, kDNSServiceClass_IN, QueryRecordCallback6, obj );
+       }
+       __except( EXCEPTION_EXECUTE_HANDLER )
+       {
+               err = kUnknownErr;
+       }
+
+       require_noerr( err, exit );
+
+       // Attach the socket to the event
+
+       __try
+       {
+               s6 = DNSServiceRefSockFD(obj->resolver6);
+       }
+       __except( EXCEPTION_EXECUTE_HANDLER )
+       {
+               s6 = INVALID_SOCKET;
+       }
+
+       err = translate_errno( s6 != INVALID_SOCKET, errno_compat(), kUnknownErr );
+       require_noerr( err, exit );
+
+       WSAEventSelect(s6, obj->data6Event, FD_READ|FD_CLOSE);
+
        obj->waitCount = 0;
-       obj->waitHandles[ obj->waitCount++ ] = obj->dataEvent;
        obj->waitHandles[ obj->waitCount++ ] = obj->cancelEvent;
+       obj->waitHandles[ obj->waitCount++ ] = obj->data4Event;
+       obj->waitHandles[ obj->waitCount++ ] = obj->data6Event;
+       
        check( obj->waitCount == sizeof_array( obj->waitHandles ) );
        
        // Copy the QuerySet so it can be returned later.
@@ -977,10 +1150,30 @@ DEBUG_LOCAL OSStatus     QueryRelease( QueryRef inRef )
        
        // Stop the query.
        
-       if( inRef->resolver )
+       if( inRef->resolver4 )
+       {
+               __try
+               {
+                       DNSServiceRefDeallocate( inRef->resolver4 );
+               }
+               __except( EXCEPTION_EXECUTE_HANDLER )
+               {
+               }
+               
+               inRef->resolver4 = NULL;
+       }
+
+       if ( inRef->resolver6 )
        {
-               DNSServiceRefDeallocate( inRef->resolver );
-               inRef->resolver = NULL;
+               __try
+               {
+                       DNSServiceRefDeallocate( inRef->resolver6 );
+               }
+               __except( EXCEPTION_EXECUTE_HANDLER )
+               {
+               }
+
+               inRef->resolver6 = NULL;
        }
        
        // Decrement the refCount. Fully release if it drops to 0. If still referenced, just exit.
@@ -999,9 +1192,14 @@ DEBUG_LOCAL OSStatus      QueryRelease( QueryRef inRef )
                ok = CloseHandle( inRef->cancelEvent );
                check_translated_errno( ok, GetLastError(), WSAEINVAL );
        }
-       if( inRef->dataEvent )
+       if( inRef->data4Event )
+       {
+               ok = CloseHandle( inRef->data4Event );
+               check_translated_errno( ok, GetLastError(), WSAEINVAL );
+       }
+       if( inRef->data6Event )
        {
-               ok = CloseHandle( inRef->dataEvent );
+               ok = CloseHandle( inRef->data6Event );
                check_translated_errno( ok, GetLastError(), WSAEINVAL );
        }
        if( inRef->querySet )
@@ -1016,11 +1214,11 @@ exit:
 }
 
 //===========================================================================================================================
-//     QueryRecordCallback
+//     QueryRecordCallback4
 //===========================================================================================================================
 
 DEBUG_LOCAL void CALLBACK_COMPAT
-       QueryRecordCallback(
+       QueryRecordCallback4(
                DNSServiceRef           inRef,
                DNSServiceFlags         inFlags,
                uint32_t                        inInterfaceIndex,
@@ -1071,19 +1269,27 @@ DEBUG_LOCAL void CALLBACK_COMPAT
        
        // Copy the data.
        
-       memcpy( &obj->addr, inRData, inRDataSize );
-       obj->addrValid = true;
+       memcpy( &obj->addr4, inRData, inRDataSize );
+       obj->addr4Valid = true;
+       obj->numValidAddrs++;
        
        // Signal that a result is ready.
        
-       check( obj->dataEvent );
-       ok = SetEvent( obj->dataEvent );
+       check( obj->data4Event );
+       ok = SetEvent( obj->data4Event );
        check_translated_errno( ok, GetLastError(), WSAEINVAL );
        
        // Stop the resolver after the first response.
        
-       DNSServiceRefDeallocate( inRef );
-       obj->resolver = NULL;
+       __try
+       {
+               DNSServiceRefDeallocate( inRef );
+       }
+       __except( EXCEPTION_EXECUTE_HANDLER )
+       {
+       }
+
+       obj->resolver4 = NULL;
 
 exit:
        NSPUnlock();
@@ -1093,6 +1299,96 @@ exit:
 #pragma mark -
 #endif
 
+
+//===========================================================================================================================
+//     QueryRecordCallback6
+//===========================================================================================================================
+
+DEBUG_LOCAL void CALLBACK_COMPAT
+       QueryRecordCallback6(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               uint32_t                        inInterfaceIndex,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inName,    
+               uint16_t                        inRRType,
+               uint16_t                        inRRClass,
+               uint16_t                        inRDataSize,
+               const void *            inRData,
+               uint32_t                        inTTL,
+               void *                          inContext )
+{
+       QueryRef                        obj;
+       const char *            src;
+       char *                          dst;
+       BOOL                            ok;
+       
+       DEBUG_UNUSED( inFlags );
+       DEBUG_UNUSED( inInterfaceIndex );
+       DEBUG_UNUSED( inTTL );
+
+       NSPLock();
+       obj = (QueryRef) inContext;
+       check( obj );
+       require_noerr( inErrorCode, exit );
+       require_quiet( inFlags & kDNSServiceFlagsAdd, exit );
+       require( inRRClass   == kDNSServiceClass_IN, exit );
+       require( inRRType    == kDNSServiceType_AAAA, exit );
+       require( inRDataSize == 16, exit );
+       
+       dlog( kDebugLevelTrace, "%s (flags=0x%08X, name=%s, rrType=%d, rDataSize=%d)\n", 
+               __ROUTINE__, inFlags, inName, inRRType, inRDataSize );
+
+       // Copy the name if needed.
+       
+       if( obj->name[ 0 ] == '\0' )
+       {
+               src = inName;
+               dst = obj->name;
+               while( *src != '\0' )
+               {
+                       *dst++ = *src++;
+               }
+               *dst = '\0';
+               obj->nameSize = (size_t)( dst - obj->name );
+               check( obj->nameSize < sizeof( obj->name ) );
+       }
+       
+       // Copy the data.
+       
+       memcpy( &obj->addr6, inRData, inRDataSize );
+
+       obj->addr6ScopeId = GetScopeId( inInterfaceIndex );
+       require( obj->addr6ScopeId, exit );
+       obj->addr6Valid   = true;
+       obj->numValidAddrs++;
+
+       // Signal that we're done
+       
+       check( obj->data6Event );
+       ok = SetEvent( obj->data6Event );
+       check_translated_errno( ok, GetLastError(), WSAEINVAL );
+
+       // Stop the resolver after the first response.
+       
+       __try
+       {
+               DNSServiceRefDeallocate( inRef );
+       }
+       __except( EXCEPTION_EXECUTE_HANDLER )
+       {
+       }
+
+       obj->resolver6 = NULL;
+
+exit:
+
+       
+       
+       NSPUnlock();
+}
+
+
 //===========================================================================================================================
 //     QueryCopyQuerySet
 //
@@ -1136,6 +1432,8 @@ exit:
        return( err );  
 }
 
+
+
 //===========================================================================================================================
 //     QueryCopyQuerySetTo
 //
@@ -1227,6 +1525,7 @@ DEBUG_LOCAL void
        }
                
        n = inQuerySet->dwNumberOfProtocols;
+
        if( n > 0 )
        {
                check( inQuerySet->lpafpProtocols );
@@ -1250,28 +1549,55 @@ DEBUG_LOCAL void
        
        // Copy the address(es).
        
-       if( ( inQuerySetFlags & LUP_RETURN_ADDR ) && inRef->addrValid )
+       if( ( inQuerySetFlags & LUP_RETURN_ADDR ) && ( inRef->numValidAddrs > 0 ) )
        {
-               struct sockaddr_in *            addr;
+               struct sockaddr_in      *       addr4;
+               struct sockaddr_in6     *       addr6;
+               int                                             index;
                
-               outQuerySet->dwNumberOfCsAddrs                                                          = 1;
-               outQuerySet->lpcsaBuffer                                                                        = (LPCSADDR_INFO) dst;
-               dst                                                                                                        += sizeof( *outQuerySet->lpcsaBuffer );
+               outQuerySet->dwNumberOfCsAddrs  = inRef->numValidAddrs;
+               outQuerySet->lpcsaBuffer                = (LPCSADDR_INFO) dst;
+               dst                                                     += ( sizeof( *outQuerySet->lpcsaBuffer ) ) * ( inRef->numValidAddrs ) ;
+               index                                                   = 0;
                
-               outQuerySet->lpcsaBuffer[ 0 ].LocalAddr.lpSockaddr                      = NULL;
-               outQuerySet->lpcsaBuffer[ 0 ].LocalAddr.iSockaddrLength         = 0;
+               if ( inRef->addr4Valid )
+               {       
+                       outQuerySet->lpcsaBuffer[ index ].LocalAddr.lpSockaddr                  = NULL;
+                       outQuerySet->lpcsaBuffer[ index ].LocalAddr.iSockaddrLength             = 0;
                
-               outQuerySet->lpcsaBuffer[ 0 ].RemoteAddr.lpSockaddr             = (LPSOCKADDR) dst;
-               outQuerySet->lpcsaBuffer[ 0 ].RemoteAddr.iSockaddrLength        = sizeof( struct sockaddr_in );
+                       outQuerySet->lpcsaBuffer[ index ].RemoteAddr.lpSockaddr                 = (LPSOCKADDR) dst;
+                       outQuerySet->lpcsaBuffer[ index ].RemoteAddr.iSockaddrLength    = sizeof( struct sockaddr_in );
                
-               addr                                                                                                            = (struct sockaddr_in *) dst;
-               memset( addr, 0, sizeof( *addr ) );
-               addr->sin_family                                                                                        = AF_INET;
-               memcpy( &addr->sin_addr, &inRef->addr, 4 );
-               dst                                                                                                        += sizeof( *addr );
+                       addr4                                                                                                                   = (struct sockaddr_in *) dst;
+                       memset( addr4, 0, sizeof( *addr4 ) );
+                       addr4->sin_family                                                                                               = AF_INET;
+                       memcpy( &addr4->sin_addr, &inRef->addr4, 4 );
+                       dst                                                                                                                     += sizeof( *addr4 );
+               
+                       outQuerySet->lpcsaBuffer[ index ].iSocketType                                   = AF_INET;              // Emulate Tcpip NSP
+                       outQuerySet->lpcsaBuffer[ index ].iProtocol                                             = IPPROTO_UDP;  // Emulate Tcpip NSP
+
+                       index++;
+               }
+
+               if ( inRef->addr6Valid )
+               {
+                       outQuerySet->lpcsaBuffer[ index ].LocalAddr.lpSockaddr                  = NULL;
+                       outQuerySet->lpcsaBuffer[ index ].LocalAddr.iSockaddrLength             = 0;
                
-               outQuerySet->lpcsaBuffer[ 0 ].iSocketType                                       = AF_INET;              // Emulate Tcpip NSP
-               outQuerySet->lpcsaBuffer[ 0 ].iProtocol                                         = IPPROTO_UDP;  // Emulate Tcpip NSP
+                       outQuerySet->lpcsaBuffer[ index ].RemoteAddr.lpSockaddr                 = (LPSOCKADDR) dst;
+                       outQuerySet->lpcsaBuffer[ index ].RemoteAddr.iSockaddrLength    = sizeof( struct sockaddr_in6 );
+               
+                       addr6                                                                                                                   = (struct sockaddr_in6 *) dst;
+                       memset( addr6, 0, sizeof( *addr6 ) );
+                       addr6->sin6_family                                                                                              = AF_INET6;
+                       addr6->sin6_scope_id                                                                                    = inRef->addr6ScopeId;
+                       memcpy( &addr6->sin6_addr, &inRef->addr6, 16 );
+                       dst                                                                                                                     += sizeof( *addr6 );
+               
+                       outQuerySet->lpcsaBuffer[ index ].iSocketType                                   = AF_INET6;             // Emulate Tcpip NSP
+                       outQuerySet->lpcsaBuffer[ index ].iProtocol                                             = IPPROTO_UDP;  // Emulate Tcpip NSP
+               }
        }
        else
        {
@@ -1281,12 +1607,12 @@ DEBUG_LOCAL void
        
        // Copy the hostent blob.
        
-       if( ( inQuerySetFlags & LUP_RETURN_BLOB ) && inRef->addrValid )
+       if( ( inQuerySetFlags & LUP_RETURN_BLOB ) && inRef->addr4Valid )
        {
                uint8_t *                               base;
                struct hostent *                he;
                uintptr_t *                             p;
-               
+
                outQuerySet->lpBlob      = (LPBLOB) dst;
                dst                             += sizeof( *outQuerySet->lpBlob );
                
@@ -1312,14 +1638,14 @@ DEBUG_LOCAL void
                *p++                    = (uintptr_t)( dst - base );
                *p++                    = 0;
                p                               = (uintptr_t *) dst;
-               *p++                    = (uintptr_t) inRef->addr;
+               *p++                    = (uintptr_t) inRef->addr4;
                dst                     = (uint8_t *) p;
                
                outQuerySet->lpBlob->cbSize     = (ULONG)( dst - base );
                outQuerySet->lpBlob->pBlobData  = (BYTE *) base;
        }
        dlog_query_set( kDebugLevelVerbose, outQuerySet );
-       
+
        check( (size_t)( dst - ( (uint8_t *) outQuerySet ) ) == debugSize );
 }
 
@@ -1392,15 +1718,21 @@ DEBUG_LOCAL size_t      QueryCopyQuerySetSize( QueryRef inRef, const WSAQUERYSETW *in
        
        // Calculate the size of the address(es).
        
-       if( ( inQuerySetFlags & LUP_RETURN_ADDR ) && inRef->addrValid )
+       if( ( inQuerySetFlags & LUP_RETURN_ADDR ) && inRef->addr4Valid )
        {
                size += sizeof( *inQuerySet->lpcsaBuffer );
                size += sizeof( struct sockaddr_in );
        }
+
+       if( ( inQuerySetFlags & LUP_RETURN_ADDR ) && inRef->addr6Valid )
+       {
+               size += sizeof( *inQuerySet->lpcsaBuffer );
+               size += sizeof( struct sockaddr_in6 );
+       }
        
        // Calculate the size of the hostent blob.
        
-       if( ( inQuerySetFlags & LUP_RETURN_BLOB ) && inRef->addrValid )
+       if( ( inQuerySetFlags & LUP_RETURN_BLOB ) && inRef->addr4Valid )
        {
                size += sizeof( *inQuerySet->lpBlob );  // Blob ptr/size structure
                size += sizeof( struct hostent );               // Old-style hostent structure
@@ -1984,3 +2316,215 @@ exit:
 
        return err;
 }
+
+
+//===========================================================================================================================
+//     GetNextLabel
+//===========================================================================================================================
+DEBUG_LOCAL const char*
+GetNextLabel(const char *cstr, char label[64])
+{
+       char *ptr = label;
+       while (*cstr && *cstr != '.')                                                           // While we have characters in the label...
+               {
+               char c = *cstr++;
+               if (c == '\\')
+                       {
+                       c = *cstr++;
+                       if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
+                               {
+                               int v0 = cstr[-1] - '0';                                                // then interpret as three-digit decimal
+                               int v1 = cstr[ 0] - '0';
+                               int v2 = cstr[ 1] - '0';
+                               int val = v0 * 100 + v1 * 10 + v2;
+                               if (val <= 255) { c = (char)val; cstr += 2; }   // If valid three-digit decimal value, use it
+                               }
+                       }
+               *ptr++ = c;
+               if (ptr >= label+64) return(NULL);
+               }
+       if (*cstr) cstr++;                                                                                      // Skip over the trailing dot (if present)
+       *ptr++ = 0;
+       return(cstr);
+}
+
+
+#ifdef ENABLE_REVERSE_LOOKUP
+//===========================================================================================================================
+//     IsReverseLookup
+//===========================================================================================================================
+
+DEBUG_LOCAL OSStatus
+IsReverseLookup( LPCWSTR name, size_t size )
+{
+       LPCWSTR         p;
+       OSStatus        err = kNoErr;
+
+       require_action_quiet( size > sizeof_string( ".0.8.e.f.ip6.arpa" ), exit, err = WSASERVICE_NOT_FOUND );
+       p = name + ( size - 1 );
+       p = ( *p == '.' ) ? ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) : ( ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) + 1 );
+       
+       if      ( ( ( p[ 0 ] != '.' )                                                   ||
+               ( ( p[ 1 ] != '0' ) )                                                   ||
+               ( ( p[ 2 ] != '.' ) )                                                   ||
+               ( ( p[ 3 ] != '8' ) )                                                   ||
+               ( ( p[ 4 ] != '.' ) )                                                   ||
+               ( ( p[ 5 ] != 'E' ) && ( p[ 5 ] != 'e' ) )              ||
+               ( ( p[ 6 ] != '.' ) )                                                   ||
+               ( ( p[ 7 ] != 'F' ) && ( p[ 7 ] != 'f' ) )              ||
+               ( ( p[ 8 ] != '.' ) )                                                   ||
+               ( ( p[ 9 ] != 'I' ) && ( p[ 9 ] != 'i' ) )              ||
+               ( ( p[ 10 ] != 'P' ) && ( p[ 10 ] != 'p' ) )    ||      
+               ( ( p[ 11 ] != '6' ) )                                                  ||
+               ( ( p[ 12 ] != '.' ) )                                                  ||
+               ( ( p[ 13 ] != 'A' ) && ( p[ 13 ] != 'a' ) )    ||
+               ( ( p[ 14 ] != 'R' ) && ( p[ 14 ] != 'r' ) )    ||
+               ( ( p[ 15 ] != 'P' ) && ( p[ 15 ] != 'p' ) )    ||
+               ( ( p[ 16 ] != 'A' ) && ( p[ 16 ] != 'a' ) ) ) )
+       {
+               require_action_quiet( size > sizeof_string( ".254.169.in-addr.arpa" ), exit, err = WSASERVICE_NOT_FOUND );
+               p = name + ( size - 1 );
+               p = ( *p == '.' ) ? ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) : ( ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) + 1 );
+       
+               require_action_quiet( ( ( p[ 0 ] == '.' )                                                &&
+                                                               ( ( p[ 1 ] == '2' ) )                                                   &&
+                                                               ( ( p[ 2 ] == '5' ) )                                                   &&
+                                                               ( ( p[ 3 ] == '4' ) )                                                   &&
+                                                               ( ( p[ 4 ] == '.' ) )                                                   &&
+                                                               ( ( p[ 5 ] == '1' ) )                                                   &&
+                                                               ( ( p[ 6 ] == '6' ) )                                                   &&
+                                                               ( ( p[ 7 ] == '9' ) )                                                   &&
+                                                               ( ( p[ 8 ] == '.' ) )                                                   &&
+                                                               ( ( p[ 9 ] == 'I' ) || ( p[ 9 ] == 'i' ) )              &&
+                                                               ( ( p[ 10 ] == 'N' ) || ( p[ 10 ] == 'n' ) )    &&      
+                                                               ( ( p[ 11 ] == '-' ) )                                                  &&
+                                                               ( ( p[ 12 ] == 'A' ) || ( p[ 12 ] == 'a' ) )    &&
+                                                               ( ( p[ 13 ] == 'D' ) || ( p[ 13 ] == 'd' ) )    &&
+                                                               ( ( p[ 14 ] == 'D' ) || ( p[ 14 ] == 'd' ) )    &&
+                                                               ( ( p[ 15 ] == 'R' ) || ( p[ 15 ] == 'r' ) )    &&
+                                                               ( ( p[ 16 ] == '.' ) )                                                  &&
+                                                               ( ( p[ 17 ] == 'A' ) || ( p[ 17 ] == 'a' ) )    &&
+                                                               ( ( p[ 18 ] == 'R' ) || ( p[ 18 ] == 'r' ) )    &&
+                                                               ( ( p[ 19 ] == 'P' ) || ( p[ 19 ] == 'p' ) )    &&
+                                                               ( ( p[ 20 ] == 'A' ) || ( p[ 20 ] == 'a' ) ) ),
+                                                               exit, err = WSASERVICE_NOT_FOUND );
+       }
+
+       // It's a reverse lookup
+
+       check( err == kNoErr );
+
+exit:
+
+       return err;
+}
+#endif
+
+//===========================================================================================================================
+//     GetScopeId
+//===========================================================================================================================
+
+DEBUG_LOCAL DWORD
+GetScopeId( DWORD ifIndex )
+{
+       DWORD                                           err;
+       int                                                     i;
+       DWORD                                           flags;
+       struct ifaddrs *                        head;
+       struct ifaddrs **                       next;
+       IP_ADAPTER_ADDRESSES *          iaaList;
+       ULONG                                           iaaListSize;
+       IP_ADAPTER_ADDRESSES *          iaa;
+       DWORD                                           scopeId = 0;
+       
+       head    = NULL;
+       next    = &head;
+       iaaList = NULL;
+       
+       require( gGetAdaptersAddressesFunctionPtr, exit );
+
+       // Get the list of interfaces. The first call gets the size and the second call gets the actual data.
+       // This loops to handle the case where the interface changes in the window after getting the size, but before the
+       // second call completes. A limit of 100 retries is enforced to prevent infinite loops if something else is wrong.
+       
+       flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
+       i = 0;
+       for( ;; )
+       {
+               iaaListSize = 0;
+               err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, NULL, &iaaListSize );
+               check( err == ERROR_BUFFER_OVERFLOW );
+               check( iaaListSize >= sizeof( IP_ADAPTER_ADDRESSES ) );
+               
+               iaaList = (IP_ADAPTER_ADDRESSES *) malloc( iaaListSize );
+               require_action( iaaList, exit, err = ERROR_NOT_ENOUGH_MEMORY );
+               
+               err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, iaaList, &iaaListSize );
+               if( err == ERROR_SUCCESS ) break;
+               
+               free( iaaList );
+               iaaList = NULL;
+               ++i;
+               require( i < 100, exit );
+               dlog( kDebugLevelWarning, "%s: retrying GetAdaptersAddresses after %d failure(s) (%d %m)\n", __ROUTINE__, i, err, err );
+       }
+       
+       for( iaa = iaaList; iaa; iaa = iaa->Next )
+       {
+               DWORD ipv6IfIndex;
+
+               if ( iaa->IfIndex > 0xFFFFFF )
+               {
+                       continue;
+               }
+               if ( iaa->Ipv6IfIndex > 0xFF )
+               {
+                       continue;
+               }
+
+               // For IPv4 interfaces, there seems to be a bug in iphlpapi.dll that causes the 
+               // following code to crash when iterating through the prefix list.  This seems
+               // to occur when iaa->Ipv6IfIndex != 0 when IPv6 is not installed on the host.
+               // This shouldn't happen according to Microsoft docs which states:
+               //
+               //     "Ipv6IfIndex contains 0 if IPv6 is not available on the interface."
+               //
+               // So the data structure seems to be corrupted when we return from
+               // GetAdaptersAddresses(). The bug seems to occur when iaa->Length <
+               // sizeof(IP_ADAPTER_ADDRESSES), so when that happens, we'll manually
+               // modify iaa to have the correct values.
+
+               if ( iaa->Length >= sizeof( IP_ADAPTER_ADDRESSES ) )
+               {
+                       ipv6IfIndex = iaa->Ipv6IfIndex;
+               }
+               else
+               {
+                       ipv6IfIndex     = 0;
+               }
+
+               // Skip psuedo and tunnel interfaces.
+               
+               if( ( ipv6IfIndex == 1 ) || ( iaa->IfType == IF_TYPE_TUNNEL ) )
+               {
+                       continue;
+               }
+
+               if ( iaa->IfIndex == ifIndex )
+               {
+                       scopeId = iaa->Ipv6IfIndex;
+                       break;
+               }
+       } 
+
+exit:
+
+       if( iaaList )
+       {
+               free( iaaList );
+       }
+
+       return scopeId;
+}
index 4648cffd03492415a05e93eebf50e2873c42e38c..ed11f5a9b6cbd1c2235ae6ecfca8ed515e10d4dc 100644 (file)
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>\r
+<?xml version="1.0" encoding="Windows-1252"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="7.00"\r
+       Version="7.10"\r
        Name="mdnsNSP"\r
        ProjectGUID="{F4F15529-F0EB-402F-8662-73C5797EE557}"\r
        Keyword="Win32Proj">\r
                                Name="VCCustomBuildTool"/>\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../DLL/Debug/dnssd.lib ws2_32.lib iphlpapi.lib"\r
+                               AdditionalDependencies="../DLL/Debug/dnssd.lib ws2_32.lib iphlpapi.lib shlwapi.lib"\r
                                OutputFile="$(OutDir)/mdnsNSP.dll"\r
                                LinkIncremental="2"\r
                                ModuleDefinitionFile="mdnsNSP.def"\r
+                               DelayLoadDLLs="dnssd.dll"\r
                                GenerateDebugInformation="TRUE"\r
                                ProgramDatabaseFile="$(OutDir)/mdnsNSP.pdb"\r
                                SubSystem="2"\r
+                               BaseAddress="0x16080000"\r
                                ImportLibrary="$(OutDir)/mdnsNSP.lib"\r
                                TargetMachine="1"/>\r
                        <Tool\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
+                       OutputDirectory=".\Release"\r
                        IntermediateDirectory=".\Release"\r
                        ConfigurationType="2"\r
                        CharacterSet="2">\r
                                Name="VCCustomBuildTool"/>\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="../DLL/Release/dnssd.lib ws2_32.lib iphlpapi.lib"\r
+                               AdditionalDependencies="../DLL/Release/dnssd.lib ws2_32.lib iphlpapi.lib shlwapi.lib"\r
                                OutputFile="$(OutDir)/mdnsNSP.dll"\r
                                LinkIncremental="1"\r
                                ModuleDefinitionFile="mdnsNSP.def"\r
+                               DelayLoadDLLs="dnssd.dll"\r
                                GenerateDebugInformation="TRUE"\r
                                ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
                                SubSystem="2"\r
                                OptimizeReferences="0"\r
                                EnableCOMDATFolding="0"\r
+                               BaseAddress="0x16080000"\r
                                ImportLibrary="$(IntDir)/mdnsNSP.lib"\r
                                TargetMachine="1"/>\r
                        <Tool\r
                                AdditionalIncludeDirectories="../"/>\r
                        <Tool\r
                                Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
                        <Tool\r
                                Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
                </Configuration>\r
        </Configurations>\r
+       <References>\r
+       </References>\r
        <Files>\r
                <Filter\r
                        Name="Source Files"\r