--- /dev/null
+/*
+ * 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 );
+ }
+}
--- /dev/null
+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
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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"
--- /dev/null
+/*
+ * 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>
-<?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
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
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
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
#define kTXTRecordKeyPath "path"
+// IE Icon resource
+
+#define kIEIconResource 32529
+
#if 0
#pragma mark == Prototypes ==
{
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
+ HINSTANCE module = NULL;
OSStatus err;
CRect rect;
CBitmap bitmap;
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 );
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 )
{
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
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
STDAPI DllRegisterServer( void )
{
- HRESULT err;
- BOOL ok;
- CString s;
+ IRunnableTask * pTask = NULL;
+ HRESULT err;
+ BOOL ok;
+ CString s;
dlog( kDebugLevelTrace, "DllRegisterServer\n" );
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 );
}
-<?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
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
-<?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
<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
<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
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
<Tool\r
Name="VCPreLinkEventTool"\r
Description="Building Output Directories"\r
- CommandLine="if not exist Release\Root mkdir Release\Root\r
-if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files"\r
-if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj" mkdir "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj""/>\r
+ CommandLine="if not exist Release mkdir Release\r
+if not exist "Release\ExplorerPlugin.Resources" mkdir "Release\ExplorerPlugin.Resources"\r
+if not exist "Release\ExplorerPlugin.Resources\en.lproj" mkdir "Release\ExplorerPlugin.Resources\en.lproj"\r
+"/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="NDEBUG"\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="Header Files"\r
\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
-<?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
<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
<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
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
<Tool\r
Name="VCPreLinkEventTool"\r
Description="Building Output Directories"\r
- CommandLine="if not exist Release\Root mkdir Release\Root\r
-if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files"\r
-if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources""/>\r
+ CommandLine="if not exist Release mkdir Release\r
+if not exist "Release\ExplorerPlugin.Resources" mkdir "Release\ExplorerPlugin.Resources"\r
+"/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="NDEBUG"\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="Header Files"\r
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
<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
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>.
#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
#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
--- /dev/null
+<?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
############################################################################
-JDK = \javasdk
+JDK = $(JAVA_HOME)
CP = copy
RM = del /Q
# @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
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
#include "stdafx.h"
#include "PrinterSetupWizardApp.h"
+#include "PrinterSetupWizardSheet.h"
#include "FirstPage.h"
#include <DebugServices.h>
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()
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
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnSetActive();
+ virtual BOOL OnKillActive();
DECLARE_MESSAGE_MAP()
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
return CPropertyPage::OnSetActive();
}
+
+
+BOOL
+CFourthPage::OnKillActive()
+{
+ CPrinterSetupWizardSheet * psheet;
+
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ psheet->SetLastPage(this);
+
+exit:
+
+ return CPropertyPage::OnKillActive();
+}
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
enum { IDD = IDD_FOURTH_PAGE };
virtual BOOL OnSetActive();
+ virtual BOOL OnKillActive();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
-<?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
<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
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
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
// 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 );
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
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
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
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
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
\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
-<?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
<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
<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
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
<Tool\r
Name="VCPreLinkEventTool"\r
Description="Building Output Directories"\r
- CommandLine="if not exist Release\Root mkdir Release\Root\r
-if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files"\r
-if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj" mkdir "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj""/>\r
+ CommandLine="if not exist Release mkdir Release\r
+if not exist "Release\PrinterWizard.Resources" mkdir "Release\PrinterWizard.Resources"\r
+if not exist "Release\PrinterWizard.Resources\en.lproj" mkdir "Release\PrinterWizard.Resources\en.lproj"\r
+"/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="NDEBUG"\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="Header Files"\r
-<?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
<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
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
<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
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
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
<Tool\r
Name="VCPreLinkEventTool"\r
Description="Building Output Directories"\r
- CommandLine="if not exist Release\Root mkdir Release\Root\r
-if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files"\r
-if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources"\r
-if not exist "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources""/>\r
+ CommandLine="if not exist Release mkdir Release\r
+if not exist "Release\PrinterWizard.Resources" mkdir "Release\PrinterWizard.Resources"\r
+"/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="NDEBUG"\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="Header Files"\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="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
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"
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);
{
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 );
}
}
//
// if the driver isn't installed, then install it
//
+
if ( !printer->driverInstalled )
{
DWORD dwResult;
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
//
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 );
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"";
{
DEBUG_UNUSED( service );
+ Queue * q = service->SelectedQueue();
HANDLE hPrinter = NULL;
PRINTER_INFO_2 pInfo;
OSStatus err;
+
+ check( q );
//
// add the printer
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;
CPrinterSetupWizardSheet * self;
Service * service;
Queue * q;
- uint32_t qpriority = kDefaultPriority;
- CString qname;
int idx;
OSStatus err;
//
service->portNumber = ntohs(inPort);
- //
- // parse the text record.
- //
-
- err = self->ParseTextRecord( service, inTXTSize, inTXT, qname, qpriority );
- require_noerr( err, exit );
-
if ( service->qtotal == 1 )
{
//
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 );
//
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 );
//
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())
{
{
// Make sure that the active page is page 2
- check( GetActivePage() == &m_pgSecond );
+ require_quiet( GetActivePage() == &m_pgSecond, exit );
if ( !--service->printer->resolving )
{
m_pgSecond.OnResolveService( service );
}
+
+exit:
+
+ return;
}
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;
// <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 )
{
memcpy( buf, val, len );
buf[len] = '\0';
- err = UTF8StringToStringObject( buf, qname );
+ err = UTF8StringToStringObject( buf, q->name );
require_noerr( err, exit );
}
memcpy( buf, val, len );
buf[len] = '\0';
- err = UTF8StringToStringObject( buf, service->pdl );
+ err = UTF8StringToStringObject( buf, q->pdl );
require_noerr( err, exit );
}
memcpy( buf, val, len );
buf[len] = '\0';
- err = UTF8StringToStringObject( buf, service->usb_MFG );
+ err = UTF8StringToStringObject( buf, q->usb_MFG );
require_noerr( err, exit );
}
memcpy( buf, val, len );
buf[len] = '\0';
- err = UTF8StringToStringObject( buf, service->usb_MDL );
+ err = UTF8StringToStringObject( buf, q->usb_MDL );
require_noerr( err, exit );
}
memcpy( buf, val, len );
buf[len] = '\0';
- err = UTF8StringToStringObject( buf, service->description );
+ err = UTF8StringToStringObject( buf, q->description );
require_noerr( err, exit );
}
memcpy( buf, val, len );
buf[len] = '\0';
- err = UTF8StringToStringObject( buf, service->product );
+ err = UTF8StringToStringObject( buf, q->product );
require_noerr( err, exit );
}
memcpy( buf, val, len );
buf[len] = '\0';
- err = UTF8StringToStringObject( buf, service->location );
+ err = UTF8StringToStringObject( buf, q->location );
require_noerr( err, exit );
}
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;
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()
CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
virtual ~CPrinterSetupWizardSheet();
+ CPropertyPage*
+ GetLastPage();
+
+ void
+ SetLastPage(CPropertyPage * page );
+
void
SetSelectedPrinter(Printer * printer);
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();
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;
DNSServiceRef m_lprBrowser;
DNSServiceRef m_ippBrowser;
DNSServiceRef m_resolver;
+
+ CPropertyPage * m_lastPage;
};
}
+inline CPropertyPage*
+CPrinterSetupWizardSheet::GetLastPage()
+{
+ return m_lastPage;
+}
+
+
+inline void
+CPrinterSetupWizardSheet::SetLastPage(CPropertyPage * lastPage)
+{
+ m_lastPage = lastPage;
+}
+
+
// Service Types
#define kPDLServiceType "_pdl-datastream._tcp."
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
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
//
// disable the printer information box
//
SetPrinterInformationState( FALSE );
+ m_descriptionField.SetWindowText( L"" );
+ m_locationField.SetWindowText( L"" );
exit:
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()
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
{
CPrinterSetupWizardSheet * psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
-
+
check( service );
+ Queue * q = service->SelectedQueue();
+
+ check( q );
+
+
//
// and set it to selected
//
//
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
{
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 );
}
+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 )
{
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.
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(
CStatic m_descriptionField;\r
CStatic m_locationLabel;\r
CStatic m_locationField;\r
+
+ bool m_gotChoice;
};
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
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 );
//
// ----------------------------------------------------
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;
check( manufacturer != NULL );
check( model != NULL );
- PopulateUI( manufacturers );
-
//
// select the manufacturer
//
}
+void
+CThirdPage::SelectMatch(Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer * manufacturer, Model * model)
+{
+ PopulateUI( manufacturers );
+
+ SelectMatch( printer, service, manufacturer, model );
+}
+
+
// --------------------------------------------------------
// CopyPrinterSettings
//
// 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;
// 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;
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 ) );
}
//
//
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;
}
}
{
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
{
// 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 )
// 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);
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 );
//
// 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:
}
+BOOL
+CThirdPage::OnKillActive()
+{
+ CPrinterSetupWizardSheet * psheet;
+
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ psheet->SetLastPage(this);
+
+exit:
+
+ return CPropertyPage::OnKillActive();
+}
+
+
// -------------------------------------------------------
// PopulateUI
//
nIndex = m_manufacturerListCtrl.InsertItem(0, manufacturer->name);
m_manufacturerListCtrl.SetItemData(nIndex, (DWORD_PTR) manufacturer);
+
+ m_manufacturerListCtrl.SetColumnWidth( 0, LVSCW_AUTOSIZE_USEHEADER );
}
return 0;
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);
printer = psheet->GetSelectedPrinter();
require_quiet( printer, exit );
- printer->deflt = m_defaultPrinterCtrl.GetState() ? true : false;
+ printer->deflt = ( m_defaultPrinterCtrl.GetCheck() == BST_CHECKED ) ? true : false;
exit:
CPrinterSetupWizardSheet * psheet;
Printer * printer;
Service * service;
+ Manufacturers manufacturers;
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_FILEMUSTEXIST, L"Setup Information (*.inf)|*.inf||", this);
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:
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
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnSetActive();
+ virtual BOOL OnKillActive();
DECLARE_MESSAGE_MAP()
//
// 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
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;
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
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
//
~Service();
+ Queue*
+ SelectedQueue();
+
void
EmptyQueues();
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;
CString name;
uint32_t priority;
+ CString pdl;
+ CString usb_MFG;
+ CString usb_MDL;
+ CString description;
+ CString location;
+ CString product;
};
inline
Printer::Printer()
+ :
+ isSharedFromOSX( false )
{
}
EmptyQueues();
}
+ inline Queue*
+ Service::SelectedQueue()
+ {
+ return queues.front();
+ }
+
inline void
Service::EmptyQueues()
{
{
Model * model = *it;
- if ( model->name = name )
+ if ( model->name == name )
{
return model;
}
/*\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
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
// 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
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)
*/
#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
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];
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
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)
}
}
-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
}
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";
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);
}
//*************************************************************************************************************
}
#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;
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,
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)
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"))
{
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;
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;
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)
--- /dev/null
+<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
-/*
+/* -*- 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
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))
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)
{
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;
}
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
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
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;
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);
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
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;
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);
}
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);
}
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;
}
}
}
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
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
#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)
#define LogOperation debugf
#endif
+#define ForceAlerts 0
+
#ifdef __cplusplus
}
#endif
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
#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
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"
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);
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)
{
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;
* 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
// 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); }
#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
////////////////////////////////////////////////////////////////////////
{
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;
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 */
}
{
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;
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
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
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
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;
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
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,
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);
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)
}
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)
{
// 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);
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, "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)
}
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);
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);
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
}
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;
//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)
&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)
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
}
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;
}
//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";
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";
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";
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;
}
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();
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
}
require_noerr( err, AuthSetFailed);
- (void) AttemptAcquireAuthority( false);
-
AuthSetFailed:
GetStrFailed:
NewAuthFailed:
Boolean CurrentlyAuthorized(void)
{
- OSStatus err;
-
- err = AuthorizationCopyRights(gAuthRef, &gAuthSet, (AuthorizationEnvironment*) NULL,
- (AuthorizationFlags) 0, (AuthorizationRights**) NULL);
-
+ OSStatus err = AttemptAcquireAuthority(true);
return err == noErr;
}
<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>
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
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;
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;
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);
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.
#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")
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.
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)
{
/* 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
*/
{
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;
--- /dev/null
+#!/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);
+}
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
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)
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;
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;
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);
}
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; }
DNSServiceResolver *l;
DNSServiceRegistration *r;
NetworkInterfaceInfoOSX *i;
+ DNSServer *s;
LogMsgIdent(mDNSResponderVersionString, "---- BEGIN STATE LOG ----");
&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 ----");
}
* 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
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;
}
#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);
}
}
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)
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
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; }
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);
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)
{
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;
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
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);
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 = (
# 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
#
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
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
# 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
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
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
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
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
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
#############################################################################
-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:
# 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
#############################################################################
@$(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"
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)
$(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
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
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.
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 \
$(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) $<
# The following target builds documentation for the Java wrappers.
-JavaDoc: setup Java
+JavaDoc: Java setup
$(JAVADOC) $(JAVASRC)/*.java -classpath $(OBJDIR) -d $(BUILDDIR) -public
#############################################################################
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
$(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
#############################################################################
$(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 $@ $<
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
#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
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);
}
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);
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++;
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++)
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
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.
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)
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
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);
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.
- 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
-------
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.
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
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.
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",
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
#include <syslog.h>
#include <string.h>
#include <sys/time.h>
+#include <sys/resource.h>
#include <time.h>
#include <errno.h>
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
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
// 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*
DaemonInfo *d;
} TCPRequestArgs;
+// args passed to UpdateAnswerList thread as void*
+typedef struct
+ {
+ DaemonInfo *d;
+ AnswerListElem *a;
+ } UpdateAnswerListArgs;
+
//
// Global Variables
//
// 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);
}
// 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;
// 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;
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; }
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; }
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
//
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)
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))
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:
// 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;
}
//
// 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;
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);
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);
}
//
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;
}
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];
}
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");
}
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);
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; }
}
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)
cr = NewAnswers;
NewAnswers = NewAnswers->next;
free(cr);
- }
+ }
+
+ return NULL;
}
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));
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;
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;
}
}
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++)
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++)
{
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)
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;
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
}
cleanup:
+ close(req->sd);
free(req);
if (in) free(in);
if (out) free(out);
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...");
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;
}
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);
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);
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
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);
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);
#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;
}
// 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"); }
#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;
}
// 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));
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); }
// 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);
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
#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
#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;
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;
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 */
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);
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
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;
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;
#ifdef NOT_HAVE_DAEMON
#include <fcntl.h>
#include <sys/stat.h>
+#include <sys/signal.h>
+
int daemon(int nochdir, int noclose)
{
switch (fork())
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
#include <net/if.h>
#include <netinet/in.h>
+#ifdef HAVE_LINUX
+#include <linux/socket.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
#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 ? \
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): */
DNSServiceErrorType errcode;
DNSServiceRef sdref;
ns_type_t rrtype;
+ nss_status status;
if (MDNS_VERBOSE)
syslog (LOG_DEBUG,
return set_err_mdns_failed (result);
}
- return handle_events (sdref, result, fullname);
+ status = handle_events (sdref, result, fullname);
+ DNSServiceRefDeallocate (sdref);
+ return status;
}
{
DNSServiceErrorType errcode;
DNSServiceRef sdref;
+ nss_status status;
if (MDNS_VERBOSE)
syslog (LOG_DEBUG,
return set_err_mdns_failed (result);
}
- return handle_events (sdref, result, addr_str);
+ status = handle_events (sdref, result, addr_str);
+ DNSServiceRefDeallocate (sdref);
+ return status;
}
-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
{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
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
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();
{
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
// 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
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.
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();
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
}
-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)
{
{
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);
}
* 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
#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
* 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):
.\" @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
.\"
.Sh HISTORY
The
.Nm
-command first appeared in Mac OS X 10.3 (Panther).
+command first appeared in Mac OS X 10.4 (Tiger).
#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
* 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()
#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
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)"
char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1];
};
-void TXTRecordCreate
+void DNSSD_API TXTRecordCreate
(
TXTRecordRef *txtRecord,
uint16_t bufferLen,
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,
return(kDNSServiceErr_NoError);
}
-DNSServiceErrorType TXTRecordRemoveValue
+DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
(
TXTRecordRef *txtRecord,
const char *key
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); }
/*********************************************************************************************
*
*
*********************************************************************************************/
-int TXTRecordContainsKey
+int DNSSD_API TXTRecordContainsKey
(
uint16_t txtLen,
const void *txtRecord,
return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0);
}
-const void * TXTRecordGetValuePtr
+const void * DNSSD_API TXTRecordGetValuePtr
(
uint16_t txtLen,
const void *txtRecord,
return (item + 1 + keylen + 1);
}
-uint16_t TXTRecordGetCount
+uint16_t DNSSD_API TXTRecordGetCount
(
uint16_t txtLen,
const void *txtRecord
return((p>e) ? (uint16_t)0 : count);
}
-DNSServiceErrorType TXTRecordGetItemAtIndex
+DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
(
uint16_t txtLen,
const void *txtRecord,
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
#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>
#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
char *msg = NULL;
ipc_msg_hdr *hdr;
int datalen;
+#if !defined(USE_TCP_LOOPBACK)
char ctrl_path[256];
+#endif
if (!reuse_socket)
{
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));
// 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
{
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;
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
# 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*
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
#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>
#endif // LOCAL_PEERCRED
#endif //__MACOSX__
+#if defined(MDNS_LAZY_REGISTER_SEARCH_DOMAINS)
+extern mStatus dDNS_RegisterSearchDomains( mDNS * const m );
+#endif
+
// Types and Data Structures
// ----------------------------------------------------------------------
#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
}
}
-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
debugf("Unable to remove %s", MDNS_UDS_SERVERPATH);
#endif
+ if (PID_FILE[0]) unlink(PID_FILE);
+
return 0;
}
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;
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;
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))
{
}
}
-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)
}
}
-static void connect_callback(void *info)
+mDNSlocal void connect_callback(void *info)
{
dnssd_sock_t sd;
dnssd_socklen_t len;
}
// handler
-static void request_callback(void *info)
+mDNSlocal void request_callback(void *info)
{
request_state *rstate = info;
transfer_state result;
// 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;
return;
}
-static void handle_resolve_request(request_state *rstate)
+mDNSlocal void handle_resolve_request(request_state *rstate)
{
DNSServiceFlags flags;
uint32_t interfaceIndex;
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;
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];
}
// 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];
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));
// 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)
{
// 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)
{
}
#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;
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;
return err;
}
-static void handle_browse_request(request_state *request)
+mDNSlocal void handle_browse_request(request_state *request)
{
DNSServiceFlags flags;
uint32_t interfaceIndex;
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; }
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;
return;
}
-static void browse_termination_callback(void *context)
+mDNSlocal void browse_termination_callback(void *context)
{
browser_info_t *info = context;
browser_t *ptr;
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;
}
// service registration
-static void handle_regservice_request(request_state *request)
+mDNSlocal void handle_regservice_request(request_state *request)
{
DNSServiceFlags flags;
uint32_t ifi;
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
// 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;
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));
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;
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;
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;
return result;
}
-static mStatus handle_update_request(request_state *rstate)
+mDNSlocal mStatus handle_update_request(request_state *rstate)
{
uint16_t rdlen;
char *ptr, *rdata;
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;
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;
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;
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;
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;
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;
}
}
-static mStatus handle_removerecord_request(request_state *rstate)
+mDNSlocal mStatus handle_removerecord_request(request_state *rstate)
{
mStatus err = mStatus_BadReferenceErr;
char *ptr;
}
// 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;
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;
}
// domain enumeration
-static void handle_enum_request(request_state *rstate)
+mDNSlocal void handle_enum_request(request_state *rstate)
{
DNSServiceFlags flags;
uint32_t ifi;
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;
}
}
-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;
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
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);
return reply;
}
-static void enum_termination_callback(void *context)
+mDNSlocal void enum_termination_callback(void *context)
{
enum_termination_t *t = context;
mDNS *coredata = gmDNS;
freeL("enum_termination_callback", t);
}
-static void handle_reconfirm_request(request_state *rstate)
+mDNSlocal void handle_reconfirm_request(request_state *rstate)
{
AuthRecord *rr;
}
// 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;
// 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;
// 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;
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;
}
// 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;
// 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;
return t_error;
}
-static int send_msg(reply_state *rs)
+mDNSlocal int send_msg(reply_state *rs)
{
ssize_t nwriten;
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");
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;
}
// 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;
// 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;
return 0;
}
-static void abort_request(request_state *rs)
+mDNSlocal void abort_request(request_state *rs)
{
reply_state *rep, *ptr;
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;
}
}
-static void unlink_request(request_state *rs)
+mDNSlocal void unlink_request(request_state *rs)
{
request_state *ptr;
}
//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()));
}
// 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;
}
-static uint32_t dnssd_htonl(uint32_t l)
+mDNSlocal uint32_t dnssd_htonl(uint32_t l)
{
uint32_t ret;
char * data;
#if defined(_WIN32)
-static char * win32_strerror(int inErrorCode)
+mDNSlocal char * win32_strerror(int inErrorCode)
{
static char buffer[1024];
DWORD n;
/*
- * 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>
#include <sys/socket.h>
#include <unistd.h>
-#include "vxWorks.h"
#include "ifLib.h"
#include "inetLib.h"
#include "pipeDrv.h"
#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
// 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
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" {
// 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
//===========================================================================================================================
//===========================================================================================================================
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
//===========================================================================================================================
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 );
}
{
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" );
}
//===========================================================================================================================
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 );
}
{
(void)sd; // Unused
(void)buf; // Unused
- (void)buflen; // Unused
+ (void)buflen; // Unused
return(0);
}
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
}
//===========================================================================================================================
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 );
mDNSexport void mDNSPlatformMemFree( void *inMem )
{
check( inMem );
-
- free( inMem );
+ if( inMem ) free( inMem );
}
//===========================================================================================================================
// mDNSPlatformRandomSeed
//===========================================================================================================================
-mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
+mDNSexport mDNSu32 mDNSPlatformRandomSeed( void )
{
return( tickGet() );
}
// mDNSPlatformTimeInit
//===========================================================================================================================
-mDNSexport mStatus mDNSPlatformTimeInit( void )
+mDNSexport mStatus mDNSPlatformTimeInit( void )
{
// No special setup is required on VxWorks -- we just use tickGet().
+
return( mStatus_NoError );
}
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
//===========================================================================================================================
#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 );
// 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 );
}
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 );
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 );
}
{
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 );
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 );
}
//===========================================================================================================================
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.
// 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
#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
/*
- * 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" {
// 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__
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
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 );
END
END
-
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
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
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
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
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.",
-<?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
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
:
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 );
}
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;
}
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
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 );
}
CSecondPage::~CSecondPage()
{
+ if ( m_setupKey )
+ {
+ RegCloseKey( m_setupKey );
+ m_setupKey = NULL;
+ }
}
CSecondPage::OnSetActive()
{
CConfigPropertySheet * psheet;
- HKEY key = NULL;
DWORD dwSize;
DWORD enabled;
DWORD err;
// 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;
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 );
}
}
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;
}
string = (TCHAR*) malloc( stringLen );
require_action( string, exit, err = kUnknownErr );
+ *string = '\0';
err = RegQueryValueEx( key, valueName, 0, NULL, (LPBYTE) string, &stringLen );
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
CButton m_advertiseServicesButton;
CButton m_sharedSecretButton;
BOOL m_modified;
+ HKEY m_setupKey;
public:
afx_msg void OnCbnSelChange();
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
CSharedSecret::CSharedSecret(CWnd* pParent /*=NULL*/)
: CDialog(CSharedSecret::IDD, pParent)
+ , m_key(_T(""))
, m_secret(_T(""))
- , m_secretName(_T(""))
{
}
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 );
}
//---------------------------------------------------------------------------------------------------------------------------
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
// 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 );
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
enum { IDD = IDR_SECRET };
void
- Commit();
+ Commit( CString zone );
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
+
+ CString m_key;
CString m_secret;
- CString m_secretName;
};
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
#include <WinServices.h>
-#define MAX_KEY_LENGTH 255\r
+#define MAX_KEY_LENGTH 255
IMPLEMENT_DYNCREATE(CThirdPage, CPropertyPage)
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()
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();
// 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:
return b;
}
-\r
- \r
+
+
//---------------------------------------------------------------------------------------------------------------------------
// CThirdPage::OnOK
{
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
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();
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()
+
#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
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
// 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
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)
#pragma once
+#if !defined(_WSPIAPI_COUNTOF)
+# define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#endif
+
#using <mscorlib.dll>
#using <System.dll>
-<?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
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.
*/
#include <windows.h>
+#include <DebugServices.h>
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;
+}
-<?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
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
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
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
--- /dev/null
+<?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
# @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
#
COREDIR = ..\..\mDNSCore
SHAREDDIR = ..\..\mDNSShared
-JDK = \javasdk
+JDK = $(JAVA_HOME)
CC = cl
RC = rc
-<?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
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
#if defined(UNICODE)
+# define kServiceParametersNode L"SOFTWARE\\Apple Computer, Inc.\\Bonjour"
# define kServiceName L"Bonjour Service"
# define kServiceDynDNSBrowseDomains L"BrowseDomains"
# define kServiceDynDNSHostNames L"HostNames"
# else
+# define kServiceParametersNode "SOFTWARE\\Apple Computer, Inc.\\Bonjour"
# define kServiceName "Bonjour Service"
# define kServiceDynDNSBrowseDomains "BrowseDomains"
# define kServiceDynDNSHostNames "HostNames"
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
*/
-#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>
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
#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];
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)
DEBUG_LOCAL HANDLE gStopEvent = NULL;
DEBUG_LOCAL CRITICAL_SECTION gEventSourceLock;
DEBUG_LOCAL GenLinkedList gEventSources;
+DEBUG_LOCAL BOOL gRetryFirewall = FALSE;
#if 0
// 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 );
DWORD value;
DWORD valueLen = sizeof(DWORD);
DWORD type;
- LPCTSTR s;
OSStatus err;
HKEY key;
//
// 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 );
//
DWORD value;
DWORD valueLen;
DWORD type;
- LPCTSTR s;
OSStatus err;
HKEY key;
//
// 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);
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);
{
RegCloseKey( key );
}
+
+ if ( lpService )
+ {
+ free( lpService );
+ }
+
+ if ( sc )
+ {
+ CloseServiceHandle ( sc );
+ }
return( err );
}
{
OSStatus err;
BOOL ok;
- TCHAR desc[ 256 ];
err = ServiceSetupEventLogging();
check_noerr( err );
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;
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.
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:
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;
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 );
}
}
}
//===========================================================================================================================
-// HaveLLRoute
+// HaveRoute
//===========================================================================================================================
static bool
-HaveLLRoute(PMIB_IPFORWARDROW rowExtant)
+HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr )
{
PMIB_IPFORWARDTABLE pIpForwardTable = NULL;
DWORD dwSize = 0;
//
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;
}
+//===========================================================================================================================
+// 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;
//
// 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.
}
//
- // 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;
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 );
IP_ADAPTER_INFO * pAdapterInfo = NULL;
IP_ADAPTER_INFO * pAdapter = NULL;
ULONG bufLen;
+ mDNSBool done = mDNSfalse;
OSStatus err;
//
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:
return( err );
}
-
-<?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
<Tool\r
Name="VCCLCompilerTool"\r
Optimization="0"\r
- AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;"C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include""\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="""";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="""";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;"C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include""\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="""";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="""";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
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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
- }
+++ /dev/null
-<?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>
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
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
#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."
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>
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)
{
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;
{
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;
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);
}
}
{
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);
}
{
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
{
// 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
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;
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)
#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;
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]);
if ( !strcmp( appPathNameA, "" ) )
{
char folder[MAX_PATH];
+ char * ext;
char * app;
GetModuleFileNameA( module, folder, MAX_PATH );
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);
{
wchar_t folder[MAX_PATH];
wchar_t * app;
+ wchar_t * ext;
GetModuleFileNameW( module, folder, MAX_PATH);
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);
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
#include "CommonServices.h"
#include "DebugServices.h"
+#include "VPCDetect.h"
#include "RegNames.h"
#include <dns_sd.h>
#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"
static GUID kWSARecvMsgGUID = WSAID_WSARECVMSG;
#endif
+#define kIPv6IfIndexBase (10000000L)
+
#if 0
#pragma mark == Prototypes ==
// 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
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
// 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 );
"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
{
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;
}
{
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:
mDNSexport mDNSs32 mDNSPlatformUTC( void )
{
- return( -1 );
+ return ( mDNSs32 ) time( NULL );
}
//===========================================================================================================================
*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 );
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
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 );
}
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 );
//===========================================================================================================================
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
// 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 )
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( ¤t->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( ¤t->name, &domain );
+ current->next = NULL;
+
+ if ( !head )
+ {
+ head = current;
+ }
- if ( last )
- {
- last->next = current;
+ if ( last )
+ {
+ last->next = current;
+ }
}
}
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;
exit:
+ if ( pAdapterInfo )
+ {
+ free( pAdapterInfo );
+ }
+
if ( fixedInfo )
{
GlobalFree( fixedInfo );
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;
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 )
{
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
}
}
- 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 )
// 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 )
{
{
mStatus err = 0;
char tempString[ 256 ];
+ DWORD tempStringLen;
domainlabel tempLabel;
+ BOOL ok;
check( 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' ) )
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.
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 )
}
if( p->ifa_flags & IFF_LOOPBACK )
{
- if( !loopback )
+ if( !loopbackv4 )
{
- loopback = p;
+ loopbackv4 = p;
}
continue;
}
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
*next = ifd;
next = &ifd->next;
++inMDNS->p->interfaceCount;
-
-
}
#endif
}
if( p->ifa_flags & IFF_LOOPBACK )
{
- if( !loopback )
+ if( !loopbackv6 )
{
- loopback = p;
+ loopbackv6 = p;
}
continue;
}
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
{
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 )
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';
// 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 )
{
if (!ifd->interfaceInfo.InterfaceID)
{
- p->scopeID = ifd->scopeID;
ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) p;
}
{
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;
}
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);
m = (mDNS *) inParam;
err = ProcessingThreadInitialize( m );
- require_noerr( err, exit );
+ check( !err );
done = 0;
while( !done )
// 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.
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;
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;
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.
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 ) )
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))
}
// 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 );
// 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( ;; )
{
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;
}
{
case AF_INET:
{
- struct sockaddr_in * sa4;
+ struct sockaddr_in * sa4;
require_action( prefixLength <= 32, exit, err = ERROR_INVALID_DATA );
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;
}
// 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!
}
}
+
+//===========================================================================================================================
+// 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
//===========================================================================================================================
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
//===========================================================================================================================
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 );
//===========================================================================================================================
mDNSlocal OSStatus
-ConvertUTF8ToLsaString( const char * input, PLSA_UNICODE_STRING output )
+MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input )
{
int size;
OSStatus err;
//===========================================================================================================================
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;
}
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
HKEY tcpipKey;
HKEY ddnsKey;
mStatus initStatus;
+ mDNSBool registeredLoopback4;
SocketRef interfaceListChangedSocket;
int interfaceCount;
mDNSInterfaceData * interfaceList;
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
*/
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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
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
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,
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
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 -
{
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:
dlog( kDebugLevelNotice, "%s: unknown reason code (%d)\n", __ROUTINE__, inReason );
break;
}
+
return( TRUE );
}
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:
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() );
( ( 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();
LPDWORD ioSize,
LPWSAQUERYSETW outResults )
{
+ BOOL data4;
+ BOOL data6;
OSStatus err;
QueryRef obj;
DWORD waitResult;
dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
+ data4 = FALSE;
+ data6 = FALSE;
obj = NULL;
NSPLock();
err = QueryRetain( (QueryRef) inLookup );
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 );
QueryCopyQuerySetTo( obj, obj->querySet, obj->querySetFlags, outResults );
outResults->dwOutputFlags = RESULT_IS_ADDED;
- obj->addrValid = false;
-
+ obj->addr4Valid = false;
+ obj->addr6Valid = false;
+
exit:
if( obj )
{
char name[ kDNSServiceMaxDomainName ];
int n;
QueryRef * p;
-
+ SOCKET s4;
+ SOCKET s6;
+
obj = NULL;
check( inQuerySet );
check( inQuerySet->lpszServiceInstanceName );
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.
// 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.
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 )
}
//===========================================================================================================================
-// QueryRecordCallback
+// QueryRecordCallback4
//===========================================================================================================================
DEBUG_LOCAL void CALLBACK_COMPAT
- QueryRecordCallback(
+ QueryRecordCallback4(
DNSServiceRef inRef,
DNSServiceFlags inFlags,
uint32_t inInterfaceIndex,
// 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();
#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
//
return( err );
}
+
+
//===========================================================================================================================
// QueryCopyQuerySetTo
//
}
n = inQuerySet->dwNumberOfProtocols;
+
if( n > 0 )
{
check( inQuerySet->lpafpProtocols );
// 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
{
// 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 );
*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 );
}
// 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
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;
+}
-<?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