Change History (most recent first):
$Log: DNSServiceBrowser.m,v $
+Revision 1.30 2005/01/27 17:46:16 cheshire
+Added comment
+
Revision 1.29 2004/06/04 20:58:36 cheshire
Move DNSServiceBrowser from mDNSMacOSX directory to Clients directory
/* Remove service from runloop, deallocate service and associated resources */
{
if ( fSocketRef != nil) {
- CFSocketInvalidate( fSocketRef);
+ CFSocketInvalidate( fSocketRef); // Note: Also closes the underlying socket
CFRelease( fSocketRef);
}
#include "stdafx.h"
#include "ExplorerPlugin.h"
#include "About.h"
+#include <DebugServices.h>
// CAbout dialog
// CAbout message handlers
+BOOL
+CAbout::OnInitDialog()
+{
+ BOOL b = CDialog::OnInitDialog();
+
+ CStatic * control = (CStatic*) GetDlgItem( IDC_ABOUT_BACKGROUND );
+ check( control );
+
+ if ( control )
+ {
+ control->SetBitmap( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_ABOUT ) ) );
+ }
+
+ return b;
+}
+
+
HBRUSH CAbout::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
switch (nCtlColor)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+ virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
public:
CStatic m_componentCtrl;
Change History (most recent first):
$Log: ExplorerBarWindow.cpp,v $
+Revision 1.15 2005/01/27 22:38:27 shersche
+add About item to tree list
+
+Revision 1.14 2005/01/25 17:55:39 shersche
+<rdar://problem/3911084> Get bitmaps from non-localizable resource module
+Bug #: 3911084
+
+Revision 1.13 2005/01/06 21:13:09 shersche
+<rdar://problem/3796779> Handle kDNSServiceErr_Firewall return codes
+Bug #: 3796779
+
Revision 1.12 2004/10/26 00:56:03 cheshire
Use "#if 0" instead of commenting out code
#include "Resource.h"
#include "ExplorerBarWindow.h"
+#include "ExplorerPlugin.h"
// MFC Debugging
#define kTXTRecordKeyPath "path"
+
#if 0
#pragma mark == Prototypes ==
#endif
mTree.Create( WS_TABSTOP | WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_NOHSCROLL , rect, this,
IDC_EXPLORER_TREE );
-
+ s.LoadString( IDS_ABOUT );
+ m_about = mTree.InsertItem( s, 0, 0 );
+
ServiceHandlerEntry * e;
// Web Site Handler
mServiceHandlers.Add( e );
s.LoadString( IDS_WEB_SITES );
- e->treeItem = mTree.InsertItem( s, 0, 0 );
+ e->treeItem = mTree.InsertItem( s, 1, 1 );
mTree.Expand( e->treeItem, TVE_EXPAND );
err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
mServiceHandlers.Add( e );
s.LoadString( IDS_FTP_SITES );
- e->treeItem = mTree.InsertItem( s, 0, 0 );
+ e->treeItem = mTree.InsertItem( s, 1, 1 );
mTree.Expand( e->treeItem, TVE_EXPAND );
err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
m_serviceRefs.push_back(e->ref);
- m_imageList.Create(16, 16, ILC_COLORDDB, 1, 0);
- bitmap.LoadBitmap(IDB_LOGO);
- m_imageList.Add(&bitmap, (CBitmap*) NULL);
+ m_imageList.Create( 16, 16, ILC_COLORDDB, 2, 0);
+ bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_GLOBE ) ) );
+ m_imageList.Add( &bitmap, (CBitmap*) NULL );
+ bitmap.Detach();
+ bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_LOGO ) ) );
+ m_imageList.Add( &bitmap, (CBitmap*) NULL );
mTree.SetImageList(&m_imageList, TVSIL_NORMAL);
exit:
// Cannot talk to the mDNSResponder service. Show the error message and exit (with kNoErr so they can see it).
- if ( err != kNoErr )
+ if ( err )
{
- s.LoadString( IDS_MDNSRESPONDER_NOT_AVAILABLE );
+ if ( err == kDNSServiceErr_Firewall )
+ {
+ s.LoadString( IDS_FIREWALL );
+ }
+ else
+ {
+ s.LoadString( IDS_MDNSRESPONDER_NOT_AVAILABLE );
+ }
+
mTree.DeleteAllItems();
mTree.InsertItem( s, 0, 0, TVI_ROOT, TVI_LAST );
+
err = kNoErr;
}
item = mTree.GetSelectedItem();
require( item, exit );
- service = reinterpret_cast < ServiceInfo * > ( mTree.GetItemData( item ) );
- require_quiet( service, exit );
+ // Tell Internet Explorer to go to the URL if it's about item
- err = StartResolve( service );
- require_noerr( err, exit );
+ if ( item == m_about )
+ {
+ CString url;
+
+ check( mOwner );
+
+ url.LoadString( IDS_ABOUT_URL );
+ mOwner->GoToURL( url );
+ }
+ else
+ {
+ service = reinterpret_cast < ServiceInfo * > ( mTree.GetItemData( item ) );
+ require_quiet( service, exit );
+
+ err = StartResolve( service );
+ require_noerr( err, exit );
+ }
exit:
*outResult = 0;
afterItem = ( index > 0 ) ? handler->array[ index - 1 ]->item : TVI_FIRST;
handler->array.InsertAt( index, service );
- service->item = mTree.InsertItem( service->displayName, handler->treeItem, afterItem );
+ service->item = mTree.InsertItem( service->displayName, 1, 1, handler->treeItem, afterItem );
mTree.SetItemData( service->item, (DWORD_PTR) service );
// Make sure the item is visible if this is the first time a service was added.
Change History (most recent first):
$Log: ExplorerBarWindow.h,v $
+Revision 1.6 2005/01/27 22:27:03 shersche
+Add m_about member for "About Rendezvous" tree item
+
Revision 1.5 2004/07/26 05:47:31 shersche
use TXTRecord APIs, fix bug in locating service to be removed
typedef std::list< DNSServiceRef > ServiceRefList;
+ HTREEITEM m_about;
ServiceRefList m_serviceRefs;
CImageList m_imageList;
};
Change History (most recent first):
$Log: ExplorerPlugin.cpp,v $
+Revision 1.6 2005/01/25 17:56:45 shersche
+<rdar://problem/3911084> Load resource DLLs, get icons and bitmaps from resource DLLs
+Bug #: 3911084
+
Revision 1.5 2004/09/15 10:33:54 shersche
<rdar://problem/3721611> Install XP toolbar button (8 bit mask) if running on XP platform, otherwise install 1 bit mask toolbar button
Bug #: 3721611
#include "ClassFactory.h"
#include "Resource.h"
+#include "loclibrary.h"
+
// MFC Debugging
#ifdef _DEBUG
DEBUG_LOCAL OSStatus RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName );
DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister );
+// Stash away pointers to our resource DLLs
+
+static HINSTANCE g_nonLocalizedResources = NULL;
+static CString g_nonLocalizedResourcesName;
+static HINSTANCE g_localizedResources = NULL;
+
+HINSTANCE
+GetNonLocalizedResources()
+{
+ return g_nonLocalizedResources;
+}
+
+HINSTANCE
+GetLocalizedResources()
+{
+ return g_localizedResources;
+}
+
#if 0
#pragma mark == Globals ==
#endif
DEBUG_LOCAL OSStatus MFCDLLProcessAttach( HINSTANCE inInstance )
{
+ wchar_t resource[MAX_PATH];
OSStatus err;
_AFX_THREAD_STATE * threadState;
AFX_MODULE_STATE * previousModuleState;
BOOL ok;
+ int res;
CWinApp * app;
app = NULL;
app = AfxGetApp();
require_action( ok, exit, err = kNotInitializedErr );
+ // Before we load the resources, let's load the error string
+
+ // errorMessage.LoadString( IDS_REINSTALL );
+ // errorCaption.LoadString( IDS_REINSTALL_CAPTION );
+
+ // Load Resources
+
+ res = PathForResource( inInstance, L"ExplorerPluginResources.dll", resource, MAX_PATH );
+
+ err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
+ require_noerr( err, exit );
+
+ g_nonLocalizedResources = LoadLibrary( resource );
+ translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ g_nonLocalizedResourcesName = resource;
+
+ res = PathForResource( inInstance, L"ExplorerPluginLocalized.dll", resource, MAX_PATH );
+ err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
+ require_noerr( err, exit );
+
+ g_localizedResources = LoadLibrary( resource );
+ translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ AfxSetResourceHandle( g_localizedResources );
+
ok = app->InitInstance();
require_action( ok, exit, err = kUnknownErr );
( versionInfo.dwMajorVersion == 5 ) &&
( versionInfo.dwMinorVersion >= 1 ) )
{
- wsprintf( data, L"%s,%d", moduleName, IDI_BUTTON_XP );
+ wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_XP );
size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
RegSetValueEx( key, L"Icon", 0, REG_SZ, (LPBYTE) data, size);
- wsprintf( data, L"%s,%d", moduleName, IDI_BUTTON_XP );
+ wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_XP );
size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
RegSetValueEx( key, L"HotIcon", 0, REG_SZ, (LPBYTE) data, size);
}
else
{
- wsprintf( data, L"%s,%d", moduleName, IDI_BUTTON_2K );
+ wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_2K );
size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
RegSetValueEx( key, L"Icon", 0, REG_SZ, (LPBYTE) data, size);
- wsprintf( data, L"%s,%d", moduleName, IDI_BUTTON_2K );
+ wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_2K );
size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
RegSetValueEx( key, L"HotIcon", 0, REG_SZ, (LPBYTE) data, size);
}
Change History (most recent first):
$Log: ExplorerPlugin.h,v $
+Revision 1.3 2005/01/25 18:35:38 shersche
+Declare APIs for obtaining handles to resource modules
+
Revision 1.2 2004/07/13 21:24:21 rpantos
Fix for <rdar://problem/3701120>.
extern HINSTANCE gInstance;
extern int gDLLRefCount;
+extern HINSTANCE GetNonLocalizedResources();
+extern HINSTANCE GetLocalizedResources();
+
-// Microsoft Visual C++ generated resource script.
-//
-#include "Resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-#include "WinVersRes.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "Resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "#include ""WinVersRes.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
- "#define _AFX_NO_OLE_RESOURCES\r\n"
- "#define _AFX_NO_TRACKER_RESOURCES\r\n"
- "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
- "\r\n"
- "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
- "LANGUAGE 9, 1\r\n"
- "#pragma code_page(1252)\r\n"
- "#include ""afxres.rc"" // Standard components\r\n"
- "#endif\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION MASTER_PROD_VERS
- PRODUCTVERSION MASTER_PROD_VERS
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "CompanyName", "Apple Computer, Inc."
- VALUE "FileDescription", "DNSServices Explorer Bar"
- VALUE "FileVersion", MASTER_PROD_VERS_STR
- VALUE "InternalName", "ExplorerPlugin.dll"
- VALUE "LegalCopyright", "Copyright (C) 2003-2004 Apple Computer, Inc."
- VALUE "OriginalFilename", "ExplorerPlugin.dll"
- VALUE "ProductName", MASTER_PROD_NAME
- VALUE "ProductVersion", MASTER_PROD_VERS_STR
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Dialog
-//
-
-IDD_LOGIN DIALOGEX 0, 0, 180, 89
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
-CAPTION "Login"
-FONT 8, "MS Shell Dlg", 0, 0, 0x0
-BEGIN
- LTEXT "Enter a username and password. Leave blank to use the default username and/or password.",
- IDC_STATIC,8,8,156,16,NOT WS_GROUP
- RTEXT "Username:",IDC_STATIC,10,34,36,8,NOT WS_GROUP
- EDITTEXT IDC_LOGIN_USERNAME_TEXT,50,32,118,12,ES_AUTOHSCROLL
- RTEXT "Password:",IDC_STATIC,10,50,36,8,NOT WS_GROUP
- EDITTEXT IDC_LOGIN_PASSWORD_TEXT,50,48,118,12,ES_PASSWORD |
- ES_AUTOHSCROLL
- DEFPUSHBUTTON "OK",IDOK,129,70,44,14
- PUSHBUTTON "Cancel",IDCANCEL,77,70,44,14
-END
-
-IDD_ABOUT DIALOGEX 0, 0, 219, 87
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR
-CAPTION "About Rendezvous"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- CONTROL 119,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE,0,0,
- 220,86
- CONTROL MASTER_PROD_VERS_STR3,IDC_COMPONENT,"Static",
- SS_SIMPLE | WS_GROUP,92,10,122,8
- LTEXT "Copyright (c) 2004 Apple Computer, Inc. All rights reserved. Apple and the Apple logo are trademarks of Apple Computer, Inc., registered in the U.S. and other countries.",
- IDC_LEGAL,92,31,123,50,0,WS_EX_RTLREADING
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// DESIGNINFO
-//
-
-#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO
-BEGIN
- IDD_LOGIN, DIALOG
- BEGIN
- BOTTOMMARGIN, 62
- END
-
- IDD_ABOUT, DIALOG
- BEGIN
- BOTTOMMARGIN, 132
- END
-END
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Bitmap
-//
-
-IDB_LOGO BITMAP "res\\logo.bmp"
-IDB_ABOUT BITMAP "res\\about.bmp"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDI_BUTTON_2K ICON "res\\button-2k.ico"
-IDI_BUTTON_XP ICON "res\\button-xp.ico"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Menu
-//
-
-IDR_CONTEXT_MENU MENU
-BEGIN
- POPUP "ContextMenu"
- BEGIN
- MENUITEM "About Rendezvous...", ID_Menu
- MENUITEM SEPARATOR
- END
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// String Table
-//
-
-STRINGTABLE
-BEGIN
- IDS_NAME "Rendezvous"
- IDS_WEB_SITES "Web Sites"
- IDS_FTP_SITES "FTP Sites"
- IDS_PRINTERS "Printers"
- IDS_MDNSRESPONDER_NOT_AVAILABLE "Rendezvous Service Not Available"
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-#define _AFX_NO_SPLITTER_RESOURCES
-#define _AFX_NO_OLE_RESOURCES
-#define _AFX_NO_TRACKER_RESOURCES
-#define _AFX_NO_PROPERTY_RESOURCES
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE 9, 1
-#pragma code_page(1252)
-#include "afxres.rc" // Standard components
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
+// Microsoft Visual C++ generated resource script.\r
+//\r
+#include "resource_dll.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "afxres.h"\r
+#include "WinVersRes.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE \r
+BEGIN\r
+ "resource_dll.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE \r
+BEGIN\r
+ "#include ""afxres.h""\r\n"\r
+ "#include ""WinVersRes.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"\r
+ "#define _AFX_NO_OLE_RESOURCES\r\n"\r
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"\r
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"\r
+ "\r\n"\r
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"\r
+ "LANGUAGE 9, 1\r\n"\r
+ "#pragma code_page(1252)\r\n"\r
+ "#include ""afxres.rc"" // Standard components\r\n"\r
+ "#endif\r\n"\r
+ "\0"\r
+END\r
+\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION MASTER_PROD_VERS\r
+ PRODUCTVERSION MASTER_PROD_VERS\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x2L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", "Apple Computer, Inc."\r
+ VALUE "FileDescription", "DNSServices Explorer Bar"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "ExplorerPlugin.dll"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "ExplorerPlugin.dll"\r
+ VALUE "ProductName", MASTER_PROD_NAME\r
+ VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x409, 1200\r
+ END\r
+END\r
+\r
+#endif // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+#define _AFX_NO_SPLITTER_RESOURCES\r
+#define _AFX_NO_OLE_RESOURCES\r
+#define _AFX_NO_TRACKER_RESOURCES\r
+#define _AFX_NO_PROPERTY_RESOURCES\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#include "afxres.rc" // Standard components\r
+#endif\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.00"
- Name="ExplorerPlugin"
- ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"
- SccProjectName=""
- SccLocalPath="">
- <Platforms>
- <Platform
- Name="Win32"/>
- </Platforms>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory=".\Debug"
- IntermediateDirectory=".\Debug"
- ConfigurationType="2"
- UseOfMFC="1"
- ATLMinimizesCRunTimeLibraryUsage="FALSE"
- CharacterSet="1">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0400"
- StringPooling="TRUE"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- ForceConformanceInForLoopScope="TRUE"
- UsePrecompiledHeader="0"
- PrecompiledHeaderFile=""
- AssemblerListingLocation=".\Debug/"
- ObjectFile=".\Debug/"
- ProgramDataBaseFileName=".\Debug/"
- BrowseInformation="1"
- WarningLevel="4"
- WarnAsError="FALSE"
- SuppressStartupBanner="TRUE"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="3"
- CallingConvention="2"
- CompileAs="0"/>
- <Tool
- Name="VCCustomBuildTool"
- Description="Registering"
- CommandLine="regsvr32.exe /s /c $(OutDir)/ExplorerPlugin.dll
-"
- Outputs="$(OUTDIR)\Register.out"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "
- AdditionalDependencies="../../mDNSWindows/DLL/Debug/dnssd.lib uafxcwd.lib ws2_32.lib"
- OutputFile="$(OutDir)/ExplorerPlugin.dll"
- LinkIncremental="1"
- SuppressStartupBanner="TRUE"
- IgnoreDefaultLibraryNames="uafxcwd.lib"
- ModuleDefinitionFile="./$(ProjectName).def"
- GenerateDebugInformation="TRUE"
- ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
- SubSystem="2"
- ImportLibrary="$(OutDir)/$(ProjectName).lib"/>
- <Tool
- Name="VCMIDLTool"
- PreprocessorDefinitions="_DEBUG"
- MkTypLibCompatible="TRUE"
- SuppressStartupBanner="TRUE"
- TargetEnvironment="1"
- TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
- Culture="1033"
- AdditionalIncludeDirectories="../../mDNSWindows"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory=".\Release"
- IntermediateDirectory=".\Release"
- ConfigurationType="2"
- UseOfMFC="1"
- ATLMinimizesCRunTimeLibraryUsage="FALSE"
- CharacterSet="1">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- GlobalOptimizations="TRUE"
- InlineFunctionExpansion="2"
- FavorSizeOrSpeed="2"
- OmitFramePointers="TRUE"
- AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0400"
- StringPooling="TRUE"
- RuntimeLibrary="0"
- BufferSecurityCheck="FALSE"
- EnableFunctionLevelLinking="FALSE"
- ForceConformanceInForLoopScope="TRUE"
- UsePrecompiledHeader="0"
- PrecompiledHeaderFile=""
- AssemblerListingLocation=".\Release/"
- ObjectFile=".\Release/"
- ProgramDataBaseFileName=".\Release/"
- BrowseInformation="1"
- WarningLevel="4"
- WarnAsError="FALSE"
- SuppressStartupBanner="TRUE"
- Detect64BitPortabilityProblems="TRUE"
- CompileAs="0"/>
- <Tool
- Name="VCCustomBuildTool"
- Description="Registering"
- CommandLine="regsvr32.exe /s /c $(OutDir)/$(ProjectName).dll
-"
- Outputs="$(OUTDIR)\Register.out"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "
- AdditionalDependencies="../../mDNSWindows/DLL/Release/dnssd.lib ws2_32.lib uafxcw.lib"
- OutputFile="$(OutDir)/$(ProjectName).dll"
- LinkIncremental="1"
- SuppressStartupBanner="TRUE"
- IgnoreDefaultLibraryNames="uafxcw.lib"
- ModuleDefinitionFile="./$(ProjectName).def"
- ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
- SubSystem="2"
- OptimizeReferences="0"
- EnableCOMDATFolding="0"
- ImportLibrary="$(OutDir)/$(ProjectName).lib"/>
- <Tool
- Name="VCMIDLTool"
- PreprocessorDefinitions="NDEBUG"
- MkTypLibCompatible="TRUE"
- SuppressStartupBanner="TRUE"
- TargetEnvironment="1"
- TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
- Culture="1033"
- AdditionalIncludeDirectories="../../mDNSWindows"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- </Configurations>
- <Files>
- <Filter
- Name="Support"
- Filter="">
- <File
- RelativePath="..\..\mDNSWindows\CommonServices.h">
- </File>
- <File
- RelativePath="..\..\mDNSWindows\DebugServices.c">
- </File>
- <File
- RelativePath="..\..\mDNSWindows\DebugServices.h">
- </File>
- <File
- RelativePath="..\..\mDNSWindows\WinServices.cpp">
- </File>
- <File
- RelativePath="..\..\mDNSWindows\WinServices.h">
- </File>
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
- <File
- RelativePath="About.cpp">
- </File>
- <File
- RelativePath="ClassFactory.cpp">
- </File>
- <File
- RelativePath="ExplorerBar.cpp">
- </File>
- <File
- RelativePath="ExplorerBarWindow.cpp">
- </File>
- <File
- RelativePath="ExplorerPlugin.cpp">
- </File>
- <File
- RelativePath="ExplorerPlugin.def">
- </File>
- <File
- RelativePath="LoginDialog.cpp">
- </File>
- <File
- RelativePath="StdAfx.cpp">
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc">
- <File
- RelativePath=".\About.h">
- </File>
- <File
- RelativePath="ClassFactory.h">
- </File>
- <File
- RelativePath="ExplorerBar.h">
- </File>
- <File
- RelativePath="ExplorerBarWindow.h">
- </File>
- <File
- RelativePath="ExplorerPlugin.h">
- </File>
- <File
- RelativePath="LoginDialog.h">
- </File>
- <File
- RelativePath="Resource.h">
- </File>
- <File
- RelativePath="StdAfx.h">
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">
- <File
- RelativePath="ExplorerPlugin.rc">
- </File>
- <File
- RelativePath="Web.ico">
- </File>
- <File
- RelativePath=".\about.bmp">
- </File>
- <File
- RelativePath=".\res\about.bmp">
- </File>
- <File
- RelativePath=".\res\cold.ico">
- </File>
- <File
- RelativePath=".\cold.ico">
- </File>
- <File
- RelativePath=".\hot.ico">
- </File>
- <File
- RelativePath=".\res\hot.ico">
- </File>
- <File
- RelativePath=".\logo.bmp">
- </File>
- <File
- RelativePath=".\res\logo.bmp">
- </File>
- </Filter>
- </Files>
- <Globals>
- <Global
- Name="RESOURCE_FILE"
- Value="ExplorerPlugin.rc"/>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding = "Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="ExplorerPlugin"\r
+ ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+ SccProjectName=""\r
+ SccLocalPath="">\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="2"\r
+ UseOfMFC="1"\r
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+ CharacterSet="1">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0501"\r
+ StringPooling="TRUE"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="1"\r
+ ForceConformanceInForLoopScope="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ PrecompiledHeaderFile=""\r
+ AssemblerListingLocation=".\Debug/"\r
+ ObjectFile=".\Debug/"\r
+ ProgramDataBaseFileName=".\Debug/"\r
+ BrowseInformation="1"\r
+ WarningLevel="4"\r
+ WarnAsError="FALSE"\r
+ SuppressStartupBanner="TRUE"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"\r
+ CallingConvention="2"\r
+ CompileAs="0"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ Description="Registering"\r
+ CommandLine="regsvr32.exe /s /c $(OutDir)/ExplorerPlugin.dll\r
+"\r
+ Outputs="$(OUTDIR)\Register.out"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ AdditionalDependencies="../../mDNSWindows/DLL/Debug/dnssd.lib uafxcwd.lib ws2_32.lib"\r
+ OutputFile="$(OutDir)/ExplorerPlugin.dll"\r
+ LinkIncremental="1"\r
+ SuppressStartupBanner="TRUE"\r
+ IgnoreDefaultLibraryNames="uafxcwd.lib"\r
+ ModuleDefinitionFile="./$(ProjectName).def"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
+ SubSystem="2"\r
+ ImportLibrary="$(OutDir)/$(ProjectName).lib"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ MkTypLibCompatible="TRUE"\r
+ SuppressStartupBanner="TRUE"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files\bin"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+ CharacterSet="1">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ GlobalOptimizations="TRUE"\r
+ InlineFunctionExpansion="2"\r
+ FavorSizeOrSpeed="2"\r
+ OmitFramePointers="TRUE"\r
+ AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0501"\r
+ StringPooling="TRUE"\r
+ RuntimeLibrary="0"\r
+ BufferSecurityCheck="FALSE"\r
+ EnableFunctionLevelLinking="FALSE"\r
+ ForceConformanceInForLoopScope="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ PrecompiledHeaderFile=""\r
+ AssemblerListingLocation=".\Release/"\r
+ ObjectFile=".\Release/"\r
+ ProgramDataBaseFileName=".\Release/"\r
+ BrowseInformation="1"\r
+ WarningLevel="4"\r
+ WarnAsError="FALSE"\r
+ SuppressStartupBanner="TRUE"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ CompileAs="0"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ Description="Registering"\r
+ CommandLine="regsvr32.exe /s /c $(OutDir)/$(ProjectName).dll\r
+"\r
+ Outputs="$(OUTDIR)\Register.out"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ AdditionalDependencies="../../mDNSWindows/DLL/Release/dnssd.lib ws2_32.lib uafxcw.lib"\r
+ OutputFile="$(OutDir)/$(ProjectName).dll"\r
+ LinkIncremental="1"\r
+ SuppressStartupBanner="TRUE"\r
+ IgnoreDefaultLibraryNames="uafxcw.lib"\r
+ ModuleDefinitionFile="./$(ProjectName).def"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+ SubSystem="2"\r
+ OptimizeReferences="0"\r
+ EnableCOMDATFolding="0"\r
+ ImportLibrary="$(IntDir)/$(ProjectName).lib"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ MkTypLibCompatible="TRUE"\r
+ SuppressStartupBanner="TRUE"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <Files>\r
+ <Filter\r
+ Name="Support"\r
+ Filter="">\r
+ <File\r
+ RelativePath="..\..\mDNSWindows\CommonServices.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSWindows\DebugServices.c">\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="..\..\mDNSWindows\isocode.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSWindows\loclibrary.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSWindows\loclibrary.h">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">\r
+ <File\r
+ RelativePath="About.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="ClassFactory.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="ExplorerBar.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="ExplorerBarWindow.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="ExplorerPlugin.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="ExplorerPlugin.def">\r
+ </File>\r
+ <File\r
+ RelativePath="LoginDialog.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="StdAfx.cpp">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc">\r
+ <File\r
+ RelativePath=".\About.h">\r
+ </File>\r
+ <File\r
+ RelativePath="ClassFactory.h">\r
+ </File>\r
+ <File\r
+ RelativePath="ExplorerBar.h">\r
+ </File>\r
+ <File\r
+ RelativePath="ExplorerBarWindow.h">\r
+ </File>\r
+ <File\r
+ RelativePath="ExplorerPlugin.h">\r
+ </File>\r
+ <File\r
+ RelativePath="LoginDialog.h">\r
+ </File>\r
+ <File\r
+ RelativePath="Resource.h">\r
+ </File>\r
+ <File\r
+ RelativePath="StdAfx.h">\r
+ </File>\r
+ <File\r
+ RelativePath="resource_dll.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="ExplorerPlugin.rc">\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ <Global\r
+ Name="RESOURCE_FILE"\r
+ Value="ExplorerPlugin.rc"/>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+// Microsoft Visual C++ generated resource script.\r
+//\r
+#include "resource_loc_res.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "afxres.h"\r
+#include "WinVersRes.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE \r
+BEGIN\r
+ "resource_loc_res.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE \r
+BEGIN\r
+ "#include ""afxres.h""\r\n"\r
+ "#include ""WinVersRes.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"\r
+ "#define _AFX_NO_OLE_RESOURCES\r\n"\r
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"\r
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"\r
+ "\r\n"\r
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"\r
+ "LANGUAGE 9, 1\r\n"\r
+ "#pragma code_page(1252)\r\n"\r
+ "#include ""afxres.rc"" // Standard components\r\n"\r
+ "#endif\r\n"\r
+ "\0"\r
+END\r
+\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION MASTER_PROD_VERS\r
+ PRODUCTVERSION MASTER_PROD_VERS\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x2L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", "Apple Computer, Inc."\r
+ VALUE "FileDescription", "DNS-SD Explorer Bar Resource Module"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "ExplorerPluginLocalized.dll"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "ExplorerPluginLocalized.dll"\r
+ VALUE "ProductName", MASTER_PROD_NAME\r
+ VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x409, 1200\r
+ END\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Dialog\r
+//\r
+\r
+IDD_LOGIN DIALOGEX 0, 0, 180, 89\r
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION\r
+CAPTION "Login"\r
+FONT 8, "MS Shell Dlg", 0, 0, 0x0\r
+BEGIN\r
+ LTEXT "Enter a username and password. Leave blank to use the default username and/or password.",\r
+ IDC_STATIC,8,8,156,16,NOT WS_GROUP\r
+ RTEXT "Username:",IDC_STATIC,10,34,36,8,NOT WS_GROUP\r
+ EDITTEXT IDC_LOGIN_USERNAME_TEXT,50,32,118,12,ES_AUTOHSCROLL\r
+ RTEXT "Password:",IDC_STATIC,10,50,36,8,NOT WS_GROUP\r
+ EDITTEXT IDC_LOGIN_PASSWORD_TEXT,50,48,118,12,ES_PASSWORD | \r
+ ES_AUTOHSCROLL\r
+ DEFPUSHBUTTON "OK",IDOK,129,70,44,14\r
+ PUSHBUTTON "Cancel",IDCANCEL,77,70,44,14\r
+END\r
+\r
+IDD_ABOUT DIALOGEX 0, 0, 219, 87\r
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+EXSTYLE WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR\r
+CAPTION "About Rendezvous"\r
+FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
+BEGIN\r
+ CONTROL "",IDC_ABOUT_BACKGROUND,"Static",SS_BITMAP | SS_REALSIZEIMAGE,0,0,\r
+ 220,86\r
+ CONTROL MASTER_PROD_VERS_STR3,IDC_COMPONENT,"Static",\r
+ SS_SIMPLE | WS_GROUP,92,10,122,8\r
+ LTEXT "Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved. Apple and the Apple logo are trademarks of Apple Computer, Inc., registered in the U.S. and other countries.",\r
+ IDC_LEGAL,92,31,123,50,0,WS_EX_RTLREADING\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// DESIGNINFO\r
+//\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+GUIDELINES DESIGNINFO \r
+BEGIN\r
+ IDD_LOGIN, DIALOG\r
+ BEGIN\r
+ BOTTOMMARGIN, 62\r
+ END\r
+\r
+ IDD_ABOUT, DIALOG\r
+ BEGIN\r
+ BOTTOMMARGIN, 132\r
+ END\r
+END\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Menu\r
+//\r
+\r
+IDR_CONTEXT_MENU MENU \r
+BEGIN\r
+ POPUP "ContextMenu"\r
+ BEGIN\r
+ MENUITEM "About Rendezvous...", ID_Menu\r
+ MENUITEM SEPARATOR\r
+ END\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// String Table\r
+//\r
+\r
+STRINGTABLE \r
+BEGIN\r
+ IDS_ABOUT "About Rendezvous"\r
+ IDS_ABOUT_URL "http://www.apple.com/macosx/features/rendezvous"\r
+ IDS_NAME "Rendezvous"\r
+ IDS_WEB_SITES "Web Sites"\r
+ IDS_FTP_SITES "FTP Sites"\r
+ IDS_PRINTERS "Printers"\r
+ IDS_MDNSRESPONDER_NOT_AVAILABLE "Rendezvous Service Not Available"\r
+ IDS_FIREWALL "Check firewall settings"\r
+END\r
+\r
+#endif // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+#define _AFX_NO_SPLITTER_RESOURCES\r
+#define _AFX_NO_OLE_RESOURCES\r
+#define _AFX_NO_TRACKER_RESOURCES\r
+#define _AFX_NO_PROPERTY_RESOURCES\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#include "afxres.rc" // Standard components\r
+#endif\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+<?xml version="1.0" encoding = "Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="ExplorerPluginLocRes"\r
+ ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+ SccProjectName=""\r
+ SccLocalPath="">\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"/>\r
+ </Platforms>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory=".\Debug\ExplorerPlugin.dll.Resources\en.lproj"\r
+ IntermediateDirectory=".\Debug"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+ CharacterSet="1">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0400"\r
+ StringPooling="TRUE"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="1"\r
+ ForceConformanceInForLoopScope="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ PrecompiledHeaderFile=""\r
+ AssemblerListingLocation=".\Debug/"\r
+ ObjectFile=".\Debug/"\r
+ ProgramDataBaseFileName=".\Debug/"\r
+ BrowseInformation="1"\r
+ WarningLevel="4"\r
+ WarnAsError="FALSE"\r
+ SuppressStartupBanner="TRUE"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"\r
+ CallingConvention="2"\r
+ CompileAs="0"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ AdditionalDependencies=""\r
+ OutputFile="$(OutDir)/ExplorerPluginLocalized.dll"\r
+ LinkIncremental="1"\r
+ SuppressStartupBanner="TRUE"\r
+ IgnoreDefaultLibraryNames=""\r
+ ModuleDefinitionFile=""\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
+ SubSystem="2"\r
+ ResourceOnlyDLL="TRUE"\r
+ ImportLibrary="$(OutDir)/$(ProjectName).lib"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ MkTypLibCompatible="TRUE"\r
+ SuppressStartupBanner="TRUE"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files\bin\ExplorerPlugin.dll.Resources\en.lproj"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+ CharacterSet="1">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ GlobalOptimizations="TRUE"\r
+ InlineFunctionExpansion="2"\r
+ FavorSizeOrSpeed="2"\r
+ OmitFramePointers="TRUE"\r
+ AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0400"\r
+ StringPooling="TRUE"\r
+ RuntimeLibrary="0"\r
+ BufferSecurityCheck="FALSE"\r
+ EnableFunctionLevelLinking="FALSE"\r
+ ForceConformanceInForLoopScope="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ PrecompiledHeaderFile=""\r
+ AssemblerListingLocation=".\Release/"\r
+ ObjectFile=".\Release/"\r
+ ProgramDataBaseFileName=".\Release/"\r
+ BrowseInformation="1"\r
+ WarningLevel="4"\r
+ WarnAsError="FALSE"\r
+ SuppressStartupBanner="TRUE"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ CompileAs="0"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ AdditionalDependencies=""\r
+ OutputFile="$(OutDir)/ExplorerPluginLocalized.dll"\r
+ LinkIncremental="1"\r
+ SuppressStartupBanner="TRUE"\r
+ IgnoreDefaultLibraryNames=""\r
+ ModuleDefinitionFile=""\r
+ ProgramDatabaseFile=""\r
+ SubSystem="2"\r
+ OptimizeReferences="0"\r
+ EnableCOMDATFolding="0"\r
+ ResourceOnlyDLL="TRUE"\r
+ ImportLibrary="$(IntDir)/$(ProjectName).lib"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ MkTypLibCompatible="TRUE"\r
+ SuppressStartupBanner="TRUE"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <Files>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc">\r
+ <File\r
+ RelativePath="resource_loc_res.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="ExplorerPluginLocRes.rc">\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ <Global\r
+ Name="RESOURCE_FILE"\r
+ Value="ExplorerPluginLocRes.rc"/>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+// Microsoft Visual C++ generated resource script.\r
+//\r
+#include "resource_res.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "afxres.h"\r
+#include "WinVersRes.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE \r
+BEGIN\r
+ "resource_res.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE \r
+BEGIN\r
+ "#include ""afxres.h""\r\n"\r
+ "#include ""WinVersRes.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"\r
+ "#define _AFX_NO_OLE_RESOURCES\r\n"\r
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"\r
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"\r
+ "\r\n"\r
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"\r
+ "LANGUAGE 9, 1\r\n"\r
+ "#pragma code_page(1252)\r\n"\r
+ "#include ""afxres.rc"" // Standard components\r\n"\r
+ "#endif\r\n"\r
+ "\0"\r
+END\r
+\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION MASTER_PROD_VERS\r
+ PRODUCTVERSION MASTER_PROD_VERS\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x2L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", "Apple Computer, Inc."\r
+ VALUE "FileDescription", "DNS-SD Explorer Bar Resource Module"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "ExplorerPluginResources.dll"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "ExplorerPluginResources.dll"\r
+ VALUE "ProductName", MASTER_PROD_NAME\r
+ VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x409, 1200\r
+ END\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Bitmap\r
+//\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
+// Icon\r
+//\r
+\r
+// Icon with lowest ID value placed first to ensure application icon\r
+// remains consistent on all systems.\r
+IDI_BUTTON_2K ICON "res\\button-2k.ico"\r
+IDI_BUTTON_XP ICON "res\\button-xp.ico"\r
+#endif // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+#define _AFX_NO_SPLITTER_RESOURCES\r
+#define _AFX_NO_OLE_RESOURCES\r
+#define _AFX_NO_TRACKER_RESOURCES\r
+#define _AFX_NO_PROPERTY_RESOURCES\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#include "afxres.rc" // Standard components\r
+#endif\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+<?xml version="1.0" encoding = "Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="ExplorerPluginRes"\r
+ ProjectGUID="{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+ SccProjectName=""\r
+ SccLocalPath="">\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"/>\r
+ </Platforms>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory=".\Debug\ExplorerPlugin.dll.Resources"\r
+ IntermediateDirectory=".\Debug"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+ CharacterSet="1">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;DEBUG=1;ENABLE_DOT_LOCAL_NAMES;WINVER=0x0400"\r
+ StringPooling="TRUE"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="1"\r
+ ForceConformanceInForLoopScope="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ PrecompiledHeaderFile=""\r
+ AssemblerListingLocation=".\Debug/"\r
+ ObjectFile=".\Debug/"\r
+ ProgramDataBaseFileName=".\Debug/"\r
+ BrowseInformation="1"\r
+ WarningLevel="4"\r
+ WarnAsError="FALSE"\r
+ SuppressStartupBanner="TRUE"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"\r
+ CallingConvention="2"\r
+ CompileAs="0"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ OutputFile="$(OutDir)\ExplorerPluginResources.dll"\r
+ LinkIncremental="1"\r
+ SuppressStartupBanner="TRUE"\r
+ IgnoreDefaultLibraryNames=""\r
+ ModuleDefinitionFile=""\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
+ SubSystem="2"\r
+ ResourceOnlyDLL="TRUE"\r
+ ImportLibrary="$(OutDir)/$(ProjectName).lib"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ MkTypLibCompatible="TRUE"\r
+ SuppressStartupBanner="TRUE"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files\bin\ExplorerPlugin.dll.Resources"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+ CharacterSet="1">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ GlobalOptimizations="TRUE"\r
+ InlineFunctionExpansion="2"\r
+ FavorSizeOrSpeed="2"\r
+ OmitFramePointers="TRUE"\r
+ AdditionalIncludeDirectories="..\..\mDNSShared;..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0400"\r
+ StringPooling="TRUE"\r
+ RuntimeLibrary="0"\r
+ BufferSecurityCheck="FALSE"\r
+ EnableFunctionLevelLinking="FALSE"\r
+ ForceConformanceInForLoopScope="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ PrecompiledHeaderFile=""\r
+ AssemblerListingLocation=".\Release/"\r
+ ObjectFile=".\Release/"\r
+ ProgramDataBaseFileName=".\Release/"\r
+ BrowseInformation="1"\r
+ WarningLevel="4"\r
+ WarnAsError="FALSE"\r
+ SuppressStartupBanner="TRUE"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ CompileAs="0"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
+ OutputFile="$(OutDir)\ExplorerPluginResources.dll"\r
+ LinkIncremental="1"\r
+ SuppressStartupBanner="TRUE"\r
+ IgnoreDefaultLibraryNames=""\r
+ ModuleDefinitionFile=""\r
+ ProgramDatabaseFile=""\r
+ SubSystem="2"\r
+ OptimizeReferences="0"\r
+ EnableCOMDATFolding="0"\r
+ ResourceOnlyDLL="TRUE"\r
+ ImportLibrary="$(IntDir)/$(ProjectName).lib"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ MkTypLibCompatible="TRUE"\r
+ SuppressStartupBanner="TRUE"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName="$(OutDir)/$(ProjectName).tlb"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <Files>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc">\r
+ <File\r
+ RelativePath="resource_res.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="ExplorerPluginRes.rc">\r
+ </File>\r
+ <File\r
+ RelativePath="Web.ico">\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\button-xp.ico">\r
+ </File>\r
+ <File\r
+ RelativePath=".\res\cold.ico">\r
+ </File>\r
+ <File\r
+ RelativePath=".\hot.ico">\r
+ </File>\r
+ <File\r
+ RelativePath=".\logo.bmp">\r
+ </File>\r
+ <File\r
+ RelativePath="res\logo.bmp">\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ <Global\r
+ Name="RESOURCE_FILE"\r
+ Value="ExplorerPluginRes.rc"/>\r
+ </Globals>\r
+</VisualStudioProject>\r
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by ExplorerPlugin.rc
-//
-#define IDS_NAME 106
-#define IDS_WEB_SITES 107
-#define IDS_FTP_SITES 108
-#define IDS_PRINTERS 109
-#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110
-#define IDB_LOGO 115
-#define IDI_BUTTON_2K 115
-#define IDD_ABOUT 118
-#define IDI_BUTTON_XP 118
-#define IDB_ABOUT 119
-#define IDR_CONTEXT_MENU 120
-#define IDD_LOGIN 145
-#define IDC_COMPONENT 1001
-#define IDC_LEGAL 1002
-#define IDC_LOGIN_USERNAME_TEXT 1182
-#define IDC_LOGIN_PASSWORD_TEXT 1183
-#define ID_Menu 40001
+/*
+ * 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@
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 119
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+ Change History (most recent first):
+
+ */
+
+// Include the core resources
+
+#include "resource_dll.h"
+
+// Include the non-localizable resources
+
+#include "resource_res.h"
+
+// Include the localizable resources
+
+#include "resource_loc_res.h"
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by ExplorerPlugin.rc\r
+//\r
+#define IDS_NAME 106\r
+#define IDS_WEB_SITES 107\r
+#define IDS_FTP_SITES 108\r
+#define IDS_PRINTERS 109\r
+#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110\r
+#define IDS_FIREWALL 111\r
+#define IDC_COMPONENT 1001\r
+#define IDC_LEGAL 1002\r
+#define IDC_LOGIN_USERNAME_TEXT 1182\r
+#define IDC_LOGIN_PASSWORD_TEXT 1183\r
+#define ID_Menu 40001\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE 119\r
+#define _APS_NEXT_COMMAND_VALUE 40001\r
+#define _APS_NEXT_CONTROL_VALUE 1001\r
+#define _APS_NEXT_SYMED_VALUE 101\r
+#endif\r
+#endif\r
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by ExplorerPluginLocRes.rc\r
+//\r
+#define IDS_NAME 106\r
+#define IDS_WEB_SITES 107\r
+#define IDS_FTP_SITES 108\r
+#define IDS_PRINTERS 109\r
+#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110\r
+#define IDS_FIREWALL 111\r
+#define IDD_ABOUT 118\r
+#define IDR_CONTEXT_MENU 120\r
+#define IDD_LOGIN 145\r
+#define IDC_ABOUT_BACKGROUND 146\r
+#define IDS_ABOUT 147\r
+#define IDS_ABOUT_URL 148\r
+#define IDC_COMPONENT 1001\r
+#define IDC_LEGAL 1002\r
+#define IDC_LOGIN_USERNAME_TEXT 1182\r
+#define IDC_LOGIN_PASSWORD_TEXT 1183\r
+#define ID_Menu 40001\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE 119\r
+#define _APS_NEXT_COMMAND_VALUE 40001\r
+#define _APS_NEXT_CONTROL_VALUE 1001\r
+#define _APS_NEXT_SYMED_VALUE 101\r
+#endif\r
+#endif\r
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by ExplorerPluginRes.rc\r
+//\r
+#define IDS_NAME 106\r
+#define IDS_WEB_SITES 107\r
+#define IDS_FTP_SITES 108\r
+#define IDS_PRINTERS 109\r
+#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110\r
+#define IDS_FIREWALL 111\r
+#define IDB_LOGO 115\r
+#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
+#define IDC_LOGIN_PASSWORD_TEXT 1183\r
+#define ID_Menu 40001\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE 119\r
+#define _APS_NEXT_COMMAND_VALUE 40001\r
+#define _APS_NEXT_CONTROL_VALUE 1001\r
+#define _APS_NEXT_SYMED_VALUE 101\r
+#endif\r
+#endif\r
Change History (most recent first):
$Log: FirstPage.cpp,v $
+Revision 1.3 2005/01/25 08:58:08 shersche
+<rdar://problem/3911084> Load icons at run-time from resource DLLs
+Bug #: 3911084
+
Revision 1.2 2004/07/13 20:15:04 shersche
<rdar://problem/3726363> Load large font name from resource
Bug #: 3726363
#include "PrinterSetupWizardApp.h"
#include "FirstPage.h"
+#include <DebugServices.h>
+
// CFirstPage dialog
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;
+ }
+
CPropertySheet* psheet = (CPropertySheet*) GetParent();
psheet->SetWizardButtons(PSWIZB_NEXT);
Change History (most recent first):
$Log: FourthPage.cpp,v $
+Revision 1.5 2005/01/06 08:17:08 shersche
+Display the selected protocol ("Raw", "LPR", "IPP") rather than the port name
+
Revision 1.4 2004/07/13 20:15:04 shersche
<rdar://problem/3726363> Load large font name from resource
Bug #: 3726363
DDX_Control(pDX, IDC_PRINTER_NAME, m_printerNameCtrl);
DDX_Control(pDX, IDC_PRINTER_MANUFACTURER, m_printerManufacturerCtrl);
DDX_Control(pDX, IDC_PRINTER_MODEL, m_printerModelCtrl);
- DDX_Control(pDX, IDC_PRINTER_PORT, m_printerPortCtrl);
+ DDX_Control(pDX, IDC_PRINTER_PROTOCOL, m_printerProtocolCtrl);
DDX_Control(pDX, IDC_PRINTER_DEFAULT, m_printerDefault);
}
m_printerNameCtrl.SetWindowText( printer->actualName );
m_printerManufacturerCtrl.SetWindowText ( printer->manufacturer );
m_printerModelCtrl.SetWindowText ( printer->model );
- m_printerPortCtrl.SetWindowText ( printer->portName );
+
+ Service * service = printer->services.front();
+ require_quiet( service, exit );
+ m_printerProtocolCtrl.SetWindowText ( service->protocol );
if (printer->deflt)
{
Change History (most recent first):
$Log: FourthPage.h,v $
+Revision 1.2 2005/01/06 08:17:08 shersche
+Display the selected protocol ("Raw", "LPR", "IPP") rather than the port name
+
Revision 1.1 2004/06/18 04:36:57 rpantos
First checked in
CStatic m_printerNameCtrl;
CStatic m_printerManufacturerCtrl;
CStatic m_printerModelCtrl;
- CStatic m_printerPortCtrl;
+ CStatic m_printerProtocolCtrl;
CStatic m_printerDefault;
};
// Microsoft Visual C++ generated resource script.\r
//\r
-#include "resource.h"\r
+#include "resource_exe.h"\r
\r
#define APSTUDIO_READONLY_SYMBOLS\r
/////////////////////////////////////////////////////////////////////////////\r
\r
1 TEXTINCLUDE \r
BEGIN\r
- "resource.h\0"\r
+ "resource_exe.h\0"\r
END\r
\r
2 TEXTINCLUDE \r
// Icon with lowest ID value placed first to ensure application icon\r
// remains consistent on all systems.\r
IDR_MAINFRAME ICON "res\\Print.ico"\r
-IDI_INFO ICON "res\\Info.ico"\r
-IDI_PRINTER ICON "res\\NetworkPrinter.ico"\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Bitmap\r
-//\r
-\r
-IDB_WATERMARK BITMAP "res\\watermark.bmp"\r
-IDB_BANNER_ICON BITMAP "res\\banner_icon.bmp"\r
-IDB_ABOUT BITMAP "res\\about.bmp"\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Dialog\r
-//\r
-\r
-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
-FONT 8, "MS Shell Dlg", 0, 0, 0x1\r
-BEGIN\r
- ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20\r
- LTEXT "Printer Setup 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
-END\r
-\r
-IDD_PRINTERSETUPWIZARD_DIALOG DIALOGEX 0, 0, 320, 200\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
-FONT 8, "MS Shell Dlg", 0, 0, 0x1\r
-BEGIN\r
- DEFPUSHBUTTON "OK",IDOK,263,7,50,16\r
- PUSHBUTTON "Cancel",IDCANCEL,263,25,50,16\r
- PUSHBUTTON "Start Wizard",IDC_BUTTON1,100,86,109,35\r
-END\r
-\r
-IDD_SECOND_PAGE DIALOGEX 0, 0, 290, 154\r
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION\r
-CAPTION "Rendezvous Printer Wizard"\r
-FONT 8, "MS Shell Dlg", 0, 0, 0x0\r
-BEGIN\r
- LTEXT "Shared Printers:",IDC_STATIC,3,0,171,8\r
- CONTROL "",IDC_BROWSE_LIST,"SysTreeView32",TVS_DISABLEDRAGDROP | \r
- TVS_SHOWSELALWAYS | TVS_FULLROWSELECT | WS_BORDER | \r
- WS_TABSTOP,2,11,286,142\r
-END\r
-\r
-IDD_FIRST_PAGE DIALOGEX 0, 0, 290, 199\r
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION\r
-CAPTION "Rendezvous Printer Wizard"\r
-FONT 8, "MS Shell Dlg", 0, 0, 0x0\r
-BEGIN\r
- LTEXT "Welcome to the Rendezvous Printer Setup Wizard",IDC_GREETING,\r
- 114,7,171,46\r
- LTEXT "Click next to continue.",IDC_STATIC,115,188,143,8\r
- LTEXT "This wizard helps you connect to a shared printer using Rendezvous. Make sure your printer is turned on and connected to your network.",\r
- IDC_STATIC,146,60,139,62\r
- ICON IDI_INFO,IDC_STATIC,118,60,21,20,SS_REALSIZEIMAGE,\r
- WS_EX_TRANSPARENT\r
-END\r
-\r
-IDD_THIRD_PAGE DIALOGEX 0, 0, 290, 154\r
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
- WS_SYSMENU\r
-CAPTION "Rendezvous Printer Wizard"\r
-FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
-BEGIN\r
- CONTROL "",IDC_PRINTER_MODEL,"SysListView32",LVS_REPORT | \r
- LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | \r
- LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,110,58,178,76\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 IDI_PRINTER,IDC_PRINTER_IMAGE,1,0,21,20,SS_REALSIZEIMAGE\r
- LTEXT "",IDC_PRINTER_NAME,40,5,173,8\r
- LTEXT "The Rendezvous Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer.",\r
- IDC_PRINTER_SELECTION_TEXT,40,23,243,26\r
- CONTROL "Use this printer as the default printer",\r
- IDC_DEFAULT_PRINTER,"Button",BS_AUTOCHECKBOX | \r
- WS_TABSTOP,3,142,224,10\r
- PUSHBUTTON "Have Disk...",IDC_HAVE_DISK,238,140,50,14\r
-END\r
-\r
-IDD_FOURTH_PAGE DIALOGEX 0, 0, 290, 199\r
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION\r
-CAPTION "Rendezvous Printer Wizard"\r
-FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
-BEGIN\r
- LTEXT "Completing the Rendezvous Printer Wizard",IDC_GOODBYE,\r
- 116,7,171,27\r
- LTEXT "You have successfully completed the Rendezvous Printer Wizard. The printer has the following settings:",\r
- IDC_STATIC,116,42,158,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 "Port:",IDC_STATIC,116,117,17,8\r
- LTEXT "Default:",IDC_STATIC,116,130,27,8\r
- LTEXT "",IDC_PRINTER_NAME,172,79,113,8\r
- LTEXT "",IDC_PRINTER_MANUFACTURER,172,91,113,8\r
- LTEXT "",IDC_PRINTER_MODEL,172,103,113,8\r
- LTEXT "",IDC_PRINTER_PORT,172,116,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
-END\r
-\r
-IDD_DIALOG1 DIALOGEX 0, 0, 265, 130\r
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
- WS_SYSMENU\r
-CAPTION "Dialog"\r
-FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
-BEGIN\r
- CONTROL 138,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE,0,0,\r
- 265,131\r
- LTEXT "Static",IDC_STATIC,77,12,19,8\r
- LTEXT "Static",IDC_STATIC,71,46,19,8\r
- LTEXT "Static",IDC_STATIC,71,89,19,8\r
-END\r
-\r
\r
/////////////////////////////////////////////////////////////////////////////\r
//\r
VALUE "FileDescription", "Rendezvous Printer Wizard"\r
VALUE "FileVersion", MASTER_PROD_VERS_STR\r
VALUE "InternalName", "RendezvousPrinterWizard.exe"\r
- VALUE "LegalCopyright", "Copyright (C) 2003-2004 Apple Computer, Inc."\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
VALUE "OriginalFilename", "RendezvousPrinterWizard.exe"\r
VALUE "ProductName", MASTER_PROD_NAME\r
VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
END\r
\r
\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// DESIGNINFO\r
-//\r
-\r
-#ifdef APSTUDIO_INVOKED\r
-GUIDELINES DESIGNINFO \r
-BEGIN\r
- IDD_SECOND_PAGE, DIALOG\r
- BEGIN\r
- BOTTOMMARGIN, 153\r
- END\r
-\r
- IDD_FIRST_PAGE, DIALOG\r
- BEGIN\r
- RIGHTMARGIN, 285\r
- BOTTOMMARGIN, 196\r
- END\r
-\r
- IDD_FOURTH_PAGE, DIALOG\r
- BEGIN\r
- RIGHTMARGIN, 285\r
- BOTTOMMARGIN, 197\r
- END\r
-END\r
-#endif // APSTUDIO_INVOKED\r
-\r
-\r
/////////////////////////////////////////////////////////////////////////////\r
//\r
// RT_MANIFEST\r
\r
STRINGTABLE \r
BEGIN\r
- IDS_ABOUTBOX "&About Printer Setup Wizard..."\r
- IDS_GOODBYE "Completing the Rendezvous Printer Setup Wizard."\r
- IDS_GREETING "Welcome to the Rendezvous Printer Setup Wizard"\r
- IDS_BROWSE_TITLE "Browse for Rendezvous Printers"\r
- IDS_BROWSE_SUBTITLE "Select the printer you want to use from the list below."\r
- IDS_CAPTION "Rendezvous Printer Wizard"\r
- IDS_GOODBYE_GOOD1 "You have successfully completed the Rendezvous 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_INSTALL_TITLE "Install Rendezvous Printer"\r
- IDS_INSTALL_SUBTITLE "The manufacturer and model determine which printer software to use."\r
-END\r
-\r
-STRINGTABLE \r
-BEGIN\r
- IDS_ERROR_SELECTING_PRINTER_TEXT \r
- "There was an error selecting this printer."\r
- IDS_ERROR_SELECTING_PRINTER_CAPTION "Error"\r
- IDS_INSTALL_ERROR_CAPTION "Error"\r
- IDS_INSTALL_ERROR_MESSAGE \r
- "You do not have sufficient access to your computer to connect to the selected printer."\r
- IDS_MANUFACTURER_HEADING "Manufacturer"\r
- IDS_MODEL_HEADING "Model"\r
- IDS_NO_RENDEZVOUS_PRINTERS "No Rendezvous Printers are available"\r
- IDS_NO_MDNSRESPONDER_SERVICE_TEXT "Rendezvous Service is not available"\r
- IDS_NO_MDNSRESPONDER_SERVICE_CAPTION "Error"\r
- IDS_PRINTER_MATCH_GOOD "The Rendezvous Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer."\r
- IDS_PRINTER_MATCH_BAD "The Rendezvous Printer Wizard cannot find a driver for this printer. Manually select from the list, or click 'Have Disk' if your printer came with an installation disk. "\r
- IDS_YES "Yes"\r
- IDS_NO "No"\r
- IDS_LARGE_FONT "MS Sans Serif"\r
+ IDS_REINSTALL "Rendezvous Printer Wizard cannot run because some of its required files are missing. Please reinstall Rendezvous Printer Wizard."\r
+ IDS_REINSTALL_CAPTION "Rendezvous Printer Wizard"\r
END\r
\r
#endif // English (U.S.) resources\r
-<?xml version="1.0" encoding = "windows-1251"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.00"
- Name="PrinterSetupWizard"
- ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"
- Keyword="MFCProj">
- <Platforms>
- <Platform
- Name="Win32"/>
- </Platforms>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="1"
- UseOfMFC="1"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared;C:\WINDDK\2600.1106\inc;C:\WINDDK\2600.1106\inc\wxp"
- PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0400;UNICODE;_UNICODE"
- StringPooling="TRUE"
- MinimalRebuild="TRUE"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- BufferSecurityCheck="TRUE"
- TreatWChar_tAsBuiltInType="TRUE"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="4"
- CallingConvention="0"
- DisableSpecificWarnings="4702"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="../../mDNSWindows/DLL/Debug/dnssd.lib ws2_32.lib iphlpapi.lib winspool.lib"
- OutputFile="$(OutDir)/RendezvousPrinterWizard.exe"
- LinkIncremental="2"
- GenerateDebugInformation="TRUE"
- SubSystem="2"
- EntryPointSymbol="wWinMainCRTStartup"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"
- PreprocessorDefinitions="_DEBUG"
- MkTypLibCompatible="FALSE"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
- Culture="1033"
- AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="1"
- UseOfMFC="1"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="1"
- OmitFramePointers="TRUE"
- AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared;C:\WINDDK\2600.1106\inc;C:\WINDDK\2600.1106\inc\wxp"
- PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0400;UNICODE;_UNICODE"
- StringPooling="TRUE"
- MinimalRebuild="FALSE"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="TRUE"
- TreatWChar_tAsBuiltInType="TRUE"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="3"
- DisableSpecificWarnings="4702"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="../../mDNSWindows/DLL/Release/dnssd.lib ws2_32.lib iphlpapi.lib winspool.lib"
- OutputFile="$(OutDir)/RendezvousPrinterWizard.exe"
- LinkIncremental="1"
- GenerateDebugInformation="TRUE"
- SubSystem="2"
- OptimizeReferences="0"
- EnableCOMDATFolding="0"
- EntryPointSymbol="wWinMainCRTStartup"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"
- PreprocessorDefinitions="NDEBUG"
- MkTypLibCompatible="FALSE"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
- Culture="1033"
- AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- </Configurations>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
- <File
- RelativePath=".\About.cpp">
- </File>
- <File
- RelativePath="FirstPage.cpp">
- </File>
- <File
- RelativePath=".\FourthPage.cpp">
- </File>
- <File
- RelativePath="PrinterSetupWizardApp.cpp">
- </File>
- <File
- RelativePath="PrinterSetupWizardSheet.cpp">
- </File>
- <File
- RelativePath="SecondPage.cpp">
- </File>
- <File
- RelativePath=".\StdioFileEx.cpp">
- </File>
- <File
- RelativePath="ThirdPage.cpp">
- </File>
- <File
- RelativePath="stdafx.cpp">
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc">
- <File
- RelativePath=".\About.h">
- </File>
- <File
- RelativePath="FirstPage.h">
- </File>
- <File
- RelativePath=".\FourthPage.h">
- </File>
- <File
- RelativePath="PrinterSetupWizardApp.h">
- </File>
- <File
- RelativePath="PrinterSetupWizardSheet.h">
- </File>
- <File
- RelativePath="Resource.h">
- </File>
- <File
- RelativePath="SecondPage.h">
- </File>
- <File
- RelativePath=".\StdioFileEx.h">
- </File>
- <File
- RelativePath="ThirdPage.h">
- </File>
- <File
- RelativePath=".\UtilTypes.h">
- </File>
- <File
- RelativePath="stdafx.h">
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest">
- <File
- RelativePath=".\res\Info.ico">
- </File>
- <File
- RelativePath=".\res\NetworkPrinter.ico">
- </File>
- <File
- RelativePath=".\res\Print.ico">
- </File>
- <File
- RelativePath=".\res\Printer.bmp">
- </File>
- <File
- RelativePath=".\res\Printer.ico">
- </File>
- <File
- RelativePath=".\res\Printer2.ico">
- </File>
- <File
- RelativePath="res\PrinterSetupWizard.ico">
- </File>
- <File
- RelativePath="res\PrinterSetupWizard.manifest">
- </File>
- <File
- RelativePath="PrinterSetupWizard.rc">
- </File>
- <File
- RelativePath="res\PrinterSetupWizard.rc2">
- </File>
- <File
- RelativePath=".\res\about.bmp">
- </File>
- <File
- RelativePath="res\banner_icon.bmp">
- </File>
- <File
- RelativePath="res\watermark.bmp">
- </File>
- </Filter>
- <Filter
- Name="Support"
- Filter="">
- <File
- RelativePath="..\..\mDNSWindows\CommonServices.h">
- </File>
- <File
- RelativePath="..\..\mDNSWindows\DebugServices.c">
- </File>
- <File
- RelativePath="..\..\mDNSWindows\DebugServices.h">
- </File>
- <File
- RelativePath="..\..\mDNSWindows\WinServices.cpp">
- </File>
- <File
- RelativePath="..\..\mDNSWindows\WinServices.h">
- </File>
- <File
- RelativePath="..\..\mDNSShared\dns_sd.h">
- </File>
- </Filter>
- <File
- RelativePath="ReadMe.txt">
- </File>
- </Files>
- <Globals>
- <Global
- Name="RESOURCE_FILE"
- Value="PrinterSetupWizard.rc"/>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding = "windows-1251"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="PrinterSetupWizard"\r
+ ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+ Keyword="MFCProj">\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="1"\r
+ UseOfMFC="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories=".;../../mDNSWindows;../../mDNSShared;C:\WINDDK\2600.1106\inc;C:\WINDDK\2600.1106\inc\wxp"\r
+ PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0501;UNICODE;_UNICODE"\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="TRUE"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="1"\r
+ BufferSecurityCheck="TRUE"\r
+ TreatWChar_tAsBuiltInType="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="4"\r
+ CallingConvention="0"\r
+ DisableSpecificWarnings="4702"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="../../mDNSWindows/DLL/Debug/dnssd.lib ws2_32.lib iphlpapi.lib winspool.lib"\r
+ OutputFile="$(OutDir)/RendezvousPrinterWizard.exe"\r
+ LinkIncremental="2"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+ SubSystem="2"\r
+ EntryPointSymbol="wWinMainCRTStartup"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ MkTypLibCompatible="FALSE"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="1"\r
+ UseOfMFC="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\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
+ PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0501;UNICODE;_UNICODE"\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="FALSE"\r
+ RuntimeLibrary="0"\r
+ EnableFunctionLevelLinking="TRUE"\r
+ TreatWChar_tAsBuiltInType="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"\r
+ DisableSpecificWarnings="4702"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="../../mDNSWindows/DLL/Release/dnssd.lib ws2_32.lib iphlpapi.lib winspool.lib"\r
+ OutputFile="$(OutDir)/RendezvousPrinterWizard.exe"\r
+ LinkIncremental="1"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+ SubSystem="2"\r
+ OptimizeReferences="0"\r
+ EnableCOMDATFolding="0"\r
+ EntryPointSymbol="wWinMainCRTStartup"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ MkTypLibCompatible="FALSE"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">\r
+ <File\r
+ RelativePath=".\About.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="FirstPage.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\FourthPage.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="PrinterSetupWizardApp.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="PrinterSetupWizardSheet.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="SecondPage.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\StdioFileEx.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="ThirdPage.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="stdafx.cpp">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc">\r
+ <File\r
+ RelativePath=".\About.h">\r
+ </File>\r
+ <File\r
+ RelativePath="FirstPage.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\FourthPage.h">\r
+ </File>\r
+ <File\r
+ RelativePath="PrinterSetupWizardApp.h">\r
+ </File>\r
+ <File\r
+ RelativePath="PrinterSetupWizardSheet.h">\r
+ </File>\r
+ <File\r
+ RelativePath="SecondPage.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\StdioFileEx.h">\r
+ </File>\r
+ <File\r
+ RelativePath="ThirdPage.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\UtilTypes.h">\r
+ </File>\r
+ <File\r
+ RelativePath="resource.h">\r
+ </File>\r
+ <File\r
+ RelativePath="resource_exe.h">\r
+ </File>\r
+ <File\r
+ RelativePath="stdafx.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\Info.ico">\r
+ </File>\r
+ <File\r
+ RelativePath="res\NetworkPrinter.ico">\r
+ </File>\r
+ <File\r
+ RelativePath="res\Print.ico">\r
+ </File>\r
+ <File\r
+ RelativePath="res\PrinterSetupWizard.manifest">\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
+ </Filter>\r
+ <Filter\r
+ Name="Support"\r
+ Filter="">\r
+ <File\r
+ RelativePath="..\..\mDNSWindows\CommonServices.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSWindows\DebugServices.c">\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\isocode.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSWindows\loclibrary.c">\r
+ <FileConfiguration\r
+ Name="Debug|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ DisableSpecificWarnings="4201"/>\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSWindows\loclibrary.h">\r
+ </File>\r
+ </Filter>\r
+ <File\r
+ RelativePath="ReadMe.txt">\r
+ </File>\r
+ </Files>\r
+ <Globals>\r
+ <Global\r
+ Name="RESOURCE_FILE"\r
+ Value="PrinterSetupWizard.rc"/>\r
+ </Globals>\r
+</VisualStudioProject>\r
Change History (most recent first):
$Log: PrinterSetupWizardApp.cpp,v $
+Revision 1.5 2005/01/25 18:30:02 shersche
+Fix call to PathForResource() by passing in NULL as first parameter.
+
+Revision 1.4 2005/01/25 08:54:41 shersche
+<rdar://problem/3911084> Load resource DLLs at startup.
+Bug #: 3911084
+
Revision 1.3 2004/07/13 21:24:23 rpantos
Fix for <rdar://problem/3701120>.
#include "PrinterSetupWizardApp.h"
#include "PrinterSetupWizardSheet.h"
#include "DebugServices.h"
+#include "loclibrary.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
+// Stash away pointers to our resource DLLs
+
+static HINSTANCE g_nonLocalizedResources = NULL;
+static HINSTANCE g_localizedResources = NULL;
+
+
+HINSTANCE
+GetNonLocalizedResources()
+{
+ return g_nonLocalizedResources;
+}
+
+
+HINSTANCE
+GetLocalizedResources()
+{
+ return g_localizedResources;
+}
+
// CPrinterSetupWizardApp
BOOL CPrinterSetupWizardApp::InitInstance()
{
+ CString errorMessage;
+ CString errorCaption;
+ wchar_t resource[MAX_PATH];
+ int res;
+ OSStatus err = kNoErr;
+
//
// initialize the debugging framework
//
debug_initialize( kDebugOutputTypeWindowsDebugger, "PrinterSetupWizard", NULL );
debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
+ // Before we load the resources, let's load the error string
+
+ errorMessage.LoadString( IDS_REINSTALL );
+ errorCaption.LoadString( IDS_REINSTALL_CAPTION );
+
+ // Load Resources
+
+ res = PathForResource( NULL, L"RendezvousPrinterWizard.dll", resource, MAX_PATH );
+ err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
+ require_noerr( err, exit );
+
+ g_nonLocalizedResources = LoadLibrary( resource );
+ translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ res = PathForResource( NULL, L"RendezvousPrinterWizardLocalized.dll", resource, MAX_PATH );
+ err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
+ require_noerr( err, exit );
+
+ g_localizedResources = LoadLibrary( resource );
+ translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );\r
+ \r
+ AfxSetResourceHandle( g_localizedResources );\r
// InitCommonControls() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
AfxEnableControlContainer();
- CPrinterSetupWizardSheet dlg(IDS_CAPTION);
+ {
+ CPrinterSetupWizardSheet dlg(IDS_CAPTION);
- m_pMainWnd = &dlg;
+ m_pMainWnd = &dlg;
- try
- {
- INT_PTR nResponse = dlg.DoModal();
-
- if (nResponse == IDOK)
+ try
{
- // TODO: Place code here to handle when the dialog is
- // dismissed with OK
+ INT_PTR nResponse = dlg.DoModal();
+
+ if (nResponse == IDOK)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with OK
+ }
+ else if (nResponse == IDCANCEL)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with Cancel
+ }
}
- else if (nResponse == IDCANCEL)
+ catch (CPrinterSetupWizardSheet::WizardException & exc)
{
- // TODO: Place code here to handle when the dialog is
- // dismissed with Cancel
+ MessageBox(NULL, exc.text, exc.caption, MB_OK|MB_ICONEXCLAMATION);
}
}
- catch (CPrinterSetupWizardSheet::WizardException & exc)
+
+exit:
+
+ if ( err )
+ {
+ MessageBox( NULL, errorMessage, errorCaption, MB_ICONERROR | MB_OK );
+ }
+
+ if ( g_nonLocalizedResources )
+ {
+ FreeLibrary( g_nonLocalizedResources );
+ }
+
+ if ( g_localizedResources )
{
- MessageBox(NULL, exc.text, exc.caption, MB_OK|MB_ICONEXCLAMATION);
+ FreeLibrary( g_localizedResources );
}
// Since the dialog has been closed, return FALSE so that we exit the
Change History (most recent first):
$Log: PrinterSetupWizardApp.h,v $
+Revision 1.2 2005/01/25 08:52:55 shersche
+<rdar://problem/3911084> Add APIs to return localizable and non-localizable resource DLL handles
+Bug #: 3911084
+
Revision 1.1 2004/06/18 04:36:57 rpantos
First checked in
};
-extern CPrinterSetupWizardApp theApp;
+extern CPrinterSetupWizardApp theApp;
+extern HINSTANCE GetNonLocalizedResources();
+extern HINSTANCE GetLocalizedResources();
--- /dev/null
+// Microsoft Visual C++ generated resource script.\r
+//\r
+#include "resource_loc_res.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "afxres.h"\r
+#include "WinVersRes.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Russian resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT\r
+#pragma code_page(1251)\r
+#endif //_WIN32\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE \r
+BEGIN\r
+ "resource_loc_res.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE \r
+BEGIN\r
+ "#include ""afxres.h""\r\n"\r
+ "#include ""WinVersRes.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"\r
+ "#define _AFX_NO_OLE_RESOURCES\r\n"\r
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"\r
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"\r
+ "\r\n"\r
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"\r
+ "LANGUAGE 9, 1\r\n"\r
+ "#pragma code_page(1252)\r\n"\r
+ "#include ""res\\PrinterSetupWizardLocRes.rc2"" // non-Microsoft Visual C++ edited resources\r\n"\r
+ "#include ""afxres.rc"" // Standard components\r\n"\r
+ "#endif\r\n"\r
+ "\0"\r
+END\r
+\r
+#endif // APSTUDIO_INVOKED\r
+\r
+#endif // Russian resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Dialog\r
+//\r
+\r
+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
+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
+ 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
+END\r
+\r
+IDD_PRINTERSETUPWIZARD_DIALOG DIALOGEX 0, 0, 320, 200\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
+FONT 8, "MS Shell Dlg", 0, 0, 0x1\r
+BEGIN\r
+ DEFPUSHBUTTON "OK",IDOK,263,7,50,16\r
+ PUSHBUTTON "Cancel",IDCANCEL,263,25,50,16\r
+ PUSHBUTTON "Start Wizard",IDC_BUTTON1,100,86,109,35\r
+END\r
+\r
+IDD_SECOND_PAGE DIALOGEX 0, 0, 290, 154\r
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION\r
+CAPTION "Rendezvous Printer Wizard"\r
+FONT 8, "MS Shell Dlg", 0, 0, 0x0\r
+BEGIN\r
+ LTEXT "Shared printers:",IDC_STATIC,3,0,171,8\r
+ CONTROL "",IDC_BROWSE_LIST,"SysTreeView32",TVS_DISABLEDRAGDROP | \r
+ TVS_SHOWSELALWAYS | TVS_FULLROWSELECT | WS_BORDER | \r
+ WS_TABSTOP,2,11,286,101\r
+ LTEXT "Description:",IDC_DESCRIPTION_LABEL,13,128,39,8\r
+ LTEXT "Location:",IDC_LOCATION_LABEL,13,139,30,8\r
+ GROUPBOX "Printer information",IDC_PRINTER_INFORMATION,2,116,286,\r
+ 37\r
+ LTEXT "",IDC_DESCRIPTION_FIELD,57,128,226,8\r
+ LTEXT "",IDC_LOCATION_FIELD,57,139,226,8\r
+END\r
+\r
+IDD_FIRST_PAGE DIALOGEX 0, 0, 290, 199\r
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION\r
+CAPTION "Rendezvous Printer Wizard"\r
+FONT 8, "MS Shell Dlg", 0, 0, 0x0\r
+BEGIN\r
+ LTEXT "Welcome to the Rendezvous Printer Setup Wizard",\r
+ IDC_GREETING,114,7,171,46\r
+ LTEXT "Click next to continue.",IDC_STATIC,115,188,143,8\r
+ LTEXT "This wizard helps you connect to a shared printer using Rendezvous. 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
+END\r
+\r
+IDD_THIRD_PAGE DIALOGEX 0, 0, 290, 154\r
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
+ WS_SYSMENU\r
+CAPTION "Rendezvous Printer Wizard"\r
+FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
+BEGIN\r
+ CONTROL "",IDC_PRINTER_MODEL,"SysListView32",LVS_REPORT | \r
+ LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | \r
+ LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,110,58,178,76\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
+ LTEXT "",IDC_PRINTER_NAME,40,5,173,8\r
+ LTEXT "The Rendezvous Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer.",\r
+ IDC_PRINTER_SELECTION_TEXT,40,23,243,26\r
+ CONTROL "Use this printer as the default printer",\r
+ IDC_DEFAULT_PRINTER,"Button",BS_AUTOCHECKBOX | \r
+ WS_TABSTOP,3,142,224,10\r
+ PUSHBUTTON "Have Disk...",IDC_HAVE_DISK,238,140,50,14\r
+END\r
+\r
+IDD_FOURTH_PAGE DIALOGEX 0, 0, 290, 199\r
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION\r
+CAPTION "Rendezvous Printer Wizard"\r
+FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
+BEGIN\r
+ LTEXT "Completing the Rendezvous Printer Wizard",IDC_GOODBYE,\r
+ 116,7,171,27\r
+ LTEXT "You have successfully completed the Rendezvous Printer Wizard. The printer has the following settings:",\r
+ IDC_STATIC,116,42,158,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_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
+END\r
+\r
+IDD_DIALOG1 DIALOGEX 0, 0, 265, 130\r
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
+ WS_SYSMENU\r
+CAPTION "Dialog"\r
+FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
+BEGIN\r
+ CONTROL 138,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE,0,0,\r
+ 265,131\r
+ LTEXT "Static",IDC_STATIC,77,12,19,8\r
+ LTEXT "Static",IDC_STATIC,71,46,19,8\r
+ LTEXT "Static",IDC_STATIC,71,89,19,8\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION MASTER_PROD_VERS\r
+ PRODUCTVERSION MASTER_PROD_VERS\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x1L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904e4"\r
+ BEGIN\r
+ VALUE "CompanyName", "Apple Computer, Inc."\r
+ VALUE "FileDescription", "Rendezvous Printer Wizard Resource Module"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "RendezvousPrinterWizardLocalized.dll"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "RendezvousPrinterWizardLocalized.dll"\r
+ VALUE "ProductName", MASTER_PROD_NAME\r
+ VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x409, 1252\r
+ END\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// String Table\r
+//\r
+\r
+STRINGTABLE \r
+BEGIN\r
+ IDS_ABOUTBOX "&About Printer Setup Wizard..."\r
+ IDS_GOODBYE "Completing the Rendezvous Printer Setup Wizard."\r
+ IDS_GREETING "Welcome to the Rendezvous Printer Setup Wizard"\r
+ IDS_BROWSE_TITLE "Browse for Rendezvous Printers"\r
+ IDS_BROWSE_SUBTITLE "Select the printer you want to use from the list below."\r
+ IDS_CAPTION "Rendezvous Printer Wizard"\r
+ IDS_GOODBYE_GOOD1 "You have successfully completed the Rendezvous 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_INSTALL_TITLE "Install Rendezvous Printer"\r
+ IDS_INSTALL_SUBTITLE "The manufacturer and model determine which printer software to use."\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+ IDS_ERROR_SELECTING_PRINTER_TEXT \r
+ "There was an error selecting this printer."\r
+ IDS_ERROR_SELECTING_PRINTER_CAPTION "Error"\r
+ IDS_INSTALL_ERROR_CAPTION "Error"\r
+ IDS_INSTALL_ERROR_MESSAGE \r
+ "You do not have sufficient access to your computer to connect to the selected printer."\r
+ IDS_MANUFACTURER_HEADING "Manufacturer"\r
+ IDS_MODEL_HEADING "Model"\r
+ IDS_NO_RENDEZVOUS_PRINTERS "No Rendezvous Printers are available"\r
+ IDS_NO_MDNSRESPONDER_SERVICE_TEXT "Rendezvous Service is not available."\r
+ IDS_NO_MDNSRESPONDER_SERVICE_CAPTION "Error"\r
+ IDS_PRINTER_MATCH_GOOD "The Rendezvous Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer."\r
+ IDS_PRINTER_MATCH_BAD "The Rendezvous Printer Wizard cannot find a driver for this printer. Manually select from the list, or click 'Have Disk' if your printer came with an installation disk. "\r
+ IDS_YES "Yes"\r
+ IDS_NO "No"\r
+ IDS_LARGE_FONT "MS Sans Serif"\r
+ IDS_FIREWALL "Please check firewall setting to ensure the Rendezvous Printer Wizard operates correctly."\r
+ IDS_ERROR_CAPTION "Error"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+ IDS_FIREWALL_CAPTION "Firewall Detected"\r
+END\r
+\r
+#endif // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+#define _AFX_NO_SPLITTER_RESOURCES\r
+#define _AFX_NO_OLE_RESOURCES\r
+#define _AFX_NO_TRACKER_RESOURCES\r
+#define _AFX_NO_PROPERTY_RESOURCES\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#include "res\PrinterSetupWizardLocRes.rc2" // non-Microsoft Visual C++ edited resources\r
+#include "afxres.rc" // Standard components\r
+#endif\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+<?xml version="1.0" encoding = "windows-1251"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="PrinterSetupWizardLocRes"\r
+ ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+ Keyword="MFCProj">\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"/>\r
+ </Platforms>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory=".\Debug\RendezvousPrinterWizard.exe.Resources\en.lproj"\r
+ IntermediateDirectory=".\Debug"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0400;UNICODE;_UNICODE"\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="TRUE"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="1"\r
+ BufferSecurityCheck="TRUE"\r
+ TreatWChar_tAsBuiltInType="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="4"\r
+ CallingConvention="0"\r
+ DisableSpecificWarnings="4702"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/RendezvousPrinterWizardLocalized.dll"\r
+ LinkIncremental="2"\r
+ GenerateDebugInformation="TRUE"\r
+ SubSystem="2"\r
+ EntryPointSymbol=""\r
+ ResourceOnlyDLL="TRUE"\r
+ ImportLibrary="$(OutDir)/Localized.lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ MkTypLibCompatible="FALSE"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files\RendezvousPrinterWizard.exe.Resources\en.lproj"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="1"\r
+ OmitFramePointers="TRUE"\r
+ AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0400;UNICODE;_UNICODE"\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="FALSE"\r
+ RuntimeLibrary="0"\r
+ EnableFunctionLevelLinking="TRUE"\r
+ TreatWChar_tAsBuiltInType="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"\r
+ DisableSpecificWarnings="4702"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/RendezvousPrinterWizardLocalized.dll"\r
+ LinkIncremental="1"\r
+ GenerateDebugInformation="FALSE"\r
+ SubSystem="2"\r
+ OptimizeReferences="0"\r
+ EnableCOMDATFolding="0"\r
+ EntryPointSymbol=""\r
+ ResourceOnlyDLL="TRUE"\r
+ ImportLibrary="$(IntDir)/$(TargetName).lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ MkTypLibCompatible="FALSE"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <Files>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc">\r
+ <File\r
+ RelativePath="resource_loc_dll.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="PrinterSetupWizardLocRes.rc">\r
+ </File>\r
+ <File\r
+ RelativePath="res\PrinterSetupWizardLocRes.rc2">\r
+ </File>\r
+ </Filter>\r
+ <File\r
+ RelativePath="ReadMe.txt">\r
+ </File>\r
+ </Files>\r
+ <Globals>\r
+ <Global\r
+ Name="RESOURCE_FILE"\r
+ Value="PrinterSetupWizardLocRes.rc"/>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+// Microsoft Visual C++ generated resource script.\r
+//\r
+#include "resource_res.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "afxres.h"\r
+#include "WinVersRes.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Russian resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT\r
+#pragma code_page(1251)\r
+#endif //_WIN32\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE \r
+BEGIN\r
+ "resource_res.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE \r
+BEGIN\r
+ "#include ""afxres.h""\r\n"\r
+ "#include ""WinVersRes.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"\r
+ "#define _AFX_NO_OLE_RESOURCES\r\n"\r
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"\r
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"\r
+ "\r\n"\r
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"\r
+ "LANGUAGE 9, 1\r\n"\r
+ "#pragma code_page(1252)\r\n"\r
+ "#include ""res\\PrinterSetupWizardRes.rc2"" // non-Microsoft Visual C++ edited resources\r\n"\r
+ "#include ""afxres.rc"" // Standard components\r\n"\r
+ "#endif\r\n"\r
+ "\0"\r
+END\r
+\r
+#endif // APSTUDIO_INVOKED\r
+\r
+#endif // Russian resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Icon\r
+//\r
+\r
+// Icon with lowest ID value placed first to ensure application icon\r
+// remains consistent on all systems.\r
+IDR_MAINFRAME ICON "res\\Print.ico"\r
+IDI_INFO ICON "res\\Info.ico"\r
+IDI_PRINTER ICON "res\\NetworkPrinter.ico"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Bitmap\r
+//\r
+\r
+IDB_WATERMARK BITMAP "res\\watermark.bmp"\r
+IDB_BANNER_ICON BITMAP "res\\banner_icon.bmp"\r
+IDB_ABOUT BITMAP "res\\about.bmp"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Dialog\r
+//\r
+\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION MASTER_PROD_VERS\r
+ PRODUCTVERSION MASTER_PROD_VERS\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x1L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904e4"\r
+ BEGIN\r
+ VALUE "CompanyName", "Apple Computer, Inc."\r
+ VALUE "FileDescription", "Rendezvous Printer Wizard Resource Module"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "RendezvousPrinterWizardLocalized.dll"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "RendezvousPrinterWizardLocalized.dll"\r
+ VALUE "ProductName", MASTER_PROD_NAME\r
+ VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x409, 1252\r
+ END\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// DESIGNINFO\r
+//\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+#endif // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+#define _AFX_NO_SPLITTER_RESOURCES\r
+#define _AFX_NO_OLE_RESOURCES\r
+#define _AFX_NO_TRACKER_RESOURCES\r
+#define _AFX_NO_PROPERTY_RESOURCES\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#include "res\PrinterSetupWizardRes.rc2" // non-Microsoft Visual C++ edited resources\r
+#include "afxres.rc" // Standard components\r
+#endif\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+<?xml version="1.0" encoding = "windows-1251"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="PrinterSetupWizardRes"\r
+ ProjectGUID="{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+ Keyword="MFCProj">\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"/>\r
+ </Platforms>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory=".\Debug\RendezvousPrinterWizard.exe.Resources"\r
+ IntermediateDirectory=".\Debug"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUGS;DEBUG=1;WINVER=0x0400;UNICODE;_UNICODE"\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="TRUE"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="1"\r
+ BufferSecurityCheck="TRUE"\r
+ TreatWChar_tAsBuiltInType="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="4"\r
+ CallingConvention="0"\r
+ DisableSpecificWarnings="4702"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/RendezvousPrinterWizard.dll"\r
+ LinkIncremental="2"\r
+ GenerateDebugInformation="TRUE"\r
+ SubSystem="2"\r
+ EntryPointSymbol=""\r
+ ResourceOnlyDLL="TRUE"\r
+ ImportLibrary="$(OutDir)/Localized.lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ MkTypLibCompatible="FALSE"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files\RendezvousPrinterWizard.exe.Resources"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="1"\r
+ OmitFramePointers="TRUE"\r
+ AdditionalIncludeDirectories="..\..\mDNSWindows"\r
+ PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;WINVER=0x0400;UNICODE;_UNICODE"\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="FALSE"\r
+ RuntimeLibrary="0"\r
+ EnableFunctionLevelLinking="TRUE"\r
+ TreatWChar_tAsBuiltInType="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"\r
+ DisableSpecificWarnings="4702"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/RendezvousPrinterWizard.dll"\r
+ LinkIncremental="1"\r
+ GenerateDebugInformation="FALSE"\r
+ SubSystem="2"\r
+ OptimizeReferences="0"\r
+ EnableCOMDATFolding="0"\r
+ EntryPointSymbol=""\r
+ ResourceOnlyDLL="TRUE"\r
+ ImportLibrary="$(IntDir)/$(TargetName).lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ MkTypLibCompatible="FALSE"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="1033"\r
+ AdditionalIncludeDirectories="$(IntDir);../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <Files>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc">\r
+ <File\r
+ RelativePath="resource_dll.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\Info.ico">\r
+ </File>\r
+ <File\r
+ RelativePath=".\res\NetworkPrinter.ico">\r
+ </File>\r
+ <File\r
+ RelativePath=".\res\Print.ico">\r
+ </File>\r
+ <File\r
+ RelativePath=".\res\Printer.bmp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\res\Printer.ico">\r
+ </File>\r
+ <File\r
+ RelativePath=".\res\Printer2.ico">\r
+ </File>\r
+ <File\r
+ RelativePath="res\PrinterSetupWizard.ico">\r
+ </File>\r
+ <File\r
+ RelativePath="PrinterSetupWizardRes.rc">\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
+ </Filter>\r
+ <File\r
+ RelativePath="ReadMe.txt">\r
+ </File>\r
+ </Files>\r
+ <Globals>\r
+ <Global\r
+ Name="RESOURCE_FILE"\r
+ Value="PrinterSetupWizardRes.rc"/>\r
+ </Globals>\r
+</VisualStudioProject>\r
Change History (most recent first):
$Log: PrinterSetupWizardSheet.cpp,v $
+Revision 1.22 2005/01/25 18:49:43 shersche
+Get icon resources from resource DLL
+
+Revision 1.21 2005/01/10 01:09:32 shersche
+Use the "note" key to populate pLocation field when setting up printer
+
+Revision 1.20 2005/01/03 19:05:01 shersche
+Store pointer to instance of wizard sheet so that print driver install thread sends a window message to the correct window
+
+Revision 1.19 2004/12/31 07:23:53 shersche
+Don't modify the button setting in SetSelectedPrinter()
+
+Revision 1.18 2004/12/29 18:53:38 shersche
+<rdar://problem/3725106>
+<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
+Bug #: 3725106, 3737413
+
Revision 1.17 2004/10/12 18:02:53 shersche
<rdar://problem/3764873> Escape '/', '@', '"' characters in printui command.
Bug #: 3764873
// Private Messages
-#define WM_SERVICE_EVENT ( WM_USER + 0x100 )
-#define WM_PROCESS_EVENT ( WM_USER + 0x101 )
-
-// Service Types
-
-#define kPDLDataStreamServiceType "_pdl-datastream._tcp"
-#define kLPRServiceType "_printer._tcp"
-#define kIPPServiceType "_ipp._tcp"
+#define WM_PROCESS_EVENT ( WM_USER + 0x100 )
// CPrinterSetupWizardSheet
+CPrinterSetupWizardSheet * CPrinterSetupWizardSheet::m_self;
IMPLEMENT_DYNAMIC(CPrinterSetupWizardSheet, CPropertySheet)
CPrinterSetupWizardSheet::CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage),
- m_selectedPrinter(NULL)
+ m_selectedPrinter(NULL),
+ m_driverThreadExitCode( 0 ),
+ m_driverThreadFinished( false )
{
m_arrow = LoadCursor(0, IDC_ARROW);
m_wait = LoadCursor(0, IDC_APPSTARTING);
m_active = m_arrow;
+ m_self = this;
Init();
}
CPrinterSetupWizardSheet::~CPrinterSetupWizardSheet()
{
- //
- // rdar://problem/3701837 memory leaks
- //
- // Clean up the ServiceRef and printer list on exit
- //
- if (m_pdlBrowser != NULL)
- {
- DNSServiceRefDeallocate(m_pdlBrowser);
- m_pdlBrowser = NULL;
- }
-
- while (m_printerList.size() > 0)
- {
- Printer * printer = m_printerList.front();
-
- m_printerList.pop_front();
-
- delete printer;
- }
-
- if (m_selectedPrinter != NULL)
+ if ( m_selectedPrinter != NULL )
{
delete m_selectedPrinter;
+ m_selectedPrinter = NULL;
}
-}
-
-// ------------------------------------------------------
-// InstallEventHandler
-//
-// Installs an event handler for DNSService events.
-//
-int
-CPrinterSetupWizardSheet::InstallEventHandler(EventHandler * handler)
-{
- PrinterList::iterator iter;
-
- m_eventHandlerList.push_back(handler);
-
- iter = m_printerList.begin();
-
- while (iter != m_printerList.end())
- {
- Printer * printer = *iter++;
-
- handler->OnAddPrinter(printer, iter != m_printerList.end());
- }
-
- return kNoErr;
+ m_self = NULL;
}
// ------------------------------------------------------
-// RemoveEventHandler
+// SetSelectedPrinter
//
-// Removes an event handler for DNSService events.
+// Manages setting a printer as the printer to install. Stops
+// any pending resolves.
//
-int
-CPrinterSetupWizardSheet::RemoveEventHandler(EventHandler * handler)
+void
+CPrinterSetupWizardSheet::SetSelectedPrinter(Printer * printer)
{
- m_eventHandlerList.remove(handler);
+ check( !printer || ( printer != m_selectedPrinter ) );
- return kNoErr;
+ m_selectedPrinter = printer;
}
-
// ------------------------------------------------------
-// SetSelectedPrinter
+// InstallPrinter
//
-// Manages setting a printer as the printer to install. Stops
-// any pending resolves.
+// Installs a printer with Windows.
+//
+// NOTE: this works one of two ways, depending on whether
+// there are drivers already installed for this printer.
+// If there are, then we can just create a port with XcvData,
+// and then call AddPrinter. If not, we use the printui.dll
+// to install the printer. Actually installing drivers that
+// are not currently installed is painful, and it's much
+// easier and less error prone to just let printui.dll do
+// the hard work for us.
//
+
OSStatus
-CPrinterSetupWizardSheet::SetSelectedPrinter(Printer * printer)
+CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
{
- OSStatus err;
+ Service * service;
+ BOOL ok;
+ OSStatus err;
+
+ service = printer->services.front();
+ check( service );
//
- // we only want one resolve going on at a time, so we check
- // state of the m_selectedPrinter
+ // if the driver isn't installed, then install it
//
- if (m_selectedPrinter != NULL)
+ if ( !printer->driverInstalled )
{
+ DWORD dwResult;
+ HANDLE hThread;
+ unsigned threadID;
+
+ m_driverThreadFinished = false;
+
+ //
+ // create the thread
+ //
+ hThread = (HANDLE) _beginthreadex_compat( NULL, 0, InstallDriverThread, printer, 0, &threadID );
+ err = translate_errno( hThread, (OSStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
//
- // if we're currently resolving, then stop the resolve
+ // go modal
//
- if (m_selectedPrinter->serviceRef)
+ while (!m_driverThreadFinished)
{
- err = StopResolve(m_selectedPrinter);
- require_noerr(err, exit);
+ MSG msg;
+
+ GetMessage( &msg, m_hWnd, 0, 0 );
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
}
+
+ //
+ // Wait until child process exits.
+ //
+ dwResult = WaitForSingleObject( hThread, INFINITE );
+ err = translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr );
+ require_noerr( err, exit );
- delete m_selectedPrinter;
- m_selectedPrinter = NULL;
- }
+ //
+ // check the return value of thread
+ //
+ require_noerr( m_driverThreadExitCode, exit );
- check( m_selectedPrinter == NULL );
+ //
+ // now we know that the driver was successfully installed
+ //
+ printer->driverInstalled = true;
+ }
- try
+ if ( service->type == kPDLServiceType )
{
- m_selectedPrinter = new Printer;
+ err = InstallPrinterPDLAndLPR( printer, service, PROTOCOL_RAWTCP_TYPE );
+ require_noerr( err, exit );
}
- catch (...)
+ else if ( service->type == kLPRServiceType )
{
- m_selectedPrinter = NULL;
+ err = InstallPrinterPDLAndLPR( printer, service, PROTOCOL_LPR_TYPE );
+ require_noerr( err, exit );
+ }
+ else if ( service->type == kIPPServiceType )
+ {
+ err = InstallPrinterIPP( printer, service );
+ require_noerr( err, exit );
+ }
+ else
+ {
+ err = kUnknownErr;
+ require_noerr( err, exit );
}
- require_action( m_selectedPrinter, exit, err = E_OUTOFMEMORY );
-
- m_selectedPrinter->window = printer->window;
- m_selectedPrinter->serviceRef = NULL;
- m_selectedPrinter->item = NULL;
- m_selectedPrinter->ifi = printer->ifi;
- m_selectedPrinter->name = printer->name;
- m_selectedPrinter->displayName = printer->displayName;
- m_selectedPrinter->actualName = printer->actualName;
- m_selectedPrinter->type = printer->type;
- m_selectedPrinter->domain = printer->domain;
- m_selectedPrinter->installed = printer->installed;
- m_selectedPrinter->deflt = printer->deflt;
- m_selectedPrinter->refs = 1;
-
- err = StartResolve(m_selectedPrinter);
- require_noerr(err, exit);
+ printer->installed = true;
+
+ //
+ // if the user specified a default printer, set it
+ //
+ if (printer->deflt)
+ {
+ ok = SetDefaultPrinter( printer->actualName );
+ err = translate_errno( ok, errno_compat(), err = kUnknownErr );
+ require_noerr( err, exit );
+ }
exit:
}
-// ------------------------------------------------------
-// InstallPrinter
-//
-// Installs a printer with Windows.
-//
-// NOTE: this works one of two ways, depending on whether
-// there are drivers already installed for this printer.
-// If there are, then we can just create a port with XcvData,
-// and then call AddPrinter. If not, we use the printui.dll
-// to install the printer. Actually installing drivers that
-// are not currently installed is painful, and it's much
-// easier and less error prone to just let printui.dll do
-// the hard work for us.
-//
-
OSStatus
-CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
+CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * service, DWORD protocol )
{
PRINTER_DEFAULTS printerDefaults = { NULL, NULL, SERVER_ACCESS_ADMINISTER };
DWORD dwStatus;
PBYTE pOutputData = NULL;
DWORD cbOutputNeeded = 0;
PORT_DATA_1 portData;
+ PRINTER_INFO_2 pInfo;
HANDLE hXcv = NULL;
HANDLE hPrinter = NULL;
+ Queue * q;
BOOL ok;
OSStatus err;
check(printer != NULL);
check(printer->installed == false);
+ q = service->queues.front();
+ check( q );
+
ok = OpenPrinter(L",XcvMonitor Standard TCP/IP Port", &hXcv, &printerDefaults);
err = translate_errno( ok, errno_compat(), kUnknownErr );
require_noerr( err, exit );
ZeroMemory(&portData, sizeof(PORT_DATA_1));
wcscpy(portData.sztPortName, printer->portName);
- portData.dwPortNumber = printer->portNumber;
+ portData.dwPortNumber = service->portNumber;
portData.dwVersion = 1;
- portData.dwProtocol = PROTOCOL_RAWTCP_TYPE;
+ portData.dwProtocol = protocol;
portData.cbSize = sizeof PORT_DATA_1;
portData.dwReserved = 0L;
- wcscpy(portData.sztQueue, printer->hostname);
- wcscpy(portData.sztIPAddress, printer->hostname);
- wcscpy(portData.sztHostAddress, printer->hostname);
+ 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 );
-
- if (printer->driverInstalled)
- {
- PRINTER_INFO_2 pInfo;
-
- ZeroMemory(&pInfo, sizeof(pInfo));
-
- pInfo.pPrinterName = printer->actualName.GetBuffer();
- pInfo.pServerName = NULL;
- pInfo.pShareName = NULL;
- pInfo.pPortName = printer->portName.GetBuffer();
- pInfo.pDriverName = printer->model.GetBuffer();
- pInfo.pComment = printer->model.GetBuffer();
- pInfo.pLocation = L"";
- pInfo.pDevMode = NULL;
- pInfo.pDevMode = NULL;
- pInfo.pSepFile = L"";
- pInfo.pPrintProcessor = L"winprint";
- pInfo.pDatatype = L"RAW";
- pInfo.pParameters = L"";
- pInfo.pSecurityDescriptor = NULL;
- pInfo.Attributes = PRINTER_ATTRIBUTE_QUEUED;
- pInfo.Priority = 0;
- pInfo.DefaultPriority = 0;
- pInfo.StartTime = 0;
- pInfo.UntilTime = 0;
-
- hPrinter = AddPrinter(NULL, 2, (LPBYTE) &pInfo);
- err = translate_errno( hPrinter, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
- }
- else
- {
- DWORD dwResult;
- HANDLE hThread;
- unsigned threadID;
-
-
- m_processFinished = false;
-
- //
- // create the thread
- //
- hThread = (HANDLE) _beginthreadex_compat( NULL, 0, InstallPrinterThread, printer, 0, &threadID );
- err = translate_errno( hThread, (OSStatus) GetLastError(), kUnknownErr );
- require_noerr( err, exit );
-
- //
- // go modal
- //
- while (!m_processFinished)
- {
- MSG msg;
-
- GetMessage( &msg, m_hWnd, 0, 0 );
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- //
- // Wait until child process exits.
- //
- dwResult = WaitForSingleObject( hThread, INFINITE );
- err = translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr );
- require_noerr( err, exit );
- }
-
- printer->installed = true;
//
- // if the user specified a default printer, set it
+ // add the printer
//
- if (printer->deflt)
- {
- ok = SetDefaultPrinter(printer->actualName);
- err = translate_errno( ok, errno_compat(), err = kUnknownErr );
- require_noerr( err, exit );
- }
+ ZeroMemory(&pInfo, sizeof(pInfo));
+
+ pInfo.pPrinterName = printer->actualName.GetBuffer();
+ pInfo.pServerName = NULL;
+ pInfo.pShareName = NULL;
+ pInfo.pPortName = printer->portName.GetBuffer();
+ pInfo.pDriverName = printer->model.GetBuffer();
+ pInfo.pComment = printer->model.GetBuffer();
+ pInfo.pLocation = service->location.GetBuffer();
+ pInfo.pDevMode = NULL;
+ pInfo.pDevMode = NULL;
+ pInfo.pSepFile = L"";
+ pInfo.pPrintProcessor = L"winprint";
+ pInfo.pDatatype = L"RAW";
+ pInfo.pParameters = L"";
+ pInfo.pSecurityDescriptor = NULL;
+ pInfo.Attributes = PRINTER_ATTRIBUTE_QUEUED;
+ pInfo.Priority = 0;
+ pInfo.DefaultPriority = 0;
+ pInfo.StartTime = 0;
+ pInfo.UntilTime = 0;
+
+ hPrinter = AddPrinter(NULL, 2, (LPBYTE) &pInfo);
+ err = translate_errno( hPrinter, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
exit:
}
+OSStatus
+CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service)
+{
+ DEBUG_UNUSED( service );
+
+ HANDLE hPrinter = NULL;
+ PRINTER_INFO_2 pInfo;
+ OSStatus err;
+
+ //
+ // add the printer
+ //
+ ZeroMemory(&pInfo, sizeof(PRINTER_INFO_2));
+
+ pInfo.pPrinterName = printer->actualName.GetBuffer();
+ pInfo.pPortName = printer->portName.GetBuffer();
+ pInfo.pDriverName = printer->model.GetBuffer();
+ pInfo.pPrintProcessor = L"winprint";
+ pInfo.pLocation = service->location.GetBuffer();
+ pInfo.Attributes = PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL;
+
+ hPrinter = AddPrinter(NULL, 2, (LPBYTE)&pInfo);
+ err = translate_errno( hPrinter, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+exit:
+
+ if ( hPrinter != NULL )
+ {
+ ClosePrinter(hPrinter);
+ }
+
+ return err;
+}
+
+
BEGIN_MESSAGE_MAP(CPrinterSetupWizardSheet, CPropertySheet)
-ON_MESSAGE( WM_SERVICE_EVENT, OnServiceEvent )
ON_MESSAGE( WM_PROCESS_EVENT, OnProcessEvent )
ON_WM_SETCURSOR()
+ON_WM_TIMER()
END_MESSAGE_MAP()
// ------------------------------------------------------
// OnInitDialog
//
-// Initializes this Dialog object. We start the browse here,
-// so that printers show up instantly when the user clicks
-// the next button.
+// Initializes this Dialog object.
//
BOOL CPrinterSetupWizardSheet::OnInitDialog()
{
- OSStatus err;
-
CPropertySheet::OnInitDialog();
-
- //
- // setup the DNS-SD browsing
- //
- err = DNSServiceBrowse( &m_pdlBrowser, 0, 0, kPDLDataStreamServiceType, NULL, OnBrowse, this );
- require_noerr( err, exit );
-
- m_serviceRefList.push_back(m_pdlBrowser);
-
- err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(m_pdlBrowser), m_hWnd, WM_SERVICE_EVENT, FD_READ|FD_CLOSE);
- require_noerr( err, exit );
-
- LoadPrinterNames();
-
-exit:
-
- if (err != kNoErr)
- {
- WizardException exc;
-
- exc.text.LoadString(IDS_NO_MDNSRESPONDER_SERVICE_TEXT);
- exc.caption.LoadString(IDS_NO_MDNSRESPONDER_SERVICE_CAPTION);
-
- throw(exc);
- }
return TRUE;
}
m_psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
m_psh.pszbmHeader = MAKEINTRESOURCE(IDB_BANNER_ICON);
- m_psh.hInstance = AfxGetInstanceHandle();
+ m_psh.hInstance = GetNonLocalizedResources();
SetWizardMode();
}
-LONG
-CPrinterSetupWizardSheet::OnServiceEvent(WPARAM inWParam, LPARAM inLParam)
-{
- if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
- {
- dlog( kDebugLevelError, "OnServiceEvent: window error\n" );
- }
- else
- {
- SOCKET sock = (SOCKET) inWParam;
-
- // iterate thru list
- ServiceRefList::iterator begin = m_serviceRefList.begin();
- ServiceRefList::iterator end = m_serviceRefList.end();
-
- while (begin != end)
- {
- DNSServiceRef ref = *begin++;
-
- check(ref != NULL);
-
- if ((SOCKET) DNSServiceRefSockFD(ref) == sock)
- {
- DNSServiceProcessResult(ref);
- break;
- }
- }
- }
-
- return ( 0 );
-}
-
-
LONG
CPrinterSetupWizardSheet::OnProcessEvent(WPARAM inWParam, LPARAM inLParam)
{
- DEBUG_UNUSED(inWParam);
DEBUG_UNUSED(inLParam);
- m_processFinished = true;
+ m_driverThreadExitCode = (DWORD) inWParam;
+ m_driverThreadFinished = true;
return 0;
}
-void DNSSD_API
-CPrinterSetupWizardSheet::OnBrowse(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inName,
- const char * inType,
- const char * inDomain,
- void * inContext )
-{
- DEBUG_UNUSED(inRef);
-
- CPrinterSetupWizardSheet * self;
- Printer * printer;
- EventHandlerList::iterator it;
- DWORD printerNameCount;
- bool moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing);
-
- require_noerr( inErrorCode, exit );
-
- self = reinterpret_cast <CPrinterSetupWizardSheet*>( inContext );
- require_quiet( self, exit );
-
- printer = self->LookUp(inName);
-
- if (inFlags & kDNSServiceFlagsAdd)
- {
- OSStatus err;
-
- if (printer != NULL)
- {
- printer->refs++;
- }
- else
- {
- try
- {
- printer = new Printer;
- }
- catch (...)
- {
- printer = NULL;
- }
-
- require_action( printer, exit, err = E_OUTOFMEMORY );
-
- printer->window = self;
- printer->ifi = inInterfaceIndex;
- printer->name = inName;
- err = UTF8StringToStringObject(inName, printer->displayName);
- check_noerr( err );
- printer->actualName = printer->displayName;
-
- //
- // Compare this name against printers that are already installed
- // to avoid name clashes. Rename as necessary
- // to come up with a unique name.
- //
- printerNameCount = 2;
-
- for (;;)
- {
- PrinterNameMap::iterator it;
-
- it = self->m_printerNames.find(printer->actualName);
-
- if (it != self->m_printerNames.end())
- {
- printer->actualName.Format(L"%s (%d)", printer->displayName, printerNameCount);
- }
- else
- {
- break;
- }
-
- printerNameCount++;
- }
-
- printer->type = inType;
- printer->domain = inDomain;
- printer->installed = false;
- printer->deflt = false;
- printer->refs = 1;
-
- self->m_printerList.push_back( printer );
-
- //
- // now invoke event handlers for AddPrinter event
- //
- for (it = self->m_eventHandlerList.begin(); it != self->m_eventHandlerList.end(); it++)
- {
- EventHandler * handler = *it;
-
- handler->OnAddPrinter(printer, moreComing);
- }
- }
- }
- else
- {
- if ((printer != NULL) && (--printer->refs == 0))
- {
- //
- // now invoke event handlers for RemovePrinter event
- //
- for (it = self->m_eventHandlerList.begin(); it != self->m_eventHandlerList.end(); it++)
- {
- EventHandler * handler = *it;
-
- handler->OnRemovePrinter(printer, moreComing);
- }
-
- self->m_printerList.remove(printer);
-
- //
- // check to see if we've selected this printer
- //
- if (self->m_selectedPrinter == printer)
- {
- //
- // this guy is being removed while we're resolving it...so let's
- // stop the resolve
- //
- if (printer->serviceRef != NULL)
- {
- self->StopResolve(printer);
- }
-
- self->m_selectedPrinter = NULL;
- }
-
- delete printer;
- }
- }
-
-exit:
-
- return;
-}
-
-
-void DNSSD_API
-CPrinterSetupWizardSheet::OnResolve(
- 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 )
-{
- DEBUG_UNUSED(inFullName);
- DEBUG_UNUSED(inInterfaceIndex);
- DEBUG_UNUSED(inFlags);
- DEBUG_UNUSED(inRef);
-
- Printer * printer;
- CPrinterSetupWizardSheet * self;
- EventHandlerList::iterator it1;
- EventHandlerList::iterator it2;
- int idx;
- OSStatus err;
-
- require_noerr( inErrorCode, exit );
-
- printer = reinterpret_cast<Printer*>( inContext );
- require_quiet( printer, exit);
-
- self = printer->window;
- require_quiet( self, exit );
-
- err = self->StopResolve(printer);
- require_noerr(err, exit);
-
- //
- // hold on to the hostname...
- //
- err = UTF8StringToStringObject( inHostName, printer->hostname );
- require_noerr( err, exit );
-
- //
- // <rdar://problem/3739200> remove the trailing dot on hostname
- //
- idx = printer->hostname.ReverseFind('.');
-
- if ((idx > 1) && ((printer->hostname.GetLength() - 1) == idx))
- {
- printer->hostname.Delete(idx, 1);
- }
-
- //
- // hold on to the port
- //
- printer->portNumber = ntohs(inPort);
-
- //
- // parse the text record. we create a stringlist of text record
- // entries that can be interrogated later
- //
- while (inTXTSize)
- {
- char buf[256];
-
- unsigned char num = *inTXT;
- check( (int) num < inTXTSize );
-
- memset(buf, 0, sizeof(buf));
- memcpy(buf, inTXT + 1, num);
-
- inTXTSize -= (num + 1);
- inTXT += (num + 1);
-
- CString elem;
-
- err = UTF8StringToStringObject( buf, elem );
- require_noerr( err, exit );
-
- int curPos = 0;
-
- CString key = elem.Tokenize(L"=", curPos);
- CString val = elem.Tokenize(L"=", curPos);
-
- key.MakeLower();
-
- if ((key == L"usb_mfg") || (key == L"usb_manufacturer"))
- {
- printer->usb_MFG = val;
- }
- else if ((key == L"usb_mdl") || (key == L"usb_model"))
- {
- printer->usb_MDL = val;
- }
- else if (key == L"description")
- {
- printer->description = val;
- }
- else if (key == L"product")
- {
- printer->product = val;
- }
- }
-
- //
- // now invoke event handlers for Resolve event
- //
- it1 = self->m_eventHandlerList.begin();
- it2 = self->m_eventHandlerList.end();
-
- while (it1 != it2)
- {
- EventHandler * handler = *it1++;
-
- handler->OnResolvePrinter(printer);
- }
-
-exit:
-
- return;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::LoadPrinterNames()
-{
- PBYTE buffer = NULL;
- OSStatus err = 0;
-
- //
- // rdar://problem/3701926 - Printer can't be installed twice
- //
- // First thing we want to do is make sure the printer isn't already installed.
- // If the printer name is found, we'll try and rename it until we
- // find a unique name
- //
- DWORD dwNeeded = 0, dwNumPrinters = 0;
-
- BOOL ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwNumPrinters);
- err = translate_errno( ok, errno_compat(), kUnknownErr );
-
- if ((err == ERROR_INSUFFICIENT_BUFFER) && (dwNeeded > 0))
- {
- try
- {
- buffer = new unsigned char[dwNeeded];
- }
- catch (...)
- {
- buffer = NULL;
- }
-
- require_action( buffer, exit, kNoMemoryErr );
- ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, buffer, dwNeeded, &dwNeeded, &dwNumPrinters);
- err = translate_errno( ok, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
-
- for (DWORD index = 0; index < dwNumPrinters; index++)
- {
- PRINTER_INFO_4 * lppi4 = (PRINTER_INFO_4*) (buffer + index * sizeof(PRINTER_INFO_4));
-
- m_printerNames[lppi4->pPrinterName] = lppi4->pPrinterName;
- }
- }
-
-exit:
-
- if (buffer != NULL)
- {
- delete [] buffer;
- }
-
- return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StartResolve(Printer * printer)
-{
- OSStatus err;
-
- check( printer );
-
- err = DNSServiceResolve( &printer->serviceRef, 0, 0, printer->name.c_str(), printer->type.c_str(), printer->domain.c_str(), (DNSServiceResolveReply) OnResolve, printer );
- require_noerr( err, exit);
-
- m_serviceRefList.push_back(printer->serviceRef);
-
- err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(printer->serviceRef), m_hWnd, WM_SERVICE_EVENT, FD_READ|FD_CLOSE);
- require_noerr( err, exit );
-
- //
- // set the cursor to arrow+hourglass
- //
- m_active = m_wait;
- SetCursor(m_active);
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StopResolve(Printer * printer)
-{
- OSStatus err;
-
- check( printer );
- check( printer->serviceRef );
-
- m_serviceRefList.remove( printer->serviceRef );
-
- err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(printer->serviceRef), m_hWnd, 0, 0);
- check(err == 0);
-
- DNSServiceRefDeallocate( printer->serviceRef );
-
- printer->serviceRef = NULL;
-
- //
- // set the cursor back to normal
- //
- m_active = m_arrow;
- SetCursor(m_active);
-
- return kNoErr;
-}
-
-
-Printer*
-CPrinterSetupWizardSheet::LookUp(const char * inName)
-{
- PrinterList::iterator it1 = m_printerList.begin();
- PrinterList::iterator it2 = m_printerList.end();
-
- while (it1 != it2)
- {
- Printer * printer = *it1++;
-
- if (printer->name == inName)
- {
- return printer;
- }
- }
-
- return NULL;
-}
-
-
unsigned WINAPI
-CPrinterSetupWizardSheet::InstallPrinterThread( LPVOID inParam )
-{
- check( inParam );
-
+CPrinterSetupWizardSheet::InstallDriverThread( LPVOID inParam )
+{
Printer * printer = (Printer*) inParam;
- CString actualName;
- CString command;
DWORD exitCode = 0;
DWORD dwResult;
OSStatus err;
PROCESS_INFORMATION pi;
BOOL ok;
- ZeroMemory( &si, sizeof(si) );
- si.cb = sizeof(si);
- ZeroMemory( &pi, sizeof(pi) );
+ check( printer );
+ check( m_self );
//
- // <rdar://problem/3764873> Escape '\', '@', '"' characters which seem to cause problems for printui
+ // because we're calling endthreadex(), C++ objects won't be cleaned up
+ // correctly. we'll nest the CString 'command' inside a block so
+ // that it's destructor will be invoked.
//
+ {
+ CString command;
- actualName = printer->actualName;
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
- actualName.Replace(L"\\", L"\\\\");
- actualName.Replace(L"@", L"\\@");
- actualName.Replace(L"\"", L"\\\"");
-
- command.Format(L"rundll32.exe printui.dll,PrintUIEntry /if /b \"%s\" /f \"%s\" /r \"%s\" /m \"%s\"", (LPCTSTR) actualName, (LPCTSTR) printer->infFileName, (LPCTSTR) printer->portName, (LPCTSTR) printer->model);
+ command.Format(L"rundll32.exe printui.dll,PrintUIEntry /ia /m \"%s\" /f \"%s\"", (LPCTSTR) printer->model, (LPCTSTR) printer->infFileName );
- ok = CreateProcess(NULL, command.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
- err = translate_errno( ok, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
+ ok = CreateProcess(NULL, command.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ err = translate_errno( ok, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
- dwResult = WaitForSingleObject( pi.hProcess, INFINITE );
- translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr );
- require_noerr( err, exit );
+ dwResult = WaitForSingleObject( pi.hProcess, INFINITE );
+ translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr );
+ require_noerr( err, exit );
- ok = GetExitCodeProcess( pi.hProcess, &exitCode );
- err = translate_errno( ok, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
+ ok = GetExitCodeProcess( pi.hProcess, &exitCode );
+ err = translate_errno( ok, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+ }
+
+exit:
//
// Close process and thread handles.
//
- CloseHandle( pi.hProcess );
- CloseHandle( pi.hThread );
+ if ( pi.hProcess )
+ {
+ CloseHandle( pi.hProcess );
+ }
-exit:
+ if ( pi.hThread )
+ {
+ CloseHandle( pi.hThread );
+ }
//
// alert the main thread
//
- printer->window->PostMessage( WM_PROCESS_EVENT, err, exitCode );
+ m_self->PostMessage( WM_PROCESS_EVENT, err, exitCode );
+
+ _endthreadex_compat( 0 );
return 0;
}
Change History (most recent first):
$Log: PrinterSetupWizardSheet.h,v $
+Revision 1.6 2005/01/03 19:05:01 shersche
+Store pointer to instance of wizard sheet so that print driver install thread sends a window message to the correct window
+
+Revision 1.5 2004/12/29 18:53:38 shersche
+<rdar://problem/3725106>
+<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
+Bug #: 3725106, 3737413
+
Revision 1.4 2004/07/13 21:24:23 rpantos
Fix for <rdar://problem/3701120>.
CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
virtual ~CPrinterSetupWizardSheet();
-
- int
- InstallEventHandler(EventHandler * handler);
- int
- RemoveEventHandler(EventHandler * handler);
-
- OSStatus
+ void
SetSelectedPrinter(Printer * printer);
Printer*
HCURSOR
GetCursor();
- //
- // handles socket events for DNSService operations
- //
- virtual LONG
- OnServiceEvent(WPARAM inWParam, LPARAM inLParam);
-
//
// handles end of process event
//
afx_msg void
OnOK();
+ HCURSOR m_active;
+ HCURSOR m_arrow;
+ HCURSOR m_wait;
+
protected:
DECLARE_MESSAGE_MAP()
CFirstPage m_pgFirst;
CThirdPage m_pgThird;
CFourthPage m_pgFourth;
- static void DNSSD_API
- OnBrowse(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inName,
- const char * inType,
- const char * inDomain,
- void * inContext );
-
- static void DNSSD_API
- OnResolve(
- 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 );
+ void
+ OnServiceResolved(
+ Service * service);
void Init(void);
private:
OSStatus
- LoadPrinterNames();
+ InstallPrinter(Printer * printer);
OSStatus
- StartResolve(Printer * printer);
+ InstallPrinterPDLAndLPR(Printer * printer, Service * service, DWORD protocol);
OSStatus
- StopResolve(Printer * printer);
-
- Printer*
- LookUp(const char * inName);
-
- OSStatus
- InstallPrinter(Printer * printer);
+ InstallPrinterIPP(Printer * printer, Service * service);
static unsigned WINAPI
- InstallPrinterThread( LPVOID inParam );
-
-
- typedef std::list<Printer*> PrinterList;
- typedef std::list<EventHandler*> EventHandlerList;
- typedef std::list<DNSServiceRef> ServiceRefList;
- typedef std::map<CString,CString> PrinterNameMap;
-
- Printer * m_selectedPrinter;
-
- PrinterNameMap m_printerNames;
- PrinterList m_printerList;
- EventHandlerList m_eventHandlerList;
- ServiceRefList m_serviceRefList;
-
- bool m_processFinished;
+ InstallDriverThread( LPVOID inParam );
- HCURSOR m_active;
- HCURSOR m_arrow;
- HCURSOR m_wait;
-
- DNSServiceRef m_pdlBrowser;
+ static CPrinterSetupWizardSheet * m_self;
+ Printer * m_selectedPrinter;
+ bool m_driverThreadFinished;
+ DWORD m_driverThreadExitCode;
};
{
return m_active;
}
+
+
+// Service Types
+
+#define kPDLServiceType "_pdl-datastream._tcp."
+#define kLPRServiceType "_printer._tcp."
+#define kIPPServiceType "_ipp._tcp."
Change History (most recent first):
$Log: SecondPage.cpp,v $
+Revision 1.10 2005/01/20 19:54:38 shersche
+Fix parse error when text record is NULL
+
+Revision 1.9 2005/01/06 08:13:50 shersche
+Don't use moreComing flag to determine number of text record, disregard queue name if qtotal isn't defined, don't disregard queue name if "rp" is the only key specified
+
+Revision 1.8 2005/01/04 21:09:14 shersche
+Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
+
+Revision 1.7 2004/12/31 07:25:27 shersche
+Tidy up printer management, and fix memory leaks when hitting 'Cancel'
+
+Revision 1.6 2004/12/30 01:24:02 shersche
+<rdar://problem/3906182> Remove references to description key
+Bug #: 3906182
+
+Revision 1.5 2004/12/30 01:02:47 shersche
+<rdar://problem/3734478> Add Printer information box that displays description and location information when printer name is selected
+Bug #: 3734478
+
+Revision 1.4 2004/12/29 18:53:38 shersche
+<rdar://problem/3725106>
+<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
+Bug #: 3725106, 3737413
+
Revision 1.3 2004/09/13 21:26:15 shersche
<rdar://problem/3796483> Use the moreComing flag to determine whether drawing should take place in OnAddPrinter and OnRemovePrinter callbacks
Bug #: 3796483
#include "PrinterSetupWizardSheet.h"
#include "SecondPage.h"
#include "DebugServices.h"
+#include "WinServices.h"
+#include <winspool.h>
// local variable is initialize but not referenced
#pragma warning(disable:4189)
+#define WM_SERVICE_EVENT ( WM_USER + 0x101 )
// CSecondPage dialog
IMPLEMENT_DYNAMIC(CSecondPage, CPropertyPage)
CSecondPage::CSecondPage()
- : CPropertyPage(CSecondPage::IDD)
+ : CPropertyPage(CSecondPage::IDD),
+ m_pdlBrowser( NULL ),
+ m_lprBrowser( NULL ),
+ m_ippBrowser( NULL ),
+ m_selected( NULL )
{
m_psp.dwFlags &= ~(PSP_HASHELP);
m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
m_emptyListItem = NULL;
m_initialized = false;
m_waiting = false;
+
+ LoadPrinterNames();
}
+
CSecondPage::~CSecondPage()
{
+ StopBrowse();
+}
+
+
+OSStatus
+CSecondPage::LoadPrinterNames()
+{
+ PBYTE buffer = NULL;
+ OSStatus err = 0;
+
+ //
+ // rdar://problem/3701926 - Printer can't be installed twice
+ //
+ // First thing we want to do is make sure the printer isn't already installed.
+ // If the printer name is found, we'll try and rename it until we
+ // find a unique name
+ //
+ DWORD dwNeeded = 0, dwNumPrinters = 0;
+
+ BOOL ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwNumPrinters);
+ err = translate_errno( ok, errno_compat(), kUnknownErr );
+
+ if ((err == ERROR_INSUFFICIENT_BUFFER) && (dwNeeded > 0))
+ {
+ try
+ {
+ buffer = new unsigned char[dwNeeded];
+ }
+ catch (...)
+ {
+ buffer = NULL;
+ }
+
+ require_action( buffer, exit, kNoMemoryErr );
+ ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, buffer, dwNeeded, &dwNeeded, &dwNumPrinters);
+ err = translate_errno( ok, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+ for (DWORD index = 0; index < dwNumPrinters; index++)
+ {
+ PRINTER_INFO_4 * lppi4 = (PRINTER_INFO_4*) (buffer + index * sizeof(PRINTER_INFO_4));
+
+ m_printerNames[lppi4->pPrinterName] = lppi4->pPrinterName;
+ }
+ }
+
+exit:
+
+ if (buffer != NULL)
+ {
+ delete [] buffer;
+ }
+
+ return err;
}
//
text.LoadString(IDS_NO_RENDEZVOUS_PRINTERS);
- m_emptyListItem = m_browseList.InsertItem( text, 0, 0, NULL, TVI_FIRST );
-
- //
- // this will remove everything else in the list...we might be navigating
- // back to this window, and the browse list might have changed since
- // we last displayed it.
- //
- if ( m_emptyListItem )
- {
- HTREEITEM item = m_browseList.GetNextVisibleItem( m_emptyListItem );
-
- while ( item )
- {
- m_browseList.DeleteItem( item );
- item = m_browseList.GetNextVisibleItem( m_emptyListItem );
- }
- }
+ LoadTextAndDisableWindow( text );
//
// disable the next button until there's a printer to select
psheet->SetWizardButtons(PSWIZB_BACK);
//
- // disable the window until there's a printer to select
+ // disable the printer information box
//
- m_browseList.EnableWindow( FALSE );
+ SetPrinterInformationState( FALSE );
exit:
}
-void CSecondPage::DoDataExchange(CDataExchange* pDX)
+OSStatus
+CSecondPage::StartOperation( DNSServiceRef ref )
{
- CPropertyPage::DoDataExchange(pDX);
- DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
+ OSStatus err;
+
+ err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(ref), m_hWnd, WM_SERVICE_EVENT, FD_READ|FD_CLOSE);
+ require_noerr( err, exit );
+
+ m_serviceRefList.push_back( ref );
+
+exit:
+
+ return err;
}
-afx_msg BOOL
-CSecondPage::OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT message)
+OSStatus
+CSecondPage::StopOperation( DNSServiceRef & ref )
{
- DEBUG_UNUSED(pWnd);
- DEBUG_UNUSED(nHitTest);
- DEBUG_UNUSED(message);
+ OSStatus err = kNoErr;
- CPrinterSetupWizardSheet * psheet;
+ if ( ref )
+ {
+ m_serviceRefList.remove( ref );
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
+ if ( IsWindow( m_hWnd ) )
+ {
+ err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD( ref ), m_hWnd, 0, 0 );
+ require_noerr( err, exit );
+ }
- SetCursor(psheet->GetCursor());
+ DNSServiceRefDeallocate( ref );
+ ref = NULL;
+ }
exit:
- return TRUE;
+ return err;
}
-BOOL
-CSecondPage::OnSetActive()
+Printer*
+CSecondPage::Lookup(const char * inName)
{
- CString noPrinters;
- CPrinterSetupWizardSheet * psheet;
+ check( IsWindow( m_hWnd ) );
+ check( inName );
+
+ HTREEITEM item = m_browseList.GetChildItem( TVI_ROOT );\r
+ while ( item )\r
+ {\r
+ Printer * printer;\r
+ DWORD_PTR data;\r
+\r
+ data = m_browseList.GetItemData( item );\r
+ printer = reinterpret_cast<Printer*>(data);\r
+\r
+ if ( printer && ( printer->name == inName ) )
+ {
+ return printer;
+ }
+\r
+ item = m_browseList.GetNextItem( item, TVGN_NEXT );
+ }
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
-
- //
- // initialize the browse list...this will remove everything currently
- // in it, and add the no rendezvous printers item
- //
- InitBrowseList();
+ return NULL;
+}
+
+
+OSStatus
+CSecondPage::StartBrowse()
+{
+ OSStatus err;
//
- // this will invoke OnAddPrinter for all the printers that we have
- // browsed
+ // setup the DNS-SD browsing
//
- psheet->InstallEventHandler(this);
+ err = DNSServiceBrowse( &m_pdlBrowser, 0, 0, kPDLServiceType, NULL, OnBrowse, this );
+ require_noerr( err, exit );
+
+ err = StartOperation( m_pdlBrowser );
+ require_noerr( err, exit );
+
+ err = DNSServiceBrowse( &m_lprBrowser, 0, 0, kLPRServiceType, NULL, OnBrowse, this );
+ require_noerr( err, exit );
+
+ err = StartOperation( m_lprBrowser );
+ require_noerr( err, exit );
+
+ err = DNSServiceBrowse( &m_ippBrowser, 0, 0, kIPPServiceType, NULL, OnBrowse, this );
+ require_noerr( err, exit );
+
+ err = StartOperation( m_ippBrowser );
+ require_noerr( err, exit );
exit:
- return CPropertyPage::OnSetActive();
+ return err;
}
-BOOL
-CSecondPage::OnKillActive()
+OSStatus
+CSecondPage::StopBrowse()
{
- CPrinterSetupWizardSheet * psheet;
+ OSStatus err;
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
+ err = StopOperation( m_pdlBrowser );
+ require_noerr( err, exit );
- //
- // we don't want our event handlers called when we don't have
- // anywhere to put the data
- //
- psheet->RemoveEventHandler(this);
+ err = StopOperation( m_lprBrowser );
+ require_noerr( err, exit );
+
+ err = StopOperation( m_ippBrowser );
+ require_noerr( err, exit );
+
+ while ( m_printers.size() > 0 )
+ {
+ Printer * printer = m_printers.front();
+
+ m_printers.pop_front();
+
+ if ( printer->resolving )
+ {
+ StopResolve( printer );
+ }
+
+ delete printer;
+ }
exit:
- return CPropertyPage::OnKillActive();
+ return err;
}
-BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
- ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList)
- ON_WM_SETCURSOR()
-END_MESSAGE_MAP()
+OSStatus
+CSecondPage::StartResolve( Printer * printer )
+{
+ CPrinterSetupWizardSheet * psheet;
+ OSStatus err = kNoErr;
+ Services::iterator it;
+
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
+ check( printer );
-// Printer::EventHandler implementation
-void
-CSecondPage::OnAddPrinter(
- Printer * printer,
- bool moreComing)
+ for ( it = printer->services.begin(); it != printer->services.end(); it++ )
+ {
+ if ( (*it)->serviceRef == NULL )
+ {
+ err = StartResolve( *it );
+ require_noerr( err, exit );
+ }
+ }
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CSecondPage::StartResolve( Service * service )
{
- check( IsWindow( m_hWnd ) );
+ CPrinterSetupWizardSheet * psheet;
+ OSStatus err = kNoErr;
- m_browseList.SetRedraw(FALSE);
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
- printer->item = m_browseList.InsertItem(printer->displayName);
+ check( service->serviceRef == NULL );
- m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
-
- m_browseList.SortChildren(TVI_ROOT);
+ //
+ // clean out any queues that were collected during a previous
+ // resolve
+ //
+ service->EmptyQueues();
+
+ //
+ // now start the new resolve
//
- // if the searching item is still in the list
- // get rid of it
+
+ err = DNSServiceResolve( &service->serviceRef, 0, 0, service->printer->name.c_str(), service->type.c_str(), service->domain.c_str(), (DNSServiceResolveReply) OnResolve, service );
+ require_noerr( err, exit );
+
+ err = StartOperation( service->serviceRef );
+ require_noerr( err, exit );
+
//
- // note that order is important here. Insert the printer
- // item before removing the placeholder so we always have
- // an item in the list to avoid experiencing the bug
- // in Microsoft's implementation of CTreeCtrl
+ // If we're not currently resolving, then disable the next button
+ // and set the cursor to hourglass
//
- if (m_emptyListItem != NULL)
- {
- m_browseList.DeleteItem(m_emptyListItem);
- m_emptyListItem = NULL;
- m_browseList.EnableWindow(TRUE);
- }
- if (!moreComing)
+ if ( !service->printer->resolving )
{
- m_browseList.SetRedraw(TRUE);
- m_browseList.Invalidate();
+ psheet->SetWizardButtons( PSWIZB_BACK );
+
+ psheet->m_active = psheet->m_wait;
+ SetCursor(psheet->m_active);
}
+
+ service->printer->resolving++;
+
+exit:
+
+ return err;
}
-void
-CSecondPage::OnRemovePrinter(
- Printer * printer,
- bool moreComing)
+OSStatus
+CSecondPage::StopResolve(Printer * printer)
{
- check( IsWindow( m_hWnd ) );
+ OSStatus err = kNoErr;
- m_browseList.SetRedraw(FALSE);
+ check( printer );
- //
- // check to make sure if we're the only item in the control...i.e.
- // the list size is 1.
- //
- if (m_browseList.GetCount() > 1)
- {
- //
- // if we're not the only thing in the list, then
- // simply remove it from the list
- //
- m_browseList.DeleteItem( printer->item );
- }
- else
- {
- //
- // if we're the only thing in the list, then redisplay
- // it with the no rendezvous printers message
- //
- InitBrowseList();
- }
+ Services::iterator it;
- if (!moreComing)
+ for ( it = printer->services.begin(); it != printer->services.end(); it++ )
{
- m_browseList.SetRedraw(TRUE);
- m_browseList.Invalidate();
+ if ( (*it)->serviceRef )
+ {
+ err = StopResolve( *it );
+ require_noerr( err, exit );
+ }
}
+
+exit:
+
+ return err;
}
-void
-CSecondPage::OnResolvePrinter(
- Printer * printer)
+OSStatus
+CSecondPage::StopResolve( Service * service )
{
- DEBUG_UNUSED(printer);
+ OSStatus err;
- check( IsWindow( m_hWnd ) );
+ check( service->serviceRef );
- CPrinterSetupWizardSheet * psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
-
- //
- // setup the sheet to enable the next button if we've successfully
- // resolved
- //
- psheet->SetWizardButtons( PSWIZB_BACK|PSWIZB_NEXT );
+ err = StopOperation( service->serviceRef );
+ require_noerr( err, exit );
+
+ service->printer->resolving--;
exit:
- return;
+ return err;
}
-void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
+void CSecondPage::DoDataExchange(CDataExchange* pDX)
{
- LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
- CPrinterSetupWizardSheet * psheet;
- int err = 0;
+ CPropertyPage::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
+ DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation);\r
+ DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel);\r
+ DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField);\r
+ DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel);\r
+ DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField);\r
+}
- HTREEITEM item = m_browseList.GetSelectedItem();
- require_quiet( item, exit );
+
+afx_msg BOOL
+CSecondPage::OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT message)
+{
+ DEBUG_UNUSED(pWnd);
+ DEBUG_UNUSED(nHitTest);
+ DEBUG_UNUSED(message);
+
+ CPrinterSetupWizardSheet * psheet;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_action( psheet, exit, err = kUnknownErr );
+ require_quiet( psheet, exit );
- Printer * printer;
+ SetCursor(psheet->GetCursor());
- printer = reinterpret_cast<Printer*>(m_browseList.GetItemData( item ) );
- require_quiet( printer, exit );
+exit:
+
+ return TRUE;
+}
+
+
+BOOL
+CSecondPage::OnSetActive()
+{
+ CPrinterSetupWizardSheet * psheet;
+ Printer * printer;
+ OSStatus err = kNoErr;
+
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_action( psheet, exit, err = kUnknownErr );
+
+ if ( ( printer = psheet->GetSelectedPrinter() ) != NULL )
+ {
+ psheet->SetSelectedPrinter( NULL );
+ delete printer;
+ }
//
- // this call will trigger a resolve. When the resolve is complete,
- // our OnResolve will be called.
+ // initialize the browse list...this will remove everything currently
+ // in it, and add the no rendezvous printers item
//
- err = psheet->SetSelectedPrinter(printer);
- require_noerr( err, exit );
+ InitBrowseList();
//
- // setup the sheet to disable the next button until we've successfully
- // resolved this printer
+ // start browing
//
- psheet->SetWizardButtons( PSWIZB_BACK );
+ err = StartBrowse();
+ require_noerr( err, exit );
exit:
- if (err != 0)
+ if ( err != kNoErr )
{
- CString text;
+ if ( err == kDNSServiceErr_Firewall )
+ {
+ CString text, caption;
+
+ text.LoadString( IDS_FIREWALL );
+ caption.LoadString( IDS_FIREWALL_CAPTION );
+
+ MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
+ }
+ else
+ {
+ CPrinterSetupWizardSheet::WizardException exc;
+
+ exc.text.LoadString( IDS_NO_MDNSRESPONDER_SERVICE_TEXT );
+ exc.caption.LoadString( IDS_ERROR_CAPTION );
+
+ throw(exc);
+ }
+ }
+
+ return CPropertyPage::OnSetActive();
+}
+
+
+BOOL
+CSecondPage::OnKillActive()
+{
+ OSStatus err = kNoErr;
+
+ if ( m_selected )
+ {
+ CPrinterSetupWizardSheet * psheet;
+
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ psheet->SetSelectedPrinter( m_selected );
+ m_printers.remove( m_selected );
+ m_selected = NULL;
+ }
+
+ err = StopBrowse();
+ require_noerr( err, exit );
+
+exit:
+
+ return CPropertyPage::OnKillActive();
+}
+
+
+void DNSSD_API
+CSecondPage::OnBrowse(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ void * inContext )
+{
+ DEBUG_UNUSED(inRef);
+
+ CSecondPage * self;
+ bool moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing);
+
+ require_noerr( inErrorCode, exit );
+
+ self = reinterpret_cast <CSecondPage*>( inContext );
+ require_quiet( self, exit );
+
+ if ( inFlags & kDNSServiceFlagsAdd )
+ {
+ self->OnAddPrinter( inInterfaceIndex, inName, inType, inDomain, moreComing );
+ }
+ else
+ {
+ self->OnRemovePrinter( inName, inType, inDomain, moreComing );
+ }
+
+exit:
+
+ return;
+}
+
+
+void DNSSD_API
+CSecondPage::OnResolve(
+ 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 )
+{
+ DEBUG_UNUSED(inFullName);
+ DEBUG_UNUSED(inInterfaceIndex);
+ DEBUG_UNUSED(inFlags);
+ DEBUG_UNUSED(inRef);
+
+ CSecondPage * self;
+ Service * service;
+ Queue * q;
+ bool qtotalDefined = false;
+ uint32_t qpriority = kDefaultPriority;
+ CString qname;
+ int idx;
+ OSStatus err;
+
+ require_noerr( inErrorCode, exit );
+
+ service = reinterpret_cast<Service*>( inContext );
+ require_quiet( service, exit);
+
+ check( service->refs != 0 );
+
+ self = service->printer->window;
+ require_quiet( self, exit );
+
+ err = self->StopOperation( service->serviceRef );
+ require_noerr( err, exit );
+
+ //
+ // hold on to the hostname...
+ //
+ err = UTF8StringToStringObject( inHostName, service->hostname );
+ require_noerr( err, exit );
+
+ //
+ // <rdar://problem/3739200> remove the trailing dot on hostname
+ //
+ idx = service->hostname.ReverseFind('.');
+
+ if ((idx > 1) && ((service->hostname.GetLength() - 1) == idx))
+ {
+ service->hostname.Delete(idx, 1);
+ }
+
+ //
+ // hold on to the port
+ //
+ service->portNumber = ntohs(inPort);
+
+ //
+ // parse the text record.
+ //
+
+ err = self->ParseTextRecord( service, inTXTSize, inTXT, qtotalDefined, qname, qpriority );
+ require_noerr( err, exit );
+
+ if ( service->qtotal == 1 )
+ {
+ //
+ // create a new queue
+ //
+ try
+ {
+ q = new Queue;
+ }
+ catch (...)
+ {
+ q = NULL;
+ }
+
+ require_action( q, exit, err = E_OUTOFMEMORY );
+
+ if ( qtotalDefined )
+ {
+ q->name = qname;
+ }
+
+ q->priority = qpriority;
+
+ service->queues.push_back( q );
+
+ //
+ // we've completely resolved this service
+ //
+
+ self->OnResolveService( service );
+ }
+ else
+ {
+ //
+ // if qtotal is more than 1, then we need to get additional
+ // text records. if not, then this service is considered
+ // resolved
+ //
+
+ err = DNSServiceQueryRecord(&service->serviceRef, 0, inInterfaceIndex, inFullName, kDNSServiceType_TXT, kDNSServiceClass_IN, OnQuery, (void*) service );
+ require_noerr( err, exit );
+
+ err = self->StartOperation( service->serviceRef );
+ require_noerr( err, exit );
+ }
+
+exit:
+
+ return;
+}
+
+
+void DNSSD_API
+CSecondPage::OnQuery(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inFullName,
+ uint16_t inRRType,
+ uint16_t inRRClass,
+ uint16_t inRDLen,
+ const void * inRData,
+ uint32_t inTTL,
+ void * inContext)
+{
+ DEBUG_UNUSED( inTTL );
+ DEBUG_UNUSED( inRRClass );
+ DEBUG_UNUSED( inRRType );
+ DEBUG_UNUSED( inFullName );
+ DEBUG_UNUSED( inInterfaceIndex );
+ DEBUG_UNUSED( inRef );
+
+ Service * service = NULL;
+ Queue * q;
+ CSecondPage * self;
+ bool qtotalDefined = false;
+ bool moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing);
+ OSStatus err = kNoErr;
+
+ require_noerr( inErrorCode, exit );
+
+ service = reinterpret_cast<Service*>( inContext );
+ require_quiet( service, exit);
+
+ self = service->printer->window;
+ require_quiet( self, exit );
+
+ if ( ( inFlags & kDNSServiceFlagsAdd ) && ( inRDLen > 0 ) && ( inRData != NULL ) )
+ {
+ const char * inTXT = ( const char * ) inRData;
+
+ //
+ // create a new queue
+ //
+ try
+ {
+ q = new Queue;
+ }
+ catch (...)
+ {
+ q = NULL;
+ }
+
+ require_action( q, exit, err = E_OUTOFMEMORY );
+
+ err = service->printer->window->ParseTextRecord( service, inRDLen, inTXT, qtotalDefined, q->name, q->priority );
+ require_noerr( err, exit );
+
+ if ( !qtotalDefined )
+ {
+ q->name = L"";
+ }
+
+ //
+ // add this queue
+ //
+
+ service->queues.push_back( q );
+
+ if ( service->queues.size() == service->qtotal )
+ {
+ //
+ // else if moreComing is not set, then we're going
+ // to assume that we're done
+ //
+
+ self->StopOperation( service->serviceRef );
+
+ //
+ // sort the queues
+ //
+
+ service->queues.sort( OrderQueueFunc );
+
+ //
+ // we've completely resolved this service
+ //
+
+ self->OnResolveService( service );
+ }
+ }
+
+exit:
+
+ if ( err && service && ( service->serviceRef != NULL ) )
+ {
+ service->printer->window->StopOperation( service->serviceRef );
+ }
+
+ return;
+}
+
+
+BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
+ ON_MESSAGE( WM_SERVICE_EVENT, OnServiceEvent )
+ ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList)
+ ON_WM_SETCURSOR()
+END_MESSAGE_MAP()
+
+
+// Printer::EventHandler implementation
+OSStatus
+CSecondPage::OnAddPrinter(
+ uint32_t inInterfaceIndex,
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ bool moreComing)
+{
+ Printer * printer;
+ Service * service;
+ CPrinterSetupWizardSheet * psheet;
+ DWORD printerNameCount;
+ bool newPrinter = false;
+ OSStatus err = kNoErr;
+
+ check( IsWindow( m_hWnd ) );
+
+ m_browseList.SetRedraw(FALSE);
+
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ printer = Lookup( inName );
+
+ if (printer == NULL)
+ {
+ try
+ {
+ printer = new Printer;
+ }
+ catch (...)
+ {
+ printer = NULL;
+ }
+
+ require_action( printer, exit, err = E_OUTOFMEMORY );
+
+ printer->window = this;
+ printer->name = inName;
+
+ err = UTF8StringToStringObject(inName, printer->displayName);
+ check_noerr( err );
+ printer->actualName = printer->displayName;
+ printer->installed = false;
+ printer->deflt = false;
+ printer->resolving = 0;
+
+ //
+ // Compare this name against printers that are already installed
+ // to avoid name clashes. Rename as necessary
+ // to come up with a unique name.
+ //
+ printerNameCount = 2;
+
+ for (;;)
+ {
+ PrinterNameMap::iterator it;
+
+ it = m_printerNames.find(printer->actualName);
+
+ if (it != m_printerNames.end())
+ {
+ printer->actualName.Format(L"%s (%d)", printer->displayName, printerNameCount);
+ }
+ else
+ {
+ break;
+ }
+
+ printerNameCount++;
+ }
+
+ newPrinter = true;
+ }
+
+ check( printer );
+
+ service = printer->LookupService( inType );
+
+ if ( service != NULL )
+ {
+ service->refs++;
+ }
+ else
+ {
+ try
+ {
+ service = new Service;
+ }
+ catch (...)
+ {
+ service = NULL;
+ }
+
+ require_action( service, exit, err = E_OUTOFMEMORY );
+
+ service->printer = printer;
+ service->ifi = inInterfaceIndex;
+ service->type = inType;
+ service->domain = inDomain;
+ service->qtotal = 1;
+ service->refs = 1;
+ service->serviceRef = NULL;
+
+ printer->services.push_back( service );
+
+ //
+ // if the printer is selected, then we'll want to start a
+ // resolve on this guy
+ //
+
+ if ( m_selected == printer )
+ {
+ StartResolve( service );
+ }
+ }
+
+ if ( newPrinter )
+ {
+ printer->item = m_browseList.InsertItem(printer->displayName);
+
+ m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
+
+ m_printers.push_back( 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
+ // get rid of it
+ //
+ // note that order is important here. Insert the printer
+ // item before removing the placeholder so we always have
+ // an item in the list to avoid experiencing the bug
+ // in Microsoft's implementation of CTreeCtrl
+ //
+ if (m_emptyListItem != NULL)
+ {
+ m_browseList.DeleteItem(m_emptyListItem);
+ m_emptyListItem = NULL;
+ m_browseList.EnableWindow(TRUE);
+ }
+ }
+
+exit:
+
+ if (!moreComing)
+ {
+ m_browseList.SetRedraw(TRUE);
+ m_browseList.Invalidate();
+ }
+
+ return err;
+}
+
+
+OSStatus
+CSecondPage::OnRemovePrinter(
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ bool moreComing)
+{
+ DEBUG_UNUSED( inDomain );
+ DEBUG_UNUSED( inType );
+
+ Printer * printer;
+ OSStatus err = kNoErr;
+
+ check( IsWindow( m_hWnd ) );
+
+ m_browseList.SetRedraw(FALSE);
+
+ printer = Lookup( inName );
+
+ if ( printer )
+ {
+ Service * service;
+
+ service = printer->LookupService( inType );
+
+ if ( service && ( --service->refs == 0 ) )
+ {
+ if ( service->serviceRef != NULL )
+ {
+ err = StopResolve( service );
+ require_noerr( err, exit );
+ }
+
+ printer->services.remove( service );
+
+ delete service;
+ }
+
+ if ( printer->services.size() == 0 )
+ {
+ //
+ // check to make sure if we're the only item in the control...i.e.
+ // the list size is 1.
+ //
+ if (m_browseList.GetCount() > 1)
+ {
+ //
+ // if we're not the only thing in the list, then
+ // simply remove it from the list
+ //
+ m_browseList.DeleteItem( printer->item );
+ }
+ else
+ {
+ //
+ // if we're the only thing in the list, then redisplay
+ // it with the no rendezvous printers message
+ //
+ InitBrowseList();
+ }
+
+ m_printers.remove( printer );
+
+ if ( m_selected == printer )
+ {
+ m_selected = NULL;
+ m_selectedName = "";
+ }
+
+ delete printer;
+ }
+ }
+
+exit:
+
+ if (!moreComing)
+ {
+ m_browseList.SetRedraw(TRUE);
+ m_browseList.Invalidate();
+ }
+
+ return err;
+}
+
+
+void
+CSecondPage::OnResolveService( Service * service )
+{
+ CPrinterSetupWizardSheet * psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ check( service );
+
+ if ( !--service->printer->resolving )
+ {
+ //
+ // sort the services now. we want the service that
+ // has the highest priority queue to be first in
+ // the list.
+ //
+
+ service->printer->services.sort( OrderServiceFunc );
+
+ //
+ // and set it to selected
+ //
+
+ m_selected = service->printer;
+ m_selectedName = service->printer->name;
+
+ //
+ // and update the printer information box
+ //
+ SetPrinterInformationState( TRUE );
+
+ m_descriptionField.SetWindowText( service->description );
+ m_locationField.SetWindowText( service->location );
+
+ psheet->SetWizardButtons( PSWIZB_BACK|PSWIZB_NEXT );
+
+ //
+ // reset the cursor
+ //
+
+ psheet->m_active = psheet->m_arrow;
+ SetCursor(psheet->m_active);
+ }
+
+exit:
+
+ return;
+}
+
+
+LONG
+CSecondPage::OnServiceEvent(WPARAM inWParam, LPARAM inLParam)
+{
+ if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
+ {
+ dlog( kDebugLevelError, "OnServiceEvent: window error\n" );
+ }
+ else
+ {
+ SOCKET sock = (SOCKET) inWParam;
+
+ // iterate thru list
+ ServiceRefList::iterator begin = m_serviceRefList.begin();
+ ServiceRefList::iterator end = m_serviceRefList.end();
+
+ while (begin != end)
+ {
+ DNSServiceRef ref = *begin++;
+
+ check(ref != NULL);
+
+ if ((SOCKET) DNSServiceRefSockFD(ref) == sock)
+ {
+ DNSServiceProcessResult(ref);
+ break;
+ }
+ }
+ }
+
+ return ( 0 );
+}
+
+
+void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
+{
+ LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
+ CPrinterSetupWizardSheet * psheet;
+ int err = 0;
+
+ HTREEITEM item = m_browseList.GetSelectedItem();
+ require_quiet( item, exit );
+
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_action( psheet, exit, err = kUnknownErr );
+
+ Printer * printer;
+
+ printer = reinterpret_cast<Printer*>(m_browseList.GetItemData( item ) );
+ require_quiet( printer, exit );
+
+ //
+ // this call will trigger a resolve. When the resolve is complete,
+ // our OnResolve will be called.
+ //
+ err = StartResolve( printer );
+ require_noerr( err, exit );
+
+ //
+ // And clear out the printer information box
+ //
+ SetPrinterInformationState( FALSE );
+ m_descriptionField.SetWindowText(L"");
+ m_locationField.SetWindowText(L"");
+
+exit:
+
+ if (err != 0)
+ {
+ CString text;
CString caption;
text.LoadString(IDS_ERROR_SELECTING_PRINTER_TEXT);
*pResult = 0;
}
+
+
+bool
+CSecondPage::OrderServiceFunc( const Service * a, const Service * b )
+{
+ Queue * q1, * q2;
+
+ q1 = (a->queues.size() > 0) ? a->queues.front() : NULL;
+
+ q2 = (b->queues.size() > 0) ? b->queues.front() : NULL;
+
+ if ( !q1 && !q2 )
+ {
+ return true;
+ }
+ else if ( q1 && !q2 )
+ {
+ return true;
+ }
+ else if ( !q1 && q2 )
+ {
+ return false;
+ }
+ else if ( q1->priority < q2->priority )
+ {
+ return true;
+ }
+ else if ( q1->priority > q2->priority )
+ {
+ return false;
+ }
+ else if ( ( a->type == kPDLServiceType ) || ( ( a->type == kLPRServiceType ) && ( b->type == kIPPServiceType ) ) )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+bool
+CSecondPage::OrderQueueFunc( const Queue * q1, const Queue * q2 )
+{
+ return ( q1->priority <= q2->priority ) ? true : false;
+}
+
+
+void
+CSecondPage::LoadTextAndDisableWindow( CString & text )
+{
+ m_emptyListItem = m_browseList.InsertItem( text, 0, 0, NULL, TVI_FIRST );
+ m_browseList.SelectItem( NULL );
+
+ //
+ // this will remove everything else in the list...we might be navigating
+ // back to this window, and the browse list might have changed since
+ // we last displayed it.
+ //
+ if ( m_emptyListItem )
+ {
+ HTREEITEM item = m_browseList.GetNextVisibleItem( m_emptyListItem );
+
+ while ( item )
+ {
+ m_browseList.DeleteItem( item );
+ item = m_browseList.GetNextVisibleItem( m_emptyListItem );
+ }
+ }
+
+ m_browseList.EnableWindow( FALSE );
+}
+
+
+void
+CSecondPage::SetPrinterInformationState( BOOL state )
+{
+ m_printerInformation.EnableWindow( state );\r
+ m_descriptionLabel.EnableWindow( state );\r
+ m_descriptionField.EnableWindow( state );\r
+ m_locationLabel.EnableWindow( state );\r
+ m_locationField.EnableWindow( state );\r
+}\r
+\r
+\r
+OSStatus
+CSecondPage::ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, bool & qtotalDefined, CString & qname, uint32_t & qpriority )
+{
+ bool rpOnly = true;
+ OSStatus err = kNoErr;
+
+ while (inTXTSize)
+ {
+ char buf[256];
+
+ unsigned char num = *inTXT;
+ check( (int) num < inTXTSize );
+
+ if ( num )
+ {
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, inTXT + 1, num);
+
+ CString elem;
+
+ err = UTF8StringToStringObject( buf, elem );
+ require_noerr( err, exit );
+
+ int curPos = 0;
+
+ CString key = elem.Tokenize(L"=", curPos);
+ CString val = elem.Tokenize(L"=", curPos);
+
+ key.MakeLower();
+
+ if ( key == L"rp" )
+ {
+ qname = val;
+ }
+ else
+ {
+ rpOnly = false;
+
+ if ((key == L"usb_mfg") || (key == L"usb_manufacturer"))
+ {
+ service->usb_MFG = val;
+ }
+ else if ((key == L"usb_mdl") || (key == L"usb_model"))
+ {
+ service->usb_MDL = val;
+ }
+ else if (key == L"ty")
+ {
+ service->description = val;
+ }
+ else if (key == L"product")
+ {
+ service->product = val;
+ }
+ else if (key == L"note")
+ {
+ service->location = val;
+ }
+ else if (key == L"qtotal")
+ {
+ service->qtotal = (unsigned short) _ttoi((LPCTSTR) val);
+ qtotalDefined = true;
+ }
+ else if (key == L"priority")
+ {
+ qpriority = _ttoi((LPCTSTR) val);
+ }
+ }
+ }
+
+ inTXTSize -= (num + 1);
+ inTXT += (num + 1);
+ }
+
+exit:
+
+ if ( rpOnly )
+ {
+ qtotalDefined = true;
+ }
+
+ return err;
+}
+
+
Change History (most recent first):
$Log: SecondPage.h,v $
+Revision 1.6 2005/01/04 21:09:14 shersche
+Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
+
+Revision 1.5 2004/12/31 07:25:27 shersche
+Tidy up printer management, and fix memory leaks when hitting 'Cancel'
+
+Revision 1.4 2004/12/30 01:02:46 shersche
+<rdar://problem/3734478> Add Printer information box that displays description and location information when printer name is selected
+Bug #: 3734478
+
+Revision 1.3 2004/12/29 18:53:38 shersche
+<rdar://problem/3725106>
+<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
+Bug #: 3725106, 3737413
+
Revision 1.2 2004/09/13 21:23:42 shersche
<rdar://problem/3796483> Add moreComing argument to OnAddPrinter and OnRemovePrinter callbacks
Bug #: 3796483
// CSecondPage dialog
-class CSecondPage : public CPropertyPage, public EventHandler
+class CSecondPage : public CPropertyPage
{
DECLARE_DYNAMIC(CSecondPage)
// Dialog Data
enum { IDD = IDD_SECOND_PAGE };
- virtual void
- OnAddPrinter(
- Printer * printer,
- bool moreComing);
-
- virtual void
- OnRemovePrinter(
- Printer * printer,
- bool moreComing);
-
- virtual void
- OnResolvePrinter(
- Printer * printer);
+ static void DNSSD_API
+ OnBrowse(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ void * inContext );
+
+ static void DNSSD_API
+ OnResolve(
+ 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 DNSSD_API
+ OnQuery(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inFullName,
+ uint16_t inRRType,
+ uint16_t inRRClass,
+ uint16_t inRDLen,
+ const void * inRData,
+ uint32_t inTTL,
+ void * inContext);
protected:
bool m_initialized;
bool m_waiting;
- afx_msg void OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);
+ LONG OnServiceEvent(WPARAM inWParam, LPARAM inLParam);
+ afx_msg void OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);
+
+private:
+
+ OSStatus
+ LoadPrinterNames();
+
+ Printer*
+ Lookup( const char * name );
+
+ OSStatus
+ StartOperation( DNSServiceRef ref );
+
+ OSStatus
+ StopOperation( DNSServiceRef & ref );
+
+ OSStatus
+ StartBrowse();
+
+ OSStatus
+ StopBrowse();
+
+ OSStatus
+ StartResolve( Printer * printer );
+
+ OSStatus
+ StartResolve( Service * service );
+
+ OSStatus
+ StopResolve( Printer * printer );
+
+ OSStatus
+ StopResolve( Service * service );
+
+ OSStatus
+ OnAddPrinter(
+ uint32_t inInterfaceIndex,
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ bool moreComing);
+
+ OSStatus
+ OnRemovePrinter(
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ bool moreComing);
+
+ void
+ OnResolveService( Service * service );
+
+ static bool
+ OrderServiceFunc( const Service * a, const Service * b );
+
+ static bool
+ OrderQueueFunc( const Queue * q1, const Queue * q2 );
+
+ void
+ LoadTextAndDisableWindow( CString & text );
+
+ void
+ SetPrinterInformationState( BOOL state );
+
+ OSStatus
+ ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, bool & qtotalDefined, CString & qname, uint32_t & qpriority );
+
+ typedef std::map<CString,CString> PrinterNameMap;
+ typedef std::list<DNSServiceRef> ServiceRefList;
+ typedef std::list<Printer*> Printers;
+
+
+ PrinterNameMap m_printerNames;
+ Printers m_printers;
+ ServiceRefList m_serviceRefList;
+ DNSServiceRef m_pdlBrowser;
+ DNSServiceRef m_lprBrowser;
+ DNSServiceRef m_ippBrowser;
+
+ Printer * m_selected;
+ std::string m_selectedName;
+\r
+private:\r
+\r
+ CStatic m_printerInformation;\r
+ CStatic m_descriptionLabel;\r
+ CStatic m_descriptionField;\r
+ CStatic m_locationLabel;\r
+ CStatic m_locationField;\r
};
Change History (most recent first):
$Log: ThirdPage.cpp,v $
+Revision 1.14 2005/01/25 08:55:54 shersche
+<rdar://problem/3911084> Load icons at run-time from resource DLL
+Bug #: 3911084
+
+Revision 1.13 2005/01/06 08:15:45 shersche
+Append queue name to end of LPR port name, correctly build port name when queue name is absent
+
+Revision 1.12 2005/01/05 01:06:12 shersche
+<rdar://problem/3841218> Strip the first substring off the product key if an initial match can't be found with the whole product key.
+Bug #: 3841218
+
+Revision 1.11 2004/12/29 18:53:38 shersche
+<rdar://problem/3725106>
+<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
+Bug #: 3725106, 3737413
+
Revision 1.10 2004/10/11 22:55:34 shersche
<rdar://problem/3827624> Use the IP port number when deriving the printer port name.
Bug #: 3827624
IMPLEMENT_DYNAMIC(CThirdPage, CPropertyPage)
CThirdPage::CThirdPage()
: CPropertyPage(CThirdPage::IDD),
- m_initialized(false)
+ m_initialized(false),
+ m_printerImage( NULL )
{
m_psp.dwFlags &= ~(PSP_HASHELP);
m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
//
// ----------------------------------------------------
void
-CThirdPage::SelectMatch(Printer * printer, Manufacturer * manufacturer, Model * model)
+CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model)
{
LVFINDINFO info;
int nIndex;
m_modelListCtrl.SetFocus();
}
- CopyPrinterSettings( printer, manufacturer, model );
+ CopyPrinterSettings( printer, service, manufacturer, model );
}
// --------------------------------------------------------
void
-CThirdPage::CopyPrinterSettings( Printer * printer, Manufacturer * manufacturer, Model * model )
+CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufacturer * manufacturer, Model * model )
{
printer->manufacturer = manufacturer->name;
printer->model = model->name;
printer->driverInstalled = model->driverInstalled;
printer->infFileName = model->infFileName;
- printer->portName.Format(L"IP_%s.%d", static_cast<LPCTSTR>(printer->hostname), printer->portNumber);
+
+ if ( service->type == kPDLServiceType )
+ {
+ printer->portName.Format(L"IP_%s.%d", static_cast<LPCTSTR>(service->hostname), service->portNumber);
+ service->protocol = L"Raw";
+ }
+ else if ( service->type == kLPRServiceType )
+ {
+ Queue * q = service->queues.front();
+ check( q );
+
+ if ( q->name.GetLength() > 0 )
+ {
+ printer->portName.Format(L"LPR_%s.%d.%s", static_cast<LPCTSTR>(service->hostname), service->portNumber, static_cast<LPCTSTR>(q->name) );
+ }
+ else
+ {
+ printer->portName.Format(L"LPR_%s.%d", static_cast<LPCTSTR>(service->hostname), service->portNumber);
+ }
+
+ service->protocol = L"LPR";
+ }
+ else if ( service->type == kIPPServiceType )
+ {
+ Queue * q = service->queues.front();
+ check( q );
+
+ if ( q->name.GetLength() > 0 )
+ {
+ printer->portName.Format(L"http://%s:%d/printers/%s", static_cast<LPCTSTR>(service->hostname), service->portNumber, static_cast<LPCTSTR>(q->name) );
+ }
+ else
+ {
+ printer->portName.Format(L"http://%s:%d/", static_cast<LPCTSTR>(service->hostname), service->portNumber );
+ }
+
+ service->protocol = L"IPP";
+ }
}
//
// get rid of all delimiters
//
+ key.Trim();
val.Remove('"');
//
CString name = s.Tokenize(L"=",curPos);
CString description = s.Tokenize(L"=",curPos);
- name.Remove('"');
+ if (name.Find('%') == 0)
+ {
+ StringMap::iterator it;
+
+ name.Remove('%');
+
+ it = strings.find(name);
+
+ if (it != strings.end())
+ {
+ name = it->second;
+ }
+ }
+ else
+ {
+ name.Remove('"');
+ }
+
name.Trim();
description.Trim();
//
if (checkForDuplicateModels == true)
{
- if ( MatchModel( iter->second, name ) != NULL )
+ if ( MatchModel( iter->second, ConvertToModelName( name ) ) != NULL )
{
continue;
}
// MatchManufacturer and MatchModel in turn.
//
-OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * printer)
+OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service)
{
CString normalizedProductName;
Manufacturer * manufacturer = NULL;
//
// first look to see if we have a usb_MFG descriptor
//
- if (printer->usb_MFG.GetLength() > 0)
+ if (service->usb_MFG.GetLength() > 0)
{
- manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( printer->usb_MFG ) );
+ manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( service->usb_MFG ) );
}
if ( manufacturer == NULL )
{
- printer->product.Remove('(');
- printer->product.Remove(')');
+ service->product.Remove('(');
+ service->product.Remove(')');
- manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( printer->product ) );
+ manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( service->product ) );
}
//
//
if ( manufacturer != NULL )
{
- if (printer->usb_MDL.GetLength() > 0)
+ if (service->usb_MDL.GetLength() > 0)
{
- model = MatchModel ( manufacturer, ConvertToModelName ( printer->usb_MDL ) );
+ model = MatchModel ( manufacturer, ConvertToModelName ( service->usb_MDL ) );
}
if ( model == NULL )
{
- printer->product.Remove('(');
- printer->product.Remove(')');
+ service->product.Remove('(');
+ service->product.Remove(')');
- model = MatchModel ( manufacturer, ConvertToModelName ( printer->product ) );
+ model = MatchModel ( manufacturer, ConvertToModelName ( service->product ) );
}
if ( model != NULL )
{
- SelectMatch(printer, manufacturer, model);
+ SelectMatch(printer, service, manufacturer, model);
found = true;
}
}
//
// now try and find the lowered string in the name passed in.
- //
- if (name.Find(lower) == 0)
+ //
+ if (name.Find(lower) != -1)
{
return iter->second;
}
{
return model;
}
+
+ //
+ // <rdar://problem/3841218>
+ // try removing the first substring and search again
+ //
+
+ if ( name.Find(' ') != -1 )
+ {
+ CString altered = name;
+ altered.Delete( 0, altered.Find(' ') + 1 );
+
+ if ( lowered.Find( altered ) != -1 )
+ {
+ return model;
+ }
+ }
}
return NULL;
CString ntPrint;
OSStatus err;
BOOL ok;
+
+ // Load printer icon\r
+\r
+ check( m_printerImage == NULL );
+ m_printerImage = (CStatic*) GetDlgItem( IDR_MANIFEST );
+ check( m_printerImage );
+
+ if ( m_printerImage != NULL )
+ {
+ m_printerImage->SetIcon( LoadIcon( GetNonLocalizedResources(), MAKEINTRESOURCE( IDI_PRINTER ) ) );
+ }
//
// The CTreeCtrl widget automatically sends a selection changed
DDX_Control(pDX, IDC_PRINTER_MODEL, m_modelListCtrl);
DDX_Control(pDX, IDC_PRINTER_NAME, m_printerName);
DDX_Control(pDX, IDC_DEFAULT_PRINTER, m_defaultPrinterCtrl);
- DDX_Control(pDX, IDC_PRINTER_SELECTION_TEXT, m_printerSelectionText);
+ DDX_Control(pDX, IDC_PRINTER_SELECTION_TEXT, m_printerSelectionText);\r
}
{
CPrinterSetupWizardSheet * psheet;
Printer * printer;
+ Service * service;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
printer = psheet->GetSelectedPrinter();
require_quiet( printer, exit );
+ service = printer->services.front();
+ require_quiet( service, exit );
+
//
// call OnInitPage once
//
//
// and try and match the printer
//
- MatchPrinter( m_manufacturers, printer );
+ MatchPrinter( m_manufacturers, printer, service );
exit:
CPrinterSetupWizardSheet * psheet;
Printer * printer;
+ Service * service;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
printer = psheet->GetSelectedPrinter();
require_quiet( printer, exit );
+ service = printer->services.front();
+ require_quiet( service, exit );
+
check ( m_manufacturerSelected );
POSITION p = m_modelListCtrl.GetFirstSelectedItemPosition();
{
m_modelSelected = (Model*) m_modelListCtrl.GetItemData(nSelected);
- CopyPrinterSettings( printer, m_manufacturerSelected, m_modelSelected );
+ CopyPrinterSettings( printer, service, m_manufacturerSelected, m_modelSelected );
psheet->SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT);
}
{
CPrinterSetupWizardSheet * psheet;
Printer * printer;
+ Service * service;
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_FILEMUSTEXIST, L"Setup Information (*.inf)|*.inf||", this);
printer = psheet->GetSelectedPrinter();
require_quiet( printer, exit );
+ service = printer->services.front();
+ require_quiet( service, exit );
+
if ( dlg.DoModal() == IDOK )
{
Manufacturers manufacturers;
PopulateUI( manufacturers );
- MatchPrinter( manufacturers, printer );
+ MatchPrinter( manufacturers, printer, service );
}
exit:
Change History (most recent first):
$Log: ThirdPage.h,v $
+Revision 1.3 2005/01/25 08:57:28 shersche
+<rdar://problem/3911084> Add m_printerControl member for dynamic loading of icons from resource DLLs
+Bug #: 3911084
+
+Revision 1.2 2004/12/29 18:53:38 shersche
+<rdar://problem/3725106>
+<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
+Bug #: 3725106, 3737413
+
Revision 1.1 2004/06/18 04:36:58 rpantos
First checked in
//
// Tries to match printer based on manufacturer and model
//
- OSStatus MatchPrinter(Manufacturers & manufacturers, Printer * printer);
+ OSStatus MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service);
//
// OnInitPage
Manufacturer * MatchManufacturer( Manufacturers & manufacturer, const CString & name );
Model * MatchModel( Manufacturer * manufacturer, const CString & name );
- void SelectMatch(Printer * printer, Manufacturer * manufacturer, Model * model);
- void CopyPrinterSettings(Printer * printer, Manufacturer * manufacturer, Model * model);
+ void SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
+ void CopyPrinterSettings(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
Manufacturers m_manufacturers;
CButton m_defaultPrinterCtrl;
public:
CStatic m_printerSelectionText;
+ CStatic * m_printerImage;
afx_msg void OnBnClickedHaveDisk();
};
Change History (most recent first):
$Log: UtilTypes.h,v $
+Revision 1.8 2005/01/06 08:18:26 shersche
+Add protocol field to service, add EmptyQueues() function to service
+
+Revision 1.7 2005/01/04 21:07:29 shersche
+add description member to service object. this member corresponds to the 'ty' key in a printer text record
+
+Revision 1.6 2004/12/30 01:24:02 shersche
+<rdar://problem/3906182> Remove references to description key
+Bug #: 3906182
+
+Revision 1.5 2004/12/29 18:53:38 shersche
+<rdar://problem/3725106>
+<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
+Bug #: 3725106, 3737413
+
Revision 1.4 2004/09/13 21:22:44 shersche
<rdar://problem/3796483> Add moreComing argument to OnAddPrinter and OnRemovePrinter callbacks
Bug #: 3796483
#pragma once
#include <dns_sd.h>
+#include <string>
#include <list>
+#include <DebugServices.h>
-class CPrinterSetupWizardSheet;
+class CSecondPage;
+
+#define kDefaultPriority 50
+#define kDefaultQTotal 1
namespace PrinterSetupWizard
{
struct Printer;
+ struct Service;
+ struct Queue;
struct Manufacturer;
struct Model;
-
- typedef std::list<CString> TextRecord;
+
+ typedef std::list<Queue*> Queues;
+ typedef std::list<Service*> Services;
typedef std::list<Model*> Models;
struct Printer
{
- DNSServiceRef serviceRef;
- CPrinterSetupWizardSheet * window;
- HTREEITEM item;
- DWORD refs;
+ Printer();
+
+ ~Printer();
+
+ Service*
+ LookupService
+ (
+ const std::string & type
+ );
+
+ CSecondPage * window;
+ HTREEITEM item;
//
- // these are from the browse reply
+ // These are from the browse reply
//
- uint32_t ifi;
- std::string name;
- CString displayName;
- CString actualName;
- std::string type;
- std::string domain;
+ std::string name;
+ CString displayName;
+ CString actualName;
//
- // these are from the resolve
+ // These keep track of the different services associated with this printer.
+ // the services are ordered according to preference.
//
- CString hostname;
- unsigned short portNumber;
- CString usb_MFG;
- CString usb_MDL;
- CString description;
- CString product;
+ Services services;
//
// these are derived from the printer matching code
// if driverInstalled is true, then model is the name
// of the driver to use in AddPrinter
//
- bool driverInstalled;
- CString infFileName;
- CString manufacturer;
- CString model;
- CString portName;
- bool deflt;
+ bool driverInstalled;
+ CString infFileName;
+ CString manufacturer;
+ CString model;
+ CString portName;
+ bool deflt;
//
// state
//
- bool installed;
+ unsigned resolving;
+ bool installed;
+ };
+
+
+ struct Service
+ {
+ Service();
+
+ ~Service();
+
+ void
+ EmptyQueues();
+
+ Printer * printer;
+ uint32_t ifi;
+ std::string type;
+ std::string domain;
+
+ //
+ // these are from the resolve
+ //
+ DNSServiceRef serviceRef;
+ CString hostname;
+ unsigned short portNumber;
+ CString usb_MFG;
+ CString usb_MDL;
+ CString description;
+ CString location;
+ CString product;
+ CString protocol;
+ unsigned short qtotal;
+
+ //
+ // There will usually one be one of these, however
+ // this will handle printers that have multiple
+ // queues. These are ordered according to preference.
+ //
+ Queues queues;
+
+ //
+ // Reference count
+ //
+ unsigned refs;
+ };
+
+
+ struct Queue
+ {
+ Queue();
+
+ ~Queue();
+
+ CString name;
+ uint32_t priority;
};
};
- class EventHandler
+ inline
+ Printer::Printer()
+ {
+ }
+
+ inline
+ Printer::~Printer()
+ {
+ while ( services.size() > 0 )
+ {
+ Service * service = services.front();
+ services.pop_front();
+ delete service;
+ }
+ }
+
+ inline Service*
+ Printer::LookupService
+ (
+ const std::string & type
+ )
{
- public:
+ Services::iterator it;
- virtual void
- OnAddPrinter(
- Printer * printer,
- bool moreComing) = 0;
+ for ( it = services.begin(); it != services.end(); it++ )
+ {
+ Service * service = *it;
- virtual void
- OnRemovePrinter(
- Printer * printer,
- bool moreComing) = 0;
+ if ( strcmp(service->type.c_str(), type.c_str()) == 0 )
+ {
+ return service;
+ }
+ }
- virtual void
- OnResolvePrinter(
- Printer * printer) = 0;
- };
+ return NULL;
+ }
+
+ inline
+ Service::Service()
+ :
+ qtotal(kDefaultQTotal)
+ {
+ }
+
+ inline
+ Service::~Service()
+ {
+ check( serviceRef == NULL );
+
+ EmptyQueues();
+ }
+
+ inline void
+ Service::EmptyQueues()
+ {
+ while ( queues.size() > 0 )
+ {
+ Queue * q = queues.front();
+ queues.pop_front();
+ delete q;
+ }
+ }
+
+ inline
+ Queue::Queue()
+ :
+ priority(kDefaultPriority)
+ {
+ }
+
+ inline
+ Queue::~Queue()
+ {
+ }
}
+
+
--- /dev/null
+//
+// Wiz97_3.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
--- /dev/null
+//
+// Wiz97_3.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Visual C++ generated include file.\r
-// Used by PrinterSetupWizard.rc\r
-//\r
-#define IDR_MANIFEST 1\r
-#define IDM_ABOUTBOX 0x0010\r
-#define IDD_ABOUTBOX 100\r
-#define IDS_ABOUTBOX 101\r
-#define IDD_PRINTERSETUPWIZARD_DIALOG 102\r
-#define IDS_GOODBYE 102\r
-#define IDS_GREETING 103\r
-#define IDS_BROWSE_TITLE 104\r
-#define IDS_BROWSE_SUBTITLE 105\r
-#define IDS_CAPTION 106\r
-#define IDD_FIRST_PAGE 107\r
-#define IDS_GOODBYE_GOOD1 107\r
-#define IDS_SEARCHING 108\r
-#define IDD_SECOND_PAGE 109\r
-#define IDS_GOODBYTE_GOOD2 109\r
-#define IDS_INSTALL_TITLE 110\r
-#define IDS_INSTALL_SUBTITLE 111\r
-#define IDS_ERROR_SELECTING_PRINTER_TEXT 112\r
-#define IDS_ERROR_SELECTING_PRINTER_CAPTION 113\r
-#define IDS_INSTALL_ERROR_CAPTION 114\r
-#define IDS_INSTALL_ERROR_MESSAGE 115\r
-#define IDS_MANUFACTURER_HEADING 116\r
-#define IDS_MODEL_HEADING 117\r
-#define IDS_NO_RENDEZVOUS_PRINTERS 118\r
-#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119\r
-#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120\r
-#define IDS_PRINTER_MATCH_GOOD 121\r
-#define IDS_PRINTER_MATCH_BAD 122\r
-#define IDS_YES 123\r
-#define IDS_NO 124\r
-#define IDS_LARGE_FONT 125\r
-#define IDR_MAINFRAME 128\r
-#define IDB_BANNER_ICON 129\r
-#define IDD_THIRD_PAGE 130\r
-#define IDB_WATERMARK 131\r
-#define IDD_FOURTH_PAGE 132\r
-#define IDI_INFO 136\r
-#define IDB_ABOUT 138\r
-#define IDD_DIALOG1 139\r
-#define IDI_ICON2 141\r
-#define IDI_PRINTER 141\r
-#define IDC_BUTTON1 1000\r
-#define IDC_LIST1 1000\r
-#define IDC_BROWSE_LIST 1000\r
-#define IDC_RADIO1 1001\r
-#define IDC_COMBO1 1001\r
-#define IDC_RADIO2 1002\r
-#define IDC_GREETING 1003\r
-#define IDC_CHECK1 1016\r
-#define IDC_DEFAULT_PRINTER 1016\r
-#define IDC_PRINTER_IMAGE 1017\r
-#define IDC_PRINTER_NAME 1018\r
-#define IDC_PRINTER_MANUFACTURER 1019\r
-#define IDC_PRINTER_MODEL 1020\r
-#define IDC_GOODBYE 1021\r
-#define IDC_PRINTER_PORT 1022\r
-#define IDC_PRINTER_DEFAULT 1023\r
-#define IDC_PRINTER_SELECTION_TEXT 1024\r
-#define IDC_HAVE_DISK 1025\r
+/*\r
+ * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.\r
+ *\r
+ * @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
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE 142\r
-#define _APS_NEXT_COMMAND_VALUE 32771\r
-#define _APS_NEXT_CONTROL_VALUE 1026\r
-#define _APS_NEXT_SYMED_VALUE 101\r
-#endif\r
-#endif\r
+ Change History (most recent first):\r
+\r
+ */\r
+ \r
+\r
+// Include resources for Wizard app\r
+\r
+#include "resource_exe.h"\r
+\r
+// Include resources for non-localizable resource DLL\r
+\r
+#include "resource_res.h"\r
+\r
+// Include resources for localizable resource DLL\r
+\r
+#include "resource_loc_res.h"\r
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by PrinterSetupWizard.rc\r
+//\r
+#define IDR_MANIFEST 1\r
+#define IDM_ABOUTBOX 0x0010\r
+#define IDD_ABOUTBOX 100\r
+#define IDS_ABOUTBOX 101\r
+#define IDD_PRINTERSETUPWIZARD_DIALOG 102\r
+#define IDS_GOODBYE 102\r
+#define IDS_GREETING 103\r
+#define IDS_BROWSE_TITLE 104\r
+#define IDS_BROWSE_SUBTITLE 105\r
+#define IDS_CAPTION 106\r
+#define IDD_FIRST_PAGE 107\r
+#define IDS_GOODBYE_GOOD1 107\r
+#define IDS_SEARCHING 108\r
+#define IDD_SECOND_PAGE 109\r
+#define IDS_GOODBYTE_GOOD2 109\r
+#define IDS_INSTALL_TITLE 110\r
+#define IDS_INSTALL_SUBTITLE 111\r
+#define IDS_ERROR_SELECTING_PRINTER_TEXT 112\r
+#define IDS_ERROR_SELECTING_PRINTER_CAPTION 113\r
+#define IDS_INSTALL_ERROR_CAPTION 114\r
+#define IDS_INSTALL_ERROR_MESSAGE 115\r
+#define IDS_MANUFACTURER_HEADING 116\r
+#define IDS_MODEL_HEADING 117\r
+#define IDS_NO_RENDEZVOUS_PRINTERS 118\r
+#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119\r
+#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120\r
+#define IDS_PRINTER_MATCH_GOOD 121\r
+#define IDS_PRINTER_MATCH_BAD 122\r
+#define IDS_YES 123\r
+#define IDS_NO 124\r
+#define IDS_LARGE_FONT 125\r
+#define IDS_FIREWALL 126\r
+#define IDS_ERROR_CAPTION 127\r
+#define IDR_MAINFRAME 128\r
+#define IDS_FIREWALL_CAPTION 128\r
+#define IDB_BANNER_ICON 129\r
+#define IDD_THIRD_PAGE 130\r
+#define IDB_WATERMARK 131\r
+#define IDD_FOURTH_PAGE 132\r
+#define IDI_INFO 136\r
+#define IDB_ABOUT 138\r
+#define IDD_DIALOG1 139\r
+#define IDI_ICON2 141\r
+#define IDI_PRINTER 141\r
+#define IDS_REINSTALL 142\r
+#define IDS_REINSTALL_CAPTION 143\r
+#define IDC_BUTTON1 1000\r
+#define IDC_LIST1 1000\r
+#define IDC_BROWSE_LIST 1000\r
+#define IDC_RADIO1 1001\r
+#define IDC_COMBO1 1001\r
+#define IDC_RADIO2 1002\r
+#define IDC_GREETING 1003\r
+#define IDC_CHECK1 1016\r
+#define IDC_DEFAULT_PRINTER 1016\r
+#define IDC_PRINTER_IMAGE 1017\r
+#define IDC_PRINTER_NAME 1018\r
+#define IDC_PRINTER_MANUFACTURER 1019\r
+#define IDC_PRINTER_MODEL 1020\r
+#define IDC_GOODBYE 1021\r
+#define IDC_PRINTER_PORT 1022\r
+#define IDC_PRINTER_PROTOCOL 1022\r
+#define IDC_PRINTER_DEFAULT 1023\r
+#define IDC_PRINTER_SELECTION_TEXT 1024\r
+#define IDC_HAVE_DISK 1025\r
+#define IDC_PRINTER_INFORMATION 1026\r
+#define IDC_LOCATION_LABEL 1029\r
+#define IDC_DESCRIPTION_FIELD 1030\r
+#define IDC_LOCATION_FIELD 1032\r
+#define IDC_DESCRIPTION_LABEL 1033\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE 142\r
+#define _APS_NEXT_COMMAND_VALUE 32771\r
+#define _APS_NEXT_CONTROL_VALUE 1034\r
+#define _APS_NEXT_SYMED_VALUE 101\r
+#endif\r
+#endif\r
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by PrinterSetupWizardLocRes.rc\r
+//\r
+#define IDR_MANIFEST 1\r
+#define IDM_ABOUTBOX 0x0010\r
+#define IDD_ABOUTBOX 100\r
+#define IDS_ABOUTBOX 101\r
+#define IDD_PRINTERSETUPWIZARD_DIALOG 102\r
+#define IDS_GOODBYE 102\r
+#define IDS_GREETING 103\r
+#define IDS_BROWSE_TITLE 104\r
+#define IDS_BROWSE_SUBTITLE 105\r
+#define IDS_CAPTION 106\r
+#define IDD_FIRST_PAGE 107\r
+#define IDS_GOODBYE_GOOD1 107\r
+#define IDS_SEARCHING 108\r
+#define IDD_SECOND_PAGE 109\r
+#define IDS_GOODBYTE_GOOD2 109\r
+#define IDS_INSTALL_TITLE 110\r
+#define IDS_INSTALL_SUBTITLE 111\r
+#define IDS_ERROR_SELECTING_PRINTER_TEXT 112\r
+#define IDS_ERROR_SELECTING_PRINTER_CAPTION 113\r
+#define IDS_INSTALL_ERROR_CAPTION 114\r
+#define IDS_INSTALL_ERROR_MESSAGE 115\r
+#define IDS_MANUFACTURER_HEADING 116\r
+#define IDS_MODEL_HEADING 117\r
+#define IDS_NO_RENDEZVOUS_PRINTERS 118\r
+#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119\r
+#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120\r
+#define IDS_PRINTER_MATCH_GOOD 121\r
+#define IDS_PRINTER_MATCH_BAD 122\r
+#define IDS_YES 123\r
+#define IDS_NO 124\r
+#define IDS_LARGE_FONT 125\r
+#define IDS_FIREWALL 126\r
+#define IDS_ERROR_CAPTION 127\r
+#define IDR_MAINFRAME 128\r
+#define IDS_FIREWALL_CAPTION 128\r
+#define IDB_BANNER_ICON 129\r
+#define IDD_THIRD_PAGE 130\r
+#define IDB_WATERMARK 131\r
+#define IDD_FOURTH_PAGE 132\r
+#define IDI_INFO 136\r
+#define IDB_ABOUT 138\r
+#define IDD_DIALOG1 139\r
+#define IDI_ICON2 141\r
+#define IDI_PRINTER 141\r
+#define IDS_REINSTALL 142\r
+#define IDS_REINSTALL_CAPTION 143\r
+#define IDC_INFO 144\r
+#define IDC_BUTTON1 1000\r
+#define IDC_LIST1 1000\r
+#define IDC_BROWSE_LIST 1000\r
+#define IDC_RADIO1 1001\r
+#define IDC_COMBO1 1001\r
+#define IDC_RADIO2 1002\r
+#define IDC_GREETING 1003\r
+#define IDC_CHECK1 1016\r
+#define IDC_DEFAULT_PRINTER 1016\r
+#define IDC_PRINTER_IMAGE 1017\r
+#define IDC_PRINTER_NAME 1018\r
+#define IDC_PRINTER_MANUFACTURER 1019\r
+#define IDC_PRINTER_MODEL 1020\r
+#define IDC_GOODBYE 1021\r
+#define IDC_PRINTER_PORT 1022\r
+#define IDC_PRINTER_PROTOCOL 1022\r
+#define IDC_PRINTER_DEFAULT 1023\r
+#define IDC_PRINTER_SELECTION_TEXT 1024\r
+#define IDC_HAVE_DISK 1025\r
+#define IDC_PRINTER_INFORMATION 1026\r
+#define IDC_LOCATION_LABEL 1029\r
+#define IDC_DESCRIPTION_FIELD 1030\r
+#define IDC_LOCATION_FIELD 1032\r
+#define IDC_DESCRIPTION_LABEL 1033\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE 142\r
+#define _APS_NEXT_COMMAND_VALUE 32771\r
+#define _APS_NEXT_CONTROL_VALUE 1034\r
+#define _APS_NEXT_SYMED_VALUE 101\r
+#endif\r
+#endif\r
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by PrinterSetupWizard.rc\r
+//\r
+#define IDR_MANIFEST 1\r
+#define IDM_ABOUTBOX 0x0010\r
+#define IDD_ABOUTBOX 100\r
+#define IDS_ABOUTBOX 101\r
+#define IDD_PRINTERSETUPWIZARD_DIALOG 102\r
+#define IDS_GOODBYE 102\r
+#define IDS_GREETING 103\r
+#define IDS_BROWSE_TITLE 104\r
+#define IDS_BROWSE_SUBTITLE 105\r
+#define IDS_CAPTION 106\r
+#define IDD_FIRST_PAGE 107\r
+#define IDS_GOODBYE_GOOD1 107\r
+#define IDS_SEARCHING 108\r
+#define IDD_SECOND_PAGE 109\r
+#define IDS_GOODBYTE_GOOD2 109\r
+#define IDS_INSTALL_TITLE 110\r
+#define IDS_INSTALL_SUBTITLE 111\r
+#define IDS_ERROR_SELECTING_PRINTER_TEXT 112\r
+#define IDS_ERROR_SELECTING_PRINTER_CAPTION 113\r
+#define IDS_INSTALL_ERROR_CAPTION 114\r
+#define IDS_INSTALL_ERROR_MESSAGE 115\r
+#define IDS_MANUFACTURER_HEADING 116\r
+#define IDS_MODEL_HEADING 117\r
+#define IDS_NO_RENDEZVOUS_PRINTERS 118\r
+#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119\r
+#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120\r
+#define IDS_PRINTER_MATCH_GOOD 121\r
+#define IDS_PRINTER_MATCH_BAD 122\r
+#define IDS_YES 123\r
+#define IDS_NO 124\r
+#define IDS_LARGE_FONT 125\r
+#define IDS_FIREWALL 126\r
+#define IDS_ERROR_CAPTION 127\r
+#define IDR_MAINFRAME 128\r
+#define IDS_FIREWALL_CAPTION 128\r
+#define IDB_BANNER_ICON 129\r
+#define IDD_THIRD_PAGE 130\r
+#define IDB_WATERMARK 131\r
+#define IDD_FOURTH_PAGE 132\r
+#define IDI_INFO 136\r
+#define IDB_ABOUT 138\r
+#define IDD_DIALOG1 139\r
+#define IDI_ICON2 141\r
+#define IDI_PRINTER 141\r
+#define IDS_REINSTALL 142\r
+#define IDS_REINSTALL_CAPTION 143\r
+#define IDC_BUTTON1 1000\r
+#define IDC_LIST1 1000\r
+#define IDC_BROWSE_LIST 1000\r
+#define IDC_RADIO1 1001\r
+#define IDC_COMBO1 1001\r
+#define IDC_RADIO2 1002\r
+#define IDC_GREETING 1003\r
+#define IDC_CHECK1 1016\r
+#define IDC_DEFAULT_PRINTER 1016\r
+#define IDC_PRINTER_IMAGE 1017\r
+#define IDC_PRINTER_NAME 1018\r
+#define IDC_PRINTER_MANUFACTURER 1019\r
+#define IDC_PRINTER_MODEL 1020\r
+#define IDC_GOODBYE 1021\r
+#define IDC_PRINTER_PORT 1022\r
+#define IDC_PRINTER_PROTOCOL 1022\r
+#define IDC_PRINTER_DEFAULT 1023\r
+#define IDC_PRINTER_SELECTION_TEXT 1024\r
+#define IDC_HAVE_DISK 1025\r
+#define IDC_PRINTER_INFORMATION 1026\r
+#define IDC_LOCATION_LABEL 1029\r
+#define IDC_DESCRIPTION_FIELD 1030\r
+#define IDC_LOCATION_FIELD 1032\r
+#define IDC_DESCRIPTION_LABEL 1033\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE 142\r
+#define _APS_NEXT_COMMAND_VALUE 32771\r
+#define _APS_NEXT_CONTROL_VALUE 1034\r
+#define _APS_NEXT_SYMED_VALUE 101\r
+#endif\r
+#endif\r
#include <string.h> // For strlen(), strcpy(), bzero()
#include <errno.h> // For errno, EINTR
#include <time.h>
+#include <sys/types.h> // For u_char
#ifdef _WIN32
#include <process.h>
typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
static int operation;
+static uint32_t interface = kDNSServiceInterfaceIndexAny;
static DNSServiceRef client = NULL;
static DNSServiceRef client2 = NULL;
static int num_printed;
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, 0, nam, typ, dom, host, registerPort.NotAnInteger, ptr-txt, txt, reg_reply, NULL));
+ return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, interface, nam, typ, dom, host, registerPort.NotAnInteger, ptr-txt, txt, reg_reply, NULL));
}
int main(int argc, char **argv)
setlinebuf(stdout); // Want to see lines as they appear, not block buffered
#endif
+ if (argc > 1 && !strcmp(argv[1], "-lo"))
+ {
+ argc--;
+ argv++;
+ interface = kDNSServiceInterfaceIndexLocalOnly;
+ printf("Using LocalOnly\n");
+ }
+
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;
switch (operation)
{
case 'E': printf("Looking for recommended registration domains:\n");
- err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsRegistrationDomains, 0, enum_reply, NULL);
+ err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsRegistrationDomains, interface, enum_reply, NULL);
break;
case 'F': printf("Looking for recommended browsing domains:\n");
- err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsBrowseDomains, 0, enum_reply, NULL);
+ err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsBrowseDomains, interface, enum_reply, NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "nicta.com.au.", NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "rendezvous.nicta.com.au.", NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "ibm.com.", NULL);
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);
- err = DNSServiceBrowse(&client, 0, 0, argv[optind+0], dom, browse_reply, NULL);
+ err = DNSServiceBrowse(&client, 0, interface, argv[optind+0], dom, browse_reply, NULL);
break;
case 'L': if (argc < optind+2) goto Fail;
dom = (argc < optind+3) ? "local" : argv[optind+2];
if (dom[0] == '.' && dom[1] == 0) dom = "local"; // We allow '.' on the command line as a synonym for "local"
printf("Lookup %s.%s.%s\n", argv[optind+0], argv[optind+1], dom);
- err = DNSServiceResolve(&client, 0, 0, argv[optind+0], argv[optind+1], dom, resolve_reply, NULL);
+ err = DNSServiceResolve(&client, 0, interface, argv[optind+0], argv[optind+1], dom, resolve_reply, NULL);
break;
case 'R': if (argc < optind+4) goto Fail;
rrtype = (argc <= optind+1) ? kDNSServiceType_A : GetRRType(argv[optind+1]);
rrclass = (argc <= optind+2) ? kDNSServiceClass_IN : atoi(argv[optind+2]);
if (rrtype == kDNSServiceType_TXT || rrtype == kDNSServiceType_PTR) flags |= kDNSServiceFlagsLongLivedQuery;
- err = DNSServiceQueryRecord(&client, flags, 0, argv[optind+0], rrtype, rrclass, qr_reply, NULL);
+ err = DNSServiceQueryRecord(&client, flags, interface, argv[optind+0], rrtype, rrclass, qr_reply, NULL);
break;
}
Opaque16 registerPort = { { 0x12, 0x34 } };
static const char TXT[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
printf("Registering Service Test._testupdate._tcp.local.\n");
- err = DNSServiceRegister(&client, 0, 0, "Test", "_testupdate._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL);
+ err = DNSServiceRegister(&client, 0, interface, "Test", "_testupdate._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL);
break;
}
for (i=0; i<sizeof(TXT); i++)
if ((i & 0x1F) == 0) TXT[i] = 0x1F; else TXT[i] = 'A' + (i >> 5);
printf("Registering Service Test._testlargetxt._tcp.local.\n");
- err = DNSServiceRegister(&client, 0, 0, "Test", "_testlargetxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT), TXT, reg_reply, NULL);
+ err = DNSServiceRegister(&client, 0, interface, "Test", "_testlargetxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT), TXT, reg_reply, NULL);
break;
}
static const char TXT1[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
static const char TXT2[] = "\xD" "Fourth String" "\xC" "Fifth String" "\xC" "Sixth String";
printf("Registering Service Test._testdualtxt._tcp.local.\n");
- err = DNSServiceRegister(&client, 0, 0, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL);
+ err = DNSServiceRegister(&client, 0, interface, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL);
if (!err) err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_TXT, sizeof(TXT2)-1, TXT2, 0);
break;
}
Opaque16 registerPort = { { pid >> 8, pid & 0xFF } };
static const char TXT[] = "\x09" "Test Data";
printf("Registering Service Test._testtxt._tcp.local.\n");
- err = DNSServiceRegister(&client, 0, 0, "Test", "_testtxt._tcp.", "", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
+ err = DNSServiceRegister(&client, 0, interface, "Test", "_testtxt._tcp.", "", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
if (!err) err = DNSServiceUpdateRecord(client, NULL, 0, sizeof(TXT)-1, TXT, 0);
break;
}
include /Developer/Makefiles/pb_makefiles/platform.make
-MVERS = "mDNSResponder-87"
+MVERS = "mDNSResponder-98"
install:
cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS)
Change History (most recent first):
$Log: DNSCommon.c,v $
+Revision 1.83 2005/01/27 22:57:55 cheshire
+Fix compile errors on gcc4
+
+Revision 1.82 2005/01/19 03:27:03 cheshire
+<rdar://problem/3961051> CPU Spin in mDNSResponder
+GetNextScheduledEvent() needs to check LocalRecordReady()
+
+Revision 1.81 2004/12/18 03:13:45 cheshire
+<rdar://problem/3751638> kDNSServiceInterfaceIndexLocalOnly should return all local records
+
+Revision 1.80 2004/12/16 21:46:43 cheshire
+Add DNSTypeName case for kDNSType_SOA
+
+Revision 1.79 2004/12/16 21:38:37 cheshire
+Add DNSTypeName case for kDNSType_NS
+
+Revision 1.78 2004/12/16 21:27:37 ksekar
+Fixed build failures when compiled with verbose debugging messages
+
+Revision 1.77 2004/12/16 20:12:59 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
+Revision 1.76 2004/12/16 08:05:29 shersche
+Remove extranenous semicolons that cause compilation errors on Windows
+
+Revision 1.75 2004/12/15 02:11:22 ksekar
+<rdar://problem/3917317> Don't check for Dynamic DNS hostname uniqueness
+
Revision 1.74 2004/12/09 22:49:15 ksekar
<rdar://problem/3913653> Wide-Area Goodbyes broken
{
newelem = (DNameListElem*)mDNSPlatformMemAllocate(sizeof(DNameListElem));
if (!newelem) { LogMsg("ERROR: malloc"); return mDNSNULL; }
- AssignDomainName(newelem->name, ptr->name);
+ AssignDomainName(&newelem->name, &ptr->name);
newelem->next = copy;
copy = newelem;
}
mDNSexport mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterfaceID id)
{
mDNSu32 slot, used = 0;
+ CacheGroup *cg;
CacheRecord *rr;
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
- for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
- if (rr->resrec.InterfaceID == id) used++;
+ FORALL_CACHERECORDS(slot, cg, rr)
+ if (rr->resrec.InterfaceID == id) used++;
return(used);
}
switch (rrtype)
{
case kDNSType_A: return("Addr");
+ case kDNSType_NS: return("NS");
case kDNSType_CNAME:return("CNAME");
+ case kDNSType_SOA: return("SOA");
case kDNSType_NULL: return("NULL");
case kDNSType_PTR: return("PTR");
case kDNSType_HINFO:return("HINFO");
mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *rr, RDataBody *rd, char *buffer)
{
char *ptr = buffer;
- mDNSu32 length = mDNS_snprintf(buffer, 79, "%4d %##s %s ", rr->rdlength, rr->name.c, DNSTypeName(rr->rrtype));
+ mDNSu32 length = mDNS_snprintf(buffer, 79, "%4d %##s %s ", rr->rdlength, rr->name->c, DNSTypeName(rr->rrtype));
switch (rr->rrtype)
{
case kDNSType_A: mDNS_snprintf(buffer+length, 79-length, "%.4a", &rd->ipv4); break;
{
return (r1->namehash == r2->namehash &&
r1->rrtype == r2->rrtype &&
- SameDomainName(&r1->name, &r2->name) &&
+ SameDomainName(r1->name, r2->name) &&
SameRData(r1, r2));
}
mDNSexport mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
{
if (rr->InterfaceID &&
- q ->InterfaceID &&
+ q ->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly &&
rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
// RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
if (rr->rrtype != kDNSType_CNAME && rr->rrtype != q->qtype && q->qtype != kDNSQType_ANY ) return(mDNSfalse);
if ( rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
- return(rr->namehash == q->qnamehash && SameDomainName(&rr->name, &q->qname));
+ return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
}
mDNSexport mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate)
{
const RDataBody *rd = &rr->rdata->u;
- const domainname *const name = estimate ? &rr->name : mDNSNULL;
+ const domainname *const name = estimate ? rr->name : mDNSNULL;
switch (rr->rrtype)
{
case kDNSType_A: return(sizeof(rd->ipv4));
{
// check if space for opt/optlen
if (ptr + (2 * sizeof(mDNSu16)) > limit) goto space_err;
- (mDNSu8 *)opt = rr->rdata->u.data + nput;
+ opt = (rdataOpt *)(rr->rdata->u.data + nput);
ptr = putVal16(ptr, opt->opt);
ptr = putVal16(ptr, opt->optlen);
nput += 2 * sizeof(mDNSu16);
if (rr->RecordType == kDNSRecordTypeUnregistered)
{
- LogMsg("PutResourceRecord ERROR! Attempt to put kDNSRecordTypeUnregistered %##s (%s)", rr->name.c, DNSTypeName(rr->rrtype));
+ LogMsg("PutResourceRecord ERROR! Attempt to put kDNSRecordTypeUnregistered %##s (%s)", rr->name->c, DNSTypeName(rr->rrtype));
return(ptr);
}
- ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->name);
+ ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name);
if (!ptr || ptr + 10 >= limit) return(mDNSNULL); // If we're out-of-space, return mDNSNULL
ptr[0] = (mDNSu8)(rr->rrtype >> 8);
ptr[1] = (mDNSu8)(rr->rrtype & 0xFF);
ptr[6] = (mDNSu8)((ttl >> 8) & 0xFF);
ptr[7] = (mDNSu8)( ttl & 0xFF);
endofrdata = putRData(msg, ptr+10, limit, rr);
- if (!endofrdata) { verbosedebugf("Ran out of space in PutResourceRecord for %##s (%s)", rr->name.c, DNSTypeName(rr->rrtype)); return(mDNSNULL); }
+ if (!endofrdata) { verbosedebugf("Ran out of space in PutResourceRecord for %##s (%s)", rr->name->c, DNSTypeName(rr->rrtype)); return(mDNSNULL); }
// Go back and fill in the actual number of data bytes we wrote
// (actualLength can be less than rdlength when domain name compression is used)
ptr[9] = (mDNSu8)(actualLength & 0xFF);
if (count) (*count)++;
- else LogMsg("PutResourceRecordTTL: ERROR: No target count to update for %##s (%s)", rr->name.c, DNSTypeName(rr->rrtype));
+ else LogMsg("PutResourceRecordTTL: ERROR: No target count to update for %##s (%s)", rr->name->c, DNSTypeName(rr->rrtype));
return(endofrdata);
}
mDNSexport mDNSu8 *putEmptyResourceRecord(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit,
mDNSu16 *count, const AuthRecord *rr)
{
- ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->resrec.name);
+ ptr = putDomainNameAsLabels(msg, ptr, limit, rr->resrec.name);
if (!ptr || ptr + 10 > limit) return(mDNSNULL); // If we're out-of-space, return mDNSNULL
ptr[0] = (mDNSu8)(rr->resrec.rrtype >> 8); // Put type
ptr[1] = (mDNSu8)(rr->resrec.rrtype & 0xFF);
AuthRecord prereq;
mDNSPlatformMemZero(&prereq, sizeof(AuthRecord));
- AssignDomainName(prereq.resrec.name, *name);
+ mDNS_SetupResourceRecord(&prereq, mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, mDNSNULL, mDNSNULL);
+ AssignDomainName(prereq.resrec.name, name);
prereq.resrec.rrtype = kDNSQType_ANY;
prereq.resrec.rrclass = kDNSClass_NONE;
ptr = putEmptyResourceRecord(msg, ptr, end, &msg->h.mDNS_numPrereqs, &prereq);
return ptr;
}
+mDNSexport mDNSu8 *putDeleteRRSet(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype)
+ {
+ const mDNSu8 *limit = msg->data + AbsoluteMaxDNSMessageData;
+ mDNSu16 class = kDNSQClass_ANY;
+
+ ptr = putDomainNameAsLabels(msg, ptr, limit, name);
+ if (!ptr || ptr + 10 >= limit) return mDNSNULL; // If we're out-of-space, return mDNSNULL
+ ptr[0] = (mDNSu8)(rrtype >> 8);
+ ptr[1] = (mDNSu8)(rrtype & 0xFF);
+ ptr[2] = (mDNSu8)(class >> 8);
+ ptr[3] = (mDNSu8)(class & 0xFF);
+ ptr[4] = ptr[5] = ptr[6] = ptr[7] = 0; // zero ttl
+ ptr[8] = ptr[9] = 0; // zero rdlength/rdata
+
+ msg->h.mDNS_numUpdates++;
+ return ptr + 10;
+ }
+
// for dynamic updates
mDNSexport mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name)
{
- const mDNSu8 *limit = msg->data + AbsoluteMaxDNSMessageData;;
+ const mDNSu8 *limit = msg->data + AbsoluteMaxDNSMessageData;
mDNSu16 class = kDNSQClass_ANY;
mDNSu16 rrtype = kDNSQType_ANY;
rdataOpt *optRD;
mDNSPlatformMemZero(&rr, sizeof(AuthRecord));
- opt->rdata = &rr.rdatastorage;
+ mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, 0, mDNSNULL, mDNSNULL);
opt->RecordType = kDNSRecordTypeKnownUnique; // to avoid warnings in other layers
opt->rrtype = kDNSType_OPT;
rr->next = mDNSNULL;
rr->resrec.RecordType = RecordType;
+ rr->resrec.name = &largecr->namestorage;
rr->NextInKAList = mDNSNULL;
rr->TimeRcvd = m ? m->timenow : 0;
rr->NextInCFList = mDNSNULL;
rr->resrec.InterfaceID = InterfaceID;
- ptr = getDomainName(msg, ptr, end, &rr->resrec.name);
+ ptr = getDomainName(msg, ptr, end, rr->resrec.name);
if (!ptr) { debugf("GetResourceRecord: Malformed RR name"); return(mDNSNULL); }
if (ptr + 10 > end) { debugf("GetResourceRecord: Malformed RR -- no type/class/ttl/len!"); return(mDNSNULL); }
rr->resrec.rdata = (RData*)&rr->rdatastorage;
rr->resrec.rdata->MaxRDLength = MaximumRDSize;
- if (!RecordType) LogMsg("GetLargeResourceRecord: No RecordType for %##s", rr->resrec.name.c);
+ if (!RecordType) LogMsg("GetLargeResourceRecord: No RecordType for %##s", rr->resrec.name->c);
switch (rr->resrec.rrtype)
{
break;
}
- rr->resrec.namehash = DomainNameHashValue(&rr->resrec.name);
+ rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
SetNewRData(&rr->resrec, mDNSNULL, 0);
return(ptr + pktrdlength);
if (m->NewQuestions->DelayAnswering) e = m->NewQuestions->DelayAnswering;
else return(m->timenow);
}
- if (m->NewLocalOnlyQuestions) return(m->timenow);
- if (m->NewLocalOnlyRecords) return(m->timenow);
- if (m->DiscardLocalOnlyRecords) return(m->timenow);
- if (m->SuppressSending) return(m->SuppressSending);
+ if (m->NewLocalOnlyQuestions) return(m->timenow);
+ if (m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords)) return(m->timenow);
+ if (m->SuppressSending) return(m->SuppressSending);
#ifndef UNICAST_DISABLED
if (e - m->uDNS_info.nextevent > 0) e = m->uDNS_info.nextevent;
#endif
Change History (most recent first):
$Log: DNSCommon.h,v $
+Revision 1.30 2005/01/19 03:12:44 cheshire
+Move LocalRecordReady() macro from mDNS.c to DNSCommon.h
+
+Revision 1.29 2004/12/15 02:11:22 ksekar
+<rdar://problem/3917317> Don't check for Dynamic DNS hostname uniqueness
+
Revision 1.28 2004/12/06 21:15:22 ksekar
<rdar://problem/3884386> mDNSResponder crashed in CheckServiceRegistrations
((RR)->rrtype == kDNSType_SRV ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
+#define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique && (X)->resrec.RecordType != kDNSRecordTypeDeregistering)
// ***************************************************************************
extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr);
+extern mDNSu8 *putDeleteRRSet(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype);
+
extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name);
extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease);
extern void mDNS_Lock(mDNS *const m);
extern void mDNS_Unlock(mDNS *const m);
-
+
#ifdef __cplusplus
}
#endif
Change History (most recent first):
$Log: DNSDigest.c,v $
+Revision 1.13 2004/12/16 20:12:59 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.12 2004/12/03 07:20:50 ksekar
<rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
mDNS_SetupResourceRecord(&tsig, mDNSNULL, 0, kDNSType_TSIG, 0, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
// key name
- AssignDomainName(tsig.resrec.name, info->keyname);
+ AssignDomainName(tsig.resrec.name, &info->keyname);
MD5_Update(&c, info->keyname.c, DomainNameLength(&info->keyname));
// class
MD5_Update(&c, (mDNSu8 *)&tsig.resrec.rroriginalttl, sizeof(tsig.resrec.rroriginalttl));
// alg name
- AssignDomainName(tsig.resrec.rdata->u.name, HMAC_MD5_AlgName);
+ AssignDomainName(&tsig.resrec.rdata->u.name, &HMAC_MD5_AlgName);
len = DomainNameLength(&HMAC_MD5_AlgName);
rdata = tsig.resrec.rdata->u.data + len;
MD5_Update(&c, HMAC_MD5_AlgName.c, len);
Change History (most recent first):
$Log: mDNS.c,v $
+Revision 1.516 2005/01/28 06:06:32 cheshire
+Update comment
+
+Revision 1.515 2005/01/27 00:21:49 cheshire
+<rdar://problem/3973798> Remove mDNSResponder sleep/wake syslog message
+
+Revision 1.514 2005/01/21 01:33:45 cheshire
+<rdar://problem/3962979> Shutdown time regression: mDNSResponder not responding to SIGTERM
+
+Revision 1.513 2005/01/21 00:07:54 cheshire
+<rdar://problem/3962717> Infinite loop when the same service is registered twice, and then suffers a name conflict
+
+Revision 1.512 2005/01/20 00:37:45 cheshire
+<rdar://problem/3941448> mDNSResponder crashed in mDNSCoreReceiveResponse
+Take care not to recycle records while they are on the CacheFlushRecords list
+
+Revision 1.511 2005/01/19 22:48:53 cheshire
+<rdar://problem/3955355> Handle services with subtypes correctly when doing mDNS_RenameAndReregisterService()
+
+Revision 1.510 2005/01/19 03:12:45 cheshire
+Move LocalRecordReady() macro from mDNS.c to DNSCommon.h
+
+Revision 1.509 2005/01/19 03:08:49 cheshire
+<rdar://problem/3961051> CPU Spin in mDNSResponder
+Log messages to help catch and report CPU spins
+
+Revision 1.508 2005/01/18 18:56:32 cheshire
+<rdar://problem/3934245> QU responses not promoted to multicast responses when appropriate
+
+Revision 1.507 2005/01/18 01:12:07 cheshire
+<rdar://problem/3956258> Logging into VPN causes mDNSResponder to reissue multicast probes
+
+Revision 1.506 2005/01/17 23:28:53 cheshire
+Fix compile error
+
+Revision 1.505 2005/01/11 02:02:56 shersche
+Move variable declaration to the beginning of statement block
+
+Revision 1.504 2004/12/20 20:24:35 cheshire
+<rdar://problem/3928456> Network efficiency: Don't keep polling if we have at least one unique-type answer
+
+Revision 1.503 2004/12/20 18:41:47 cheshire
+<rdar://problem/3591622> Low memory support: Provide answers even when we don't have cache space
+
+Revision 1.502 2004/12/20 18:04:08 cheshire
+<rdar://problem/3923098> For now, don't put standard wide-area unicast responses in our main cache
+
+Revision 1.501 2004/12/19 23:50:18 cheshire
+<rdar://problem/3751638> kDNSServiceInterfaceIndexLocalOnly should return all local records
+Don't show "No active interface to send" messages for kDNSServiceInterfaceIndexLocalOnly services
+
+Revision 1.500 2004/12/18 03:13:46 cheshire
+<rdar://problem/3751638> kDNSServiceInterfaceIndexLocalOnly should return all local records
+
+Revision 1.499 2004/12/17 23:37:45 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+(and other repetitive configuration changes)
+
+Revision 1.498 2004/12/17 05:25:46 cheshire
+<rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
+
+Revision 1.497 2004/12/17 03:20:58 cheshire
+<rdar://problem/3925168> Don't send unicast replies we know will be ignored
+
+Revision 1.496 2004/12/16 22:18:26 cheshire
+Make AddressIsLocalSubnet() a little more selective -- ignore point-to-point interfaces
+
+Revision 1.495 2004/12/16 21:27:37 ksekar
+Fixed build failures when compiled with verbose debugging messages
+
+Revision 1.494 2004/12/16 20:46:56 cheshire
+Fix compiler warnings
+
+Revision 1.493 2004/12/16 20:13:00 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
+Revision 1.492 2004/12/16 08:03:24 shersche
+Fix compilation error when UNICAST_DISABLED is set
+
Revision 1.491 2004/12/11 01:52:11 cheshire
<rdar://problem/3785820> Support kDNSServiceFlagsAllowRemoteQuery for registering services too
Merge in license terms from Quinn's copy, in preparation for Darwin release
*/
-#define TEST_LOCALONLY_FOR_EVERYTHING 0
-
#include "DNSCommon.h" // Defines general DNS untility routines
#include "uDNS.h" // Defines entry points into unicast-specific routines
// Disable certain benign warnings with Microsoft compilers
mDNSexport const mDNSAddr zeroAddr = { mDNSAddrType_None, {{{ 0 }}} };
mDNSexport const mDNSInterfaceID mDNSInterface_Any = 0;
-mDNSexport const mDNSInterfaceID mDNSInterface_LocalOnly = (mDNSInterfaceID)-1;
+mDNSexport const mDNSInterfaceID mDNSInterface_LocalOnly = (mDNSInterfaceID)1;
-// Note that mDNSInterfaceMark is the same value as mDNSInterface_LocalOnly, but they are used in different contexts
mDNSlocal const mDNSInterfaceID mDNSInterfaceMark = (mDNSInterfaceID)~0;
#define UnicastDNSPortAsNumber 53
#define kMaxUpdateCredits 10
#define kUpdateCreditRefreshInterval (mDNSPlatformOneSecond * 6)
-static const char *const mDNS_DomainTypeNames[] =
+mDNSexport const char *const mDNS_DomainTypeNames[] =
{
- "_browse._dns-sd._udp.",
- "_default._browse._dns-sd._udp.",
- "_register._dns-sd._udp.",
- "_default._register._dns-sd._udp.",
- "_legacy._browse._dns-sd._udp."
+ "b._dns-sd._udp.", // Browse
+ "db._dns-sd._udp.", // Default Browse
+ "lb._dns-sd._udp.", // Legacy Browse
+ "r._dns-sd._udp.", // Registration
+ "dr._dns-sd._udp." // Default Registration
};
#ifdef UNICAST_DISABLED
m->NextScheduledQuery = (q->LastQTime + q->ThisQInterval);
}
+mDNSlocal CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name)
+ {
+ CacheGroup *cg;
+ for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
+ if (cg->namehash == namehash && SameDomainName(cg->name, name))
+ break;
+ return(cg);
+ }
+
+mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr)
+ {
+ return(CacheGroupForName(m, slot, rr->namehash, rr->name));
+ }
+
+mDNSlocal mDNSBool AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
+ {
+ NetworkInterfaceInfo *intf;
+
+ if (addr->type == mDNSAddrType_IPv4)
+ {
+ if (addr->ip.v4.b[0] == 169 && addr->ip.v4.b[1] == 254) return(mDNStrue);
+ for (intf = m->HostInterfaces; intf; intf = intf->next)
+ if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
+ if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0)
+ return(mDNStrue);
+ }
+
+ if (addr->type == mDNSAddrType_IPv6)
+ {
+ if (addr->ip.v6.b[0] == 0xFE && addr->ip.v6.b[1] == 0x80) return(mDNStrue);
+ for (intf = m->HostInterfaces; intf; intf = intf->next)
+ if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
+ if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) &&
+ (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) &&
+ (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) &&
+ (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0))
+ return(mDNStrue);
+ }
+
+ return(mDNSfalse);
+ }
+
+// Set up a AuthRecord with sensible default values.
+// These defaults may be overwritten with new values before mDNS_Register is called
+mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
+ mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, mDNSRecordCallback Callback, void *Context)
+ {
+ mDNSPlatformMemZero(&rr->uDNS_info, sizeof(uDNS_RegInfo));
+ // Don't try to store a TTL bigger than we can represent in platform time units
+ if (ttl > 0x7FFFFFFFUL / mDNSPlatformOneSecond)
+ ttl = 0x7FFFFFFFUL / mDNSPlatformOneSecond;
+ else if (ttl == 0) // And Zero TTL is illegal
+ ttl = DefaultTTLforRRType(rrtype);
+
+ // Field Group 1: The actual information pertaining to this resource record
+ rr->resrec.RecordType = RecordType;
+ rr->resrec.InterfaceID = InterfaceID;
+ rr->resrec.name = &rr->namestorage;
+ rr->resrec.rrtype = rrtype;
+ rr->resrec.rrclass = kDNSClass_IN;
+ rr->resrec.rroriginalttl = ttl;
+// rr->resrec.rdlength = MUST set by client and/or in mDNS_Register_internal
+// rr->resrec.rdestimate = set in mDNS_Register_internal
+// rr->resrec.rdata = MUST be set by client
+
+ if (RDataStorage)
+ rr->resrec.rdata = RDataStorage;
+ else
+ {
+ rr->resrec.rdata = &rr->rdatastorage;
+ rr->resrec.rdata->MaxRDLength = sizeof(RDataBody);
+ }
+
+ // Field Group 2: Persistent metadata for Authoritative Records
+ rr->Additional1 = mDNSNULL;
+ rr->Additional2 = mDNSNULL;
+ rr->DependentOn = mDNSNULL;
+ rr->RRSet = mDNSNULL;
+ rr->RecordCallback = Callback;
+ rr->RecordContext = Context;
+
+ rr->HostTarget = mDNSfalse;
+ rr->AllowRemoteQuery = mDNSfalse;
+ rr->ForceMCast = mDNSfalse;
+
+ // Field Group 3: Transient state for Authoritative Records (set in mDNS_Register_internal)
+
+ rr->namestorage.c[0] = 0; // MUST be set by client before calling mDNS_Register()
+ }
+
+// For a single given DNSQuestion, deliver an add/remove result for the single given AuthRecord
+// Used by AnswerLocalQuestions() and AnswerNewLocalOnlyQuestion()
+mDNSlocal void AnswerLocalOnlyQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, mDNSBool AddRecord)
+ {
+ // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
+ if (AddRecord) rr->LocalAnswer = mDNStrue;
+ m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
+ if (q->QuestionCallback)
+ q->QuestionCallback(m, q, &rr->resrec, AddRecord);
+ m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
+ }
+
+// When a new local AuthRecord is created or deleted, AnswerLocalQuestions() runs though our LocalOnlyQuestions delivering answers to each,
+// stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion().
+// If the AuthRecord is marked mDNSInterface_LocalOnly, then we also deliver it to any other questions we have using mDNSInterface_Any.
+// Used by AnswerForNewLocalRecords() and mDNS_Deregister_internal()
+mDNSlocal void AnswerLocalQuestions(mDNS *const m, AuthRecord *rr, mDNSBool AddRecord)
+ {
+ if (m->CurrentQuestion) LogMsg("AnswerLocalQuestions ERROR m->CurrentQuestion already set");
+
+ m->CurrentQuestion = m->LocalOnlyQuestions;
+ while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions)
+ {
+ DNSQuestion *q = m->CurrentQuestion;
+ m->CurrentQuestion = q->next;
+ if (ResourceRecordAnswersQuestion(&rr->resrec, q))
+ AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, AddRecord); // MUST NOT dereference q again
+ }
+
+ // If this AuthRecord is marked LocalOnly, then we want to deliver it to all local 'mDNSInterface_Any' questions
+ if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
+ {
+ m->CurrentQuestion = m->Questions;
+ while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
+ {
+ DNSQuestion *q = m->CurrentQuestion;
+ m->CurrentQuestion = q->next;
+ if (ResourceRecordAnswersQuestion(&rr->resrec, q))
+ AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, AddRecord); // MUST NOT dereference q again
+ }
+ }
+
+ m->CurrentQuestion = mDNSNULL;
+ }
+
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
if (r1->InterfaceID &&
r2->InterfaceID &&
r1->InterfaceID != r2->InterfaceID) return(mDNSfalse);
- return(mDNSBool)(r1->rrtype == r2->rrtype && r1->rrclass == r2->rrclass && r1->namehash == r2->namehash && SameDomainName(&r1->name, &r2->name));
+ return(mDNSBool)(r1->rrtype == r2->rrtype && r1->rrclass == r2->rrclass && r1->namehash == r2->namehash && SameDomainName(r1->name, r2->name));
}
// PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if our
authrr->resrec.InterfaceID &&
pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse);
if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) && pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
- return(mDNSBool)(pktrr->resrec.rrclass == authrr->resrec.rrclass && pktrr->resrec.namehash == authrr->resrec.namehash && SameDomainName(&pktrr->resrec.name, &authrr->resrec.name));
+ return(mDNSBool)(pktrr->resrec.rrclass == authrr->resrec.rrclass && pktrr->resrec.namehash == authrr->resrec.namehash && SameDomainName(pktrr->resrec.name, authrr->resrec.name));
}
// IdenticalResourceRecord returns true if two resources records have
{
if (!r1) { LogMsg("IdenticalResourceRecord ERROR: r1 is NULL"); return(mDNSfalse); }
if (!r2) { LogMsg("IdenticalResourceRecord ERROR: r2 is NULL"); return(mDNSfalse); }
- if (r1->rrtype != r2->rrtype || r1->rrclass != r2->rrclass || r1->namehash != r2->namehash || !SameDomainName(&r1->name, &r2->name)) return(mDNSfalse);
+ if (r1->rrtype != r2->rrtype || r1->rrclass != r2->rrclass || r1->namehash != r2->namehash || !SameDomainName(r1->name, r2->name)) return(mDNSfalse);
return(SameRData(r1, r2));
}
mDNSlocal mDNSBool ShouldSuppressKnownAnswer(const CacheRecord *const ka, const AuthRecord *const rr)
{
// If RR signature is different, or data is different, then don't suppress our answer
- if (!IdenticalResourceRecord(&ka->resrec,&rr->resrec)) return(mDNSfalse);
+ if (!IdenticalResourceRecord(&ka->resrec, &rr->resrec)) return(mDNSfalse);
// If the requester's indicated TTL is less than half the real TTL,
// we need to give our answer before the requester's copy expires.
if (!target) debugf("SetTargetToHostName: Don't know how to set the target of rrtype %d", rr->resrec.rrtype);
if (target && SameDomainName(target, &m->MulticastHostname))
- debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name.c, target->c);
+ debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name->c, target->c);
if (target && !SameDomainName(target, &m->MulticastHostname))
{
- AssignDomainName(*target, m->MulticastHostname);
+ AssignDomainName(target, &m->MulticastHostname);
SetNewRData(&rr->resrec, mDNSNULL, 0);
// If we're in the middle of probing this record, we need to start again,
// changing to the new rdata. However, in practice, we only do SetTargetToHostName for unique records,
// so when we announce them we'll set the kDNSClass_UniqueRRSet and clear any stale data that way.
if (rr->RequireGoodbye && rr->resrec.RecordType == kDNSRecordTypeShared)
- debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
rr->AnnounceCount = InitialAnnounceCount;
rr->RequireGoodbye = mDNSfalse;
AuthRecord *r;
AuthRecord **p = &m->ResourceRecords;
AuthRecord **d = &m->DuplicateRecords;
- AuthRecord **l = &m->LocalOnlyRecords;
mDNSPlatformMemZero(&rr->uDNS_info, sizeof(uDNS_RegInfo));
if ((mDNSs32)rr->resrec.rroriginalttl <= 0)
{ LogMsg("mDNS_Register_internal: TTL must be 1 - 0x7FFFFFFF %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
-#if TEST_LOCALONLY_FOR_EVERYTHING
- rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
-#endif
-
#ifndef UNICAST_DISABLED
- if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly || rr->ForceMCast || IsLocalDomain(&rr->resrec.name))
+ if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly || rr->ForceMCast || IsLocalDomain(rr->resrec.name))
rr->uDNS_info.id = zeroID;
else return uDNS_RegisterRecord(m, rr);
#endif
while (*p && *p != rr) p=&(*p)->next;
while (*d && *d != rr) d=&(*d)->next;
- while (*l && *l != rr) l=&(*l)->next;
- if (*d || *p || *l)
+ if (*d || *p)
{
- LogMsg("Error! Tried to register a AuthRecord %p %##s (%s) that's already in the list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ LogMsg("Error! Tried to register a AuthRecord %p %##s (%s) that's already in the list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
return(mStatus_AlreadyRegistered);
}
else
{
LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique",
- rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
return(mStatus_Invalid);
}
if (!(rr->DependentOn->resrec.RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeVerified)))
{
LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn->RecordType bad type %X",
- rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType);
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType);
return(mStatus_Invalid);
}
}
rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType);
rr->AnnounceCount = InitialAnnounceCount;
rr->RequireGoodbye = mDNSfalse;
+ rr->LocalAnswer = mDNSfalse;
rr->IncludeInProbe = mDNSfalse;
rr->ImmedAnswer = mDNSNULL;
rr->ImmedUnicast = mDNSfalse;
rr->UpdateBlocked = 0;
// rr->resrec.interface = already set in mDNS_SetupResourceRecord
-// rr->resrec.name.c = MUST be set by client
+// rr->resrec.name->c = MUST be set by client
// rr->resrec.rrtype = already set in mDNS_SetupResourceRecord
// rr->resrec.rrclass = already set in mDNS_SetupResourceRecord
// rr->resrec.rroriginalttl = already set in mDNS_SetupResourceRecord
rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue);
}
- if (!ValidateDomainName(&rr->resrec.name))
+ if (!ValidateDomainName(rr->resrec.name))
{ LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
// Some (or perhaps all) versions of BIND named (name daemon) don't allow updates with zero-length rdata. It's common for
if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata))
{ LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
- rr->resrec.namehash = DomainNameHashValue(&rr->resrec.name);
+ rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
rr->resrec.rdatahash = RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u);
rr->resrec.rdnamehash = target ? DomainNameHashValue(target) : 0;
if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
{
- debugf("Adding %p %##s (%s) to LocalOnly list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
- *l = rr;
- if (!m->NewLocalOnlyRecords) m->NewLocalOnlyRecords = rr;
// If this is supposed to be unique, make sure we don't have any name conflicts
if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
{
const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr;
- for (r = m->LocalOnlyRecords; r; r=r->next)
+ for (r = m->ResourceRecords; r; r=r->next)
{
const AuthRecord *s2 = r->RRSet ? r->RRSet : r;
if (s1 != s2 && SameResourceRecordSignature(&r->resrec, &rr->resrec) && !SameRData(&r->resrec, &rr->resrec))
break;
}
- if (r) // If we found a conflict, set DiscardLocalOnlyRecords so we'll deliver the callback
+ if (r) // If we found a conflict, set RecordType = kDNSRecordTypeDeregistering so we'll deliver the callback
{
- debugf("Name conflict %p %##s (%s)", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
- m->DiscardLocalOnlyRecords = mDNStrue;
- }
- else // else no conflict, so set ProbeCount to zero and update RecordType as appropriate
- {
- rr->ProbeCount = 0;
- if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
+ debugf("Name conflict %p %##s (%s)", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+ rr->resrec.RecordType = kDNSRecordTypeDeregistering;
+ rr->resrec.rroriginalttl = 0;
+ rr->ImmedAnswer = mDNSInterfaceMark;
+ m->NextScheduledResponse = m->timenow;
}
}
}
+
+ // Now that we've finished building our new record, make sure it's not identical to one we already have
+ for (r = m->ResourceRecords; r; r=r->next) if (RecordIsLocalDuplicate(r, rr)) break;
+
+ if (r)
+ {
+ debugf("Adding %p %##s (%s) to duplicate list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+ *d = rr;
+ // If the previous copy of this record is already verified unique,
+ // then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
+ // Setting ProbeCount to zero will cause SendQueries() to advance this record to
+ // kDNSRecordTypeVerified state and call the client callback at the next appropriate time.
+ if (rr->resrec.RecordType == kDNSRecordTypeUnique && r->resrec.RecordType == kDNSRecordTypeVerified)
+ rr->ProbeCount = 0;
+ }
else
{
- // Now that's we've finished building our new record, make sure it's not identical to one we already have
- for (r = m->ResourceRecords; r; r=r->next) if (RecordIsLocalDuplicate(r, rr)) break;
-
- if (r)
- {
- debugf("Adding %p %##s (%s) to duplicate list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
- *d = rr;
- // If the previous copy of this record is already verified unique,
- // then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
- // Setting ProbeCount to zero will cause SendQueries() to advance this record to
- // kDNSRecordTypeVerified state and call the client callback at the next appropriate time.
- if (rr->resrec.RecordType == kDNSRecordTypeUnique && r->resrec.RecordType == kDNSRecordTypeVerified)
- rr->ProbeCount = 0;
- }
- else
- {
- debugf("Adding %p %##s (%s) to active record list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
- *p = rr;
- }
+ debugf("Adding %p %##s (%s) to active record list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+ if (!m->NewLocalRecords) m->NewLocalRecords = rr;
+ *p = rr;
}
// For records that are not going to probe, acknowledge them right away
- if (rr->resrec.RecordType != kDNSRecordTypeUnique) AcknowledgeRecord(m, rr);
+ if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering)
+ AcknowledgeRecord(m, rr);
return(mStatus_NoError);
}
{
m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
LogMsg("Excessive name conflicts (%lu) for %##s (%s); rate limiting in effect",
- m->NumFailedProbes, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ m->NumFailedProbes, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
}
}
// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
mDNSlocal mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt)
{
+ AuthRecord *r2;
mDNSu8 RecordType = rr->resrec.RecordType;
AuthRecord **p = &m->ResourceRecords; // Find this record in our list of active records
#ifndef UNICAST_DISABLED
- if (!(rr->resrec.InterfaceID == mDNSInterface_LocalOnly || rr->ForceMCast || IsLocalDomain(&rr->resrec.name)))
+ if (!(rr->resrec.InterfaceID == mDNSInterface_LocalOnly || rr->ForceMCast || IsLocalDomain(rr->resrec.name)))
return uDNS_DeregisterRecord(m, rr);
#endif
- if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly) p = &m->LocalOnlyRecords;
while (*p && *p != rr) p=&(*p)->next;
if (*p)
// We found our record on the main list. See if there are any duplicates that need special handling.
if (drt == mDNS_Dereg_conflict) // If this was a conflict, see that all duplicates get the same treatment
{
- AuthRecord *r2 = m->DuplicateRecords;
- while (r2)
- {
- if (RecordIsLocalDuplicate(r2, rr)) { mDNS_Deregister_internal(m, r2, drt); r2 = m->DuplicateRecords; }
- else r2=r2->next;
- }
+ // Scan for duplicates of rr, and mark them for deregistration at the end of this routine, after we've finished
+ // deregistering rr. We need to do this scan *before* we give the client the chance to free and reuse the rr memory.
+ for (r2 = m->DuplicateRecords; r2; r2=r2->next) if (RecordIsLocalDuplicate(r2, rr)) r2->ProbeCount = 0xFF;
}
else
{
if (*d)
{
AuthRecord *dup = *d;
- debugf("Duplicate record %p taking over from %p %##s (%s)", dup, rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ debugf("Duplicate record %p taking over from %p %##s (%s)", dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
*d = dup->next; // Cut replacement record from DuplicateRecords list
dup->next = rr->next; // And then...
rr->next = dup; // ... splice it in right after the record we're about to delete
while (*p && *p != rr) p=&(*p)->next;
// If we found our record on the duplicate list, then make sure we don't send a goodbye for it
if (*p) rr->RequireGoodbye = mDNSfalse;
- if (*p) debugf("DNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ if (*p) debugf("DNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
}
if (!*p)
{
// No need to log an error message if we already know this is a potentially repeated deregistration
if (drt != mDNS_Dereg_repeat)
- LogMsg("mDNS_Deregister_internal: Record %p %##s (%s) not found in list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ LogMsg("mDNS_Deregister_internal: Record %p %##s (%s) not found in list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
return(mStatus_BadReferenceErr);
}
// we need to retract that announcement before we delete the record
if (RecordType == kDNSRecordTypeShared && rr->RequireGoodbye)
{
- verbosedebugf("mDNS_Deregister_internal: Sending deregister for %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ verbosedebugf("mDNS_Deregister_internal: Sending deregister for %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
rr->resrec.RecordType = kDNSRecordTypeDeregistering;
rr->resrec.rroriginalttl = 0;
rr->ImmedAnswer = mDNSInterfaceMark;
- if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
- m->DiscardLocalOnlyRecords = mDNStrue;
- else
- {
- if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0)
- m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10);
- }
+ if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0)
+ m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10);
}
else
{
*p = rr->next; // Cut this record from the list
// If someone is about to look at this, bump the pointer forward
- if (m->CurrentRecord == rr) m->CurrentRecord = rr->next;
- if (m->NewLocalOnlyRecords == rr) m->NewLocalOnlyRecords = rr->next;
+ if (m->CurrentRecord == rr) m->CurrentRecord = rr->next;
+ if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next;
rr->next = mDNSNULL;
if (RecordType == kDNSRecordTypeUnregistered)
debugf("mDNS_Deregister_internal: Record %##s (%s) already marked kDNSRecordTypeUnregistered",
- rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
else if (RecordType == kDNSRecordTypeDeregistering)
debugf("mDNS_Deregister_internal: Record %##s (%s) already marked kDNSRecordTypeDeregistering",
- rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
else
{
- verbosedebugf("mDNS_Deregister_internal: Deleting record for %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ verbosedebugf("mDNS_Deregister_internal: Deleting record for %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
rr->resrec.RecordType = kDNSRecordTypeUnregistered;
}
if ((drt == mDNS_Dereg_conflict || drt == mDNS_Dereg_repeat) && RecordType == kDNSRecordTypeShared)
debugf("mDNS_Deregister_internal: Cannot have a conflict on a shared record! %##s (%s)",
- rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
// If we have an update queued up which never executed, give the client a chance to free that memory
if (rr->NewRData) CompleteRDataUpdate(m, rr); // Update our rdata, clear the NewRData pointer, and return memory to the client
+ if (rr->LocalAnswer) AnswerLocalQuestions(m, rr, mDNSfalse);
+
// CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
// is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
// In this case the likely client action to the mStatus_MemFree message is to free the memory,
// so any attempt to touch rr after this is likely to lead to a crash.
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
- if (drt == mDNS_Dereg_conflict)
+ if (drt != mDNS_Dereg_conflict)
+ {
+ if (rr->RecordCallback) rr->RecordCallback(m, rr, mStatus_MemFree); // MUST NOT touch rr after this
+ }
+ else
{
RecordProbeFailure(m, rr);
- if (rr->RecordCallback) rr->RecordCallback(m, rr, mStatus_NameConflict);
+ if (rr->RecordCallback) rr->RecordCallback(m, rr, mStatus_NameConflict); // MUST NOT touch rr after this
+ // Now that we've finished deregistering rr, check our DuplicateRecords list for any that we marked previously.
+ // Note that with all the client callbacks going on, by the time we get here all the
+ // records we marked may have been explicitly deregistered by the client anyway.
+ r2 = m->DuplicateRecords;
+ while (r2)
+ {
+ if (r2->ProbeCount != 0xFF) r2 = r2->next;
+ else { mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict); r2 = m->DuplicateRecords; }
+ }
}
- else if (rr->RecordCallback) rr->RecordCallback(m, rr, mStatus_MemFree);
m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
}
return(mStatus_NoError);
rr->NR_AdditionalTo = add;
*nrpp = &rr->NextResponse;
}
- debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
}
mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID)
if (RRTypeIsAddressType(rr2->resrec.rrtype) && // For all address records (A/AAAA) ...
ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) && // ... which are valid for answer ...
rr->resrec.rdnamehash == rr2->resrec.namehash && // ... whose name is the name of the SRV target
- SameDomainName(&rr->resrec.rdata->u.srv.target, &rr2->resrec.name))
+ SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name))
AddRecordToResponseList(nrpp, rr2, rr);
}
}
while (m->CurrentRecord)
{
AuthRecord *rr = m->CurrentRecord;
- m->CurrentRecord = rr->next;
if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
CompleteDeregistration(m, rr); // Don't touch rr after this
+ else
+ m->CurrentRecord = rr->next;
}
}
ResourceRecordIsValidAnswer(r2) && // ... which are valid for answer ...
rr->LastMCTime - r2->LastMCTime >= 0 && // ... which we have not sent recently ...
rr->resrec.rdnamehash == r2->resrec.namehash && // ... whose name is the name of the SRV target
- SameDomainName(&rr->resrec.rdata->u.srv.target, &r2->resrec.name) &&
+ SameDomainName(&rr->resrec.rdata->u.srv.target, r2->resrec.name) &&
(rr->ImmedAnswer == mDNSInterfaceMark || rr->ImmedAnswer == r2->resrec.InterfaceID))
r2->ImmedAdditional = r2->resrec.InterfaceID; // ... then mark this address record for sending too
rr->ThisAPInterval *= 2;
rr->LastAPTime = m->timenow;
if (rr->LastAPTime + rr->ThisAPInterval - rr->AnnounceUntil >= 0) rr->AnnounceCount = 0;
- debugf("Announcing %##s (%s) %d", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->AnnounceCount);
+ debugf("Announcing %##s (%s) %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->AnnounceCount);
}
}
else if (rr->ImmedAnswer) // Else, just respond to a single query on single interface:
m->CurrentRecord = rr->next;
if (rr->SendRNow)
- { LogMsg("SendResponses: No active interface to send: %s", ARDisplayString(m, rr)); rr->SendRNow = mDNSNULL; }
+ {
+ if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
+ LogMsg("SendResponses: No active interface to send: %s", ARDisplayString(m, rr));
+ rr->SendRNow = mDNSNULL;
+ }
if (rr->ImmedAnswer)
{
rr->NextRequiredQuery -= TicksTTL(rr)/20 * (MaxUnansweredQueries - rr->UnansweredQueries);
rr->NextRequiredQuery += mDNSRandom((mDNSu32)TicksTTL(rr)/50);
verbosedebugf("SetNextCacheCheckTime: %##s (%s) NextRequiredQuery in %ld sec",
- rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond);
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond);
}
if (m->NextCacheCheck - (rr->NextRequiredQuery + CacheCheckGracePeriod(rr)) > 0)
mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **queryptr, DNSQuestion *q,
CacheRecord ***kalistptrptr, mDNSu32 *answerforecast)
{
- mDNSBool ucast = (q->LargeAnswers || q->ThisQInterval <= InitialQuestionInterval*2) && m->CanReceiveUnicastOn5353;
+ mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353;
mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
const mDNSu8 *const limit = query->data + NormalMaxDNSMessageData;
mDNSu8 *newptr = putQuestion(query, *queryptr, limit, &q->qname, q->qtype, (mDNSu16)(q->qclass | ucbit));
else
{
mDNSu32 forecast = *answerforecast;
+ const mDNSu32 slot = HashSlot(&q->qname);
+ CacheGroup *cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
CacheRecord *rr;
CacheRecord **ka = *kalistptrptr; // Make a working copy of the pointer we're going to update
- for (rr=m->rrcache_hash[HashSlot(&q->qname)]; rr; rr=rr->next) // If we have a resource record in our cache,
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // If we have a resource record in our cache,
if (rr->resrec.InterfaceID == q->SendQNow && // received on this interface
rr->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
*kalistptrptr = ka; // Update the known answer list pointer
if (ucast) m->ExpectUnicastResponse = m->timenow;
- for (rr=m->rrcache_hash[HashSlot(&q->qname)]; rr; rr=rr->next) // For every resource record in our cache,
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // For every resource record in our cache,
if (rr->resrec.InterfaceID == q->SendQNow && // received on this interface
rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList && // which is not in the known answer list
ResourceRecordAnswersQuestion(&rr->resrec, q)) // which answers our question
mDNSlocal void ReconfirmAntecedents(mDNS *const m, DNSQuestion *q)
{
mDNSu32 slot;
+ CacheGroup *cg;
CacheRecord *rr;
domainname *target;
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
- for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
- if ((target = GetRRDomainNameTarget(&rr->resrec)) && rr->resrec.rdnamehash == q->qnamehash && SameDomainName(target, &q->qname))
- mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForNoAnswer);
+ FORALL_CACHERECORDS(slot, cg, rr)
+ if ((target = GetRRDomainNameTarget(&rr->resrec)) && rr->resrec.rdnamehash == q->qnamehash && SameDomainName(target, &q->qname))
+ mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForNoAnswer);
}
// Only DupSuppressInfos newer than the specified 'time' are allowed to remain active
{
// We forecast: qname (n) type (2) class (2)
mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4;
+ const mDNSu32 slot = HashSlot(&q->qname);
+ CacheGroup *cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
CacheRecord *rr;
- for (rr=m->rrcache_hash[HashSlot(&q->qname)]; rr; rr=rr->next) // If we have a resource record in our cache,
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // If we have a resource record in our cache,
if (rr->resrec.rdlength <= SmallRecordLimit && // which is small enough to sensibly fit in the packet
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
if (m->timenow - m->NextScheduledQuery >= 0)
{
mDNSu32 slot;
+ CacheGroup *cg;
CacheRecord *rr;
m->NextScheduledQuery = m->timenow + 0x78000000;
// We're expecting to send a query anyway, so see if any expiring cache records are close enough
// to their NextRequiredQuery to be worth batching them together with this one
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
- for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
- if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
- if (m->timenow + TicksTTL(rr)/50 - rr->NextRequiredQuery >= 0)
- {
- q = rr->CRActiveQuestion;
- ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(rr)/20, rr->resrec.InterfaceID);
- if (q->Target.type) q->SendQNow = mDNSInterfaceMark; // If unicast query, mark it
- else if (q->SendQNow == mDNSNULL) q->SendQNow = rr->resrec.InterfaceID;
- else if (q->SendQNow != rr->resrec.InterfaceID) q->SendQNow = mDNSInterfaceMark;
- }
+ FORALL_CACHERECORDS(slot, cg, rr)
+ if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
+ if (m->timenow + TicksTTL(rr)/50 - rr->NextRequiredQuery >= 0)
+ {
+ q = rr->CRActiveQuestion;
+ ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(rr)/20, rr->resrec.InterfaceID);
+ if (q->Target.type) q->SendQNow = mDNSInterfaceMark; // If unicast query, mark it
+ else if (q->SendQNow == mDNSNULL) q->SendQNow = rr->resrec.InterfaceID;
+ else if (q->SendQNow != rr->resrec.InterfaceID) q->SendQNow = mDNSInterfaceMark;
+ }
- // Scan our list of questions to see which unicast queries need to be sent
+ // Scan our list of questions to see which *unicast* queries need to be sent
for (q = m->Questions; q; q=q->next)
if (q->Target.type && (q->SendQNow || TimeToSendThisQuestion(q, m->timenow)))
{
qptr = putQuestion(&m->omsg, qptr, limit, &q->qname, q->qtype, q->qclass);
mDNSSendDNSMessage(m, &m->omsg, qptr, mDNSInterface_Any, &q->Target, q->TargetPort, -1, mDNSNULL);
q->ThisQInterval *= 2;
+ if (q->ThisQInterval > MaxQuestionInterval)
+ q->ThisQInterval = MaxQuestionInterval;
q->LastQTime = m->timenow;
q->LastQTxTime = m->timenow;
q->RecentAnswerPkts = 0;
m->ExpectUnicastResponse = m->timenow;
}
- // Scan our list of questions to see which ones we're definitely going to send
+ // Scan our list of questions to see which *multicast* queries we're definitely going to send
for (q = m->Questions; q; q=q->next)
if (!q->Target.type && TimeToSendThisQuestion(q, m->timenow))
{
// Scan our list of questions
// (a) to see if there are any more that are worth accelerating, and
- // (b) to update the state variables for all the questions we're going to send
+ // (b) to update the state variables for *all* the questions we're going to send
for (q = m->Questions; q; q=q->next)
{
if (q->SendQNow ||
q->LastQTxTime = m->timenow;
q->RecentAnswerPkts = 0;
+ if (q->RequestUnicast) q->RequestUnicast--;
}
// For all questions (not just the ones we're sending) check what the next scheduled event will be
SetNextQueryTime(m,q);
mDNSBool ucast = (rr->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353;
mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
const mDNSu8 *const limit = m->omsg.data + ((m->omsg.h.numQuestions) ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData);
- mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit, &rr->resrec.name, kDNSQType_ANY, (mDNSu16)(rr->resrec.rrclass | ucbit));
+ mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit, rr->resrec.name, kDNSQType_ANY, (mDNSu16)(rr->resrec.rrclass | ucbit));
// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
mDNSu32 forecast = answerforecast + 12 + rr->resrec.rdestimate;
if (newptr && newptr + forecast < limit)
answerforecast = forecast;
rr->SendRNow = (rr->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
rr->IncludeInProbe = mDNStrue;
- verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->ProbeCount);
+ verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->ProbeCount);
}
else
{
- verbosedebugf("SendQueries: Retracting Question %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ verbosedebugf("SendQueries: Retracting Question %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
m->omsg.h.numQuestions--;
}
}
mDNSu8 *newptr = PutResourceRecordTTL(&m->omsg, queryptr, &m->omsg.h.numAnswers, &rr->resrec, rr->resrec.rroriginalttl - SecsSinceRcvd);
if (newptr)
{
- verbosedebugf("SendQueries: Put %##s (%s) at %d - %d", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data);
+ verbosedebugf("SendQueries: Put %##s (%s) at %d - %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data);
queryptr = newptr;
KnownAnswerList = rr->NextInKAList;
rr->NextInKAList = mDNSNULL;
rr->IncludeInProbe = mDNSfalse;
if (newptr) queryptr = newptr;
else LogMsg("SendQueries: How did we fail to have space for the Update record %##s (%s)?",
- rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
}
if (queryptr > m->omsg.data)
AuthRecord *rr;
for (rr = m->ResourceRecords; rr; rr=rr->next)
if (rr->SendRNow)
- { LogMsg("SendQueries: No active interface to send: %s", ARDisplayString(m, rr)); rr->SendRNow = mDNSNULL; }
+ {
+ if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
+ LogMsg("SendQueries: No active interface to send: %s", ARDisplayString(m, rr));
+ rr->SendRNow = mDNSNULL;
+ }
}
}
mDNSlocal void AnswerQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, CacheRecord *rr, mDNSBool AddRecord)
{
verbosedebugf("AnswerQuestionWithResourceRecord:%4lu %s TTL%6lu %##s (%s)",
- q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
// Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerQuestionWithResourceRecord(... mDNStrue)
// may be called twice, once when the record is received, and again when it's time to notify local clients.
SetNextCacheCheckTime(m, rr);
}
+ // If this is:
+ // (a) a no-cache add, where we've already done at least one 'QM' query, or
+ // (b) a normal add, where we have at least one unique-type answer,
+ // then there's no need to keep polling the network.
+ // (If we have an answer in the cache, then we'll automatically ask again in time to stop it expiring.)
+ if ((AddRecord == 2 && !q->RequestUnicast) ||
+ (AddRecord == 1 && (q->ExpectUnique || (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask))))
+ if (ActiveQuestion(q))
+ {
+ q->LastQTime = m->timenow;
+ q->LastQTxTime = m->timenow;
+ q->ThisQInterval = MaxQuestionInterval;
+ q->RequestUnicast = mDNSfalse;
+ }
+
if (rr->DelayDelivery) return; // We'll come back later when CacheRecordDeferredAdd() calls us
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
const mDNSs32 threshhold = m->timenow + mDNSPlatformOneSecond; // See if there are any records expiring within one second
const mDNSs32 start = m->timenow - 0x10000000;
mDNSs32 delay = start;
+ CacheGroup *cg = CacheGroupForName(m, slot, namehash, name);
CacheRecord *rr;
- for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
- if (rr->resrec.namehash == namehash && SameDomainName(&rr->resrec.name, name))
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
+ if (rr->resrec.namehash == namehash && SameDomainName(rr->resrec.name, name))
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);
{
q->LastAnswerPktNum = m->PktNum;
if (ActiveQuestion(q) && ++q->RecentAnswerPkts >= 10 &&
- q->ThisQInterval > InitialQuestionInterval*16 && m->timenow - q->LastQTxTime < mDNSPlatformOneSecond)
+ q->ThisQInterval > InitialQuestionInterval*32 && m->timenow - q->LastQTxTime < mDNSPlatformOneSecond)
{
LogMsg("CacheRecordAdd: %##s (%s) got immediate answer burst; restarting exponential backoff sequence",
q->qname.c, DNSTypeName(q->qtype));
- q->LastQTime = m->timenow - InitialQuestionInterval + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*4);
- q->ThisQInterval = InitialQuestionInterval;
+ q->LastQTime = m->timenow - InitialQuestionInterval + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*4);
+ q->ThisQInterval = InitialQuestionInterval;
SetNextQueryTime(m,q);
}
}
- verbosedebugf("CacheRecordAdd %p %##s (%s) %lu", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl);
+ verbosedebugf("CacheRecordAdd %p %##s (%s) %lu", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl);
q->CurrentAnswers++;
if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
m->CurrentQuestion = mDNSNULL;
}
+// NoCacheAnswer is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call.
+// If new questions are created as a result of invoking client callbacks, they will be added to
+// the end of the question list, and m->NewQuestions will be set to indicate the first new question.
+// rr is a new CacheRecord just received from the wire (kDNSRecordTypePacketAns/AnsUnique/Add/AddUnique)
+// but we don't have any place to cache it. We'll deliver question 'add' events now, but we won't have any
+// way to deliver 'remove' events in future, nor will we be able to include this in known-answer lists,
+// so we immediately bump ThisQInterval up to MaxQuestionInterval to avoid pounding the network.
+// NOTE: NoCacheAnswer calls AnswerQuestionWithResourceRecord which can call a user callback,
+// which may change the record list and/or question list.
+// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
+mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr)
+ {
+ LogMsg("No cache space: Delivering non-cached result for %##s", m->rec.r.resrec.name->c);
+ if (m->CurrentQuestion) LogMsg("CacheRecordAdd ERROR m->CurrentQuestion already set");
+ m->CurrentQuestion = m->Questions;
+ while (m->CurrentQuestion)
+ {
+ DNSQuestion *q = m->CurrentQuestion;
+ m->CurrentQuestion = q->next;
+ if (ResourceRecordAnswersQuestion(&rr->resrec, q))
+ AnswerQuestionWithResourceRecord(m, q, rr, 2); // Value '2' indicates "don't expect 'remove' events for this"
+ // MUST NOT dereference q again after calling AnswerQuestionWithResourceRecord()
+ }
+ m->CurrentQuestion = mDNSNULL;
+ }
+
// CacheRecordRmv is only called from CheckCacheExpiration, which is called from mDNS_Execute
// If new questions are created as a result of invoking client callbacks, they will be added to
// the end of the question list, and m->NewQuestions will be set to indicate the first new question.
m->CurrentQuestion = q->next;
if (ResourceRecordAnswersQuestion(&rr->resrec, q))
{
- verbosedebugf("CacheRecordRmv %p %##s (%s)", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ verbosedebugf("CacheRecordRmv %p %##s (%s)", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
if (q->CurrentAnswers == 0)
LogMsg("CacheRecordRmv ERROR: How can CurrentAnswers already be zero for %p %##s (%s)?", q, q->qname.c, DNSTypeName(q->qtype));
else
m->CurrentQuestion = mDNSNULL;
}
-mDNSlocal void ReleaseCacheRR(mDNS *const m, CacheRecord *r)
+mDNSlocal void ReleaseCacheEntity(mDNS *const m, CacheEntity *e)
{
- if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->rdatastorage)
- mDNSPlatformMemFree(r->resrec.rdata);
- r->resrec.rdata = mDNSNULL;
- r->next = m->rrcache_free;
- m->rrcache_free = r;
+#if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
+ unsigned int i;
+ for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF;
+#endif
+ e->next = m->rrcache_free;
+ m->rrcache_free = e;
m->rrcache_totalused--;
}
+mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp)
+ {
+ CacheEntity *e = (CacheEntity *)(*cp);
+ //LogMsg("ReleaseCacheGroup: Releasing CacheGroup for %p, %##s", (*cp)->name->c, (*cp)->name->c);
+ if ((*cp)->rrcache_tail != &(*cp)->members) LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)");
+ //if ((*cp)->name != (domainname*)((*cp)->namestorage)) LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage));
+ if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name);
+ (*cp)->name = mDNSNULL;
+ *cp = (*cp)->next; // Cut record from list
+ ReleaseCacheEntity(m, e);
+ }
+
+mDNSlocal void ReleaseCacheRecord(mDNS *const m, CacheRecord *r)
+ {
+ if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->rdatastorage) mDNSPlatformMemFree(r->resrec.rdata);
+ r->resrec.rdata = mDNSNULL;
+ ReleaseCacheEntity(m, (CacheEntity *)r);
+ }
+
// Note: We want to be careful that we deliver all the CacheRecordRmv calls before delivering CacheRecordDeferredAdd calls
// The in-order nature of the cache lists ensures that all callbacks for old records are delivered before callbacks for newer records
-mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot)
+mDNSlocal void CheckCacheExpiration(mDNS *const m, CacheGroup *cg)
{
- CacheRecord **rp = &(m->rrcache_hash[slot]);
+ CacheRecord **rp = &cg->members;
if (m->lock_rrcache) { LogMsg("CheckCacheExpiration ERROR! Cache already locked!"); return; }
m->lock_rrcache = 1;
CacheRecordRmv(m, rr);
m->rrcache_active--;
}
- m->rrcache_used[slot]--;
- ReleaseCacheRR(m, rr);
+ ReleaseCacheRecord(m, rr);
}
else // else, not expired; see if we need to query
{
rp = &rr->next;
}
}
- if (m->rrcache_tail[slot] != rp) verbosedebugf("CheckCacheExpiration: Updating m->rrcache_tail[%lu] from %p to %p", slot, m->rrcache_tail[slot], rp);
- m->rrcache_tail[slot] = rp;
+ if (cg->rrcache_tail != rp) verbosedebugf("CheckCacheExpiration: Updating CacheGroup tail from %p to %p", cg->rrcache_tail, rp);
+ cg->rrcache_tail = rp;
m->lock_rrcache = 0;
}
CacheRecord *rr;
DNSQuestion *q = m->NewQuestions; // Grab the question we're going to answer
const mDNSu32 slot = HashSlot(&q->qname);
+ CacheGroup *cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
verbosedebugf("AnswerNewQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- CheckCacheExpiration(m, slot);
+ if (cg) CheckCacheExpiration(m, cg);
m->NewQuestions = q->next; // Advance NewQuestions to the next *after* calling CheckCacheExpiration();
if (m->lock_rrcache) LogMsg("AnswerNewQuestion ERROR! Cache already locked!");
m->lock_rrcache = 1;
if (m->CurrentQuestion) LogMsg("AnswerNewQuestion ERROR m->CurrentQuestion already set");
m->CurrentQuestion = q; // Indicate which question we're answering, so we'll know if it gets deleted
- for (rr=m->rrcache_hash[slot]; rr; rr=rr->next)
+
+ if (q->InterfaceID == mDNSInterface_Any) // If 'mDNSInterface_Any' question, see if we want to tell it about LocalOnly records
+ {
+ if (m->CurrentRecord) LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentRecord already set");
+ m->CurrentRecord = m->ResourceRecords;
+ while (m->CurrentRecord && m->CurrentRecord != m->NewLocalRecords)
+ {
+ AuthRecord *rr = m->CurrentRecord;
+ m->CurrentRecord = rr->next;
+ if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
+ if (ResourceRecordAnswersQuestion(&rr->resrec, q))
+ {
+ AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, mDNStrue);
+ // MUST NOT dereference q again after calling AnswerLocalOnlyQuestionWithResourceRecord()
+ if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here
+ }
+ }
+ m->CurrentRecord = mDNSNULL;
+ }
+
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
if (ResourceRecordAnswersQuestion(&rr->resrec, q))
{
// SecsSinceRcvd is whole number of elapsed seconds, rounded down
if (rr->resrec.rroriginalttl <= SecsSinceRcvd)
{
LogMsg("AnswerNewQuestion: How is rr->resrec.rroriginalttl %lu <= SecsSinceRcvd %lu for %##s (%s)",
- rr->resrec.rroriginalttl, SecsSinceRcvd, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ rr->resrec.rroriginalttl, SecsSinceRcvd, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
continue; // Go to next one in loop
}
if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here
}
else if (RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype))
- if (rr->resrec.namehash == q->qnamehash && SameDomainName(&rr->resrec.name, &q->qname))
+ if (rr->resrec.namehash == q->qnamehash && SameDomainName(rr->resrec.name, &q->qname))
ShouldQueryImmediately = mDNSfalse;
if (ShouldQueryImmediately && m->CurrentQuestion == q)
{
- q->ThisQInterval = InitialQuestionInterval;
- q->LastQTime = m->timenow - q->ThisQInterval;
+ q->ThisQInterval = InitialQuestionInterval;
+ q->LastQTime = m->timenow - q->ThisQInterval;
m->NextScheduledQuery = m->timenow;
}
m->CurrentQuestion = mDNSNULL;
m->lock_rrcache = 0;
}
-mDNSlocal void AnswerLocalOnlyQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, mDNSBool AddRecord)
- {
- // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
- if (AddRecord) rr->RequireGoodbye = mDNStrue;
- m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
- if (q->QuestionCallback)
- q->QuestionCallback(m, q, &rr->resrec, AddRecord);
- m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
- }
-
+// When a NewLocalOnlyQuestion is created, AnswerNewLocalOnlyQuestion runs though our ResourceRecords delivering any appropriate answers,
+// stopping if it reaches a NewLocalRecord -- these will be handled by AnswerLocalQuestions
mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
{
DNSQuestion *q = m->NewLocalOnlyQuestions; // Grab the question we're going to answer
m->CurrentQuestion = q; // Indicate which question we're answering, so we'll know if it gets deleted
if (m->CurrentRecord) LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentRecord already set");
- m->CurrentRecord = m->LocalOnlyRecords;
- while (m->CurrentRecord && m->CurrentRecord != m->NewLocalOnlyRecords)
+ m->CurrentRecord = m->ResourceRecords;
+ while (m->CurrentRecord && m->CurrentRecord != m->NewLocalRecords)
{
AuthRecord *rr = m->CurrentRecord;
m->CurrentRecord = rr->next;
m->CurrentRecord = mDNSNULL;
}
-mDNSlocal void AnswerLocalOnlyQuestions(mDNS *const m, AuthRecord *rr, mDNSBool AddRecord)
- {
- if (m->CurrentQuestion) LogMsg("AnswerLocalOnlyQuestions ERROR m->CurrentQuestion already set");
- m->CurrentQuestion = m->LocalOnlyQuestions;
- while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions)
- {
- DNSQuestion *q = m->CurrentQuestion;
- m->CurrentQuestion = q->next;
- if (ResourceRecordAnswersQuestion(&rr->resrec, q))
- {
- debugf("AnswerLocalOnlyQuestions %p %##s (%s) %lu", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl);
- AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, AddRecord);
- // MUST NOT dereference q again after calling AnswerLocalOnlyQuestionWithResourceRecord()
- }
- }
- m->CurrentQuestion = mDNSNULL;
- }
-
-mDNSlocal void DiscardLocalOnlyRecords(mDNS *const m)
- {
- AuthRecord *rr = m->LocalOnlyRecords;
- while (rr)
- {
- if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
- { AnswerLocalOnlyQuestions(m, rr, mDNSfalse); CompleteDeregistration(m, rr); return; }
- if (rr->ProbeCount) { mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict); return; }
- rr=rr->next;
- }
- m->DiscardLocalOnlyRecords = mDNSfalse;
- }
-
-mDNSlocal void AnswerForNewLocalOnlyRecords(mDNS *const m)
- {
- AuthRecord *rr = m->NewLocalOnlyRecords;
- m->NewLocalOnlyRecords = m->NewLocalOnlyRecords->next;
- AnswerLocalOnlyQuestions(m, rr, mDNStrue);
- }
-
-mDNSlocal CacheRecord *GetFreeCacheRR(mDNS *const m, mDNSu16 RDLength)
+mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const PreserveCG)
{
- CacheRecord *r = mDNSNULL;
+ CacheEntity *e = mDNSNULL;
if (m->lock_rrcache) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); }
m->lock_rrcache = 1;
mDNSu32 slot;
for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
{
- CacheRecord **rp = &(m->rrcache_hash[slot]);
- while (*rp)
+ CacheGroup **cp = &m->rrcache_hash[slot];
+ while (*cp)
{
- // Records that answer still-active questions are not candidates for deletion
- if ((*rp)->CRActiveQuestion)
- rp=&(*rp)->next;
- else
+ CacheRecord **rp = &(*cp)->members;
+ while (*rp)
{
- CacheRecord *rr = *rp;
- *rp = (*rp)->next; // Cut record from list
- m->rrcache_used[slot]--; // Decrement counts
- ReleaseCacheRR(m, rr);
+ // Records that answer still-active questions are not candidates for recycling
+ // Records that are currently linked into the CacheFlushRecords list may not be recycled, or we'll crash
+ if ((*rp)->CRActiveQuestion || (*rp)->NextInCFList)
+ rp=&(*rp)->next;
+ else
+ {
+ CacheRecord *rr = *rp;
+ *rp = (*rp)->next; // Cut record from list
+ ReleaseCacheRecord(m, rr);
+ }
}
+ if ((*cp)->rrcache_tail != rp) verbosedebugf("GetFreeCacheRR: Updating rrcache_tail[%lu] from %p to %p", slot, (*cp)->rrcache_tail, rp);
+ (*cp)->rrcache_tail = rp;
+ if ((*cp)->members || (*cp)==PreserveCG) cp=&(*cp)->next;
+ else ReleaseCacheGroup(m, cp);
}
- if (m->rrcache_tail[slot] != rp) verbosedebugf("GetFreeCacheRR: Updating m->rrcache_tail[%lu] from %p to %p", slot, m->rrcache_tail[slot], rp);
- m->rrcache_tail[slot] = rp;
}
#if MDNS_DEBUGMSGS
debugf("Clear unused records; m->rrcache_totalused was %lu; now %lu", oldtotalused, m->rrcache_totalused);
#endif
}
-
- if (m->rrcache_free) // If there are records in the free list, take one
- {
- r = m->rrcache_free;
- m->rrcache_free = r->next;
- }
- if (r)
+ if (m->rrcache_free) // If there are records in the free list, take one
{
+ e = m->rrcache_free;
+ m->rrcache_free = e->next;
if (++m->rrcache_totalused >= m->rrcache_report)
{
- debugf("RR Cache now using %ld records", m->rrcache_totalused);
+ LogOperation("RR Cache now using %ld objects", m->rrcache_totalused);
if (m->rrcache_report < 100) m->rrcache_report += 10;
else m->rrcache_report += 100;
}
- mDNSPlatformMemZero(r, sizeof(*r));
+ mDNSPlatformMemZero(e, sizeof(*e));
+ }
+
+ m->lock_rrcache = 0;
+
+ return(e);
+ }
+
+mDNSlocal CacheRecord *GetCacheRecord(mDNS *const m, CacheGroup *cg, mDNSu16 RDLength)
+ {
+ CacheRecord *r = (CacheRecord *)GetCacheEntity(m, cg);
+ if (r)
+ {
r->resrec.rdata = (RData*)&r->rdatastorage; // By default, assume we're usually going to be using local storage
-
if (RDLength > InlineCacheRDSize) // If RDLength is too big, allocate extra storage
{
r->resrec.rdata = (RData*)mDNSPlatformMemAllocate(sizeofRDataHeader + RDLength);
if (r->resrec.rdata) r->resrec.rdata->MaxRDLength = r->resrec.rdlength = RDLength;
- else { ReleaseCacheRR(m, r); r = mDNSNULL; }
+ else { ReleaseCacheEntity(m, (CacheEntity*)r); r = mDNSNULL; }
}
}
+ return(r);
+ }
- m->lock_rrcache = 0;
+mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr)
+ {
+ mDNSu16 namelen = DomainNameLength(rr->name);
+ CacheGroup *cg = (CacheGroup*)GetCacheEntity(m, mDNSNULL);
+ if (!cg) { LogMsg("GetCacheGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); }
+ cg->next = m->rrcache_hash[slot];
+ cg->namehash = rr->namehash;
+ cg->members = mDNSNULL;
+ cg->rrcache_tail = &cg->members;
+ cg->name = (domainname*)cg->namestorage;
+ //LogMsg("GetCacheGroup: %-10s %d-byte cache name %##s", (namelen > InlineCacheGroupNameSize) ? "Allocating" : "Inline", namelen, rr->name->c);
+ if (namelen > InlineCacheGroupNameSize) cg->name = mDNSPlatformMemAllocate(namelen);
+ if (!cg->name)
+ {
+ LogMsg("GetCacheGroup: Failed to allocate name storage for %##s", rr->name->c);
+ ReleaseCacheEntity(m, (CacheEntity*)cg);
+ return(mDNSNULL);
+ }
+ AssignDomainName(cg->name, rr->name);
- return(r);
+ if (CacheGroupForRecord(m, slot, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c);
+ m->rrcache_hash[slot] = cg;
+ if (CacheGroupForRecord(m, slot, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c);
+
+ return(cg);
}
mDNSlocal void PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr)
{
mDNSu32 slot;
m->NextCacheCheck = m->timenow + 0x3FFFFFFF;
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) CheckCacheExpiration(m, slot);
+ for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
+ {
+ CacheGroup **cp = &m->rrcache_hash[slot];
+ while (*cp)
+ {
+ CheckCacheExpiration(m, *cp);
+ if ((*cp)->members) cp=&(*cp)->next;
+ else ReleaseCacheGroup(m, cp);
+ }
+ }
}
// 4. See if we can answer any of our new local questions from the cache
if (m->NewQuestions->DelayAnswering && m->timenow - m->NewQuestions->DelayAnswering < 0) break;
AnswerNewQuestion(m);
}
- if (i >= 1000) debugf("mDNS_Execute: AnswerNewQuestion exceeded loop limit");
+ if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewQuestion exceeded loop limit");
- for (i=0; m->DiscardLocalOnlyRecords && i<1000; i++) DiscardLocalOnlyRecords(m);
- if (i >= 1000) debugf("mDNS_Execute: DiscardLocalOnlyRecords exceeded loop limit");
-
for (i=0; m->NewLocalOnlyQuestions && i<1000; i++) AnswerNewLocalOnlyQuestion(m);
- if (i >= 1000) debugf("mDNS_Execute: AnswerNewLocalOnlyQuestion exceeded loop limit");
+ if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewLocalOnlyQuestion exceeded loop limit");
- for (i=0; m->NewLocalOnlyRecords && i<1000; i++) AnswerForNewLocalOnlyRecords(m);
- if (i >= 1000) debugf("mDNS_Execute: AnswerLocalOnlyQuestions exceeded loop limit");
+ for (i=0; i<1000 && m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords); i++)
+ {
+ AuthRecord *rr = m->NewLocalRecords;
+ m->NewLocalRecords = m->NewLocalRecords->next;
+ AnswerLocalQuestions(m, rr, mDNStrue);
+ }
+ if (i >= 1000) LogMsg("mDNS_Execute: AnswerForNewLocalRecords exceeded loop limit");
// 5. See what packets we need to send
if (m->mDNSPlatformStatus != mStatus_NoError || m->SleepState) DiscardDeregistrations(m);
mDNS_Lock(m);
m->SleepState = sleepstate;
- LogMsg("%s at %ld", sleepstate ? "Sleeping" : "Waking", m->timenow);
+ LogOperation("%s at %ld", sleepstate ? "Sleeping" : "Waking", m->timenow);
if (sleepstate)
{
{
DNSQuestion *q;
mDNSu32 slot;
+ CacheGroup *cg;
CacheRecord *cr;
#ifndef UNICAST_DISABLED
if (ActiveQuestion(q))
{
q->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question
+ q->RequestUnicast = 2; // Set to 2 because is decremented once *before* we check it
q->LastQTime = m->timenow - q->ThisQInterval;
q->RecentAnswerPkts = 0;
ExpireDupSuppressInfo(q->DupSuppress, m->timenow);
// 2. Re-validate our cache records
m->NextCacheCheck = m->timenow;
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
- for (cr = m->rrcache_hash[slot]; cr; cr=cr->next)
- mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForCableDisconnect);
+ FORALL_CACHERECORDS(slot, cg, cr)
+ mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForCableDisconnect);
// 3. Retrigger probing and announcing for all our authoritative records
for (rr = m->ResourceRecords; rr; rr=rr->next)
if (!result) result = CompareRData(our, &m->rec.r);
switch (result)
{
- case 1: debugf("ResolveSimultaneousProbe: %##s (%s): We won", our->resrec.name.c, DNSTypeName(our->resrec.rrtype));
+ 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));
+ 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;
}
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
}
if (!FoundUpdate)
- debugf("ResolveSimultaneousProbe: %##s (%s): No Update Record found", our->resrec.name.c, DNSTypeName(our->resrec.rrtype));
+ debugf("ResolveSimultaneousProbe: %##s (%s): No Update Record found", our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
exit:
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
}
mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, ResourceRecord *pktrr)
{
+ mDNSu32 slot = HashSlot(pktrr->name);
+ CacheGroup *cg = CacheGroupForRecord(m, slot, pktrr);
CacheRecord *rr;
- for (rr = m->rrcache_hash[HashSlot(&pktrr->name)]; rr; rr=rr->next)
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
if (pktrr->InterfaceID == rr->resrec.InterfaceID && IdenticalResourceRecord(pktrr, &rr->resrec)) break;
return(rr);
}
const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast, mDNSBool QueryWasLocalUnicast,
DNSMessage *const response)
{
+ mDNSBool FromLocalSubnet = AddressIsLocalSubnet(m, InterfaceID, srcaddr);
AuthRecord *ResponseRecords = mDNSNULL;
AuthRecord **nrp = &ResponseRecords;
CacheRecord *ExpectedAnswers = mDNSNULL; // Records in our cache we expect to see updated
{
NumAnswersForThisQuestion++;
// Notes:
- // NR_AnswerTo pointing into query packet means "answer via immediate legacy unicast" (may also choose to multicast as well)
- // NR_AnswerTo == (mDNSu8*)~1 means "answer via delayed unicast" (to modern querier)
+ // NR_AnswerTo pointing into query packet means "answer via immediate legacy unicast" (may *also* choose to multicast)
+ // NR_AnswerTo == (mDNSu8*)~1 means "answer via delayed unicast" (to modern querier; may promote to multicast instead)
// NR_AnswerTo == (mDNSu8*)~0 means "definitely answer via multicast" (can't downgrade to unicast later)
- if (QuestionNeedsMulticastResponse)
+ // If we're not multicasting this record because the kDNSQClass_UnicastResponse bit was set,
+ // but the multicast querier is not on a matching subnet (e.g. because of overalyed subnets on one link)
+ // then we'll multicast it anyway (if we unicast, the receiver will ignore it because it has an apparently non-local source)
+ if (QuestionNeedsMulticastResponse || (!FromLocalSubnet && QueryWasMulticast && !LegacyQuery))
{
// We only mark this question for sending if it is at least one second since the last time we multicast it
- // on this interface. If it is more than a second, or LastMCInterface is different, then we should multicast it.
+ // on this interface. If it is more than a second, or LastMCInterface is different, then we may multicast it.
// This is to guard against the case where someone blasts us with queries as fast as they can.
if (m->timenow - (rr->LastMCTime + mDNSPlatformOneSecond) >= 0 ||
(rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID))
// For any query generating a unicast response we don't do this because we can't assume we will see the response
if (QuestionNeedsMulticastResponse)
{
+ const mDNSu32 slot = HashSlot(&pktq.qname);
+ CacheGroup *cg = CacheGroupForName(m, slot, pktq.qnamehash, &pktq.qname);
CacheRecord *rr;
// Make a list indicating which of our own cache records we expect to see updated as a result of this query
// Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated
- for (rr = m->rrcache_hash[HashSlot(&pktq.qname)]; rr; rr=rr->next)
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
if (ResourceRecordAnswersQuestion(&rr->resrec, &pktq) && rr->resrec.rdlength <= SmallRecordLimit)
if (!rr->NextInKAList && eap != &rr->NextInKAList)
{
mDNSBool SendUnicastResponse = mDNSfalse; // Send modern unicast response (not legacy unicast response)
// If it's been a while since we multicast this, then send a multicast response for conflict detection, etc.
- if (m->timenow - (rr->LastMCTime + TicksTTL(rr)/4) >= 0) SendMulticastResponse = mDNStrue;
+ if (m->timenow - (rr->LastMCTime + TicksTTL(rr)/4) >= 0)
+ {
+ SendMulticastResponse = mDNStrue;
+ // If this record was marked for modern (delayed) unicast response, then mark it as promoted to
+ // multicast response instead (don't want to end up ALSO setting SendUnicastResponse in the check below).
+ // If this record was marked for legacy unicast response, then we mustn't change the NR_AnswerTo value.
+ if (rr->NR_AnswerTo == (mDNSu8*)~1) rr->NR_AnswerTo = (mDNSu8*)~0;
+ }
// If the client insists on a multicast response, then we'd better send one
if (rr->NR_AnswerTo == (mDNSu8*)~0) SendMulticastResponse = mDNStrue;
return(responseptr);
}
-mDNSlocal mDNSBool AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
- {
- NetworkInterfaceInfo *intf;
-
- if (addr->type == mDNSAddrType_IPv4)
- {
- if (addr->ip.v4.b[0] == 169 && addr->ip.v4.b[1] == 254) return(mDNStrue);
- for (intf = m->HostInterfaces; intf; intf = intf->next)
- if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID)
- if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0)
- return(mDNStrue);
- }
-
- if (addr->type == mDNSAddrType_IPv6)
- {
- if (addr->ip.v6.b[0] == 0xFE && addr->ip.v6.b[1] == 0x80) return(mDNStrue);
- for (intf = m->HostInterfaces; intf; intf = intf->next)
- if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID)
- if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) &&
- (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) &&
- (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) &&
- (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0))
- return(mDNStrue);
- }
-
- return(mDNSfalse);
- }
-
mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
const mDNSInterfaceID InterfaceID)
{
int i;
const mDNSu8 *ptr = LocateAnswers(response, end); // We ignore questions (if any) in a DNS response packet
- CacheRecord *CacheFlushRecords = mDNSNULL;
+ CacheRecord *CacheFlushRecords = (CacheRecord*)1; // "(CacheRecord*)1" is special (non-zero) end-of-list marker
CacheRecord **cfp = &CacheFlushRecords;
// All records in a DNS response packet are treated as equally valid statements of truth. If we want
// If we get a unicast response when we weren't expecting one, then we assume it is someone trying to spoof us
if (!mDNSAddrIsDNSMulticast(dstaddr))
+ {
if (!AddressIsLocalSubnet(m, InterfaceID, srcaddr) || (mDNSu32)(m->timenow - m->ExpectUnicastResponse) > (mDNSu32)(mDNSPlatformOneSecond*2))
return;
+ // For now we don't put standard wide-area unicast responses in our main cache
+ // (Later we should fix this and cache all known results in a unified manner.)
+ if (response->h.id.NotAnInteger != 0 || srcport.NotAnInteger != MulticastDNSPort.NotAnInteger)
+ return;
+ }
for (i = 0; i < totalrecords && ptr && ptr < end; i++)
{
// If we'd previously verified this record, put it back to probing state and try again
if (rr->resrec.RecordType == kDNSRecordTypeVerified)
{
- debugf("mDNSCoreReceiveResponse: Reseting to Probing: %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ debugf("mDNSCoreReceiveResponse: Reseting to Probing: %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
rr->resrec.RecordType = kDNSRecordTypeUnique;
rr->ProbeCount = DefaultProbeCountForTypeUnique + 1;
rr->ThisAPInterval = DefaultAPIntervalForRecordType(kDNSRecordTypeUnique);
// If we're probing for this record, we just failed
else if (rr->resrec.RecordType == kDNSRecordTypeUnique)
{
- debugf("mDNSCoreReceiveResponse: Will rename %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ debugf("mDNSCoreReceiveResponse: Will rename %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
}
// We assumed this record must be unique, but we were wrong.
else if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique)
{
debugf("mDNSCoreReceiveResponse: Unexpected conflict on %##s (%s) -- discarding our record",
- rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
}
else
debugf("mDNSCoreReceiveResponse: Unexpected record type %X %##s (%s)",
- rr->resrec.RecordType, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
+ rr->resrec.RecordType, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
}
}
// Else, matching signature, different type or rdata, but not a considered a conflict.
// 2. See if we want to add this packet resource record to our cache
if (m->rrcache_size) // Only try to cache answers if we have a cache to put them in
{
- const mDNSu32 slot = HashSlot(&m->rec.r.resrec.name);
+ const mDNSu32 slot = HashSlot(m->rec.r.resrec.name);
+ CacheGroup *cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec);
CacheRecord *rr;
// 2a. Check if this packet resource record is already in our cache
- for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
{
// If we found this exact resource record, refresh its TTL
if (rr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&m->rec.r.resrec, &rr->resrec))
{
// If this packet record has the kDNSClass_UniqueRRSet flag set, then add it to our cache flushing list
if (rr->NextInCFList == mDNSNULL && cfp != &rr->NextInCFList)
- { *cfp = rr; cfp = &rr->NextInCFList; }
+ { *cfp = rr; cfp = &rr->NextInCFList; *cfp = (CacheRecord*)1; }
// If this packet record is marked unique, and our previous cached copy was not, then fix it
if (!(rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask))
// (unless it is just a deletion of a record we never had, in which case we don't care)
if (!rr && m->rec.r.resrec.rroriginalttl > 0)
{
- rr = GetFreeCacheRR(m, m->rec.r.resrec.rdlength);
- if (!rr) debugf("No cache space to add record for %#s", m->rec.r.resrec.name.c);
+ // If we don't have a CacheGroup for this name, make one now
+ if (!cg) cg = GetCacheGroup(m, slot, &m->rec.r.resrec);
+ if (cg) rr = GetCacheRecord(m, cg, m->rec.r.resrec.rdlength); // Make a cache record, being careful not to recycle cg
+ if (!rr) NoCacheAnswer(m, &m->rec.r);
else
{
RData *saveptr = rr->resrec.rdata; // Save the rr->resrec.rdata pointer
- *rr = m->rec.r;
- rr->resrec.rdata = saveptr; // and then restore it after the structure assignment
+ *rr = m->rec.r; // Block copy the CacheRecord object
+ rr->resrec.rdata = saveptr; // Restore rr->resrec.rdata after the structure assignment
+ rr->resrec.name = cg->name; // And set rr->resrec.name to point into our CacheGroup header
if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask)
- { *cfp = rr; cfp = &rr->NextInCFList; }
+ { *cfp = rr; cfp = &rr->NextInCFList; *cfp = (CacheRecord*)1; }
// If this is an oversized record with external storage allocated, copy rdata to external storage
+ if (rr->resrec.rdata != (RData*)&rr->rdatastorage && !(m->rec.r.resrec.rdlength > InlineCacheRDSize))
+ LogMsg("rr->resrec.rdata != &rr->rdatastorage but length <= InlineCacheRDSize %##s", m->rec.r.resrec.name->c);
if (m->rec.r.resrec.rdlength > InlineCacheRDSize)
mDNSPlatformMemCopy(m->rec.r.resrec.rdata, rr->resrec.rdata, sizeofRDataHeader + m->rec.r.resrec.rdlength);
rr->next = mDNSNULL; // Clear 'next' pointer
- *(m->rrcache_tail[slot]) = rr; // Append this record to tail of cache slot list
- m->rrcache_tail[slot] = &(rr->next); // Advance tail pointer
- m->rrcache_used[slot]++;
+ *(cg->rrcache_tail) = rr; // Append this record to tail of cache slot list
+ cg->rrcache_tail = &(rr->next); // Advance tail pointer
if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) // If marked unique, assume we may have
rr->DelayDelivery = m->timenow + mDNSPlatformOneSecond; // to delay delivery of this 'add' event
else
- rr->DelayDelivery = CheckForSoonToExpireRecords(m, &rr->resrec.name, rr->resrec.namehash, slot);
- //debugf("Adding RR %##s to cache (%d)", m->rec.r.name.c, m->rrcache_used);
+ rr->DelayDelivery = CheckForSoonToExpireRecords(m, rr->resrec.name, rr->resrec.namehash, slot);
CacheRecordAdd(m, rr);
// MUST do this AFTER CacheRecordAdd(), because that's what sets CRActiveQuestion for us
SetNextCacheCheckTime(m, rr);
// If we've just received one or more records with their cache flush bits set,
// then scan that cache slot to see if there are any old stale records we need to flush
- while (CacheFlushRecords)
+ while (CacheFlushRecords != (CacheRecord*)1)
{
CacheRecord *r1 = CacheFlushRecords, *r2;
- const mDNSu32 slot = HashSlot(&r1->resrec.name);
+ const mDNSu32 slot = HashSlot(r1->resrec.name);
+ CacheGroup *cg = CacheGroupForRecord(m, slot, &r1->resrec);
CacheFlushRecords = CacheFlushRecords->NextInCFList;
r1->NextInCFList = mDNSNULL;
- for (r2 = m->rrcache_hash[slot]; r2; r2=r2->next)
- if (SameResourceRecordSignature(&r1->resrec, &r2->resrec) && m->timenow - r2->TimeRcvd > mDNSPlatformOneSecond)
+ for (r2 = cg ? cg->members : mDNSNULL; r2; r2=r2->next)
+ if (SameResourceRecordSignature(&r1->resrec, &r2->resrec))
{
- verbosedebugf("Cache flush %p X %p %##s (%s)", r1, r2, r2->resrec.name.c, DNSTypeName(r2->resrec.rrtype));
- // We set stale records to expire in one second.
- // This gives the owner a chance to rescue it if necessary.
- // This is important in the case of multi-homing and bridged networks:
- // Suppose host X is on Ethernet. X then connects to an AirPort base station, which happens to be
- // bridged onto the same Ethernet. When X announces its AirPort IP address with the cache-flush bit
- // set, the AirPort packet will be bridged onto the Ethernet, and all other hosts on the Ethernet
- // will promptly delete their cached copies of the (still valid) Ethernet IP address record.
- // By delaying the deletion by one second, we give X a change to notice that this bridging has
- // happened, and re-announce its Ethernet IP address to rescue it from deletion from all our caches.
- // We set UnansweredQueries to MaxUnansweredQueries to avoid expensive and unnecessary
- // final expiration queries for this record.
- r2->resrec.rroriginalttl = 1;
- r2->TimeRcvd = m->timenow;
- r2->UnansweredQueries = MaxUnansweredQueries;
- SetNextCacheCheckTime(m, r2);
+ // If record is recent, just ensure the whole RRSet has the same TTL (as required by DNS semantics)
+ // else, if record is old, mark it to be flushed
+ if (m->timenow - r2->TimeRcvd < mDNSPlatformOneSecond)
+ r2->resrec.rroriginalttl = r1->resrec.rroriginalttl;
+ else
+ {
+ verbosedebugf("Cache flush %p X %p %##s (%s)", r1, r2, r2->resrec.name->c, DNSTypeName(r2->resrec.rrtype));
+ // We set stale records to expire in one second.
+ // This gives the owner a chance to rescue it if necessary.
+ // This is important in the case of multi-homing and bridged networks:
+ // Suppose host X is on Ethernet. X then connects to an AirPort base station, which happens to be
+ // bridged onto the same Ethernet. When X announces its AirPort IP address with the cache-flush bit
+ // set, the AirPort packet will be bridged onto the Ethernet, and all other hosts on the Ethernet
+ // will promptly delete their cached copies of the (still valid) Ethernet IP address record.
+ // By delaying the deletion by one second, we give X a change to notice that this bridging has
+ // happened, and re-announce its Ethernet IP address to rescue it from deletion from all our caches.
+ // We set UnansweredQueries to MaxUnansweredQueries to avoid expensive and unnecessary
+ // final expiration queries for this record.
+ r2->resrec.rroriginalttl = 1;
+ r2->TimeRcvd = m->timenow;
+ r2->UnansweredQueries = MaxUnansweredQueries;
+ SetNextCacheCheckTime(m, r2);
+ }
}
if (r1->DelayDelivery) // If we were planning to delay delivery of this record, see if we still need to
{
- r1->DelayDelivery = CheckForSoonToExpireRecords(m, &r1->resrec.name, r1->resrec.namehash, slot);
+ r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, slot);
if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1);
}
}
const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery;
mDNSu8 QR_OP;
mDNSu8 *ptr = mDNSNULL;
+ const mDNSu8 UpdateR = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update;
#ifndef UNICAST_DISABLED
mDNSIPPort NATPort = mDNSOpaque16fromIntVal(NATMAP_PORT);
- const mDNSu8 UpdateR = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update;
-
+
if (srcport.NotAnInteger == NATPort.NotAnInteger)
{
mDNS_Lock(m);
if (q->DuplicateOf == question) // To see if any questions were referencing this as their duplicate
{
q->ThisQInterval = question->ThisQInterval;
+ q->RequestUnicast = question->RequestUnicast;
q->LastQTime = question->LastQTime;
q->RecentAnswerPkts = 0;
q->DuplicateOf = FindDuplicateQuestion(m, q);
mDNSlocal mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question)
{
-#if TEST_LOCALONLY_FOR_EVERYTHING
- question->InterfaceID = mDNSInterface_LocalOnly;
-#endif
-
if (question->Target.type && !ValidQuestionTarget(question))
{
LogMsg("Warning! Target.type = %ld port = %u (Client forgot to initialize before calling mDNS_StartQuery?)",
question->qnamehash = DomainNameHashValue(&question->qname); // MUST do this before FindDuplicateQuestion()
question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, HashSlot(&question->qname));
question->ThisQInterval = InitialQuestionInterval * 2; // MUST be > zero for an active question
+ question->RequestUnicast = 2; // Set to 2 because is decremented once *before* we check it
question->LastQTime = m->timenow - m->RandomQueryDelay; // Avoid inter-machine synchronization
question->LastAnswerPktNum = m->PktNum;
question->RecentAnswerPkts = 0;
mDNSlocal mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question)
{
+ const mDNSu32 slot = HashSlot(&question->qname);
+ CacheGroup *cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname);
CacheRecord *rr;
DNSQuestion **q = &m->Questions;
// If there are any cache records referencing this as their active question, then see if any other
// question that is also referencing them, else their CRActiveQuestion needs to get set to NULL.
- for (rr = m->rrcache_hash[HashSlot(&question->qname)]; rr; rr=rr->next)
+ for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
{
if (rr->CRActiveQuestion == question)
{
for (q = m->Questions; q; q=q->next) // Scan our list of questions
if (ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q))
break;
- verbosedebugf("mDNS_StopQuery_internal: Cache RR %##s (%s) setting CRActiveQuestion to %p", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), q);
+ verbosedebugf("mDNS_StopQuery_internal: Cache RR %##s (%s) setting CRActiveQuestion to %p", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), q);
rr->CRActiveQuestion = q; // Question used to be active; new value may or may not be null
if (!q) m->rrcache_active--; // If no longer active, decrement rrcache_active count
}
{
query->GotSRV = mDNStrue;
query->qAv4.InterfaceID = answer->InterfaceID;
- AssignDomainName(query->qAv4.qname, answer->rdata->u.srv.target);
+ AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target);
query->qAv6.InterfaceID = answer->InterfaceID;
- AssignDomainName(query->qAv6.qname, answer->rdata->u.srv.target);
+ AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target);
mDNS_StartQuery(m, &query->qAv4);
// Only do the AAAA query if this machine actually has IPv6 active
if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6);
else
{
query->qAv4.InterfaceID = answer->InterfaceID;
- AssignDomainName(query->qAv4.qname, answer->rdata->u.srv.target);
+ AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target);
query->qAv6.InterfaceID = answer->InterfaceID;
- AssignDomainName(query->qAv6.qname, answer->rdata->u.srv.target);
+ AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target);
}
debugf("FoundServiceInfoSRV: Restarting address queries for %##s", query->qAv4.qname.c);
mDNS_StartQuery(m, &query->qAv4);
}
else
{
- debugf("FoundServiceInfo: answer %##s type %d (%s) unexpected", answer->name.c, answer->rrtype, DNSTypeName(answer->rrtype));
+ debugf("FoundServiceInfo: answer %##s type %d (%s) unexpected", answer->name->c, answer->rrtype, DNSTypeName(answer->rrtype));
return;
}
query->qSRV.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
query->qSRV.InterfaceID = info->InterfaceID;
query->qSRV.Target = zeroAddr;
- AssignDomainName(query->qSRV.qname, info->name);
+ AssignDomainName(&query->qSRV.qname, &info->name);
query->qSRV.qtype = kDNSType_SRV;
query->qSRV.qclass = kDNSClass_IN;
query->qSRV.LongLived = mDNSfalse;
query->qTXT.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
query->qTXT.InterfaceID = info->InterfaceID;
query->qTXT.Target = zeroAddr;
- AssignDomainName(query->qTXT.qname, info->name);
+ AssignDomainName(&query->qTXT.qname, &info->name);
query->qTXT.qtype = kDNSType_TXT;
query->qTXT.qclass = kDNSClass_IN;
query->qTXT.LongLived = mDNSfalse;
return(status);
}
-mDNSexport void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query)
+mDNSexport void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *q)
{
mDNS_Lock(m);
// We use mDNS_StopQuery_internal here because we're already holding the lock
- if (query->qSRV.ThisQInterval >= 0 || uDNS_IsActiveQuery(&query->qSRV, &m->uDNS_info))
- mDNS_StopQuery_internal(m, &query->qSRV);
- if (query->qTXT.ThisQInterval >= 0 || uDNS_IsActiveQuery(&query->qTXT, &m->uDNS_info))
- mDNS_StopQuery_internal(m, &query->qTXT);
- if (query->qAv4.ThisQInterval >= 0 || uDNS_IsActiveQuery(&query->qAv4, &m->uDNS_info))
- mDNS_StopQuery_internal(m, &query->qAv4);
- if (query->qAv6.ThisQInterval >= 0 || uDNS_IsActiveQuery(&query->qAv6, &m->uDNS_info))
- mDNS_StopQuery_internal(m, &query->qAv6);
+ if (q->qSRV.ThisQInterval >= 0 || uDNS_IsActiveQuery(&q->qSRV, &m->uDNS_info)) mDNS_StopQuery_internal(m, &q->qSRV);
+ if (q->qTXT.ThisQInterval >= 0 || uDNS_IsActiveQuery(&q->qTXT, &m->uDNS_info)) mDNS_StopQuery_internal(m, &q->qTXT);
+ if (q->qAv4.ThisQInterval >= 0 || uDNS_IsActiveQuery(&q->qAv4, &m->uDNS_info)) mDNS_StopQuery_internal(m, &q->qAv4);
+ if (q->qAv6.ThisQInterval >= 0 || uDNS_IsActiveQuery(&q->qAv6, &m->uDNS_info)) mDNS_StopQuery_internal(m, &q->qAv6);
mDNS_Unlock(m);
}
question->ForceMCast = mDNSfalse;
question->QuestionCallback = Callback;
question->QuestionContext = Context;
- if (DomainType > mDNS_DomainTypeBrowseLegacy) return(mStatus_BadParamErr);
+ if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr);
if (!MakeDomainNameFromDNSNameString(&question->qname, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr);
if (!dom) dom = &localdomain;
if (!AppendDomainName(&question->qname, dom)) return(mStatus_BadParamErr);
#pragma mark - Responder Functions
#endif
-// Set up a AuthRecord with sensible default values.
-// These defaults may be overwritten with new values before mDNS_Register is called
-mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
- mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, mDNSRecordCallback Callback, void *Context)
- {
- mDNSPlatformMemZero(&rr->uDNS_info, sizeof(uDNS_RegInfo));
- // Don't try to store a TTL bigger than we can represent in platform time units
- if (ttl > 0x7FFFFFFFUL / mDNSPlatformOneSecond)
- ttl = 0x7FFFFFFFUL / mDNSPlatformOneSecond;
- else if (ttl == 0) // And Zero TTL is illegal
- ttl = DefaultTTLforRRType(rrtype);
-
- // Field Group 1: Persistent metadata for Authoritative Records
- rr->Additional1 = mDNSNULL;
- rr->Additional2 = mDNSNULL;
- rr->DependentOn = mDNSNULL;
- rr->RRSet = mDNSNULL;
- rr->RecordCallback = Callback;
- rr->RecordContext = Context;
-
- rr->resrec.RecordType = RecordType;
- rr->HostTarget = mDNSfalse;
- rr->AllowRemoteQuery = mDNSfalse;
- rr->ForceMCast = mDNSfalse;
-
- // Field Group 2: Transient state for Authoritative Records (set in mDNS_Register_internal)
- // Field Group 3: Transient state for Cache Records (set in mDNS_Register_internal)
-
- // Field Group 4: The actual information pertaining to this resource record
- rr->resrec.InterfaceID = InterfaceID;
- rr->resrec.name.c[0] = 0; // MUST be set by client
- rr->resrec.rrtype = rrtype;
- rr->resrec.rrclass = kDNSClass_IN;
- rr->resrec.rroriginalttl = ttl;
-// rr->resrec.rdlength = MUST set by client and/or in mDNS_Register_internal
-// rr->resrec.rdestimate = set in mDNS_Register_internal
-// rr->resrec.rdata = MUST be set by client
-
- if (RDataStorage)
- rr->resrec.rdata = RDataStorage;
- else
- {
- rr->resrec.rdata = &rr->rdatastorage;
- rr->resrec.rdata->MaxRDLength = sizeof(RDataBody);
- }
- }
-
mDNSexport mStatus mDNS_Register(mDNS *const m, AuthRecord *const rr)
{
mStatus status;
const mDNSu16 newrdlength, RData *const newrdata, mDNSRecordUpdateCallback *Callback)
{
#ifndef UNICAST_DISABLED
- mDNSBool unicast = !(rr->resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&rr->resrec.name));
+ mDNSBool unicast = !(rr->resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(rr->resrec.name));
#else
mDNSBool unicast = mDNSfalse;
#endif
{
domainlabel name;
domainname type, domain;
- DeconstructServiceName(&rr->resrec.name, &name, &type, &domain);
+ DeconstructServiceName(rr->resrec.name, &name, &type, &domain);
rr->AnnounceCount = InitialAnnounceCount;
// iChat often does suprious record updates where no data has changed. For the _presence service type, using
// name/value pairs, the mDNSPlatformMemSame() check above catches this and correctly suppresses the wasteful
if (rr->AnnounceCount > rr->UpdateCredits + 1) rr->AnnounceCount = (mDNSu8)(rr->UpdateCredits + 1);
if (rr->UpdateCredits <= 5)
{
- mDNSs32 delay = 6 - rr->UpdateCredits; // Delay 1 second, then 2, then 3, etc. up to 6 seconds maximum
- if (!rr->UpdateBlocked) rr->UpdateBlocked = NonZeroTime(m->timenow + delay * mDNSPlatformOneSecond);
+ mDNSu32 delay = 6 - rr->UpdateCredits; // Delay 1 second, then 2, then 3, etc. up to 6 seconds maximum
+ if (!rr->UpdateBlocked) rr->UpdateBlocked = NonZeroTime(m->timenow + (mDNSs32)delay * mDNSPlatformOneSecond);
rr->ThisAPInterval *= 4;
rr->LastAPTime = rr->UpdateBlocked - rr->ThisAPInterval;
- LogMsg("Excessive update rate for %##s; delaying announcement by %ld second%s", rr->resrec.name.c, delay, delay > 1 ? "s" : "");
+ LogMsg("Excessive update rate for %##s; delaying announcement by %ld second%s", rr->resrec.name->c, delay, delay > 1 ? "s" : "");
}
rr->resrec.rroriginalttl = newttl;
}
#endif
// 1. Set up Address record to map from host name ("foo.local.") to IP address
// 2. Set up reverse-lookup PTR record to map from our address back to our host name
- AssignDomainName(set->RR_A.resrec.name, m->MulticastHostname);
+ AssignDomainName(set->RR_A.resrec.name, &m->MulticastHostname);
if (set->ip.type == mDNSAddrType_IPv4)
{
set->RR_A.resrec.rrtype = kDNSType_A;
mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
}
- MakeDomainNameFromDNSNameString(&set->RR_PTR.resrec.name, buffer);
+ MakeDomainNameFromDNSNameString(set->RR_PTR.resrec.name, buffer);
set->RR_PTR.HostTarget = mDNStrue; // Tell mDNS that the target of this PTR is to be kept in sync with our host name
set->RR_PTR.ForceMCast = mDNStrue; // This PTR points to our dot-local name, so don't ever try to write it into a uDNS server
if (m->HIHardware.c[0] > 0 && m->HISoftware.c[0] > 0 && m->HIHardware.c[0] + m->HISoftware.c[0] <= 254)
{
mDNSu8 *p = set->RR_HINFO.resrec.rdata->u.data;
- AssignDomainName(set->RR_HINFO.resrec.name, m->MulticastHostname);
+ AssignDomainName(set->RR_HINFO.resrec.name, &m->MulticastHostname);
set->RR_HINFO.DependentOn = &set->RR_A;
mDNSPlatformMemCopy(&m->HIHardware, p, 1 + (mDNSu32)m->HIHardware.c[0]);
p += 1 + (int)p[0];
if (SameDomainName(&m->MulticastHostname, &newmname)) { LogMsg("mDNS_SetFQDN - hostname unchanged"); return; }
mDNS_Lock(m);
- AssignDomainName(m->MulticastHostname, newmname);
+ AssignDomainName(&m->MulticastHostname, &newmname);
// 1. Stop advertising our address records on all interfaces
for (intf = m->HostInterfaces; intf; intf = intf->next)
char *msg = "Unknown result";
if (result == mStatus_NoError) msg = "Name registered";
else if (result == mStatus_NameConflict) msg = "Name conflict";
- debugf("mDNS_HostNameCallback: %##s (%s) %s (%ld)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), msg, result);
+ debugf("mDNS_HostNameCallback: %##s (%s) %s (%ld)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), msg, result);
}
#endif
debugf("mDNS_HostNameCallback: MemFree (ignored)");
}
else
- LogMsg("mDNS_HostNameCallback: Unknown error %ld for registration of record %s", result, rr->resrec.name.c);
+ LogMsg("mDNS_HostNameCallback: Unknown error %ld for registration of record %s", result, rr->resrec.name->c);
}
mDNSlocal void UpdateInterfaceProtocols(mDNS *const m, NetworkInterfaceInfo *active)
}
}
-mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set)
+mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSs32 delay)
{
mDNSBool FirstOfType = mDNStrue;
NetworkInterfaceInfo **p = &m->HostInterfaces;
set->next = mDNSNULL;
*p = set;
+ if (set->Advertise)
+ AdvertiseInterface(m, set);
+
debugf("mDNS_RegisterInterface: InterfaceID %p %#a %s", set->InterfaceID, &set->ip,
set->InterfaceActive ?
"not represented in list; marking active and retriggering queries" :
// giving the false impression that there's an active representative of this interface when there really isn't.
// Therefore, when registering an interface, we want to re-trigger our questions and re-probe our Resource Records,
// even if we believe that we previously had an active representative of this interface.
- if ((m->KnownBugs & mDNS_KnownBug_PhantomInterfaces) || FirstOfType || set->InterfaceActive)
+ if (set->McastTxRx && ((m->KnownBugs & mDNS_KnownBug_PhantomInterfaces) || FirstOfType || set->InterfaceActive))
{
DNSQuestion *q;
AuthRecord *rr;
+ mDNSs32 initial = InitialQuestionInterval;
+
// Use a small amount of randomness:
// In the case of a network administrator turning on an Ethernet hub so that all the connected machines establish link at
// exactly the same time, we don't want them to all go and hit the network with identical queries at exactly the same moment.
if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval);
+
+ if (delay)
+ {
+ LogMsg("Repeated transitions for interface %s (%#a); delaying packets by %d seconds",
+ set->ifname, &set->ip, delay/mDNSPlatformOneSecond);
+ initial = InitialQuestionInterval * 8; // Delay between first and second queries is eight seconds
+ if (!m->SuppressProbes ||
+ m->SuppressProbes - (m->timenow + delay) < 0)
+ m->SuppressProbes = (m->timenow + delay);
+ }
for (q = m->Questions; q; q=q->next) // Scan our list of questions
if (!q->InterfaceID || q->InterfaceID == set->InterfaceID) // If non-specific Q, or Q on this specific interface,
{ // then reactivate this question
- q->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question
- q->LastQTime = m->timenow - q->ThisQInterval;
+ q->ThisQInterval = initial; // MUST be > zero for an active question
+ q->RequestUnicast = 2; // Set to 2 because is decremented once *before* we check it
+ q->LastQTime = m->timenow - q->ThisQInterval + delay;
q->RecentAnswerPkts = 0;
- if (ActiveQuestion(q)) m->NextScheduledQuery = m->timenow;
+ SetNextQueryTime(m,q);
}
// For all our non-specific authoritative resource records (and any dormant records specific to this interface)
{
if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType);
- rr->AnnounceCount = InitialAnnounceCount;
+ rr->AnnounceCount = delay ? (mDNSu8)1 : InitialAnnounceCount;
rr->ThisAPInterval = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
InitializeLastAPTime(m, rr);
}
}
- if (set->Advertise)
- AdvertiseInterface(m, set);
-
mDNS_Unlock(m);
return(mStatus_NoError);
}
}
else
{
+ mDNSu32 slot;
+ CacheGroup *cg;
CacheRecord *rr;
DNSQuestion *q;
- mDNSu32 slot;
debugf("mDNS_DeregisterInterface: Last representative of InterfaceID %p deregistered; marking questions etc. dormant",
set->InterfaceID);
// 2. Flush any cache records received on this interface
revalidate = mDNSfalse; // Don't revalidate if we're flushing the records
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
- for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
- if (rr->resrec.InterfaceID == set->InterfaceID)
- PurgeCacheResourceRecord(m, rr);
+ FORALL_CACHERECORDS(slot, cg, rr)
+ if (rr->resrec.InterfaceID == set->InterfaceID)
+ PurgeCacheResourceRecord(m, rr);
}
}
if (revalidate && !m->mDNS_shutdown)
{
mDNSu32 slot;
+ CacheGroup *cg;
CacheRecord *rr;
m->NextCacheCheck = m->timenow;
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
- for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
- if (rr->resrec.InterfaceID == set->InterfaceID)
- mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForCableDisconnect);
+ FORALL_CACHERECORDS(slot, cg, rr)
+ if (rr->resrec.InterfaceID == set->InterfaceID)
+ mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForCableDisconnect);
}
mDNS_Unlock(m);
if (result == mStatus_NoError) msg = "Name Registered";
else if (result == mStatus_NameConflict) msg = "Name Conflict";
else if (result == mStatus_MemFree) msg = "Memory Free";
- debugf("ServiceCallback: %##s (%s) %s (%ld)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), msg, result);
+ debugf("ServiceCallback: %##s (%s) %s (%ld)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), msg, result);
}
#endif
if (result == mStatus_MemFree)
{
- // If the PTR record or any of the subtype PTR record are still in the process of deregistering,
+ // If the PTR record or any of the subtype PTR records are still in the process of deregistering,
// don't pass on the NameConflict/MemFree message until every record is finished cleaning up.
mDNSu32 i;
if (sr->RR_PTR.resrec.RecordType != kDNSRecordTypeUnregistered) return;
// Set up the record names
// For now we only create an advisory record for the main type, not for subtypes
// We need to gain some operational experience before we decide if there's a need to create them for subtypes too
- if (ConstructServiceName(&sr->RR_ADV.resrec.name, (domainlabel*)"\x09_services", (domainname*)"\x07_dns-sd\x04_udp", domain) == mDNSNULL)
+ if (ConstructServiceName(sr->RR_ADV.resrec.name, (domainlabel*)"\x09_services", (domainname*)"\x07_dns-sd\x04_udp", domain) == mDNSNULL)
return(mStatus_BadParamErr);
- if (ConstructServiceName(&sr->RR_PTR.resrec.name, mDNSNULL, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
- if (ConstructServiceName(&sr->RR_SRV.resrec.name, name, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
+ if (ConstructServiceName(sr->RR_PTR.resrec.name, mDNSNULL, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
+ if (ConstructServiceName(sr->RR_SRV.resrec.name, name, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
AssignDomainName(sr->RR_TXT.resrec.name, sr->RR_SRV.resrec.name);
// 1. Set up the ADV record rdata to advertise our service type
- AssignDomainName(sr->RR_ADV.resrec.rdata->u.name, sr->RR_PTR.resrec.name);
+ AssignDomainName(&sr->RR_ADV.resrec.rdata->u.name, sr->RR_PTR.resrec.name);
// 2. Set up the PTR record rdata to point to our service name
// We set up two additionals, so when a client asks for this PTR we automatically send the SRV and the TXT too
- AssignDomainName(sr->RR_PTR.resrec.rdata->u.name, sr->RR_SRV.resrec.name);
+ AssignDomainName(&sr->RR_PTR.resrec.rdata->u.name, sr->RR_SRV.resrec.name);
sr->RR_PTR.Additional1 = &sr->RR_SRV;
sr->RR_PTR.Additional2 = &sr->RR_TXT;
for (i=0; i<NumSubTypes; i++)
{
domainname st;
- AssignDomainName(st, sr->SubTypes[i].resrec.name);
+ AssignDomainName(&st, sr->SubTypes[i].resrec.name);
+ st.c[1+st.c[0]] = 0; // Only want the first label, not the whole FQDN (particularly for mDNS_RenameAndReregisterService())
AppendDomainName(&st, type);
mDNS_SetupResourceRecord(&sr->SubTypes[i], mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, ServiceCallback, sr);
- if (ConstructServiceName(&sr->SubTypes[i].resrec.name, mDNSNULL, &st, domain) == mDNSNULL) return(mStatus_BadParamErr);
- AssignDomainName(sr->SubTypes[i].resrec.rdata->u.name, sr->RR_SRV.resrec.name);
+ if (ConstructServiceName(sr->SubTypes[i].resrec.name, mDNSNULL, &st, domain) == mDNSNULL) return(mStatus_BadParamErr);
+ AssignDomainName(&sr->SubTypes[i].resrec.rdata->u.name, sr->RR_SRV.resrec.name);
sr->SubTypes[i].Additional1 = &sr->RR_SRV;
sr->SubTypes[i].Additional2 = &sr->RR_TXT;
}
sr->RR_SRV.resrec.rdata->u.srv.port = port;
// Setting HostTarget tells DNS that the target of this SRV is to be automatically kept in sync with our host name
- if (sr->Host.c[0]) AssignDomainName(sr->RR_SRV.resrec.rdata->u.srv.target, sr->Host);
+ if (sr->Host.c[0]) AssignDomainName(&sr->RR_SRV.resrec.rdata->u.srv.target, &sr->Host);
else { sr->RR_SRV.HostTarget = mDNStrue; sr->RR_SRV.resrec.rdata->u.srv.target.c[0] = '\0'; }
// 4. Set up the TXT record rdata,
#ifndef UNICAST_DISABLED
// If the client has specified an explicit InterfaceID,
// then we do a multicast registration on that interface, even for unicast domains.
- if (!(InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&sr->RR_SRV.resrec.name)))
+ if (!(InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(sr->RR_SRV.resrec.name)))
{
mStatus status;
mDNS_Lock(m);
AssignDomainName(extra->r.resrec.name, sr->RR_SRV.resrec.name);
#ifndef UNICAST_DISABLED
- if (!(sr->RR_SRV.resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&sr->RR_SRV.resrec.name)))
+ if (!(sr->RR_SRV.resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(sr->RR_SRV.resrec.name)))
{
mDNS_Lock(m);
// Some (or perhaps all) versions of BIND named (name daemon) don't allow updates with zero-length rdata.
extra->r.DependentOn = &sr->RR_SRV;
- debugf("mDNS_AddRecordToService adding record to %##s", extra->r.resrec.name.c);
+ debugf("mDNS_AddRecordToService adding record to %##s", extra->r.resrec.name->c);
status = mDNS_Register_internal(m, &extra->r);
if (status == mStatus_NoError) *e = extra;
while (*e && *e != extra) e = &(*e)->next;
if (!*e)
{
- debugf("mDNS_RemoveRecordFromService failed to remove record from %##s", extra->r.resrec.name.c);
+ debugf("mDNS_RemoveRecordFromService failed to remove record from %##s", extra->r.resrec.name->c);
status = mStatus_BadReferenceErr;
}
else
{
- debugf("mDNS_RemoveRecordFromService removing record from %##s", extra->r.resrec.name.c);
+ debugf("mDNS_RemoveRecordFromService removing record from %##s", extra->r.resrec.name->c);
extra->r.RecordCallback = MemFreeCallback;
extra->r.RecordContext = Context;
*e = (*e)->next;
#ifndef UNICAST_DISABLED
- if (!(sr->RR_SRV.resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&sr->RR_SRV.resrec.name)))
+ if (!(sr->RR_SRV.resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(sr->RR_SRV.resrec.name)))
status = uDNS_DeregisterRecord(m, &extra->r);
else
#endif
ExtraResourceRecord *extras = sr->Extras;
mStatus err;
- DeconstructServiceName(&sr->RR_SRV.resrec.name, &name1, &type, &domain);
+ DeconstructServiceName(sr->RR_SRV.resrec.name, &name1, &type, &domain);
if (!newname)
{
name2 = name1;
IncrementLabelSuffix(&name2, mDNStrue);
newname = &name2;
}
- LogMsg("Service \"%##s\" renamed to \"%#s\"", sr->RR_SRV.resrec.name.c, newname->c);
+ LogMsg("Service \"%##s\" renamed to \"%#s\"", sr->RR_SRV.resrec.name->c, newname->c);
if (sr->RR_SRV.HostTarget == mDNSfalse && sr->Host.c[0]) host = &sr->Host;
err = mDNS_RegisterService(m, sr, newname, &type, &domain,
if (!sr->RR_SRV.resrec.rdata->u.srv.port.NotAnInteger) return(mDNS_DeregisterNoSuchService(m, &sr->RR_SRV));
#ifndef UNICAST_DISABLED
- if (!(sr->RR_SRV.resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&sr->RR_SRV.resrec.name)))
+ if (!(sr->RR_SRV.resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(sr->RR_SRV.resrec.name)))
{
mStatus status;
mDNS_Lock(m);
#endif
if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeUnregistered)
{
- debugf("Service set for %##s already deregistered", sr->RR_SRV.resrec.name.c);
+ debugf("Service set for %##s already deregistered", sr->RR_SRV.resrec.name->c);
return(mStatus_BadReferenceErr);
}
else if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeDeregistering)
{
- debugf("Service set for %##s already in the process of deregistering", sr->RR_SRV.resrec.name.c);
+ debugf("Service set for %##s already in the process of deregistering", sr->RR_SRV.resrec.name->c);
return(mStatus_NoError);
}
else
const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context)
{
mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_SRV, kHostNameTTL, kDNSRecordTypeUnique, Callback, Context);
- if (ConstructServiceName(&rr->resrec.name, name, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
+ if (ConstructServiceName(rr->resrec.name, name, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
rr->resrec.rdata->u.srv.priority = 0;
rr->resrec.rdata->u.srv.weight = 0;
rr->resrec.rdata->u.srv.port = zeroIPPort;
- if (host && host->c[0]) AssignDomainName(rr->resrec.rdata->u.srv.target, *host);
+ if (host && host->c[0]) AssignDomainName(&rr->resrec.rdata->u.srv.target, host);
else rr->HostTarget = mDNStrue;
return(mDNS_Register(m, rr));
}
mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname)
{
mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, mDNSNULL, mDNSNULL);
- if (!MakeDomainNameFromDNSNameString(&rr->resrec.name, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr);
+ if (!MakeDomainNameFromDNSNameString(rr->resrec.name, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr);
if (!MakeDomainNameFromDNSNameString(&rr->resrec.rdata->u.name, domname)) return(mStatus_BadParamErr);
return(mDNS_Register(m, rr));
}
#pragma mark - Startup and Shutdown
#endif
-mDNSlocal void mDNS_GrowCache_internal(mDNS *const m, CacheRecord *storage, mDNSu32 numrecords)
+mDNSlocal void mDNS_GrowCache_internal(mDNS *const m, CacheEntity *storage, mDNSu32 numrecords)
{
if (storage && numrecords)
{
mDNSu32 i;
+ LogOperation("Adding cache storage for %d more records (%d bytes)", numrecords, numrecords*sizeof(CacheEntity));
for (i=0; i<numrecords; i++) storage[i].next = &storage[i+1];
storage[numrecords-1].next = m->rrcache_free;
m->rrcache_free = storage;
}
}
-mDNSexport void mDNS_GrowCache(mDNS *const m, CacheRecord *storage, mDNSu32 numrecords)
+mDNSexport void mDNS_GrowCache(mDNS *const m, CacheEntity *storage, mDNSu32 numrecords)
{
mDNS_Lock(m);
mDNS_GrowCache_internal(m, storage, numrecords);
}
mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
- CacheRecord *rrcachestorage, mDNSu32 rrcachesize,
+ CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
{
mDNSu32 slot;
m->rrcache_report = 10;
m->rrcache_free = mDNSNULL;
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
- {
- m->rrcache_hash[slot] = mDNSNULL;
- m->rrcache_tail[slot] = &m->rrcache_hash[slot];
- m->rrcache_used[slot] = 0;
- }
+ for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) m->rrcache_hash[slot] = mDNSNULL;
mDNS_GrowCache_internal(m, rrcachestorage, rrcachesize);
m->HISoftware.c[0] = 0;
m->ResourceRecords = mDNSNULL;
m->DuplicateRecords = mDNSNULL;
- m->LocalOnlyRecords = mDNSNULL;
- m->NewLocalOnlyRecords = mDNSNULL;
- m->DiscardLocalOnlyRecords = mDNSfalse;
+ m->NewLocalRecords = mDNSNULL;
m->CurrentRecord = mDNSNULL;
m->HostInterfaces = mDNSNULL;
m->ProbeFailTime = 0;
rrcache_totalused = m->rrcache_totalused;
for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
{
- while (m->rrcache_hash[slot])
+ while(m->rrcache_hash[slot])
{
- CacheRecord *rr = m->rrcache_hash[slot];
- m->rrcache_hash[slot] = rr->next;
- if (rr->CRActiveQuestion) rrcache_active++;
- m->rrcache_used[slot]--;
- ReleaseCacheRR(m, rr);
+ CacheGroup *cg = m->rrcache_hash[slot];
+ while (cg->members)
+ {
+ CacheRecord *rr = cg->members;
+ cg->members = cg->members->next;
+ if (rr->CRActiveQuestion) rrcache_active++;
+ ReleaseCacheRecord(m, rr);
+ }
+ cg->rrcache_tail = &cg->members;
+ ReleaseCacheGroup(m, &m->rrcache_hash[slot]);
}
- // Reset tail pointer back to empty state (not that it really matters on exit, but we'll do it anyway, for the sake of completeness)
- m->rrcache_tail[slot] = &m->rrcache_hash[slot];
}
debugf("mDNS_Close: RR Cache was using %ld records, %lu active", rrcache_totalused, rrcache_active);
if (rrcache_active != m->rrcache_active)
LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active);
- m->Questions = mDNSNULL; // We won't be answering any more questions!
-
for (intf = m->HostInterfaces; intf; intf = intf->next)
if (intf->Advertise)
DeadvertiseInterface(m, intf);
while (m->CurrentRecord)
{
AuthRecord *rr = m->CurrentRecord;
- m->CurrentRecord = rr->next;
if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
{
- debugf("mDNS_Close: Record type %X still in ResourceRecords list %##s", rr->resrec.RecordType, rr->resrec.name.c);
+ debugf("mDNS_Close: Record type %X still in ResourceRecords list %##s", rr->resrec.RecordType, rr->resrec.name->c);
mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
}
+ else
+ m->CurrentRecord = rr->next;
}
if (m->ResourceRecords) debugf("mDNS_Close: Sending final packets for deregistering records");
else debugf("mDNS_Close: No deregistering records remain");
// If any deregistering records remain, send their deregistration announcements before we exit
- if (m->mDNSPlatformStatus != mStatus_NoError)
- DiscardDeregistrations(m);
- else
- while (m->ResourceRecords)
- SendResponses(m);
+ if (m->mDNSPlatformStatus != mStatus_NoError) DiscardDeregistrations(m);
+ else if (m->ResourceRecords) SendResponses(m);
+ if (m->ResourceRecords) LogMsg("mDNS_Close failed to send goodbye for: %s", ARDisplayString(m, m->ResourceRecords));
mDNS_Unlock(m);
debugf("mDNS_Close: mDNSPlatformClose");
Change History (most recent first):
$Log: mDNSDebug.h,v $
+Revision 1.25 2004/12/14 21:34:16 cheshire
+Add "#define ANSWER_REMOTE_HOSTNAME_QUERIES 0" and comment
+
Revision 1.24 2004/09/16 01:58:21 cheshire
Fix compiler warnings
extern void LogMsgIdent(const char *ident, const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(2,3);
extern void LogMsgNoIdent(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
+// Set this symbol to 1 to answer remote queries for our Address, reverse mapping PTR, and HINFO records
+#define ANSWER_REMOTE_HOSTNAME_QUERIES 0
+
// Set this symbol to 1 to do extra debug checks on malloc() and free()
// Set this symbol to 2 to write a log message for every malloc() and free()
#define MACOSX_MDNS_MALLOC_DEBUGGING 0
Change History (most recent first):
$Log: mDNSEmbeddedAPI.h,v $
+Revision 1.275 2005/01/27 22:57:55 cheshire
+Fix compile errors on gcc4
+
+Revision 1.274 2005/01/19 21:01:54 ksekar
+<rdar://problem/3955355> uDNS needs to support subtype registration and browsing
+
+Revision 1.273 2005/01/19 19:15:31 ksekar
+Refinement to <rdar://problem/3954575> - Simplify mDNS_PurgeResultsForDomain logic and move into daemon layer
+
+Revision 1.272 2005/01/18 18:10:55 ksekar
+<rdar://problem/3954575> Use 10.4 resolver API to get search domains
+
+Revision 1.271 2005/01/15 00:56:41 ksekar
+<rdar://problem/3954575> Unicast services don't disappear when logging
+out of VPN
+
+Revision 1.270 2005/01/14 18:34:22 ksekar
+<rdar://problem/3954571> Services registered outside of firewall don't succeed after location change
+
+Revision 1.269 2005/01/11 22:50:52 ksekar
+Fixed constant naming (was using kLLQ_DefLease for update leases)
+
+Revision 1.268 2004/12/22 22:25:47 ksekar
+<rdar://problem/3734265> NATPMP: handle location changes
+
+Revision 1.267 2004/12/22 00:13:49 ksekar
+<rdar://problem/3873993> Change version, port, and polling interval for LLQ
+
+Revision 1.266 2004/12/18 03:13:45 cheshire
+<rdar://problem/3751638> kDNSServiceInterfaceIndexLocalOnly should return all local records
+
+Revision 1.265 2004/12/17 23:37:45 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+(and other repetitive configuration changes)
+
+Revision 1.264 2004/12/17 05:25:46 cheshire
+<rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
+
+Revision 1.263 2004/12/16 20:40:25 cheshire
+Fix compile warnings
+
+Revision 1.262 2004/12/16 20:13:00 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
+Revision 1.261 2004/12/14 21:21:20 ksekar
+<rdar://problem/3825979> NAT-PMP: Update response format to contain "Seconds Since Boot"
+
Revision 1.260 2004/12/12 23:51:42 ksekar
<rdar://problem/3845683> Wide-area registrations should fallback to using DHCP hostname as target
mStatus_NoAuth = -65555,
mStatus_NoSuchKey = -65556,
mStatus_NATTraversal = -65557,
- mStatus_DblNAT = -65558,
+ mStatus_DoubleNAT = -65558,
mStatus_BadTime = -65559,
mStatus_BadSig = -65560, // while we define this per RFC 2845, BIND 9 returns Refused for bad/missing signatures
mStatus_BadKey = -65561,
// For records containing a hostname (in the name on the left, or in the rdata on the right),
// like A, AAAA, reverse-mapping PTR, and SRV, we use a two-minute TTL by default, because we don't want
// them to hang around for too long in the cache if the host in question crashes or otherwise goes away.
-#define kStandardTTL (3600 * 100 / 80)
-#define kHostNameTTL 120
+// Wide-area service discovery records have a very short TTL to aviod poluting intermediate caches with
+// dynamic records. When discovered via Long Lived Queries (with change notifications), resource record
+// TTLs can be safely ignored.
+
+#define kStandardTTL (3600UL * 100 / 80)
+#define kHostNameTTL 120UL
+#define kWideAreaTTL 3
#define DefaultTTLforRRType(X) (((X) == kDNSType_A || (X) == kDNSType_AAAA || (X) == kDNSType_SRV) ? kHostNameTTL : kStandardTTL)
// 184 were sixteen-byte AAAA records
// 780 were various PTR, TXT and SRV records from 12-64 bytes
// Only 69 records had rdata bigger than 64 bytes
+// Note that since CacheRecord object and a CacheGroup object are allocated out of the same pool, it's sensible to
+// have them both be the same size. Making one smaller without making the other smaller won't actually save any memory.
#define InlineCacheRDSize 64
+#define InlineCacheGroupNameSize 144
+
typedef union
{
mDNSu8 data[StandardAuthRDSize];
typedef struct AuthRecord_struct AuthRecord;
typedef struct CacheRecord_struct CacheRecord;
-typedef struct ResourceRecord_struct ResourceRecord;
+typedef struct CacheGroup_struct CacheGroup;
typedef struct DNSQuestion_struct DNSQuestion;
typedef struct mDNS_struct mDNS;
typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
// The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
typedef void mDNSRecordUpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData);
-struct ResourceRecord_struct
+typedef struct
{
mDNSu8 RecordType; // See enum above
mDNSInterfaceID InterfaceID; // Set if this RR is specific to one interface
// For records received off the wire, InterfaceID is *always* set to the receiving interface
// For our authoritative records, InterfaceID is usually zero, except for those few records
// that are interface-specific (e.g. address records, especially linklocal addresses)
- domainname name;
+ domainname *name;
mDNSu16 rrtype;
mDNSu16 rrclass;
mDNSu32 rroriginalttl; // In seconds
mDNSu32 rdatahash; // 32-bit hash of the raw rdata
mDNSu32 rdnamehash; // Set if this rdata contains a domain name (e.g. PTR, SRV, CNAME etc.)
RData *rdata; // Pointer to storage for this rdata
- };
+ } ResourceRecord;
// Unless otherwise noted, states may apply to either independent record registrations or service registrations
typedef enum
regState_NATMap = 10, // establishing NAT port mapping or learning public address
regState_UpdatePending = 11, // update in flight as result of mDNS_Update call
regState_NoTarget = 12, // service registration pending registration of hostname (ServiceRegistrations only)
- regState_ExtraQueued = 13 // extra record to be registered upon completion of service registration (RecordRegistrations only)
+ regState_ExtraQueued = 13, // extra record to be registered upon completion of service registration (RecordRegistrations only)
+ regState_NATError = 14 // unable to complete NAT traversal
} regState_t;
// context for both ServiceRecordSet and individual AuthRec structs
// NAT traversal context
NATTraversalInfo *NATinfo; // may be NULL
-
+
// state for deferred operations
mDNSBool ClientCallbackDeferred; // invoke client callback on completion of pending operation(s)
mStatus DeferredStatus; // status to deliver when above flag is set
mDNSBool SRVUpdateDeferred; // do we need to change target or port once current operation completes?
- mDNSBool LostTarget; // temporarily deregistered service because its target was deregistered
+ mDNSBool SRVChanged; // temporarily deregistered service because its SRV target or port changed
// uDNS_UpdateRecord support fields
mDNSBool UpdateQueued; // Update the rdata once the current pending operation completes
// mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you
AuthRecord *next; // Next in list; first element of structure for efficiency reasons
+ // Field Group 1: Common ResourceRecord fields
ResourceRecord resrec;
uDNS_RegInfo uDNS_info;
- // Persistent metadata for Authoritative Records
+ // Field Group 2: Persistent metadata for Authoritative Records
AuthRecord *Additional1; // Recommended additional record to include in response
AuthRecord *Additional2; // Another additional
AuthRecord *DependentOn; // This record depends on another for its uniqueness checking
mDNSu8 AllowRemoteQuery; // Set if we allow hosts not on the local link to query this record
mDNSu8 ForceMCast; // Set by client to advertise solely via multicast, even for apparently unicast names
- // Transient state for Authoritative Records
+ // Field Group 3: Transient state for Authoritative Records
mDNSu8 Acknowledged; // Set if we've given the success callback to the client
mDNSu8 ProbeCount; // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
mDNSu8 AnnounceCount; // Number of announcements remaining (kDNSRecordTypeShared)
mDNSu8 RequireGoodbye; // Set if this RR has been announced on the wire and will require a goodbye packet
+ mDNSu8 LocalAnswer; // Set if this RR has been delivered to LocalOnly questions
mDNSu8 IncludeInProbe; // Set if this RR is being put into a probe right now
mDNSInterfaceID ImmedAnswer; // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
mDNSu8 ImmedUnicast; // Set if we may send our response directly via unicast to the requester
mDNSs32 NextUpdateCredit; // Time next token is added to bucket
mDNSs32 UpdateBlocked; // Set if update delaying is in effect
+ domainname namestorage;
RData rdatastorage; // Normally the storage is right here, except for oversized records
// rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes
// are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage
AuthRecord ar; // Note: Must be last struct in field to accomodate oversized AuthRecords
} ARListElem;
+struct CacheGroup_struct // Header object for a list of CacheRecords with the same name
+ {
+ CacheGroup *next; // Next CacheGroup object in this hash table bucket
+ mDNSu32 namehash; // Name-based (i.e. case insensitive) hash of name
+ CacheRecord *members; // List of CacheRecords with this same name
+ CacheRecord **rrcache_tail; // Tail end of that list
+ domainname *name; // Common name for all CacheRecords in this list
+ mDNSu8 namestorage[InlineCacheGroupNameSize];
+ };
+
struct CacheRecord_struct
{
CacheRecord *next; // Next in list; first element of structure for efficiency reasons
struct { mDNSu16 MaxRDLength; mDNSu8 data[InlineCacheRDSize]; } rdatastorage; // Storage for small records is right here
};
+// Storage sufficient to hold either a CacheGroup header or a CacheRecord
+typedef union CacheEntity_union CacheEntity;
+union CacheEntity_union { CacheEntity *next; CacheGroup cg; CacheRecord cr; };
+
typedef struct
{
CacheRecord r;
mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize]; // Glue on the necessary number of extra bytes
+ domainname namestorage; // Needs to go *after* the extra rdata bytes
} LargeCacheRecord;
typedef struct uDNS_HostnameInfo
// LLQ constants
#define kDNSOpt_LLQ 1
#define kDNSOpt_Lease 2
-#define kLLQ_Vers 0 // prerelease
+#define kLLQ_Vers 1
#define kLLQ_DefLease 7200 // 2 hours
-#define kUpdate_DefLease 7200
#define kLLQ_MAX_TRIES 3 // retry an operation 3 times max
#define kLLQ_INIT_RESEND 2 // resend an un-ack'd packet after 2 seconds, then double for each additional
#define kLLQ_DEF_RETRY 1800 // retry a failed operation after 30 minutes
DupSuppressInfo DupSuppress[DupSuppressInfoSize];
mDNSInterfaceID SendQNow; // The interface this query is being sent on right now
mDNSBool SendOnAll; // Set if we're sending this question on all active interfaces
+ mDNSu32 RequestUnicast; // Non-zero if we want to send query with kDNSQClass_UnicastResponse bit set
mDNSs32 LastQTxTime; // Last time this Q was sent on one (but not necessarily all) interfaces
uDNS_QuestionInfo uDNS_info;
#define NATMAP_DEFAULT_LEASE (60 * 60) // lease life in seconds
#define NATMAP_VERS 0
#define NATMAP_PORT 5351
-#define ADDR_REQUEST_PKTLEN 2
-#define ADDR_REPLY_PKTLEN 8
-#define PORTMAP_PKTLEN 12
#define NATMAP_RESPONSE_MASK 0x80
typedef enum
typedef enum
{
- NATState_Init,
- NATState_Request,
- NATState_Established,
- NATState_Legacy,
- NATState_Error,
- NATState_Refresh,
- NATState_Deleted
+ NATState_Init = 0,
+ NATState_Request = 1,
+ NATState_Established = 2,
+ NATState_Legacy = 3,
+ NATState_Error = 4,
+ NATState_Refresh = 5,
+ NATState_Deleted = 6
} NATState_t;
// Note: we have no explicit "cancelled" state, where a service/interface is deregistered while we
// have an outstanding NAT request. This is conveyed by the "reg" pointer being set to NULL
+typedef packedstruct
+ {
+ mDNSu8 vers;
+ mDNSu8 opcode;
+ } NATAddrRequest;
+
+typedef packedstruct
+ {
+ mDNSu8 vers;
+ mDNSu8 opcode;
+ mDNSOpaque16 err;
+ mDNSOpaque32 uptime;
+ mDNSv4Addr PubAddr;
+ } NATAddrReply;
+
+typedef packedstruct
+ {
+ mDNSu8 vers;
+ mDNSu8 opcode;
+ mDNSOpaque16 unused;
+ mDNSIPPort priv;
+ mDNSIPPort pub;
+ mDNSOpaque32 lease;
+ } NATPortMapRequest;
+
+typedef packedstruct
+ {
+ mDNSu8 vers;
+ mDNSu8 opcode;
+ mDNSOpaque16 err;
+ mDNSOpaque32 uptime;
+ mDNSIPPort priv;
+ mDNSIPPort pub;
+ mDNSOpaque32 lease;
+ } NATPortMapReply;
+
// Pass NULL for pkt on error (including timeout)
typedef void (*NATResponseHndlr)(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len);
NATOp_t op;
NATResponseHndlr ReceiveResponse;
union { AuthRecord *RecordRegistration; ServiceRecordSet *ServiceRegistration; } reg;
- mDNSIPPort PublicPort;
- mDNSu8 request[PORTMAP_PKTLEN]; // buffer for request messages
- int requestlen; // length of buffer used
+ mDNSAddr Router;
+ mDNSIPPort PublicPort;
+ union { NATAddrRequest AddrReq; NATPortMapRequest PortReq; } request;
mDNSs32 retry; // absolute time when we retry
mDNSs32 RetryInterval; // delta between time sent and retry
int ntries;
DNSQuestion ReverseMap; // Reverse-map query to find static hostname for service target
mDNSBool ReverseMapActive; // Is above query active?
domainname StaticHostname; // Current answer to reverse-map query (above)
+ mDNSBool DelaySRVUpdate; // Delay SRV target/port update to avoid "flap"
+ mDNSs32 NextSRVUpdate; // Time to perform delayed update
} uDNS_GlobalInfo;
struct mDNS_struct
mDNSu32 rrcache_totalused; // Number of cache entries currently occupied
mDNSu32 rrcache_active; // Number of cache entries currently occupied by records that answer active questions
mDNSu32 rrcache_report;
- CacheRecord *rrcache_free;
- CacheRecord *rrcache_hash[CACHE_HASH_SLOTS];
- CacheRecord **rrcache_tail[CACHE_HASH_SLOTS];
- mDNSu32 rrcache_used[CACHE_HASH_SLOTS];
+ CacheEntity *rrcache_free;
+ CacheGroup *rrcache_hash[CACHE_HASH_SLOTS];
// Fields below only required for mDNS Responder...
domainlabel nicelabel; // Rich text label encoded using canonically precomposed UTF-8
UTF8str255 HISoftware;
AuthRecord *ResourceRecords;
AuthRecord *DuplicateRecords; // Records currently 'on hold' because they are duplicates of existing records
- AuthRecord *LocalOnlyRecords; // Local records registered with InterfaceID set to mDNSInterface_LocalOnly
- AuthRecord *NewLocalOnlyRecords; // Fresh local-only records not yet delivered to local-only questions
- mDNSBool DiscardLocalOnlyRecords;// Set when we have "remove" events we need to deliver to local-only questions
+ AuthRecord *NewLocalRecords; // Fresh local-only records not yet delivered to local-only questions
AuthRecord *CurrentRecord; // Next AuthRecord about to be examined
NetworkInterfaceInfo *HostInterfaces;
mDNSs32 ProbeFailTime;
LargeCacheRecord rec; // Resource Record extracted from received message
};
+#define FORALL_CACHERECORDS(SLOT,CG,CR) \
+ for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++) \
+ for((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next) \
+ for ((CR) = (CG)->members; (CR); (CR)=(CR)->next)
+
// ***************************************************************************
#if 0
#pragma mark - Useful Static Constants
extern const mDNSAddr zeroAddr;
extern const mDNSInterfaceID mDNSInterface_Any; // Zero
-extern const mDNSInterfaceID mDNSInterface_LocalOnly; // (mDNSInterfaceID)-1;
+extern const mDNSInterfaceID mDNSInterface_LocalOnly; // Special value
extern const mDNSIPPort UnicastDNSPort;
extern const mDNSIPPort MulticastDNSPort;
extern const mDNSOpaque16 UpdateRespFlags;
#define localdomain (*(const domainname *)"\x5local")
-
+#define LocalReverseMapomain (*(const domainname *)"\x3" "254" "\x3" "169" "\x7" "in-addr" "\x4" "arpa")
+
// ***************************************************************************
#if 0
#pragma mark - Inline functions
// If we're not doing inline functions, then this header needs to have the extern declarations
#if !defined(mDNSinline)
+extern mDNSs32 NonZeroTime(mDNSs32 t);
extern mDNSu16 mDNSVal16(mDNSOpaque16 x);
extern mDNSu32 mDNSVal32(mDNSOpaque32 x);
extern mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v);
// code is not entered by an interrupt-time timer callback while in the middle of processing a client call.
extern mStatus mDNS_Init (mDNS *const m, mDNS_PlatformSupport *const p,
- CacheRecord *rrcachestorage, mDNSu32 rrcachesize,
+ CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
mDNSBool AdvertiseLocalAddresses,
mDNSCallback *Callback, void *Context);
// See notes above on use of NoCache/ZeroCacheSize
#define mDNS_Init_NoInitCallback mDNSNULL
#define mDNS_Init_NoInitCallbackContext mDNSNULL
-extern void mDNS_GrowCache (mDNS *const m, CacheRecord *storage, mDNSu32 numrecords);
+extern void mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords);
extern void mDNS_Close (mDNS *const m);
extern mDNSs32 mDNS_Execute (mDNS *const m);
{
mDNS_DomainTypeBrowse = 0,
mDNS_DomainTypeBrowseDefault = 1,
- mDNS_DomainTypeRegistration = 2,
- mDNS_DomainTypeRegistrationDefault = 3,
- mDNS_DomainTypeBrowseLegacy = 4,
+ mDNS_DomainTypeBrowseLegacy = 2,
+ mDNS_DomainTypeRegistration = 3,
+ mDNS_DomainTypeRegistrationDefault = 4,
+
+ mDNS_DomainTypeMax = 4
} mDNS_DomainType;
+extern const char *const mDNS_DomainTypeNames[];
+
extern mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom,
const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context);
#define mDNS_StopGetDomains mDNS_StopQuery
// A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory,
// because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
// This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
-#define AssignDomainName(DST, SRC) mDNSPlatformMemCopy((SRC).c, (DST).c, DomainNameLength(&(SRC)))
+#define AssignDomainName(DST, SRC) mDNSPlatformMemCopy((SRC)->c, (DST)->c, DomainNameLength((SRC)))
// Comparison functions
extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
// Calling this routine multiple times for a zone replaces previously entered values. Call with a NULL key
// to dissable authentication for the zone.
-extern mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const mDNSu8 *sharedSecret, mDNSu32 ssLen, mDNSBool base64);
+extern mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const char *sharedSecret, mDNSu32 ssLen, mDNSBool base64);
// Hostname/Unicast Interface Configuration
extern void mDNS_UpdateLLQs(mDNS *m);
extern void mDNS_AddDNSServer(mDNS *const m, const mDNSAddr *dnsAddr, const domainname *domain);
extern void mDNS_DeleteDNSServers(mDNS *const m);
-
+
// Routines called by the core, exported by DNSDigest.c
// Convert a base64 encoded key into a binary byte stream
// not lightweight second-by-second CPU power management modes.)
extern void mDNS_SetFQDN(mDNS *const m);
-extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set);
+extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set, mDNSs32 delay);
extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set);
extern void mDNSCoreInitComplete(mDNS *const m, mStatus result);
extern void mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end,
char assert9[(sizeof(mDNSOpaque16) == 2 ) ? 1 : -1];
char assertA[(sizeof(mDNSOpaque32) == 4 ) ? 1 : -1];
char assertB[(sizeof(mDNSOpaque128) == 16 ) ? 1 : -1];
+ char assertC[(sizeof(CacheRecord ) >= sizeof(CacheGroup) ) ? 1 : -1];
};
// ***************************************************************************
Change History (most recent first):
$Log: uDNS.c,v $
+Revision 1.183 2005/01/27 22:57:55 cheshire
+Fix compile errors on gcc4
+
+Revision 1.182 2005/01/25 18:55:05 ksekar
+Shortened log message
+
+Revision 1.181 2005/01/25 02:17:32 cheshire
+<rdar://problem/3971263> Don't use query ID zero in uDNS queries
+
+Revision 1.180 2005/01/19 21:01:54 ksekar
+<rdar://problem/3955355> uDNS needs to support subtype registration and browsing
+
+Revision 1.179 2005/01/19 19:15:35 ksekar
+Refinement to <rdar://problem/3954575> - Simplify mDNS_PurgeResultsForDomain logic and move into daemon layer
+
+Revision 1.178 2005/01/17 23:47:58 cheshire
+<rdar://problem/3904954> Wide-area services not found on little-endian
+
+Revision 1.177 2005/01/17 23:41:26 cheshire
+Fix compile errors
+
+Revision 1.176 2005/01/17 21:03:04 cheshire
+<rdar://problem/3904954> Wide-area services not found on little-endian
+
+Revision 1.175 2005/01/15 00:56:41 ksekar
+<rdar://problem/3954575> Unicast services don't disappear when logging
+out of VPN
+
+Revision 1.174 2005/01/14 18:44:28 ksekar
+<rdar://problem/3954609> mDNSResponder is crashing when changing domains
+
+Revision 1.173 2005/01/14 18:34:22 ksekar
+<rdar://problem/3954571> Services registered outside of firewall don't succeed after location change
+
+Revision 1.172 2005/01/11 22:50:52 ksekar
+Fixed constant naming (was using kLLQ_DefLease for update leases)
+
+Revision 1.171 2005/01/10 04:52:49 ksekar
+Changed LogMsg to debugf
+
+Revision 1.170 2005/01/08 00:50:05 ksekar
+Fixed spelling mistake in log msg
+
+Revision 1.169 2005/01/08 00:42:18 ksekar
+<rdar://problem/3922758> Clean up syslog messages
+
+Revision 1.168 2004/12/23 23:22:47 ksekar
+<rdar://problem/3933606> Unicast known answers "name" pointers point to garbage stack memory
+
+Revision 1.167 2004/12/22 22:25:47 ksekar
+<rdar://problem/3734265> NATPMP: handle location changes
+
+Revision 1.166 2004/12/22 00:04:12 ksekar
+<rdar://problem/3930324> mDNSResponder crashing in ReceivePortMapReply
+
+Revision 1.165 2004/12/18 03:14:22 cheshire
+DblNAT -> DoubleNAT
+
+Revision 1.164 2004/12/17 03:55:40 ksekar
+Don't use -1 as special meaning for expiration timer (it is a valid
+value, and is redundant with our state variables)
+
+Revision 1.163 2004/12/17 03:51:53 ksekar
+<rdar://problem/3920991> Don't update TXT record if service registration fails
+
+Revision 1.162 2004/12/17 01:29:11 ksekar
+<rdar://problem/3920598> Questions can go deaf on location changes
+
+Revision 1.161 2004/12/16 20:42:02 cheshire
+Fix compiler warnings
+
+Revision 1.160 2004/12/16 20:13:00 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
+Revision 1.159 2004/12/15 02:11:22 ksekar
+<rdar://problem/3917317> Don't check for Dynamic DNS hostname uniqueness
+
+Revision 1.158 2004/12/15 02:04:28 ksekar
+Refinement to previous checkin - we should still return NatTraversal error when the port mapping fails
+
+Revision 1.157 2004/12/15 01:39:21 ksekar
+Refinement to previous checkin - we should still return NatTraversal error when the port mapping fails
+
+Revision 1.156 2004/12/15 01:18:57 ksekar
+<rdar://problem/3825979> Call DeregisterService on nat port map failure
+
+Revision 1.155 2004/12/14 21:21:20 ksekar
+<rdar://problem/3825979> NAT-PMP: Update response format to contain "Seconds Since Boot"
+
+Revision 1.154 2004/12/14 20:52:27 cheshire
+Add question->qnamehash and cr->resrec.namehash to log message
+
+Revision 1.153 2004/12/14 20:45:02 cheshire
+Improved error logging in "unexpected answer" message
+
+Revision 1.152 2004/12/14 03:02:10 ksekar
+<rdar://problem/3919016> Rare race condition can cause crash
+
Revision 1.151 2004/12/13 21:45:08 ksekar
uDNS_DeregisterService should return NoError if called twice (to follow mDNS behavior expected by daemon layer)
typedef struct
{
- domainname zoneName;
+ domainname zoneName;
mDNSAddr primaryAddr;
mDNSu16 zoneClass;
mDNSIPPort llqPort;
// other async result structs go here
} AsyncOpResult;
-typedef void AsyncOpCallback(mStatus err, mDNS *const m, void *info, const AsyncOpResult *result);
+typedef void AsyncOpCallback(mStatus err, mDNS *const m, void *info, const AsyncOpResult *result);
// Private Function Prototypes
// foo), or when they aid in the grouping or readability of code (e.g. state machine code that is easier
// read top-to-bottom.)
+mDNSlocal mDNSBool FreeNATInfo(mDNS *m, NATTraversalInfo *n);
mDNSlocal void hndlTruncatedAnswer(DNSQuestion *question, const mDNSAddr *src, mDNS *m);
mDNSlocal mStatus startGetZoneData(domainname *name, mDNS *m, mDNSBool findUpdatePort, mDNSBool findLLQPort, AsyncOpCallback callback, void *callbackInfo);
mDNSlocal mDNSBool recvLLQResponse(mDNS *m, DNSMessage *msg, const mDNSu8 *end, const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSInterfaceID InterfaceID);
mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs);
mDNSlocal void serviceRegistrationCallback(mStatus err, mDNS *const m, void *srsPtr, const AsyncOpResult *result);
mDNSlocal void SendRecordUpdate(mDNS *m, AuthRecord *rr, uDNS_RegInfo *info);
-mDNSlocal mStatus RegisterService(mDNS *m, ServiceRecordSet *srs);
mDNSlocal void SuspendLLQs(mDNS *m, mDNSBool DeregisterActive);
mDNSlocal void RestartQueries(mDNS *m);
mDNSlocal void startLLQHandshake(mDNS *m, LLQ_Info *info, mDNSBool defer);
{
static mDNSBool randomized = mDNSfalse;
- if (!randomized) { u->NextMessageID = mDNSRandom(~0); randomized = mDNStrue; }
+ if (!randomized) { u->NextMessageID = (mDNSu16)mDNSRandom(0xFFFF); randomized = mDNStrue; }
+ if (u->NextMessageID == 0) u->NextMessageID++;
return mDNSOpaque16fromIntVal(u->NextMessageID++);
}
return mStatus_UnknownErr;
}
-mDNSlocal void unlinkSRS(uDNS_GlobalInfo *u, ServiceRecordSet *srs)
+mDNSlocal void unlinkSRS(mDNS *m, ServiceRecordSet *srs)
{
+ uDNS_GlobalInfo *u = &m->uDNS_info;
ServiceRecordSet **p;
+ NATTraversalInfo *n = u->NATTraversals;
+
+ // verify that no NAT objects reference this service
+ while (n)
+ {
+ if (n->reg.ServiceRegistration == srs)
+ {
+ NATTraversalInfo *tmp = n;
+ n = n->next;
+ LogMsg("ERROR: Unlinking service record set %##s still referenced by NAT traversal object!", srs->RR_SRV.resrec.name->c);
+ FreeNATInfo(m, tmp);
+ }
+ else n = n->next;
+ }
+
for (p = &u->ServiceRegistrations; *p; p = &(*p)->next)
if (*p == srs) { *p = srs->next; srs->next = mDNSNULL; return; }
LogMsg("ERROR: unlinkSRS - SRS not found in ServiceRegistrations list");
// (for service record sets, use RR_SRV as representative for time checks
mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr)
{
- rr->LastAPTime = mDNSPlatformTimeNow(m);
+ rr->LastAPTime = mDNSPlatformTimeNow(m);
if (rr->ThisAPInterval < INIT_UCAST_POLL_INTERVAL) { rr->ThisAPInterval = INIT_UCAST_POLL_INTERVAL; return; }
if (rr->ThisAPInterval*2 <= MAX_UCAST_POLL_INTERVAL) { rr->ThisAPInterval *= 2; return; }
if (rr->ThisAPInterval != MAX_UCAST_POLL_INTERVAL) { rr->ThisAPInterval = MAX_UCAST_POLL_INTERVAL; }
s = umalloc(sizeof(*s));
if (!s) { LogMsg("Error: mDNS_AddDNSServer - malloc"); goto end; }
s->addr = *addr;
- AssignDomainName(s->domain, *d);
+ AssignDomainName(&s->domain, d);
s->next = mDNSNULL;
*p = s;
zone = (const domainname *)(zone->c + 1 + zone->c[0]);
}
return mDNSNULL;
- }
+ }
mDNSlocal void DeleteAuthInfoForZone(uDNS_GlobalInfo *u, const domainname *zone)
{
}
}
-mDNSexport mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const mDNSu8 *sharedSecret, mDNSu32 ssLen, mDNSBool base64)
+mDNSexport mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const char *sharedSecret, mDNSu32 ssLen, mDNSBool base64)
{
uDNS_AuthInfo *info;
mDNSu8 keybuf[1024];
info = (uDNS_AuthInfo*)umalloc(sizeof(uDNS_AuthInfo) + ssLen);
if (!info) { LogMsg("ERROR: umalloc"); status = mStatus_NoMemoryErr; goto exit; }
ubzero(info, sizeof(uDNS_AuthInfo));
- AssignDomainName(info->zone, *zone);
- AssignDomainName(info->keyname, *key);
+ AssignDomainName(&info->zone, zone);
+ AssignDomainName(&info->keyname, key);
if (base64)
{
- keylen = DNSDigest_Base64ToBin((const char*)sharedSecret, keybuf, 1024);
+ keylen = DNSDigest_Base64ToBin(sharedSecret, keybuf, 1024);
if (keylen < 0)
{
LogMsg("ERROR: mDNS_UpdateDomainRequiresAuthentication - could not convert shared secret from base64");
ufree(info);
status = mStatus_UnknownErr;
goto exit;
- }
- DNSDigest_ConstructHMACKey(info, keybuf, (mDNSu32)keylen);
+ }
+ DNSDigest_ConstructHMACKey(info, keybuf, (mDNSu32)keylen);
}
- else DNSDigest_ConstructHMACKey(info, sharedSecret, ssLen);
+ else DNSDigest_ConstructHMACKey(info, (mDNSu8*)sharedSecret, ssLen);
// link into list
info->next = m->uDNS_info.AuthInfoList;
#pragma mark - NAT Traversal
#endif
-mDNSlocal mDNSBool MapServicePort(mDNS *m)
- {
- uDNS_HostnameInfo *i;
-
- //!!!KRS this could be cached
- for (i = m->uDNS_info.Hostnames; i; i= i->next)
- if (i->ar->uDNS_info.NATinfo && i->ar->uDNS_info.NATinfo->state != NATState_Error) return mDNStrue;
-
- return mDNSfalse;
- }
-
mDNSlocal mDNSBool DomainContainsLabelString(const domainname *d, const char *str)
{
const domainlabel *l;
info->state = NATState_Init;
info->ReceiveResponse = callback;
info->PublicPort.NotAnInteger = 0;
+ info->Router = u->Router;
return info;
}
mDNSlocal mDNSBool FreeNATInfo(mDNS *m, NATTraversalInfo *n)
{
NATTraversalInfo *ptr, *prev = mDNSNULL;
+ ServiceRecordSet *s = m->uDNS_info.ServiceRegistrations;
+
+ // Verify that object is not referenced by any services
+ while (s)
+ {
+ if (s->uDNS_info.NATinfo == n)
+ {
+ LogMsg("Error: Freeing NAT info object still referenced by Service Record Set %##s!", s->RR_SRV.resrec.name->c);
+ s->uDNS_info.NATinfo = mDNSNULL;
+ }
+ s = s->next;
+ }
if (n == m->uDNS_info.LLQNatInfo) m->uDNS_info.LLQNatInfo = mDNSNULL;
ptr = m->uDNS_info.NATTraversals;
if (u->Router.ip.v4.NotAnInteger)
{
// send msg if we have a router
+ const mDNSu8 *end = (mDNSu8 *)&info->request;
+ if (info->op == NATOp_AddrRequest) end += sizeof(NATAddrRequest);
+ else end += sizeof(NATPortMapRequest);
+
dst.type = u->Router.type;
dst.ip.v4 = u->Router.ip.v4;
dstport = mDNSOpaque16fromIntVal(NATMAP_PORT);
- err = mDNSPlatformSendUDP(m, info->request, info->request+info->requestlen, 0, &dst, dstport);
+ err = mDNSPlatformSendUDP(m, &info->request, end, 0, &dst, dstport);
if (!err) (info->ntries++); // don't increment attempt counter if the send failed
}
mDNSlocal void ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len)
{
- NATErr_t NatErr = NATErr_None;
mStatus err = mStatus_NoError;
AuthRecord *rr = mDNSNULL;
- mDNSAddr addr;
+ NATAddrReply *response = (NATAddrReply *)pkt;
+ mDNSAddr addr;
if (n->state != NATState_Request)
{
}
else
{
- if (len < ADDR_REPLY_PKTLEN)
+ if (len < sizeof(*response))
{
LogMsg("ReceiveNATAddrResponse: response too short (%d bytes)", len);
err = mStatus_NATTraversal;
goto end;
}
- if (pkt[0] != NATMAP_VERS)
+ if (response->vers != NATMAP_VERS)
{
LogMsg("ReceiveNATAddrResponse: received version %d (expect version %d)", pkt[0], NATMAP_VERS);
err = mStatus_NATTraversal;
goto end;
}
- if (pkt[1] != (NATOp_AddrRequest | NATMAP_RESPONSE_MASK))
+ if (response->opcode != (NATOp_AddrRequest | NATMAP_RESPONSE_MASK))
{
- LogMsg("ReceiveNATAddrResponse: bad response code %d", pkt[1]);
+ LogMsg("ReceiveNATAddrResponse: bad response code %d", response->opcode);
err = mStatus_NATTraversal;
goto end;
}
- NatErr = (NATErr_t)((NATErr_t)pkt[2] << 8 | (NATErr_t)pkt[3]);
- if (NatErr) { LogMsg("ReceiveAddrResponse: received error %d", err); err = mStatus_NATTraversal; goto end; }
-
- addr.ip.v4.b[0] = pkt[4];
- addr.ip.v4.b[1] = pkt[5];
- addr.ip.v4.b[2] = pkt[6];
- addr.ip.v4.b[3] = pkt[7];
+ if (response->err.NotAnInteger)
+ { LogMsg("ReceiveAddrResponse: received error %d", mDNSVal16(response->err)); err = mStatus_NATTraversal; goto end; }
+
+ addr.ip.v4 = response->PubAddr;
n->state = NATState_Established;
}
if (IsPrivateV4Addr(&addr))
{
LogMsg("ReceiveNATAddrResponse: Double NAT");
- err = mStatus_DblNAT;
+ err = mStatus_DoubleNAT;
goto end;
}
}
return;
}
- else LogMsg("Received public IP address %d.%d.%d.%d from NAT.", addr.ip.v4.b[0], addr.ip.v4.b[1], addr.ip.v4.b[2], addr.ip.v4.b[3]);
+ else LogMsg("Received public IP address %d.%d.%d.%d from NAT.", addr.ip.v4.b[0], addr.ip.v4.b[1], addr.ip.v4.b[2], addr.ip.v4.b[3]);
rr->resrec.rdata->u.ipv4 = addr.ip.v4; // replace rdata w/ public address
uDNS_RegisterRecord(m, rr);
}
mDNSlocal void StartGetPublicAddr(mDNS *m, uDNS_HostnameInfo *hInfo)
{
- mDNSu8 *msg;
+ NATAddrRequest *req;
uDNS_GlobalInfo *u = &m->uDNS_info;
NATTraversalInfo *info = AllocNATInfo(m, NATOp_AddrRequest, ReceiveNATAddrResponse);
- if (!info) { uDNS_RegisterRecord(m, hInfo->ar); return; }
+ if (!info) { uDNS_RegisterRecord(m, hInfo->ar); return; }
hInfo->ar->uDNS_info.NATinfo = info;
info->reg.RecordRegistration = hInfo->ar;
info->state = NATState_Request;
// format message
- msg = info->request;
- msg[0] = NATMAP_VERS;
- msg[1] = NATOp_AddrRequest;
- info->requestlen = ADDR_REQUEST_PKTLEN;
+ req = &info->request.AddrReq;
+ req->vers = NATMAP_VERS;
+ req->opcode = NATOp_AddrRequest;
if (!u->Router.ip.v4.NotAnInteger)
{
llqInfo->question->LastQTime = mDNSPlatformTimeNow(m) - (2 * INIT_UCAST_POLL_INTERVAL); // trigger immediate poll
llqInfo->question->ThisQInterval = INIT_UCAST_POLL_INTERVAL;
}
- else { llqInfo->state = LLQ_GetZoneInfo; startLLQHandshake(m, llqInfo, mDNSfalse); }
+ else { llqInfo->state = LLQ_GetZoneInfo; startLLQHandshake(m, llqInfo, mDNSfalse); }
}
}
}
mDNSlocal void ReceivePortMapReply(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len)
{
- NATErr_t err;
ServiceRecordSet *srs;
- mDNSIPPort priv, pktpriv, pub;
+ mDNSIPPort priv;
mDNSu32 lease;
mDNSBool deletion;
+ NATPortMapReply *reply = (NATPortMapReply *)pkt;
if (n->state != NATState_Request && n->state != NATState_Refresh)
{ LogMsg("ReceivePortMapReply: bad state %d", n->state); return; }
- deletion = !(n->request[8] | n->request[9] | n->request[10] | n->request[11]); // zero lease
+ deletion = (!n->request.PortReq.lease.NotAnInteger);
if (deletion) { n->state = NATState_Deleted; return; }
// note that we explicitly ignore timeouts here
// we keep the context struct around so that the SendServiceDeregistration code can reference
if (!pkt) // timeout
{
#ifdef _LEGACY_NAT_TRAVERSAL_
+ mDNSIPPort pub;
int ntries = 0;
mStatus err;
- mDNSBool tcp = (srs && DomainContainsLabelString(&srs->RR_PTR.resrec.name, "_tcp"));
+ mDNSBool tcp = (srs && DomainContainsLabelString(srs->RR_PTR.resrec.name, "_tcp"));
pub = priv; // initially request priv == pub
while (1)
#endif // _LEGACY_NAT_TRAVERSAL_
}
- if (len < PORTMAP_PKTLEN) { LogMsg("ReceivePortMapReply: response too short (%d bytes)", len); goto end; }
- if (pkt[0] != NATMAP_VERS) { LogMsg("ReceivePortMapReply: received version %d (expect version %d)", pkt[0], NATMAP_VERS); goto end; }
- if (pkt[1] != (n->op | NATMAP_RESPONSE_MASK)) { LogMsg("ReceivePortMapReply: bad response code %d", pkt[1]); goto end; }
- err = (NATErr_t)((NATErr_t)pkt[2] << 8 | (NATErr_t)pkt[3]);
- if (err) { LogMsg("ReceivePortMapReply: received error %d", err); goto end; }
-
- pktpriv.b[0] = pkt[4];
- pktpriv.b[1] = pkt[5];
- pub.b[0] = pkt[6];
- pub.b[1] = pkt[7];
+ if (len < sizeof(*reply)) { LogMsg("ReceivePortMapReply: response too short (%d bytes)", len); goto end; }
+ if (reply->vers != NATMAP_VERS) { LogMsg("ReceivePortMapReply: received version %d (expect version %d)", pkt[0], NATMAP_VERS); goto end; }
+ if (reply->opcode != (n->op | NATMAP_RESPONSE_MASK)) { LogMsg("ReceivePortMapReply: bad response code %d", pkt[1]); goto end; }
+ if (reply->err.NotAnInteger) { LogMsg("ReceivePortMapReply: received error %d", mDNSVal16(reply->err)); goto end; }
+ if (priv.NotAnInteger != reply->priv.NotAnInteger)
+ { LogMsg("ReceivePortMapReply: reply private port does not match requested private port"); goto end; }
- lease = (mDNSu32) ((mDNSu32)pkt[8] << 24 | (mDNSu32)pkt[9] << 16 | (mDNSu32)pkt[10] << 8 | pkt[11]);
- if (lease > 0x70000000UL / mDNSPlatformOneSecond)
- lease = 0x70000000UL / mDNSPlatformOneSecond;
+ lease = (mDNSu32)mDNSVal32(reply->lease);
+ if (lease > 0x70000000UL / mDNSPlatformOneSecond) lease = 0x70000000UL / mDNSPlatformOneSecond;
- if (priv.NotAnInteger != pktpriv.NotAnInteger)
- { LogMsg("ReceivePortMapReply: reply private port does not match requested private port"); goto end; }
-
- if (n->state == NATState_Refresh && pub.NotAnInteger != n->PublicPort.NotAnInteger)
- LogMsg("ReceivePortMapReply: NAT refresh changed public port from %d to %d", mDNSVal16(n->PublicPort), mDNSVal16(pub));
+ if (n->state == NATState_Refresh && reply->pub.NotAnInteger != n->PublicPort.NotAnInteger)
+ LogMsg("ReceivePortMapReply: NAT refresh changed public port from %d to %d", mDNSVal16(n->PublicPort), mDNSVal16(reply->pub));
// !!!KRS we need to update the SRV here!
- n->PublicPort = pub;
+ n->PublicPort = reply->pub;
- n->retry = mDNSPlatformTimeNow(m) + ((mDNSs32)lease * mDNSPlatformOneSecond/2); // retry half way to expiration
+ n->retry = mDNSPlatformTimeNow(m) + ((mDNSs32)lease * mDNSPlatformOneSecond / 2); // retry half way to expiration
if (n->state == NATState_Refresh) { n->state = NATState_Established; return; }
n->state = NATState_Established;
{
LogMsg("NAT Port Mapping: timeout");
n->state = NATState_Error;
- if (!srs) { LLQNatMapComplete(m); return; }
- FreeNATInfo(m, n);
- srs->uDNS_info.NATinfo = mDNSNULL;
- unlinkSRS(&m->uDNS_info, srs);
- srs->uDNS_info.state = regState_Unregistered;
- srs->ServiceCallback(m, srs, mStatus_NATTraversal);
+ if (srs) srs->uDNS_info.state = regState_NATError;
+ else LLQNatMapComplete(m);
return; // note - unsafe to touch srs here
}
LogMsg("Mapped private port %d to public port %d", mDNSVal16(priv), mDNSVal16(n->PublicPort));
if (!srs) { LLQNatMapComplete(m); return; }
- srs->uDNS_info.state = regState_FetchingZoneData;
- startGetZoneData(&srs->RR_SRV.resrec.name, m, mDNStrue, mDNSfalse, serviceRegistrationCallback, srs);
+
+ if (srs->uDNS_info.ns.ip.v4.NotAnInteger) SendServiceRegistration(m, srs); // non-zero server address means we already have necessary zone data to send update
+ else
+ {
+ srs->uDNS_info.state = regState_FetchingZoneData;
+ startGetZoneData(srs->RR_SRV.resrec.name, m, mDNStrue, mDNSfalse, serviceRegistrationCallback, srs);
+ }
}
mDNSlocal void FormatPortMaprequest(NATTraversalInfo *info, mDNSIPPort port)
{
- mDNSu8 *msg = info->request;
- mDNSOpaque32 lease = mDNSOpaque32fromIntVal(NATMAP_DEFAULT_LEASE);
-
- msg[0] = NATMAP_VERS;
- msg[1] = info->op;
- msg[2] = 0; // reserved
- msg[3] = 0; // reserved
- msg[4] = port.b[0]; // private port
- msg[5] = port.b[1];
- msg[6] = port.b[0]; // requested pub. port
- msg[7] = port.b[1];
-
- msg[8] = lease.b[0];
- msg[9] = lease.b[1];
- msg[10] = lease.b[2];
- msg[11] = lease.b[3];
+ NATPortMapRequest *req = &info->request.PortReq;
+
+ req->vers = NATMAP_VERS;
+ req->opcode = info->op;
+ req->unused.NotAnInteger = 0;
+ req->priv = port;
+ req->pub = port;
+ req->lease = mDNSOpaque32fromIntVal(NATMAP_DEFAULT_LEASE);
}
mDNSlocal void SendInitialPMapReq(mDNS *m, NATTraversalInfo *info)
NATOp_t op;
NATTraversalInfo *info;
- if (DomainContainsLabelString(&srs->RR_PTR.resrec.name, "_tcp")) op = NATOp_MapTCP;
- else if (DomainContainsLabelString(&srs->RR_PTR.resrec.name, "_udp")) op = NATOp_MapUDP;
- else { LogMsg("StartNATPortMap: could not determine transport protocol of service %##s", srs->RR_SRV.resrec.name.c); goto error; }
+ if (DomainContainsLabelString(srs->RR_PTR.resrec.name, "_tcp")) op = NATOp_MapTCP;
+ else if (DomainContainsLabelString(srs->RR_PTR.resrec.name, "_udp")) op = NATOp_MapUDP;
+ else { LogMsg("StartNATPortMap: could not determine transport protocol of service %##s", srs->RR_SRV.resrec.name->c); goto error; }
+ if (srs->uDNS_info.NATinfo) { LogMsg("Error: StartNATPortMap - NAT info already initialized!"); FreeNATInfo(m, srs->uDNS_info.NATinfo); }
info = AllocNATInfo(m, op, ReceivePortMapReply);
srs->uDNS_info.NATinfo = info;
info->reg.ServiceRegistration = srs;
info->state = NATState_Request;
- info->requestlen = PORTMAP_PKTLEN;
FormatPortMaprequest(info, srs->RR_SRV.resrec.rdata->u.srv.port);
SendInitialPMapReq(m, info);
return;
error:
- startGetZoneData(&srs->RR_SRV.resrec.name, m, mDNStrue, mDNSfalse, serviceRegistrationCallback, srs);
+ startGetZoneData(srs->RR_SRV.resrec.name, m, mDNStrue, mDNSfalse, serviceRegistrationCallback, srs);
}
mDNSlocal void DeleteNATPortMapping(mDNS *m, NATTraversalInfo *nat, ServiceRecordSet *srs)
if (nat->state == NATState_Established) // let other edge-case states expire for simplicity
{
// zero lease
- nat->request[8] = 0;
- nat->request[9] = 0;
- nat->request[10] = 0 ;
- nat->request[11] = 0;
+ nat->request.PortReq.lease.NotAnInteger = 0;
nat->state = NATState_Request;
- SendNATMsg(nat, m);
+ SendNATMsg(nat, m);
}
#ifdef _LEGACY_NAT_TRAVERSAL_
else if (nat->state == NATState_Legacy)
{
mStatus err = mStatus_NoError;
- mDNSBool tcp = srs ? DomainContainsLabelString(&srs->RR_PTR.resrec.name, "_tcp") : mDNSfalse;
+ mDNSBool tcp = srs ? DomainContainsLabelString(srs->RR_PTR.resrec.name, "_tcp") : mDNSfalse;
err = LNT_UnmapPort(nat->PublicPort, tcp);
if (err) LogMsg("Legacy NAT Traversal - unmap request failed with error %ld", err);
}
u->LLQNatInfo = info;
- info->reg.RecordRegistration = mDNSNULL;
+ info->reg.RecordRegistration = mDNSNULL;
info->reg.ServiceRegistration = mDNSNULL;
info->state = NATState_Request;
- info->requestlen = PORTMAP_PKTLEN;
FormatPortMaprequest(info, m->UnicastPort4);
SendInitialPMapReq(m, info);
return;
while (hi)
{
if (hi->ar->uDNS_info.state == regState_Registered || hi->ar->uDNS_info.state == regState_Refresh)
- { AssignDomainName(*dst, hi->ar->resrec.name); return mDNStrue; }
+ { AssignDomainName(dst, hi->ar->resrec.name); return mDNStrue; }
hi = hi->next;
}
- if (u->StaticHostname.c[0]) { AssignDomainName(*dst, u->StaticHostname); return mDNStrue; }
+ if (u->StaticHostname.c[0]) { AssignDomainName(dst, &u->StaticHostname); return mDNStrue; }
return mDNSfalse;
}
mDNSlocal void UpdateSRV(mDNS *m, ServiceRecordSet *srs)
- {
+ {
uDNS_GlobalInfo *u = &m->uDNS_info;
ExtraResourceRecord *e;
+
+ // Target change if:
+ // We have a target and were previously waiting for one, or
+ // We had a target and no longer do, or
+ // The target has changed
+
domainname newtarget;
domainname *curtarget = &srs->RR_SRV.resrec.rdata->u.srv.target;
- mDNSBool havetarget = GetServiceTarget(u, &srs->RR_SRV, &newtarget);
+ mDNSBool HaveTarget = GetServiceTarget(u, &srs->RR_SRV, &newtarget);
+ mDNSBool TargetChanged = (HaveTarget && srs->uDNS_info.state == regState_NoTarget) || (curtarget->c[0] && !HaveTarget) || !SameDomainName(curtarget, &newtarget);
+ mDNSBool HaveZoneData = srs->uDNS_info.ns.ip.v4.NotAnInteger ? mDNStrue : mDNSfalse;
- if ((!havetarget && srs->uDNS_info.state == regState_NoTarget) || (havetarget && SameDomainName(curtarget, &newtarget))) return; // target unchanged
+ // Nat state change if:
+ // We were behind a NAT, and now we are behind a new NAT, or
+ // We're not behind a NAT but our port was previously mapped to a different public port
+ // We were not behind a NAT and now we are
+
+ NATTraversalInfo *nat = srs->uDNS_info.NATinfo;
+ mDNSIPPort port = srs->RR_SRV.resrec.rdata->u.srv.port;
+ mDNSBool NATChanged = mDNSfalse;
+ mDNSBool NowBehindNAT = port.NotAnInteger && IsPrivateV4Addr(&u->PrimaryIP);
+ mDNSBool WereBehindNAT = nat != mDNSNULL;
+ mDNSBool NATRouterChanged = nat && nat->Router.ip.v4.NotAnInteger != u->Router.ip.v4.NotAnInteger;
+ mDNSBool PortWasMapped = nat && (nat->state == NATState_Established || nat->state == NATState_Legacy) && nat->PublicPort.NotAnInteger != port.NotAnInteger;
+
+ if (WereBehindNAT && NowBehindNAT && NATRouterChanged) NATChanged = mDNStrue;
+ else if (!NowBehindNAT && PortWasMapped) NATChanged = mDNStrue;
+ else if (!WereBehindNAT && NowBehindNAT) NATChanged = mDNStrue;
+
+ if (!TargetChanged && !NATChanged) return;
+
+ debugf("UpdateSRV (%##s) HadZoneData=%d, TargetChanged=%d, HaveTarget=%d, NowBehindNAT=%d, WereBehindNAT=%d, NATRouterChanged=%d, PortWasMapped=%d",
+ srs->RR_SRV.resrec.name->c, HaveZoneData, TargetChanged, HaveTarget, NowBehindNAT, WereBehindNAT, NATRouterChanged, PortWasMapped);
switch(srs->uDNS_info.state)
{
// let the in-flight operation complete before updating
srs->uDNS_info.SRVUpdateDeferred = mDNStrue;
return;
-
+
+ case regState_NATError:
+ if (!NATChanged) return;
+ // if nat changed, register if we have a target (below)
+
case regState_NoTarget:
- // Service has not been registered due to lack of a target hostname
- if (havetarget) SendServiceRegistration(m, srs);
+ if (HaveTarget)
+ {
+ debugf("UpdateSRV: %s service %##s", HaveZoneData ? (NATChanged && NowBehindNAT ? "Starting Port Map for" : "Registering") : "Getting Zone Data for", srs->RR_SRV.resrec.name->c);
+ if (!HaveZoneData)
+ {
+ srs->uDNS_info.state = regState_FetchingZoneData;
+ startGetZoneData(srs->RR_SRV.resrec.name, m, mDNStrue, mDNSfalse, serviceRegistrationCallback, srs);
+ }
+ else
+ {
+ if (nat && (NATChanged || !NowBehindNAT)) { srs->uDNS_info.NATinfo = mDNSNULL; FreeNATInfo(m, nat); }
+ if (NATChanged && NowBehindNAT) { srs->uDNS_info.state = regState_NATMap; StartNATPortMap(m, srs); }
+ else SendServiceRegistration(m, srs);
+ }
+ }
return;
case regState_Registered:
- // target lost or changed. deregister service. upon completion, we'll look for a new target
- // extra will be re-registed if the service is re-registered
- for (e = srs->Extras; e; e = e->next) e->r.uDNS_info.state = regState_ExtraQueued;
-
- srs->uDNS_info.LostTarget = mDNStrue;
+ // target or nat changed. deregister service. upon completion, we'll look for a new target
+ debugf("UpdateSRV: SRV record changed for service %##s - deregistering (will re-register with new SRV)", srs->RR_SRV.resrec.name->c);
+ for (e = srs->Extras; e; e = e->next) e->r.uDNS_info.state = regState_ExtraQueued; // extra will be re-registed if the service is re-registered
+ srs->uDNS_info.SRVChanged = mDNStrue;
SendServiceDeregistration(m, srs);
return;
}
if (result == mStatus_MemFree)
{
- debugf("MemFree: %##s IP %d.%d.%d.%d", rr->resrec.name.c, ip[0], ip[1], ip[2], ip[3]);
+ debugf("MemFree: %##s IP %d.%d.%d.%d", rr->resrec.name->c, ip[0], ip[1], ip[2], ip[3]);
if (hi) ufree(hi);
- ufree(rr);
- return;
- }
-
- if (result == mStatus_NameConflict && rr->resrec.RecordType == kDNSRecordTypeUnique)
- {
- // if we get a name conflict, make sure our name/addr isn't already registered by re-registering
- debugf("Name in use - retrying as type KnownUnique");
- rr->resrec.RecordType = kDNSRecordTypeKnownUnique;
- uDNS_RegisterRecord(m, rr);
+ ufree(rr);
return;
}
- if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique)
- {
- // we've already tried to re-register. reset RecordType before returning RR to client
- if (result == mStatus_NoSuchRecord) // name is advertised for some other address
- result = mStatus_NameConflict;
- }
-
if (result)
{
// don't unlink or free - we can retry when we get a new address/router
- LogMsg("HostnameCallback: Error %ld for registration of %##s IP %d.%d.%d.%d", result, rr->resrec.name.c, ip[0], ip[1], ip[2], ip[3]);
+ LogMsg("HostnameCallback: Error %ld for registration of %##s IP %d.%d.%d.%d", result, rr->resrec.name->c, ip[0], ip[1], ip[2], ip[3]);
if (!hi) { ufree(rr); return; }
if (hi->ar->uDNS_info.state != regState_Unregistered) LogMsg("Error: HostnameCallback invoked with error code for record not in regState_Unregistered!");
- (const void *)rr->RecordContext = hi->StatusContext;
+ rr->RecordContext = (void *)hi->StatusContext;
if (hi->StatusCallback)
hi->StatusCallback(m, rr, result); // client may NOT make API calls here
rr->RecordContext = (void *)hi;
// Deliver success to client
if (!hi) { LogMsg("HostnameCallback invoked with orphaned address record"); return; }
- LogMsg("Registered hostname %##s IP %d.%d.%d.%d", rr->resrec.name.c, ip[0], ip[1], ip[2], ip[3]);
- (const void *)rr->RecordContext = hi->StatusContext;
+ LogMsg("Registered hostname %##s IP %d.%d.%d.%d", rr->resrec.name->c, ip[0], ip[1], ip[2], ip[3]);
+ rr->RecordContext = (void *)hi->StatusContext;
if (hi->StatusCallback)
hi->StatusCallback(m, rr, result); // client may NOT make API calls here
rr->RecordContext = (void *)hi;
// register record or begin NAT traversal
mDNSlocal void AdvertiseHostname(mDNS *m, uDNS_HostnameInfo *h)
{
- if (IsPrivateV4Addr(&m->uDNS_info.PrimaryIP))
+ if (IsPrivateV4Addr(&m->uDNS_info.PrimaryIP))
StartGetPublicAddr(m, h);
- else
+ else
{
mDNSu8 *ip = m->uDNS_info.PrimaryIP.ip.v4.b;
- LogMsg("Advertising %##s IP %d.%d.%d.%d", h->ar->resrec.name.c, ip[0], ip[1], ip[2], ip[3]);
- uDNS_RegisterRecord(m, h->ar);
+ LogMsg("Advertising %##s IP %d.%d.%d.%d", h->ar->resrec.name->c, ip[0], ip[1], ip[2], ip[3]);
+ uDNS_RegisterRecord(m, h->ar);
}
}
{
const domainname *pktname = &answer->rdata->u.name;
domainname *storedname = &m->uDNS_info.StaticHostname;
+ uDNS_HostnameInfo *h = m->uDNS_info.Hostnames;
+
(void)question;
debugf("FoundStaticHostname: %##s -> %##s (%s)", question->qname.c, answer->rdata->u.name.c, AddRecord ? "added" : "removed");
if (AddRecord && !SameDomainName(pktname, storedname))
{
- AssignDomainName(*storedname, *pktname);
+ AssignDomainName(storedname, pktname);
+ while (h)
+ {
+ if (h->ar && (h->ar->uDNS_info.state == regState_FetchingZoneData || h->ar->uDNS_info.state == regState_Pending || h->ar->uDNS_info.state == regState_NATMap))
+ {
+ // if we're in the process of registering a dynamic hostname, delay SRV update so we don't have to reregister services if the dynamic name succeeds
+ m->uDNS_info.DelaySRVUpdate = mDNStrue;
+ m->uDNS_info.NextSRVUpdate = mDNSPlatformTimeNow(m) + (5 * mDNSPlatformOneSecond);
+ return;
+ }
+ h = h->next;
+ }
UpdateSRVRecords(m);
}
else if (!AddRecord && SameDomainName(pktname, storedname))
DNSQuestion *q = &m->uDNS_info.ReverseMap;
mDNSu8 *ip = m->uDNS_info.PrimaryIP.ip.v4.b;
mStatus err;
-
- ubzero(q, sizeof(*q));
if (m->uDNS_info.ReverseMapActive)
{
m->uDNS_info.ReverseMapActive = mDNSfalse;
}
+ m->uDNS_info.StaticHostname.c[0] = 0;
if (!m->uDNS_info.PrimaryIP.ip.v4.NotAnInteger) return;
+ ubzero(q, sizeof(*q));
mDNS_snprintf(buf, MAX_ESCAPED_DOMAIN_NAME, "%d.%d.%d.%d.in-addr.arpa.", ip[3], ip[2], ip[1], ip[0]);
- if (!MakeDomainNameFromDNSNameString(&q->qname, buf)) { LogMsg("Error: GetStaticHostname - bad name %s", buf); return; }
+ if (!MakeDomainNameFromDNSNameString(&q->qname, buf)) { LogMsg("Error: GetStaticHostname - bad name %s", buf); return; }
- q->InterfaceID = mDNSInterface_Any;
+ q->InterfaceID = mDNSInterface_Any;
q->Target = zeroAddr;
q->qtype = kDNSType_PTR;
q->qclass = kDNSClass_IN;
else m->uDNS_info.ReverseMapActive = mDNStrue;
}
-// Deregister hostnames and register new names for each host domain with the current global
+// Deregister hostnames and register new names for each host domain with the current global
// values for the hostlabel and primary IP address
mDNSlocal void UpdateHostnameRegistrations(mDNS *m)
{
- uDNS_GlobalInfo *u = &m->uDNS_info;
+ uDNS_GlobalInfo *u = &m->uDNS_info;
AuthRecord *new;
uDNS_HostnameInfo *i;
{
new = umalloc(sizeof(AuthRecord));
if (!new) { LogMsg("ERROR: UpdateHostnameRegistration - malloc"); return; }
- mDNS_SetupResourceRecord(new, mDNSNULL, 0, kDNSType_A, 1, kDNSRecordTypeUnique, HostnameCallback, i);
+ mDNS_SetupResourceRecord(new, mDNSNULL, 0, kDNSType_A, kWideAreaTTL, kDNSRecordTypeKnownUnique, HostnameCallback, i);
}
// setup new record
new->resrec.rdata->u.ipv4 = u->PrimaryIP.ip.v4;
if (i->ar->uDNS_info.state != regState_Unregistered)
- {
+ {
// delete old record
i->ar->RecordContext = mDNSNULL; // clear backpointer to HostnameInfo
- uDNS_DeregisterRecord(m, i->ar);
+ uDNS_DeregisterRecord(m, i->ar);
i->ar = new;
}
// advertise new
AdvertiseHostname(m, i);
- }
+ }
}
mDNSexport void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext)
// check if domain already registered
for (ptr = u->Hostnames; ptr; ptr = ptr->next)
{
- if (SameDomainName(fqdn, &ptr->ar->resrec.name))
+ if (SameDomainName(fqdn, ptr->ar->resrec.name))
{ LogMsg("Host Domain %##s already in list", fqdn->c); goto exit; }
}
if (!new || !new->ar) { LogMsg("ERROR: mDNS_AddDynDNSHostname - malloc"); goto exit; }
new->StatusCallback = StatusCallback;
new->StatusContext = StatusContext;
- mDNS_SetupResourceRecord(new->ar, mDNSNULL, 0, kDNSType_A, 1, kDNSRecordTypeUnique, HostnameCallback, new);
- AppendDomainName(&new->ar->resrec.name, fqdn);
+ mDNS_SetupResourceRecord(new->ar, mDNSNULL, 0, kDNSType_A, 1, kDNSRecordTypeKnownUnique, HostnameCallback, new);
+ AppendDomainName(new->ar->resrec.name, fqdn);
new->next = u->Hostnames;
u->Hostnames = new;
if (u->PrimaryIP.ip.v4.NotAnInteger)
mDNS_Lock(m);
- while (*ptr && !SameDomainName(fqdn, &(*ptr)->ar->resrec.name)) ptr = &(*ptr)->next;
- if (!*ptr) LogMsg("mDNS_RemoveDynDNSHostName: no such domainname %##s", fqdn->c);
+ while (*ptr && !SameDomainName(fqdn, (*ptr)->ar->resrec.name)) ptr = &(*ptr)->next;
+ if (!*ptr) LogMsg("mDNS_RemoveDynDNSHostName: no such domainname %##s", fqdn->c);
else
{
uDNS_HostnameInfo *hi = *ptr;
*ptr = (*ptr)->next; // unlink
- hi->ar->RecordContext = mDNSNULL; // about to free wrapper struct
+ hi->ar->RecordContext = mDNSNULL; // about to free wrapper struct
if (hi->ar->uDNS_info.state != regState_Unregistered) uDNS_DeregisterRecord(m, hi->ar);
else { ufree(hi->ar); hi->ar = mDNSNULL; }
ufree(hi);
if (router && router->type !=mDNSAddrType_IPv4) { LogMsg("mDNS_SetPrimaryInterfaceInfo passed non-V4 address. Discarding."); return; }
mDNS_Lock(m);
- AddrChanged = addr ? (addr->ip.v4.NotAnInteger != u->PrimaryIP.ip.v4.NotAnInteger) : u->PrimaryIP.ip.v4.NotAnInteger;
- RouterChanged = router ? (router->ip.v4.NotAnInteger != u->Router.ip.v4.NotAnInteger) : u->Router.ip.v4.NotAnInteger;
+ AddrChanged = ((addr ? addr ->ip.v4.NotAnInteger : 0) != u->PrimaryIP.ip.v4.NotAnInteger);
+ RouterChanged = ((router ? router->ip.v4.NotAnInteger : 0) != u->Router .ip.v4.NotAnInteger);
#if MDNS_DEBUGMSGS
if (addr && (AddrChanged || RouterChanged))
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 (AddrChanged)
+ if ((AddrChanged || RouterChanged ) && (addr && router))
{
- if (addr)
- {
- UpdateHostnameRegistrations(m);
- UpdateSRVRecords(m);
- }
+ UpdateHostnameRegistrations(m);
+ UpdateSRVRecords(m);
GetStaticHostname(m); // look up reverse map record to find any static hostnames for our IP address
}
mDNSlocal void addKnownAnswer(DNSQuestion *question, const CacheRecord *rr)
{
CacheRecord *newCR = mDNSNULL;
- mDNSu32 size;
+ mDNSu32 size;
size = sizeof(CacheRecord) + rr->resrec.rdlength - InlineCacheRDSize;
newCR = (CacheRecord *)umalloc(size);
umemcpy(newCR, rr, size);
newCR->resrec.rdata = (RData*)&newCR->rdatastorage;
newCR->resrec.rdata->MaxRDLength = rr->resrec.rdlength;
+ newCR->resrec.name = &question->qname;
newCR->next = question->uDNS_info.knownAnswers;
question->uDNS_info.knownAnswers = newCR;
}
ka = question->uDNS_info.knownAnswers;
while (ka)
{
- debugf("deriving goodbye for %##s", ka->resrec.name.c);
+ debugf("deriving goodbye for %##s", ka->resrec.name->c);
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
question->QuestionCallback(m, question, &ka->resrec, mDNSfalse);
ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAns, lcr);
if (!ptr) goto pkt_error;
cr = &lcr->r;
- if (ResourceRecordAnswersQuestion(&cr->resrec, question))
+ if (ResourceRecordAnswersQuestion(&cr->resrec, question))
{
cr->next = answers;
answers = cr;
// record is in KA list but not answer list - remove from KA list
if (prev) prev->next = ka->next;
else question->uDNS_info.knownAnswers = ka->next;
- debugf("deriving goodbye for %##s", ka->resrec.name.c);
+ debugf("deriving goodbye for %##s", ka->resrec.name->c);
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
question->QuestionCallback(m, question, &ka->resrec, mDNSfalse);
m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
return;
malloc_error:
- LogMsg("ERROR: Malloc");
+ LogMsg("ERROR: Malloc");
}
mDNSlocal void pktResponseHndlr(mDNS * const m, DNSMessage *msg, const mDNSu8 *end, DNSQuestion *question, mDNSBool llq)
mDNSBool goodbye, inKAList, followedCName = mDNSfalse;
LLQ_Info *llqInfo = question->uDNS_info.llq;
domainname origname;
+ origname.c[0] = 0;
if (question != m->uDNS_info.CurrentQuery)
{ LogMsg("ERROR: pktResponseHdnlr called without CurrentQuery ptr set!"); return; }
else
{
debugf("Following cname %##s -> %##s", question->qname.c, cr->resrec.rdata->u.name.c);
- AssignDomainName(origname, question->qname);
- AssignDomainName(question->qname, cr->resrec.rdata->u.name);
+ AssignDomainName(&origname, &question->qname);
+ AssignDomainName(&question->qname, &cr->resrec.rdata->u.name);
question->qnamehash = DomainNameHashValue(&question->qname);
followedCName = mDNStrue;
- i = -1; // restart packet answer matching
+ i = -1; // restart packet answer matching
ptr = LocateAnswers(msg, end);
continue;
}
debugf("pktResponseHndlr - CurrentQuery changed by QuestionCallback - returning");
return;
}
- }
- else if (!followedCName || !SameDomainName(&cr->resrec.name, &origname))
- LogMsg("Question %##s type %d - unexpected answer %##s type %d", question->qname.c, question->qtype, cr->resrec.name.c, cr->resrec.rrtype);
+ }
+ else if (!followedCName || !SameDomainName(cr->resrec.name, &origname))
+ LogMsg("Question %##s %X %s %##s- unexpected answer %##s %X %s",
+ question->qname.c, question->qnamehash, DNSTypeName(question->qtype), origname.c,
+ cr->resrec.name->c, cr->resrec.namehash, DNSTypeName(cr->resrec.rrtype));
}
if (!llq || llqInfo->state == LLQ_Poll || llqInfo->deriveRemovesOnResume)
for (i = 0; i < msg->h.numAdditionals; i++)
{
- ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr);;
+ ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr);
if (!ptr) goto finish;
if (lcr.r.resrec.rrtype == kDNSType_TSIG)
{
if (rd + alglen > rdend) goto finish;
rd += alglen; // algorithm name
- if (rd + 6 > rdend) goto finish;
+ if (rd + 6 > rdend) goto finish;
rd += 6; // 48-bit timestamp
if (rd + sizeof(mDNSOpaque16) > rdend) goto finish;
rd += sizeof(mDNSOpaque16); // fudge
if (rd + sizeof(mDNSOpaque16) > rdend) goto finish;
err = mDNSVal16(*(mDNSOpaque16 *)rd); // error code
- if (err == TSIG_ErrBadSig) { LogMsg("%##s: bad signature", displayname->c); err = mStatus_BadSig; }
- else if (err == TSIG_ErrBadKey) { LogMsg("%##s: bad key", displayname->c); err = mStatus_BadKey; }
- else if (err == TSIG_ErrBadTime) { LogMsg("%##s: bad time", displayname->c); err = mStatus_BadTime; }
- else if (err) { LogMsg("%##s: unknown tsig error %d", err); err = mStatus_UnknownErr; }
+ if (err == TSIG_ErrBadSig) { LogMsg("%##s: bad signature", displayname->c); err = mStatus_BadSig; }
+ else if (err == TSIG_ErrBadKey) { LogMsg("%##s: bad key", displayname->c); err = mStatus_BadKey; }
+ else if (err == TSIG_ErrBadTime) { LogMsg("%##s: bad time", displayname->c); err = mStatus_BadTime; }
+ else if (err) { LogMsg("%##s: unknown tsig error %d", displayname->c, err); err = mStatus_UnknownErr; }
goto finish;
}
}
}
mDNSlocal mStatus checkUpdateResult(domainname *displayname, mDNSu8 rcode, mDNS *m, const DNSMessage *msg, const mDNSu8 *end)
- {
+ {
(void)msg; // currently unused, needed for TSIG errors
if (!rcode) return mStatus_NoError;
else if (rcode == kDNSFlag1_RC_YXDomain)
else if (rcode == kDNSFlag1_RC_Refused)
{
LogMsg("Update %##s refused", displayname->c);
- return mStatus_Refused;
+ return mStatus_Refused;
}
else if (rcode == kDNSFlag1_RC_NXRRSet)
{
mStatus tsigerr = ParseTSIGError(m, msg, end, displayname);
if (!tsigerr)
{
- LogMsg("Format Error: %##s", displayname->c);
+ LogMsg("Format Error: %##s", displayname->c);
return mStatus_UnknownErr;
}
else return tsigerr;
mDNSlocal void hndlServiceUpdateReply(mDNS * const m, ServiceRecordSet *srs, mStatus err)
{
mDNSBool InvokeCallback = mDNSfalse;
- AuthRecord *UpdateR = mDNSNULL;
uDNS_RegInfo *info = &srs->uDNS_info;
NATTraversalInfo *nat = srs->uDNS_info.NATinfo;
ExtraResourceRecord **e = &srs->Extras;
if (err == mStatus_NameConflict && !info->TestForSelfConflict)
{
info->TestForSelfConflict = mDNStrue;
- debugf("checking for self-conflict of service %##s", srs->RR_SRV.resrec.name.c);
+ debugf("checking for self-conflict of service %##s", srs->RR_SRV.resrec.name->c);
SendServiceRegistration(m, srs);
return;
}
info->TestForSelfConflict = mDNSfalse;
if (err == mStatus_NoSuchRecord) err = mStatus_NameConflict; // NoSuchRecord implies that our prereq was not met, so we actually have a name conflict
if (err) info->state = regState_Unregistered;
- else info->state = regState_Registered;
+ else info->state = regState_Registered;
InvokeCallback = mDNStrue;
break;
}
else if (err == mStatus_UnknownErr && info->lease)
{
- LogMsg("Re-trying update of service %##s without lease option", srs->RR_SRV.resrec.name.c);
+ LogMsg("Re-trying update of service %##s without lease option", srs->RR_SRV.resrec.name->c);
info->lease = mDNSfalse;
- info->expire = -1;
SendServiceRegistration(m, srs);
return;
}
else
{
- if (err) { LogMsg("Error %ld for registration of service %##s", err, srs->RR_SRV.resrec.name.c); info->state = regState_Unregistered; } //!!!KRS make sure all structs will still get cleaned up when client calls DeregisterService with this state
+ if (err) { LogMsg("Error %ld for registration of service %##s", err, srs->RR_SRV.resrec.name->c); info->state = regState_Unregistered; } //!!!KRS make sure all structs will still get cleaned up when client calls DeregisterService with this state
else info->state = regState_Registered;
InvokeCallback = mDNStrue;
break;
case regState_Refresh:
if (err)
{
- LogMsg("Error %ld for refresh of service %##s", err, srs->RR_SRV.resrec.name.c);
+ LogMsg("Error %ld for refresh of service %##s", err, srs->RR_SRV.resrec.name->c);
InvokeCallback = mDNStrue;
- info->state = regState_Unregistered;
+ info->state = regState_Unregistered;
}
else info->state = regState_Registered;
break;
case regState_DeregPending:
- if (err) LogMsg("Error %ld for deregistration of service %##s", err, srs->RR_SRV.resrec.name.c);
- if (info->LostTarget)
+ if (err) LogMsg("Error %ld for deregistration of service %##s", err, srs->RR_SRV.resrec.name->c);
+ if (info->SRVChanged)
{
- info->state = regState_NoTarget;
+ info->state = regState_NoTarget; // NoTarget will allow us to pick up new target OR nat traversal state
break;
- }
+ }
err = mStatus_MemFree;
InvokeCallback = mDNStrue;
if (nat)
info->state = regState_Unregistered;
break;
case regState_DeregDeferred:
- if (err) { debugf("Error %ld received prior to deferred derigstration of %##s", err, srs->RR_SRV.resrec.name.c); }
- debugf("Performing deferred deregistration of %##s", srs->RR_SRV.resrec.name.c);
- info->state = regState_Registered; // benign to set even if we've got an error
- SendServiceDeregistration(m, srs);
- return;
- case regState_UpdatePending:
- // find the record being updated
- UpdateR = &srs->RR_TXT;
if (err)
{
- LogMsg("hndlServiceUpdateReply: error updating resource record");
- UpdateR->uDNS_info.state = regState_Unregistered;
- InvokeCallback = mDNStrue; // signal error via service callback
+ debugf("Error %ld received prior to deferred derigstration of %##s", err, srs->RR_SRV.resrec.name->c);
+ err = mStatus_MemFree;
+ InvokeCallback = mDNStrue;
+ info->state = regState_Unregistered;
+ break;
}
else
{
- UpdateR->uDNS_info.state = regState_Registered;
- SwapRData(m, UpdateR, mDNStrue);
+ debugf("Performing deferred deregistration of %##s", srs->RR_SRV.resrec.name->c);
+ info->state = regState_Registered;
+ SendServiceDeregistration(m, srs);
+ return;
}
- info->state = regState_Registered;
- break;
+ case regState_UpdatePending:
+ // mDNS clients don't expect asyncronous UpdateRecord errors, so we just log (rare) failures
+ if (err) LogMsg("hndlServiceUpdateReply: error updating TXT record for service %##s", srs->RR_SRV.resrec.name->c);
+ info->state = regState_Registered;
+ SwapRData(m, &srs->RR_TXT, mDNStrue); // deallocate old rdata
+ break;
case regState_FetchingZoneData:
case regState_Registered:
case regState_Cancelled:
case regState_NATMap:
case regState_NoTarget:
case regState_ExtraQueued:
+ case regState_NATError:
LogMsg("hndlServiceUpdateReply called for service %##s in unexpected state %d with error %ld. Unlinking.",
- srs->RR_SRV.resrec.name.c, info->state, err);
+ srs->RR_SRV.resrec.name->c, info->state, err);
err = mStatus_UnknownErr;
}
- if ((info->LostTarget || info->SRVUpdateDeferred) && (info->state == regState_NoTarget || info->state == regState_Registered))
+ if ((info->SRVChanged || info->SRVUpdateDeferred) && (info->state == regState_NoTarget || info->state == regState_Registered))
{
+ if (InvokeCallback)
+ {
+ info->ClientCallbackDeferred = mDNStrue;
+ info->DeferredStatus = err;
+ }
+ info->SRVChanged = mDNSfalse;
UpdateSRV(m, srs);
return;
}
{
uDNS_RegInfo *einfo = &(*e)->r.uDNS_info;
if (einfo->state == regState_ExtraQueued)
- {
+ {
if (info->state == regState_Registered && !err)
{
// extra resource record queued for this service - copy zone info and register
- AssignDomainName(einfo->zone, info->zone);
+ AssignDomainName(&einfo->zone, &info->zone);
einfo->ns = info->ns;
einfo->port = info->port;
einfo->lease = info->lease;
else e = &(*e)->next;
}
- srs->RR_SRV.ThisAPInterval = INIT_UCAST_POLL_INTERVAL - 1; // reset retry delay for future refreshes, dereg, etc.
- if (srs->RR_TXT.uDNS_info.UpdateQueued) SendRecordUpdate(m, &srs->RR_TXT, &srs->uDNS_info);
-
- if (info->state == regState_Unregistered) unlinkSRS(&m->uDNS_info, srs);
-
+ if (info->state == regState_Unregistered) unlinkSRS(m, srs);
+ else if (srs->RR_TXT.uDNS_info.UpdateQueued && !err)
+ {
+ if (InvokeCallback)
+ {
+ // if we were supposed to give a client callback, we'll do it after we update the primary txt record
+ info->ClientCallbackDeferred = mDNStrue;
+ info->DeferredStatus = err;
+ }
+ srs->RR_TXT.uDNS_info.UpdateQueued = mDNSfalse;
+ info->state = regState_UpdatePending;
+ SendServiceRegistration(m, srs);
+ return;
+ }
+ else srs->RR_SRV.ThisAPInterval = INIT_UCAST_POLL_INTERVAL - 1; // reset retry delay for future refreshes, dereg, etc.
+
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
if (InvokeCallback) srs->ServiceCallback(m, srs, err);
else if (info->ClientCallbackDeferred)
{
if (err)
{
- LogMsg("Update record failed for %##s (err %d)", rr->resrec.name.c, err);
+ LogMsg("Update record failed for %##s (err %d)", rr->resrec.name->c, err);
rr->uDNS_info.state = regState_Unregistered;
}
else
{
- debugf("Update record %##s - success", rr->resrec.name.c);
+ debugf("Update record %##s - success", rr->resrec.name->c);
rr->uDNS_info.state = regState_Registered;
SwapRData(m, rr, mDNStrue);
}
}
if (rr->uDNS_info.state == regState_DeregPending)
- {
- debugf("Received reply for deregister record %##s type %d", rr->resrec.name.c, rr->resrec.rrtype);
+ {
+ debugf("Received reply for deregister record %##s type %d", rr->resrec.name->c, rr->resrec.rrtype);
if (err) LogMsg("ERROR: Deregistration of record %##s type %d failed with error %ld",
- rr->resrec.name.c, rr->resrec.rrtype, err);
+ rr->resrec.name->c, rr->resrec.rrtype, err);
err = mStatus_MemFree;
if (unlinkAR(&m->uDNS_info.RecordRegistrations, rr))
LogMsg("ERROR: Could not unlink resource record following deregistration");
if (err)
{
LogMsg("Cancelling deferred deregistration record %##s type %d due to registration error %ld",
- rr->resrec.name.c, rr->resrec.rrtype, err);
+ rr->resrec.name->c, rr->resrec.rrtype, err);
unlinkAR(&m->uDNS_info.RecordRegistrations, rr);
rr->uDNS_info.state = regState_Unregistered;
return;
}
LogMsg("Calling deferred deregistration of record %##s type %d",
- rr->resrec.name.c, rr->resrec.rrtype);
+ rr->resrec.name->c, rr->resrec.rrtype);
rr->uDNS_info.state = regState_Registered;
- uDNS_DeregisterRecord(m, rr);
+ uDNS_DeregisterRecord(m, rr);
return;
}
{
if (rr->uDNS_info.lease && err == mStatus_UnknownErr)
{
- LogMsg("Re-trying update of record %##s without lease option", rr->resrec.name.c);
+ LogMsg("Re-trying update of record %##s without lease option", rr->resrec.name->c);
rr->uDNS_info.lease = mDNSfalse;
- rr->uDNS_info.expire = -1;
sendRecordRegistration(m, rr);
return;
}
LogMsg("Registration of record %##s type %d failed with error %ld",
- rr->resrec.name.c, rr->resrec.rrtype, err);
- unlinkAR(&u->RecordRegistrations, rr);
+ rr->resrec.name->c, rr->resrec.rrtype, err);
+ unlinkAR(&u->RecordRegistrations, rr);
rr->uDNS_info.state = regState_Unregistered;
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
if (rr->RecordCallback) rr->RecordCallback(m, rr, err);
{
if (rr->uDNS_info.UpdateQueued)
{
- debugf("%##s: sending queued update", rr->resrec.name.c);
+ debugf("%##s: sending queued update", rr->resrec.name->c);
rr->uDNS_info.state = regState_Registered;
SendRecordUpdate(m ,rr, &rr->uDNS_info);
return;
}
if (rr->uDNS_info.state == regState_Refresh)
- rr->uDNS_info.state = regState_Registered;
+ rr->uDNS_info.state = regState_Registered;
else
{
rr->uDNS_info.state = regState_Registered;
}
LogMsg("Received unexpected response for record %##s type %d, in state %d, with response error %ld",
- rr->resrec.name.c, rr->resrec.rrtype, rr->uDNS_info.state, err);
+ rr->resrec.name->c, rr->resrec.rrtype, rr->uDNS_info.state, err);
}
if (lease > 0)
{
expire = (mDNSPlatformTimeNow(m) + (((mDNSs32)lease * mDNSPlatformOneSecond)) * 3/4);
- if (info->state == regState_UpdatePending)
+ if (info->state == regState_UpdatePending)
// if updating individual record, the service record set may expire sooner
{ if (expire - info->expire < 0) info->expire = expire; }
else info->expire = expire;
}
- else info->expire = -1;
+ else info->lease = mDNSfalse;
}
mDNSexport void uDNS_ReceiveNATMap(mDNS *m, mDNSu8 *pkt, mDNSu16 len)
NATOp_t op;
// check length, version, opcode
- if (len < ADDR_REPLY_PKTLEN && len < PORTMAP_PKTLEN) { LogMsg("NAT Traversal message too short (%d bytes)", len); return; }
+ if (len < sizeof(NATPortMapReply) && len < sizeof(NATAddrReply)) { LogMsg("NAT Traversal message too short (%d bytes)", len); return; }
if (pkt[0] != NATMAP_VERS) { LogMsg("Received NAT Traversal response with version %d (expect version %d)", pkt[0], NATMAP_VERS); return; }
op = pkt[1];
if (!(op & NATMAP_RESPONSE_MASK)) { LogMsg("Received NAT Traversal message that is not a response (opcode %d)", op); return; }
if ((cur->state == NATState_Request || cur->state == NATState_Refresh) &&
(cur->op | NATMAP_RESPONSE_MASK) == op)
cur->ReceiveResponse(cur, m, pkt, len); // callback may delete "cur"
- // specific request/reply matching logic handled by callback - we don't know if this was a match, so we don't break here
+ // specific request/reply matching logic handled by callback - we don't know if this was a match, so we don't break here
}
}
(void)InterfaceID;
if (QR_OP == StdR)
- {
+ {
// !!!KRS we should to a table lookup here to see if it answers an LLQ or a 1-shot
// LLQ Responses over TCP not currently supported
if (srcaddr && recvLLQResponse(m, msg, end, srcaddr, srcport, InterfaceID)) return;
{
if (sptr->uDNS_info.id.NotAnInteger == msg->h.id.NotAnInteger)
{
- err = checkUpdateResult(&sptr->RR_SRV.resrec.name, rcode, m, msg, end);
+ err = checkUpdateResult(sptr->RR_SRV.resrec.name, rcode, m, msg, end);
if (!err) SetUpdateExpiration(m, msg, end, &sptr->uDNS_info);
hndlServiceUpdateReply(m, sptr, err);
return;
{
if (rptr->uDNS_info.id.NotAnInteger == msg->h.id.NotAnInteger)
{
- err = checkUpdateResult(&rptr->resrec.name, rcode, m, msg, end);
- if (!err) SetUpdateExpiration(m, msg, end, &rptr->uDNS_info);
+ err = checkUpdateResult(rptr->resrec.name, rcode, m, msg, end);
+ if (!err) SetUpdateExpiration(m, msg, end, &rptr->uDNS_info);
hndlRecordUpdateReply(m, rptr, err);
return;
}
*addr = zeroAddr;
ncount = name ? CountLabels(name) : 0;
while (p)
- {
+ {
scount = CountLabels(&p->domain);
if (scount <= ncount && scount > curmatchlen)
{
mDNSlocal mDNSu8 *putLLQ(DNSMessage *const msg, mDNSu8 *ptr, DNSQuestion *question, LLQOptData *data, mDNSBool includeQuestion)
{
AuthRecord rr;
- ResourceRecord *opt = &rr.resrec;
+ ResourceRecord *opt = &rr.resrec;
rdataOpt *optRD;
//!!!KRS when we implement multiple llqs per message, we'll need to memmove anything past the question section
ptr = putQuestion(msg, ptr, msg->data + AbsoluteMaxDNSMessageData, &question->qname, question->qtype, question->qclass);
if (!ptr) { LogMsg("ERROR: putLLQ - putQuestion"); return mDNSNULL; }
}
- // locate OptRR if it exists, set pointer to end
+ // locate OptRR if it exists, set pointer to end
// !!!KRS implement me
// format opt rr (fields not specified are zero-valued)
ubzero(&rr, sizeof(AuthRecord));
- opt->rdata = &rr.rdatastorage;
-
- opt->RecordType = kDNSRecordTypeKnownUnique; // to avoid warnings in other layers
- opt->rrtype = kDNSType_OPT;
+ mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
opt->rdlength = LLQ_OPT_SIZE;
opt->rdestimate = LLQ_OPT_SIZE;
for (i = 0; i < msg->h.numAdditionals; i++)
// { ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); if (!ptr) return mDNSfalse; }
//!!!KRS workaround for LH server bug, which puts OPT as first additional
- { ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); if (!ptr) return mDNSfalse; if (lcr.r.resrec.rrtype == kDNSType_OPT) break; }
+ { ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); if (!ptr) return mDNSfalse; if (lcr.r.resrec.rrtype == kDNSType_OPT) break; }
if (lcr.r.resrec.rrtype != kDNSType_OPT) return mDNSfalse;
- if (lcr.r.resrec.rdlength < (index + 1) * LLQ_OPT_SIZE) return mDNSfalse; // rdata too small
+ if (lcr.r.resrec.rdlength < (index + 1) * LLQ_OPT_SIZE) return mDNSfalse; // rdata too small
umemcpy(llq, (mDNSu8 *)&lcr.r.resrec.rdata->u.opt.OptData.llq + (index * sizeof(LLQOptData)), sizeof(LLQOptData)); // !!! Should convert to host byte order?
return mDNStrue;
}
qInfo->retry = qInfo->expire - ((mDNSs32)pktData.lease * mDNSPlatformOneSecond/2);
qInfo->origLease = pktData.lease;
- qInfo->state = LLQ_Established;
+ qInfo->state = LLQ_Established;
}
mDNSlocal void sendLLQRefresh(mDNS *m, DNSQuestion *q, mDNSu32 lease)
else info->ntries++;
info->state = LLQ_Refresh;
q->LastQTime = timenow;
- info->retry = (info->expire - q->LastQTime) / 2;
+ info->retry = (info->expire - q->LastQTime) / 2;
}
mDNSlocal mDNSBool recvLLQEvent(mDNS *m, DNSQuestion *q, DNSMessage *msg, const mDNSu8 *end, const mDNSAddr *srcaddr, mDNSIPPort srcport, mDNSInterfaceID InterfaceID)
(void)InterfaceID; // unused
// find Opt RR, verify correct ID
- if (!getLLQAtIndex(m, msg, end, &opt, 0)) { debugf("Pkt does not contain LLQ Opt"); return mDNSfalse; }
- if (opt.llqOp != kLLQOp_Event) { LogMsg("recvLLQEvent - Bad LLQ Opcode %d", opt.llqOp); return mDNSfalse; }
- if (!q->uDNS_info.llq) { LogMsg("Error: recvLLQEvent - question onject does not contain LLQ metadata"); return mDNSfalse; }
- if (!sameID(opt.id, q->uDNS_info.llq->id)) { LogMsg("recvLLQEvent - incorrect ID. Discarding"); return mDNSfalse; }
+ if (!getLLQAtIndex(m, msg, end, &opt, 0)) { debugf("Pkt does not contain LLQ Opt"); return mDNSfalse; }
+ if (opt.llqOp != kLLQOp_Event) { LogMsg("recvLLQEvent - Bad LLQ Opcode %d", opt.llqOp); return mDNSfalse; }
+ if (!q->uDNS_info.llq) { LogMsg("Error: recvLLQEvent - question object does not contain LLQ metadata"); return mDNSfalse; }
+ if (!sameID(opt.id, q->uDNS_info.llq->id)) { return mDNSfalse; }
// invoke response handler
m->uDNS_info.CurrentQuery = q;
InitializeDNSMessage(&ack.h, msg->h.id, ResponseFlags);
ackEnd = putQuestion(&ack, ack.data, ack.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
if (!ackEnd) { LogMsg("ERROR: recvLLQEvent - putQuestion"); return mDNSfalse; }
- err = mDNSSendDNSMessage(m, &ack, ackEnd, mDNSInterface_Any, srcaddr, srcport, -1, mDNSNULL);
+ err = mDNSSendDNSMessage(m, &ack, ackEnd, mDNSInterface_Any, srcaddr, srcport, -1, mDNSNULL);
if (err) LogMsg("ERROR: recvLLQEvent - mDNSSendDNSMessage returned %ld", err);
return mDNStrue;
}
info->retry = info->expire - ((mDNSs32)llq->lease * mDNSPlatformOneSecond / 2);
info->origLease = llq->lease;
- info->state = LLQ_Established;
+ info->state = LLQ_Established;
q->uDNS_info.responseCallback = llqResponseHndlr;
llqResponseHndlr(m, pktMsg, end, q, mDNSNULL);
error:
- info->state = LLQ_Error;
+ info->state = LLQ_Error;
}
{ LogMsg("ERROR: recvSetupResponse - mismatched question in response for llq setup %##s", q->qname.c); goto poll; }
if (!getLLQAtIndex(m, pktMsg, end, &llq, 0)) { debugf("recvSetupResponse - GetLLQAtIndex"); goto poll; }
- if (llq.llqOp != kLLQOp_Setup) { LogMsg("ERROR: recvSetupResponse - bad op %d", llq.llqOp); goto poll; }
- if (llq.vers != kLLQ_Vers) { LogMsg("ERROR: recvSetupResponse - bad vers %d", llq.vers); goto poll; }
+ if (llq.llqOp != kLLQOp_Setup) { LogMsg("ERROR: recvSetupResponse - bad op %d", llq.llqOp); goto poll; }
+ if (llq.vers != kLLQ_Vers) { LogMsg("ERROR: recvSetupResponse - bad vers %d", llq.vers); goto poll; }
if (info->state == LLQ_InitialRequest) { hndlRequestChallenge(m, pktMsg, end, &llq, q); return; }
if (info->state == LLQ_SecondaryRequest) { hndlChallengeResponseAck(m, pktMsg, end, &llq, q); return; }
DNSMessage msg;
mDNSu8 *end;
LLQOptData llqData;
- DNSQuestion *q = info->question;
+ DNSQuestion *q = info->question;
mStatus err = mStatus_NoError;
mDNSs32 timenow = mDNSPlatformTimeNow(m);
uDNS_GlobalInfo *u = &m->uDNS_info;
StartLLQNatMap(m);
return;
}
- if (u->LLQNatInfo->state == NATState_Error) goto poll;
+ if (u->LLQNatInfo->state == NATState_Error) goto poll;
if (u->LLQNatInfo->state != NATState_Established && u->LLQNatInfo->state != NATState_Legacy)
{ info->state = LLQ_NatMapWait; info->NATMap = mDNStrue; return; }
info->NATMap = mDNStrue; // this llq references the global llq nat mapping
{
debugf("startLLQHandshake: %d failed attempts for LLQ %##s. Polling.", kLLQ_MAX_TRIES, q->qname.c, kLLQ_DEF_RETRY / 60);
goto poll;
- }
+ }
// set llq rdata
llqData.vers = kLLQ_Vers;
if (!end)
{
LogMsg("ERROR: startLLQHandshake - putLLQ");
- info->state = LLQ_Error;
+ info->state = LLQ_Error;
return;
}
while (q)
{
llqInfo = q->uDNS_info.llq;
- if (q->LongLived &&
+ if (q->LongLived &&
llqInfo &&
- q->qnamehash == pktQ.qnamehash &&
+ q->qnamehash == pktQ.qnamehash &&
q->qtype == pktQ.qtype &&
SameDomainName(&q->qname, &pktQ.qname))
{
u->CurrentQuery = q;
- if (llqInfo->state == LLQ_Established || (llqInfo->state == LLQ_Refresh && msg->h.numAnswers))
+ if (llqInfo->state == LLQ_Established || (llqInfo->state == LLQ_Refresh && msg->h.numAnswers))
{ if (recvLLQEvent(m, q, msg, end, srcaddr, srcport, InterfaceID)) return mDNStrue; }
else if (msg->h.id.NotAnInteger == q->uDNS_info.id.NotAnInteger)
{
//!!!KRS should we unlink info<->question here?
return;
case LLQ_GetZoneInfo:
- case LLQ_SuspendDeferred:
+ case LLQ_SuspendDeferred:
info->question = mDNSNULL; // remove ref to question, as it may be freed when we get called back from async op
info->state = LLQ_Cancelled;
- return;
+ return;
case LLQ_Established:
case LLQ_Refresh:
// refresh w/ lease 0
sendLLQRefresh(m, question, 0);
- goto end;
- default:
- debugf("stopLLQ - silently discarding LLQ in state %d", info->state);
+ goto end;
+ default:
+ debugf("stopLLQ - silently discarding LLQ in state %d", info->state);
goto end;
}
mDNSlocal mStatus startInternalQuery(DNSQuestion *q, mDNS *m, InternalResponseHndlr callback, void *hndlrContext)
{
ubzero(&q->uDNS_info, sizeof(uDNS_QuestionInfo));
- q->QuestionContext = hndlrContext;
+ q->QuestionContext = hndlrContext;
q->uDNS_info.responseCallback = callback;
q->uDNS_info.context = hndlrContext;
return startQuery(m, q, 1);
// state machine actions
typedef enum
{
- smContinue, // continue immediately to next state
- smBreak, // break until next packet/timeout
+ smContinue, // continue immediately to next state
+ smBreak, // break until next packet/timeout
smError // terminal error - cleanup and abort
} smAction;
ntaState state; // determines what we do upon receiving a packet
mDNS *m;
domainname zone; // left-hand-side of SOA record
- mDNSu16 zoneClass;
+ mDNSu16 zoneClass;
domainname ns; // mname in SOA rdata, verified in confirmNS state
mDNSv4Addr addr; // address of nameserver
DNSQuestion question; // storage for any active question
DNSQuestion extraQuestion; // additional storage
mDNSBool questionActive; // if true, StopQuery() can be called on the question field
- mDNSBool findUpdatePort;
+ mDNSBool findUpdatePort;
mDNSBool findLLQPort;
mDNSIPPort updatePort;
mDNSIPPort llqPort;
ntaContext *context = (ntaContext*)umalloc(sizeof(ntaContext));
if (!context) { LogMsg("ERROR: startGetZoneData - umalloc failed"); return mStatus_NoMemoryErr; }
ubzero(context, sizeof(ntaContext));
- AssignDomainName(context->origName, *name);
+ AssignDomainName(&context->origName, name);
context->state = init;
context->m = m;
context->callback = callback;
if (action == smBreak) return;
if (action == smContinue) context->state = complete;
case foundPort:
- case complete: break;
+ case complete: break;
}
if (context->state != complete)
result.type = zoneDataResult;
result.zoneData.primaryAddr.ip.v4.NotAnInteger = context->addr.NotAnInteger;
result.zoneData.primaryAddr.type = mDNSAddrType_IPv4;
- AssignDomainName(result.zoneData.zoneName, context->zone);
+ AssignDomainName(&result.zoneData.zoneName, &context->zone);
result.zoneData.zoneClass = context->zoneClass;
result.zoneData.llqPort = context->findLLQPort ? context->llqPort : zeroIPPort;
result.zoneData.updatePort = context->findUpdatePort ? context->updatePort : zeroIPPort;
context->callback(mStatus_NoError, context->m, context->callbackInfo, &result);
- goto cleanup;
+ goto cleanup;
error:
if (context && context->callback)
- context->callback(mStatus_UnknownErr, context->m, context->callbackInfo, mDNSNULL);
+ context->callback(mStatus_UnknownErr, context->m, context->callbackInfo, mDNSNULL);
cleanup:
if (context && context->questionActive)
{
uDNS_StopQuery(context->m, &context->question);
context->questionActive = mDNSfalse;
- }
+ }
if (context) ufree(context);
}
if (msg)
{
- // if msg contains SOA record in answer or authority sections, update context/state and return
+ // if msg contains SOA record in answer or authority sections, update context/state and return
int i;
ptr = LocateAnswers(msg, end);
for (i = 0; i < msg->h.numAnswers; i++)
{
ptr = GetLargeResourceRecord(context->m, msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
if (!ptr) { LogMsg("ERROR: hndlLookupSOA, Answers - GetLargeResourceRecord returned NULL"); return smError; }
- if (rr->rrtype == kDNSType_SOA && SameDomainName(context->curSOA, &rr->name))
+ if (rr->rrtype == kDNSType_SOA && SameDomainName(context->curSOA, rr->name))
{
processSOA(context, rr);
return smContinue;
}
- }
+ }
ptr = LocateAuthorities(msg, end);
// SOA not in answers, check in authority
for (i = 0; i < msg->h.numAuthorities; i++)
{
ptr = GetLargeResourceRecord(context->m, msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); ///!!!KRS using type PacketAns for auth
- if (!ptr) { LogMsg("ERROR: hndlLookupSOA, Authority - GetLargeResourceRecord returned NULL"); return smError; }
+ if (!ptr) { LogMsg("ERROR: hndlLookupSOA, Authority - GetLargeResourceRecord returned NULL"); return smError; }
if (rr->rrtype == kDNSType_SOA)
{
processSOA(context, rr);
return smContinue;
}
}
- }
+ }
if (context->state != init && !context->curSOA->c[0])
{
- // we've gone down to the root and have not found an SOA
- LogMsg("ERROR: hndlLookupSOA - recursed to root label of %##s without finding SOA",
+ // we've gone down to the root and have not found an SOA
+ LogMsg("ERROR: hndlLookupSOA - recursed to root label of %##s without finding SOA",
context->origName.c);
return smError;
}
else context->curSOA = (domainname *)(context->curSOA->c + context->curSOA->c[0]+1);
context->state = lookupSOA;
- AssignDomainName(query->qname, *context->curSOA);
+ AssignDomainName(&query->qname, context->curSOA);
query->qtype = kDNSType_SOA;
query->qclass = kDNSClass_IN;
err = startInternalQuery(query, context->m, getZoneData, context);
context->questionActive = mDNStrue;
if (err) LogMsg("hndlLookupSOA: startInternalQuery returned error %ld (breaking until next periodic retransmission)", err);
- return smBreak; // break from state machine until we receive another packet
+ return smBreak; // break from state machine until we receive another packet
}
mDNSlocal void processSOA(ntaContext *context, ResourceRecord *rr)
{
- AssignDomainName(context->zone, rr->name);
+ AssignDomainName(&context->zone, rr->name);
context->zoneClass = rr->rrclass;
- AssignDomainName(context->ns, rr->rdata->u.soa.mname);
+ AssignDomainName(&context->ns, &rr->rdata->u.soa.mname);
context->state = foundZone;
}
if (context->state == foundZone)
{
// we've just learned the zone. confirm that an NS record exists
- AssignDomainName(query->qname, context->zone);
+ AssignDomainName(&query->qname, &context->zone);
query->qtype = kDNSType_NS;
query->qclass = kDNSClass_IN;
err = startInternalQuery(query, context->m, getZoneData, context);
- context->questionActive = mDNStrue;
+ context->questionActive = mDNStrue;
if (err) LogMsg("confirmNS: startInternalQuery returned error %ld (breaking until next periodic retransmission", err);
context->state = lookupNS;
return smBreak; // break from SM until we receive another packet
ptr = GetLargeResourceRecord(context->m, msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
if (!ptr) { LogMsg("ERROR: confirmNS, Answers - GetLargeResourceRecord returned NULL"); return smError; }
if (rr->rrtype == kDNSType_NS &&
- SameDomainName(&context->zone, &rr->name) && SameDomainName(&context->ns, &rr->rdata->u.name))
+ SameDomainName(&context->zone, rr->name) && SameDomainName(&context->ns, &rr->rdata->u.name))
{
context->state = foundNS;
- return smContinue; // next routine will examine additionals section of A record
- }
+ return smContinue; // next routine will examine additionals section of A record
+ }
}
LogMsg("ERROR: could not confirm existence of record %##s NS %##s", context->zone.c, context->ns.c);
return smError;
mStatus err;
DNSQuestion *query = &context->question;
- AssignDomainName(query->qname, context->ns);
+ AssignDomainName(&query->qname, &context->ns);
query->qtype = kDNSType_A;
query->qclass = kDNSClass_IN;
err = startInternalQuery(query, context->m, getZoneData, context);
- context->questionActive = mDNStrue;
+ context->questionActive = mDNStrue;
if (err) LogMsg("confirmNS: startInternalQuery returned error %ld (breaking until next periodic retransmission)", err);
context->state = lookupA;
return smBreak;
LogMsg("ERROR: lookupNSAddr, Additionals - GetLargeResourceRecord returned NULL");
return queryNSAddr(context);
}
- if (rr->rrtype == kDNSType_A && SameDomainName(&context->ns, &rr->name))
+ if (rr->rrtype == kDNSType_A && SameDomainName(&context->ns, rr->name))
{
context->addr.NotAnInteger = rr->rdata->u.ipv4.NotAnInteger;
context->state = foundA;
for (i = 0; i < msg->h.numAnswers; i++)
{
ptr = GetLargeResourceRecord(context->m, msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
- if (!ptr) { LogMsg("ERROR: lookupNSAddr, Answers - GetLargeResourceRecord returned NULL"); break; }
- if (rr->rrtype == kDNSType_A && SameDomainName(&context->ns, &rr->name))
+ if (!ptr) { LogMsg("ERROR: lookupNSAddr, Answers - GetLargeResourceRecord returned NULL"); break; }
+ if (rr->rrtype == kDNSType_A && SameDomainName(&context->ns, rr->name))
{
context->addr.NotAnInteger = rr->rdata->u.ipv4.NotAnInteger;
context->state = foundA;
return smContinue;
}
- }
+ }
LogMsg("ERROR: lookupNSAddr: Address record not found in answer section");
return smError;
}
err = startInternalQuery(q, context->m, getZoneData, context);
context->questionActive = mDNStrue;
if (err) LogMsg("hndlLookupSOA: startInternalQuery returned error %ld (breaking until next periodic retransmission)", err);
- return smBreak; // break from state machine until we receive another packet
+ return smBreak; // break from state machine until we receive another packet
}
mDNSlocal smAction hndlLookupPorts(DNSMessage *msg, const mDNSu8 *end, ntaContext *context)
if (!info->nread)
{
// read msg len
- n = mDNSPlatformReadTCP(sd, &info->replylen, 2);
+ mDNSu8 lenbuf[2];
+ n = mDNSPlatformReadTCP(sd, lenbuf, 2);
if (n != 2)
{
LogMsg("ERROR:conQueryCallback - attempt to read message length failed (read returned %d)", n);
goto error;
}
+ info->replylen = (mDNSu16)((mDNSu16)lenbuf[0] << 8 | lenbuf[1]);
}
n = mDNSPlatformReadTCP(sd, ((char *)&info->reply) + info->nread, info->replylen - info->nread);
if (n < 0) { LogMsg("ERROR: conQueryCallback - read returned %d", n); goto error; }
info->nread += n;
if (info->nread == info->replylen)
{
- // finished reading message
- uDNS_ReceiveMsg(m, &info->reply, ((mDNSu8 *)&info->reply) + info->replylen, mDNSNULL, zeroIPPort, mDNSNULL, zeroIPPort, question->InterfaceID);
+ // Finished reading message; convert the integer parts which are in IETF byte-order (MSB first, LSB second)
+ DNSMessage *msg = &info->reply;
+ mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions;
+ msg->h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]);
+ msg->h.numAnswers = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]);
+ msg->h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]);
+ msg->h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]);
+ uDNS_ReceiveMsg(m, msg, (mDNSu8 *)msg + info->replylen, mDNSNULL, zeroIPPort, mDNSNULL, zeroIPPort, question->InterfaceID);
mDNSPlatformTCPCloseConnection(sd);
ufree(info);
}
ptr = putZone(&msg, ptr, end, ®Info->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
if (!ptr) goto error;
- if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique || rr->uDNS_info.state == regState_Refresh)
+ if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique)
{
- // KnownUnique means the record must ALREADY exist, as does refresh
- // prereq: record must exist (put record in prereq section w/ TTL 0)
- ptr = PutResourceRecordTTLJumbo(&msg, ptr, &msg.h.mDNS_numPrereqs, &rr->resrec, 0);
- if (!ptr) goto error;
+ // KnownUnique: Delete any previous value
+ ptr = putDeleteRRSet(&msg, ptr, rr->resrec.name, rr->resrec.rrtype);
+ if (!ptr) goto error;
}
+
else if (rr->resrec.RecordType != kDNSRecordTypeShared)
{
- ptr = putPrereqNameNotInUse(&rr->resrec.name, &msg, ptr, end);
+ ptr = putPrereqNameNotInUse(rr->resrec.name, &msg, ptr, end);
if (!ptr) goto error;
}
if (!ptr) goto error;
if (rr->uDNS_info.lease)
- { ptr = putUpdateLease(&msg, ptr, kLLQ_DefLease); if (!ptr) goto error; }
-
- rr->uDNS_info.expire = -1;
-
+ { ptr = putUpdateLease(&msg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) goto error; }
+
err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, ®Info->ns, regInfo->port, -1, GetAuthInfoForZone(u, ®Info->zone));
if (err) LogMsg("ERROR: sendRecordRegistration - mDNSSendDNSMessage - %ld", err);
SetRecordRetry(m, rr);
- if (regInfo->state != regState_Refresh) regInfo->state = regState_Pending;
+ if (regInfo->state != regState_Refresh && regInfo->state != regState_DeregDeferred) regInfo->state = regState_Pending;
return;
error:
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
if (rr->RecordCallback) rr->RecordCallback(m, rr, err);
m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
- // NOTE: not safe to touch any client structures here
+ // NOTE: not safe to touch any client structures here
}
-mDNSlocal void RecordRegistrationCallback(mStatus err, mDNS *const m, void *authPtr, const AsyncOpResult *result)
+mDNSlocal void RecordRegistrationCallback(mStatus err, mDNS *const m, void *authPtr, const AsyncOpResult *result)
{
AuthRecord *newRR = (AuthRecord*)authPtr;
const zoneData_t *zoneData = mDNSNULL;
// make sure record is still in list
for (ptr = u->RecordRegistrations; ptr; ptr = ptr->next)
if (ptr == newRR) break;
- if (!ptr) { LogMsg("RecordRegistrationCallback - RR no longer in list. Discarding."); return; }
+ if (!ptr) { LogMsg("RecordRegistrationCallback - RR no longer in list. Discarding."); return; }
// check error/result
if (err) { LogMsg("RecordRegistrationCallback: error %ld", err); goto error; }
{
//!!!KRS we should send a memfree callback here!
debugf("Registration of %##s type %d cancelled prior to update",
- newRR->resrec.name.c, newRR->resrec.rrtype);
+ newRR->resrec.name->c, newRR->resrec.rrtype);
newRR->uDNS_info.state = regState_Unregistered;
unlinkAR(&u->RecordRegistrations, newRR);
return;
LogMsg("ERROR: New resource record's class (%d) does not match zone class (%d)",
newRR->resrec.rrclass, zoneData->zoneClass);
goto error;
- }
+ }
// cache zone data
- AssignDomainName(newRR->uDNS_info.zone, zoneData->zoneName);
+ AssignDomainName(&newRR->uDNS_info.zone, &zoneData->zoneName);
newRR->uDNS_info.ns.type = mDNSAddrType_IPv4;
newRR->uDNS_info.ns.ip.v4.NotAnInteger = zoneData->primaryAddr.ip.v4.NotAnInteger;
if (zoneData->updatePort.NotAnInteger) newRR->uDNS_info.port = zoneData->updatePort;
mDNSBool mapped = mDNSfalse;
domainname target;
AuthRecord *srv = &srs->RR_SRV;
+ mDNSu32 i;
+ if (!rInfo->ns.ip.v4.NotAnInteger) { LogMsg("SendServiceRegistration - NS not set!"); return; }
+
id = newMessageID(u);
InitializeDNSMessage(&msg.h, id, UpdateReqFlags);
// setup resource records
- SetNewRData(&srs->RR_PTR.resrec, mDNSNULL, 0);
+ SetNewRData(&srs->RR_PTR.resrec, mDNSNULL, 0);
SetNewRData(&srs->RR_TXT.resrec, mDNSNULL, 0);
// replace port w/ NAT mapping if necessary
if (srs->uDNS_info.TestForSelfConflict)
{
- // update w/ prereq that records already exist to make sure previous registration was ours
+ // update w/ prereq that SRV already exist to make sure previous registration was ours, and delete any stale TXT records
if (!(ptr = PutResourceRecordTTLJumbo(&msg, ptr, &msg.h.mDNS_numPrereqs, &srs->RR_SRV.resrec, 0))) goto error;
- if (!(ptr = PutResourceRecordTTLJumbo(&msg, ptr, &msg.h.mDNS_numPrereqs, &srs->RR_TXT.resrec, 0))) goto error;
+ if (!(ptr = putDeleteRRSet(&msg, ptr, srs->RR_TXT.resrec.name, srs->RR_TXT.resrec.rrtype))) goto error;
}
- else if (srs->uDNS_info.state != regState_Refresh)
+ else if (srs->uDNS_info.state != regState_Refresh && srs->uDNS_info.state != regState_UpdatePending)
{
// use SRV name for prereq
- ptr = putPrereqNameNotInUse(&srv->resrec.name, &msg, ptr, end);
+ ptr = putPrereqNameNotInUse(srv->resrec.name, &msg, ptr, end);
if (!ptr) goto error;
}
//!!!KRS Need to do bounds checking and use TCP if it won't fit!!!
if (!(ptr = PutResourceRecordTTLJumbo(&msg, ptr, &msg.h.mDNS_numUpdates, &srs->RR_PTR.resrec, srs->RR_PTR.resrec.rroriginalttl))) goto error;
- if (!(ptr = PutResourceRecordTTLJumbo(&msg, ptr, &msg.h.mDNS_numUpdates, &srs->RR_TXT.resrec, srs->RR_TXT.resrec.rroriginalttl))) goto error;
+
+ for (i = 0; i < srs->NumSubTypes; i++)
+ if (!(ptr = PutResourceRecordTTLJumbo(&msg, ptr, &msg.h.mDNS_numUpdates, &srs->SubTypes[i].resrec, srs->SubTypes[i].resrec.rroriginalttl))) goto error;
+
+ if (rInfo->state == regState_UpdatePending)
+ {
+ // we're updating the txt record - delete old, add new
+ if (!(ptr = putDeletionRecord(&msg, ptr, &srs->RR_TXT.resrec))) goto error; // delete old rdata
+ SwapRData(m, &srs->RR_TXT, mDNSfalse); // add the new rdata
+ if (!(ptr = PutResourceRecordTTLJumbo(&msg, ptr, &msg.h.mDNS_numUpdates, &srs->RR_TXT.resrec, srs->RR_TXT.resrec.rroriginalttl))) goto error;
+ SwapRData(m, &srs->RR_TXT, mDNSfalse); // replace old rdata in case we need to retransmit
+ }
+ else
+ if (!(ptr = PutResourceRecordTTLJumbo(&msg, ptr, &msg.h.mDNS_numUpdates, &srs->RR_TXT.resrec, srs->RR_TXT.resrec.rroriginalttl))) goto error;
if (!GetServiceTarget(u, srv, &target))
{
- debugf("Couldn't get target for service %##s", srv->resrec.name.c);
- rInfo->state = regState_NoTarget;
+ debugf("Couldn't get target for service %##s", srv->resrec.name->c);
+ rInfo->state = regState_NoTarget;
return;
- }
- if (!SameDomainName(&target, &srv->resrec.rdata->u.srv.target))
- {
- AssignDomainName(srv->resrec.rdata->u.srv.target, target);
- SetNewRData(&srv->resrec, mDNSNULL, 0);
}
+ if (!SameDomainName(&target, &srv->resrec.rdata->u.srv.target))
+ {
+ AssignDomainName(&srv->resrec.rdata->u.srv.target, &target);
+ SetNewRData(&srv->resrec, mDNSNULL, 0);
+ }
+
ptr = PutResourceRecordTTLJumbo(&msg, ptr, &msg.h.mDNS_numUpdates, &srv->resrec, srv->resrec.rroriginalttl);
if (!ptr) goto error;
- // !!!KRS do subtypes/extras etc.
if (srs->uDNS_info.lease)
- { ptr = putUpdateLease(&msg, ptr, kLLQ_DefLease); if (!ptr) goto error; }
+ { ptr = putUpdateLease(&msg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) goto error; }
- srs->uDNS_info.expire = -1;
-
err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rInfo->ns, rInfo->port, -1, GetAuthInfoForZone(u, &rInfo->zone));
if (err) { LogMsg("ERROR: SendServiceRegistration - mDNSSendDNSMessage - %ld", err); goto error; }
- if (rInfo->state != regState_Refresh)
+ if (rInfo->state != regState_Refresh && rInfo->state != regState_DeregDeferred && srs->uDNS_info.state != regState_UpdatePending)
rInfo->state = regState_Pending;
SetRecordRetry(m, &srs->RR_SRV);
error:
LogMsg("SendServiceRegistration - Error formatting message");
- if (mapped) srv->resrec.rdata->u.srv.port = privport;
- unlinkSRS(u, srs);
+ if (mapped) srv->resrec.rdata->u.srv.port = privport;
+ unlinkSRS(m, srs);
rInfo->state = regState_Unregistered;
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
srs->ServiceCallback(m, srs, err);
m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
//!!!KRS will mem still be free'd on error?
- // NOTE: not safe to touch any client structures here
+ // NOTE: not safe to touch any client structures here
}
mDNSlocal void serviceRegistrationCallback(mStatus err, mDNS *const m, void *srsPtr, const AsyncOpResult *result)
{
ServiceRecordSet *srs = (ServiceRecordSet *)srsPtr;
const zoneData_t *zoneData = mDNSNULL;
- uDNS_GlobalInfo *u = &m->uDNS_info;
if (err) goto error;
if (!result) { LogMsg("ERROR: serviceRegistrationCallback invoked with NULL result and no error"); goto error; }
{
// client cancelled registration while fetching zone data
srs->uDNS_info.state = regState_Unregistered;
- unlinkSRS(u, srs);
+ unlinkSRS(m, srs);
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
srs->ServiceCallback(m, srs, mStatus_MemFree);
m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
if (srs->RR_SRV.resrec.rrclass != zoneData->zoneClass)
{
- LogMsg("Service %##s - class does not match zone", srs->RR_SRV.resrec.name.c);
+ LogMsg("Service %##s - class does not match zone", srs->RR_SRV.resrec.name->c);
goto error;
}
+
// cache zone data
- AssignDomainName(srs->uDNS_info.zone, zoneData->zoneName);
+ AssignDomainName(&srs->uDNS_info.zone, &zoneData->zoneName);
srs->uDNS_info.ns.type = mDNSAddrType_IPv4;
srs->uDNS_info.ns = zoneData->primaryAddr;
- if (zoneData->updatePort.NotAnInteger) srs->uDNS_info.port = zoneData->updatePort;
+ if (zoneData->updatePort.NotAnInteger) srs->uDNS_info.port = zoneData->updatePort;
else
{
debugf("Update port not advertised via SRV - guessing port 53, no lease option");
srs->uDNS_info.port = UnicastDNSPort;
srs->uDNS_info.lease = mDNSfalse;
}
- SendServiceRegistration(m, srs);
+
+ if (srs->RR_SRV.resrec.rdata->u.srv.port.NotAnInteger && IsPrivateV4Addr(&m->uDNS_info.PrimaryIP))
+ { srs->uDNS_info.state = regState_NATMap; StartNATPortMap(m, srs); }
+ else SendServiceRegistration(m, srs);
return;
error:
- unlinkSRS(u, srs);
+ unlinkSRS(m, srs);
srs->uDNS_info.state = regState_Unregistered;
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
srs->ServiceCallback(m, srs, err);
m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
- //!!!KRS will mem still be free'd on error?
// NOTE: not safe to touch any client structures here
}
AuthRecord *ptr = m->uDNS_info.RecordRegistrations;
while (ptr && ptr != rr) ptr = ptr->next;
- if (ptr) { LogMsg("Error: SetupRecordRegistration - record %##s already in list!", rr->resrec.name.c); return mStatus_AlreadyRegistered; }
+ if (ptr) { LogMsg("Error: SetupRecordRegistration - record %##s already in list!", rr->resrec.name->c); return mStatus_AlreadyRegistered; }
if (rr->uDNS_info.state == regState_FetchingZoneData ||
rr->uDNS_info.state == regState_Pending ||
rr->uDNS_info.state == regState_Registered)
{
LogMsg("Requested double-registration of physical record %##s type %d",
- rr->resrec.name.c, rr->resrec.rrtype);
+ rr->resrec.name->c, rr->resrec.rrtype);
return mStatus_AlreadyRegistered;
}
rr->resrec.rdlength = GetRDLength(&rr->resrec, mDNSfalse);
rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue);
- if (!ValidateDomainName(&rr->resrec.name))
+ if (!ValidateDomainName(rr->resrec.name))
{
LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr));
return mStatus_Invalid;
// Don't do this until *after* we've set rr->resrec.rdlength
if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata))
- {
+ {
LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr));
return mStatus_Invalid;
}
- rr->resrec.namehash = DomainNameHashValue(&rr->resrec.name);
+ rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
rr->resrec.rdatahash = RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u);
rr->resrec.rdnamehash = target ? DomainNameHashValue(target) : 0;
{
mStatus err = SetupRecordRegistration(m, rr);
if (err) return err;
- else return startGetZoneData(&rr->resrec.name, m, mDNStrue, mDNSfalse, RecordRegistrationCallback, rr);
+ else return startGetZoneData(rr->resrec.name, m, mDNStrue, mDNSfalse, RecordRegistrationCallback, rr);
}
mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr)
if (!(ptr = putDeletionRecord(&msg, ptr, &rr->resrec))) goto error;
err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rr->uDNS_info.ns, rr->uDNS_info.port, -1, GetAuthInfoForZone(u, &rr->uDNS_info.zone));
- if (err) LogMsg("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %ld", err);
+ if (err) LogMsg("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %ld", err);
SetRecordRetry(m, rr);
rr->uDNS_info.state = regState_DeregPending;
{
case regState_NATMap:
// we're in the middle of a NAT traversal operation
- if (!n) LogMsg("uDNS_DeregisterRecord: no NAT info context");
+ if (!n) LogMsg("uDNS_DeregisterRecord: no NAT info context");
else FreeNATInfo(m, n); // cause response to outstanding request to be ignored.
- // Note: normally here we're trying to determine our public address,
- //in which case there is not state to be torn down. For simplicity,
- //we allow other operations to expire.
+ // Note: normally here we're trying to determine our public address,
+ //in which case there is not state to be torn down. For simplicity,
+ //we allow other operations to expire.
rr->uDNS_info.NATinfo = mDNSNULL;
rr->uDNS_info.state = regState_Unregistered;
break;
case regState_ExtraQueued:
rr->uDNS_info.state = regState_Unregistered;
- break;
+ break;
case regState_FetchingZoneData:
rr->uDNS_info.state = regState_Cancelled;
return mStatus_NoError;
case regState_Pending:
case regState_UpdatePending:
rr->uDNS_info.state = regState_DeregDeferred;
- LogMsg("Deferring deregistration of record %##s until registration completes", rr->resrec.name.c);
+ LogMsg("Deferring deregistration of record %##s until registration completes", rr->resrec.name->c);
return mStatus_NoError;
- case regState_Registered:
+ case regState_Registered:
case regState_DeregPending:
break;
case regState_DeregDeferred:
case regState_Cancelled:
LogMsg("Double deregistration of record %##s type %d",
- rr->resrec.name.c, rr->resrec.rrtype);
+ rr->resrec.name->c, rr->resrec.rrtype);
return mStatus_UnknownErr;
case regState_Unregistered:
LogMsg("Requested deregistration of unregistered record %##s type %d",
- rr->resrec.name.c, rr->resrec.rrtype);
+ rr->resrec.name->c, rr->resrec.rrtype);
return mStatus_UnknownErr;
+ case regState_NATError:
case regState_NoTarget:
- LogMsg("ERROR: uDNS_DeregisterRecord called for record %##s with bad state (regState_NoTarget)", rr->resrec.name.c);
+ LogMsg("ERROR: uDNS_DeregisterRecord called for record %##s with bad state %s", rr->resrec.name->c, rr->uDNS_info.state == regState_NoTarget ? "regState_NoTarget" : "regState_NATError");
return mStatus_UnknownErr;
}
{
// unlink and deliver memfree
- unlinkAR(&u->RecordRegistrations, rr);
+ unlinkAR(&u->RecordRegistrations, rr);
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
if (rr->RecordCallback) rr->RecordCallback(m, rr, mStatus_MemFree);
m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
SendRecordDeregistration(m, rr);
return mStatus_NoError;
}
-
-// register a service already in list with initialized state
-mDNSlocal mStatus RegisterService(mDNS *m, ServiceRecordSet *srs)
- {
- uDNS_RegInfo *info = &srs->uDNS_info;
- srs->RR_SRV.resrec.rroriginalttl = 3;
- srs->RR_TXT.resrec.rroriginalttl = 3;
- srs->RR_PTR.resrec.rroriginalttl = 3;
+mDNSexport mStatus uDNS_RegisterService(mDNS *const m, ServiceRecordSet *srs)
+ {
+ mDNSu32 i;
+ domainname target;
+ uDNS_RegInfo *info = &srs->uDNS_info;
+ ServiceRecordSet **p = &m->uDNS_info.ServiceRegistrations;
+ while (*p && *p != srs) p=&(*p)->next;
+ if (*p) { LogMsg("uDNS_RegisterService: %p %##s already in list", srs, srs->RR_SRV.resrec.name->c); return(mStatus_AlreadyRegistered); }
+ ubzero(info, sizeof(*info));
+ *p = srs;
+ srs->next = mDNSNULL;
+
+ srs->RR_SRV.resrec.rroriginalttl = kWideAreaTTL;
+ srs->RR_TXT.resrec.rroriginalttl = kWideAreaTTL;
+ srs->RR_PTR.resrec.rroriginalttl = kWideAreaTTL;
+ for (i = 0; i < srs->NumSubTypes;i++) srs->SubTypes[i].resrec.rroriginalttl = kWideAreaTTL;
info->lease = mDNStrue;
- if (srs->RR_SRV.resrec.rdata->u.srv.port.NotAnInteger && MapServicePort(m))
+ srs->RR_SRV.resrec.rdata->u.srv.target.c[0] = 0;
+ if (!GetServiceTarget(&m->uDNS_info, &srs->RR_SRV, &target))
{
- // !!!KRS if interface is already in NATState_Legacy, don't try NATPMP
- info->state = regState_NATMap;
- StartNATPortMap(m, srs);
+ // defer registration until we've got a target
+ LogMsg("uDNS_RegisterService - no target for %##s", srs->RR_SRV.resrec.name->c);
+ info->state = regState_NoTarget;
return mStatus_NoError;
- }
+ }
info->state = regState_FetchingZoneData;
- return startGetZoneData(&srs->RR_SRV.resrec.name, m, mDNStrue, mDNSfalse, serviceRegistrationCallback, srs);
- }
-
-mDNSexport mStatus uDNS_RegisterService(mDNS *const m, ServiceRecordSet *srs)
- {
- // Note: ServiceRegistrations list is in the order they were created; important for in-order event delivery
- ServiceRecordSet **p = &m->uDNS_info.ServiceRegistrations;
- while (*p && *p != srs) p=&(*p)->next;
- if (*p) { LogMsg("uDNS_RegisterService: %p %##s already in list", srs, srs->RR_SRV.resrec.name.c); return(mStatus_AlreadyRegistered); }
- ubzero(&srs->uDNS_info, sizeof(uDNS_RegInfo));
- srs->uDNS_info.state = regState_Unregistered;
- *p = srs;
- srs->next = mDNSNULL;
- return RegisterService(m, srs);
- }
+ return startGetZoneData(srs->RR_SRV.resrec.name, m, mDNStrue, mDNSfalse, serviceRegistrationCallback, srs);
+ }
mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs)
{
mDNSu8 *ptr = msg.data;
mDNSu8 *end = (mDNSu8 *)&msg + sizeof(DNSMessage);
mStatus err = mStatus_UnknownErr;
-
+ mDNSu32 i;
+
id = newMessageID(u);
InitializeDNSMessage(&msg.h, id, UpdateReqFlags);
ptr = putZone(&msg, ptr, end, &info->zone, mDNSOpaque16fromIntVal(srs->RR_SRV.resrec.rrclass));
if (!ptr) { LogMsg("ERROR: SendServiceDeregistration - putZone"); goto error; }
- if (!(ptr = putDeleteAllRRSets(&msg, ptr, &srs->RR_SRV.resrec.name))) goto error; // this deletes SRV, TXT, and Extras
+ if (!(ptr = putDeleteAllRRSets(&msg, ptr, srs->RR_SRV.resrec.name))) goto error; // this deletes SRV, TXT, and Extras
if (!(ptr = putDeletionRecord(&msg, ptr, &srs->RR_PTR.resrec))) goto error;
+ for (i = 0; i < srs->NumSubTypes; i++)
+ if (!(ptr = putDeletionRecord(&msg, ptr, &srs->SubTypes[i].resrec))) goto error;
+
err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &info->ns, info->port, -1, GetAuthInfoForZone(u, &info->zone));
if (err) { LogMsg("ERROR: SendServiceDeregistration - mDNSSendDNSMessage - %ld", err); goto error; }
return;
error:
- unlinkSRS(u, srs);
+ unlinkSRS(m, srs);
info->state = regState_Unregistered;
}
// the server when we delete all RRSets for this name
while (*r)
{
- if (SameDomainName(&srs->RR_SRV.resrec.name, &(*r)->resrec.name)) *r = (*r)->next;
+ if (SameDomainName(srs->RR_SRV.resrec.name, (*r)->resrec.name)) *r = (*r)->next;
else r = &(*r)->next;
}
// don't re-register with a new target following deregistration
- srs->uDNS_info.LostTarget = srs->uDNS_info.SRVUpdateDeferred = mDNSfalse;
+ srs->uDNS_info.SRVChanged = srs->uDNS_info.SRVUpdateDeferred = mDNSfalse;
+
+ if (nat)
+ {
+ if (nat->state == NATState_Established || nat->state == NATState_Refresh || nat->state == NATState_Legacy)
+ DeleteNATPortMapping(m, nat, srs);
+ nat->reg.ServiceRegistration = mDNSNULL;
+ srs->uDNS_info.NATinfo = mDNSNULL;
+ FreeNATInfo(m, nat);
+ }
switch (srs->uDNS_info.state)
{
- case regState_NATMap:
- // we're in the middle of nat mapping. clear ptr from NAT info to RR, unlink and give memfree
- if (!nat) LogMsg("uDNS_DeregisterRecord: no NAT info context");
- else { nat->reg.ServiceRegistration = mDNSNULL; FreeNATInfo(m, nat); }
- unlinkSRS(u, srs);
- srs->uDNS_info.state = regState_Unregistered;
- m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
- srs->ServiceCallback(m, srs, mStatus_MemFree);
- m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
- return mStatus_NoError;
case regState_Unregistered:
- errmsg = "service not registered";
- goto error;
+ debugf("uDNS_DeregisterService - service %##s not registered", srs->RR_SRV.resrec.name->c);
+ return mStatus_BadReferenceErr;
case regState_FetchingZoneData:
// let the async op complete, then terminate
srs->uDNS_info.state = regState_Cancelled;
case regState_DeregPending:
case regState_DeregDeferred:
case regState_Cancelled:
- debugf("Double deregistration of service %##s", srs->RR_SRV.resrec.name.c);
+ debugf("Double deregistration of service %##s", srs->RR_SRV.resrec.name->c);
return mStatus_NoError;
- case regState_NoTarget:
- unlinkSRS(u, srs);
+ case regState_NATError: // not registered
+ case regState_NATMap: // not registered
+ case regState_NoTarget: // not registered
+ unlinkSRS(m, srs);
srs->uDNS_info.state = regState_Unregistered;
m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
srs->ServiceCallback(m, srs, mStatus_MemFree);
m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
return mStatus_NoError;
case regState_Registered:
- if (nat) DeleteNATPortMapping(m, nat, srs);
srs->uDNS_info.state = regState_DeregPending;
SendServiceDeregistration(m, srs);
return mStatus_NoError;
return mStatus_BadReferenceErr;
}
-// note that the RegInfo will be either for the record, or for the parent ServiceRecordSet
mDNSlocal void SendRecordUpdate(mDNS *m, AuthRecord *rr, uDNS_RegInfo *info)
{
DNSMessage msg;
mDNSOpaque16 id;
mStatus err = mStatus_UnknownErr;
+ if (info != &rr->uDNS_info) LogMsg("ERROR: SendRecordUpdate - incorrect info struct!");
rr->uDNS_info.UpdateQueued = mDNSfalse; // if this was queued, clear flag
id = newMessageID(u);
InitializeDNSMessage(&msg.h, id, UpdateReqFlags);
if (!ptr) goto error; // (rdata gets changed permanently on success)
if (info->lease)
- { ptr = putUpdateLease(&msg, ptr, kLLQ_DefLease); if (!ptr) goto error; }
+ { ptr = putUpdateLease(&msg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) goto error; }
// don't report send errors - retransmission will occurr if necessary
err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &info->ns, info->port, -1, GetAuthInfoForZone(u, &info->zone));
if (err) debugf("ERROR: sendRecordRegistration - mDNSSendDNSMessage - %ld", err);
- //!!! Update this when we implement retransmission for services
+ //!!! Update this when we implement retransmission for services
SetRecordRetry(m, rr);
rr->uDNS_info.state = regState_UpdatePending;
error:
LogMsg("ERROR: SendRecordUpdate. Error formatting update message.");
- info ->state = regState_Registered;
+ info ->state = regState_Registered;
}
mDNSexport mStatus uDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra)
extra->r.resrec.RecordType = kDNSRecordTypeShared; // don't want it to conflict with the service name
extra->r.RecordCallback = mDNSNULL; // don't generate callbacks for extra RRs
- if (sr->uDNS_info.state == regState_Registered || sr->uDNS_info.state == regState_Refresh)
+ if (sr->uDNS_info.state == regState_Registered || sr->uDNS_info.state == regState_Refresh)
err = uDNS_RegisterRecord(m, &extra->r);
else
{
case regState_FetchingZoneData:
case regState_NATMap:
case regState_ExtraQueued:
- // change rdata directly since it hasn't been sent yet
+ // change rdata directly since it hasn't been sent yet
SwapRData(m, rr, mDNStrue);
return mStatus_NoError;
return mStatus_NoError;
case regState_Registered:
- SendRecordUpdate(m, rr, info);
+ if (parent) { info->state = regState_UpdatePending; SendServiceRegistration(m, parent); }
+ else SendRecordUpdate(m, rr, info);
return mStatus_NoError;
+ case regState_NATError:
case regState_NoTarget:
- LogMsg("Bad state (regState_NoTarget)"); return mStatus_UnknownErr; // state for service records only
+ LogMsg("ERROR: uDNS_UpdateRecord called for record %##s with bad state %s", rr->resrec.name->c, rr->uDNS_info.state == regState_NoTarget ? "regState_NoTarget" : "regState_NATError");
+ return mStatus_UnknownErr; // states for service records only
}
unreg_error:
LogMsg("Requested update of record %##s type %d, part of service not currently registered",
- rr->resrec.name.c, rr->resrec.rrtype);
+ rr->resrec.name->c, rr->resrec.rrtype);
return mStatus_Invalid;
}
{
cur = ptr;
ptr = ptr->next;
- if (cur->retry - timenow < 0)
+ if (cur->op != NATOp_AddrRequest || cur->state != NATState_Established) // no refresh necessary for established Add requests
{
- if (cur->state == NATState_Established) RefreshNATMapping(cur, m);
- else if (cur->state == NATState_Request || cur->state == NATState_Refresh)
+ if (cur->retry - timenow < 0)
{
- if (cur->ntries >= NATMAP_MAX_TRIES) cur->ReceiveResponse(cur, m, mDNSNULL, 0); // may invalidate "cur"
- else SendNATMsg(cur, m);
+ if (cur->state == NATState_Established) RefreshNATMapping(cur, m);
+ else if (cur->state == NATState_Request || cur->state == NATState_Refresh)
+ {
+ if (cur->ntries >= NATMAP_MAX_TRIES) cur->ReceiveResponse(cur, m, mDNSNULL, 0); // may invalidate "cur"
+ else SendNATMsg(cur, m);
+ }
}
+ else if (cur->retry - nextevent < 0) nextevent = cur->retry;
}
- else if (cur->retry - nextevent < 0) nextevent = cur->retry;
}
return nextevent;
}
u->CurrentQuery = u->ActiveQueries;
while (u->CurrentQuery)
{
- q = u->CurrentQuery;
+ q = u->CurrentQuery;
info = &q->uDNS_info;
llq = info->llq;
- if (!info->internal && ((!q->LongLived && !info->Answered) || (llq && llq->state < LLQ_Established)) &&
+ if (!info->internal && ((!q->LongLived && !info->Answered) || (llq && llq->state < LLQ_Established)) &&
info->RestartTime + RESTART_GOODBYE_DELAY - timenow < 0)
{
// if we've been spinning on restart setup, and we have known answers, give goodbyes (they may be re-added later)
while (info->knownAnswers)
- {
+ {
CacheRecord *cr = info->knownAnswers;
info->knownAnswers = info->knownAnswers->next;
m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
ufree(cr);
if (q != u->CurrentQuery) { debugf("CheckQueries - question removed via callback."); break; }
- }
+ }
}
if (q != u->CurrentQuery) continue;
if (q->LongLived && llq->state != LLQ_Poll)
- {
+ {
if (llq->state >= LLQ_InitialRequest && llq->state <= LLQ_Established)
{
- if (llq->retry - timenow < 0)
+ if (llq->retry - timenow < 0)
{
// sanity check to avoid packet flood bugs
- if (!llq->retry)
+ if (!llq->retry)
LogMsg("ERROR: retry timer not set for LLQ %##s in state %d", q->qname.c, llq->state);
else if (llq->state == LLQ_Established || llq->state == LLQ_Refresh)
sendLLQRefresh(m, q, llq->origLease);
- else if (llq->state == LLQ_InitialRequest)
+ else if (llq->state == LLQ_InitialRequest)
startLLQHandshake(m, llq, mDNSfalse);
else if (llq->state == LLQ_SecondaryRequest)
sendChallengeResponse(m, q, mDNSNULL);
- else if (llq->state == LLQ_Retry)
+ else if (llq->state == LLQ_Retry)
{ llq->ntries = 0; startLLQHandshake(m, llq, mDNSfalse); }
}
else if (llq->retry - nextevent < 0) nextevent = llq->retry;
//!!!KRS list should be pre-sorted by expiration
for (rr = u->RecordRegistrations; rr; rr = rr->next)
{
- rInfo = &rr->uDNS_info;
+ rInfo = &rr->uDNS_info;
if (rInfo->state == regState_Pending || rInfo->state == regState_DeregPending || rInfo->state == regState_UpdatePending || rInfo->state == regState_DeregDeferred || rInfo->state == regState_Refresh)
{
if (rr->LastAPTime + rr->ThisAPInterval - timenow < 0)
{
-#if MDNS_DEBUGMSGS
+#if MDNS_DEBUGMSGS
char *op = "(unknown operation)";
if (rInfo->state == regState_Pending) op = "registration";
else if (rInfo->state == regState_DeregPending) op = "deregistration";
else if (rInfo->state == regState_Refresh) op = "refresh";
- debugf("Retransmit record %s %##s", op, rr->resrec.name.c);
+ debugf("Retransmit record %s %##s", op, rr->resrec.name->c);
#endif
- //LogMsg("Retransmit record %##s", rr->resrec.name.c);
+ //LogMsg("Retransmit record %##s", rr->resrec.name->c);
if (rInfo->state == regState_DeregPending) SendRecordDeregistration(m, rr);
else if (rInfo->state == regState_UpdatePending) SendRecordUpdate(m, rr, rInfo);
else sendRecordRegistration(m, rr);
}
if (rr->LastAPTime + rr->ThisAPInterval - nextevent < 0) nextevent = rr->LastAPTime + rr->ThisAPInterval;
}
- if (rInfo->lease && rInfo->state == regState_Registered && rInfo->expire > 0)
- {
+ if (rInfo->lease && rInfo->state == regState_Registered)
+ {
if (rInfo->expire - timenow < 0)
{
- debugf("refreshing record %##s", rr->resrec.name.c);
+ debugf("refreshing record %##s", rr->resrec.name->c);
rInfo->state = regState_Refresh;
sendRecordRegistration(m, rr);
}
if (rInfo->expire - nextevent < 0) nextevent = rInfo->expire;
- }
+ }
}
return nextevent;
}
s = s->next;
rInfo = &srs->uDNS_info;
- if (rInfo->state == regState_Pending || rInfo->state == regState_DeregPending || rInfo->state == regState_DeregDeferred || rInfo->state == regState_Refresh)
+ if (rInfo->state == regState_Pending || rInfo->state == regState_DeregPending || rInfo->state == regState_DeregDeferred || rInfo->state == regState_Refresh || rInfo->state == regState_UpdatePending)
{
if (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval - timenow < 0)
{
-#if MDNS_DEBUGMSGS
+#if MDNS_DEBUGMSGS
char *op = "unknown";
if (rInfo->state == regState_Pending) op = "registration";
else if (rInfo->state == regState_DeregPending) op = "deregistration";
else if (rInfo->state == regState_Refresh) op = "refresh";
- debugf("Retransmit service %s %##s", op, srs->RR_SRV.resrec.name.c);
+ else if (rInfo->state == regState_UpdatePending) op = "txt record update";
+ debugf("Retransmit service %s %##s", op, srs->RR_SRV.resrec.name->c);
#endif
if (rInfo->state == regState_DeregPending) { SendServiceDeregistration(m, srs); continue; }
else SendServiceRegistration (m, srs);
}
if (nextevent - srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval > 0)
nextevent = srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval;
- }
+ }
- if (rInfo->lease && rInfo->state == regState_Registered && rInfo->expire > 0)
- {
+ if (rInfo->lease && rInfo->state == regState_Registered)
+ {
if (rInfo->expire - timenow < 0)
- {
- debugf("refreshing service %##s", srs->RR_SRV.resrec.name.c);
+ {
+ debugf("refreshing service %##s", srs->RR_SRV.resrec.name->c);
rInfo->state = regState_Refresh;
SendServiceRegistration(m, srs);
}
if (rInfo->expire - nextevent < 0) nextevent = rInfo->expire;
- }
+ }
}
return nextevent;
}
mDNSexport void uDNS_Execute(mDNS *const m)
{
uDNS_GlobalInfo *u = &m->uDNS_info;
- mDNSs32 nexte, timenow = mDNSPlatformTimeNow(m);
+ mDNSs32 nexte, timenow = mDNSPlatformTimeNow(m);
u->nextevent = timenow + MIN_UCAST_PERIODIC_EXEC;
+
+ if (u->DelaySRVUpdate && u->NextSRVUpdate - timenow < 0)
+ {
+ u->DelaySRVUpdate = mDNSfalse;
+ UpdateSRVRecords(m);
+ }
nexte = CheckNATMappings(m, timenow);
if (nexte - u->nextevent < 0) u->nextevent = nexte;
q->uDNS_info.Answered = mDNSfalse;
if (q->LongLived)
{
- if (!llqInfo) { LogMsg("Error: RestartQueries - %##s long-lived with NULL info", q->qname.c); continue; }
- if (llqInfo->state == LLQ_Suspended || llqInfo->state == LLQ_NatMapWait)
+ if (!llqInfo) { LogMsg("Error: RestartQueries - %##s long-lived with NULL info", q->qname.c); continue; }
+ if (llqInfo->state == LLQ_Suspended || llqInfo->state == LLQ_NatMapWait)
{
llqInfo->ntries = -1;
llqInfo->deriveRemovesOnResume = mDNStrue;
mDNSs32 timenow = mDNSPlatformTimeNow(m);
while (rr)
- {
+ {
if (rr->uDNS_info.state == regState_Registered ||
rr->uDNS_info.state == regState_Refresh)
{
// construct deletion update
ptr = putZone(&msg, ptr, end, &rr->uDNS_info.zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
- if (!ptr) { LogMsg("Error: SleepRecordRegistrations - could not put zone"); return; }
+ if (!ptr) { LogMsg("Error: SleepRecordRegistrations - could not put zone"); return; }
ptr = putDeletionRecord(&msg, ptr, &rr->resrec);
if (!ptr) { LogMsg("Error: SleepRecordRegistrations - could not put deletion record"); return; }
srs->uDNS_info.state = regState_DeregPending; // state expected by SendDereg()
SendServiceDeregistration(m, srs);
srs->uDNS_info.id = origid;
- srs->uDNS_info.state = regState_Refresh;
+ srs->uDNS_info.state = regState_Refresh;
srs->RR_SRV.LastAPTime = timenow;
srs->RR_SRV.ThisAPInterval = 300 * mDNSPlatformOneSecond;
}
Change History (most recent first):
$Log: uDNS.h,v $
+Revision 1.29 2005/01/11 22:50:53 ksekar
+Fixed constant naming (was using kLLQ_DefLease for update leases)
+
+Revision 1.28 2004/12/22 00:13:49 ksekar
+<rdar://problem/3873993> Change version, port, and polling interval for LLQ
+
Revision 1.27 2004/11/23 04:06:50 cheshire
Get rid of floating point constant -- in a small embedded device, bringing in all
the floating point libraries just to halve an integer value is a bit too heavyweight.
#define MIN_UCAST_PERIODIC_EXEC (5 * mDNSPlatformOneSecond)
#define INIT_UCAST_POLL_INTERVAL mDNSPlatformOneSecond // this interval is used after send failures on network transitions
// which typically heal quickly, so we start agressively and exponentially back off
-#define MAX_UCAST_POLL_INTERVAL (15 * 60 * mDNSPlatformOneSecond)
+#define MAX_UCAST_POLL_INTERVAL (60 * 60 * mDNSPlatformOneSecond)
#define RESPONSE_WINDOW (60 * mDNSPlatformOneSecond) // require server responses within one minute of request
#define UPDATE_PORT_NAME "_dns-update._udp."
#define LLQ_PORT_NAME "_dns-llq._udp"
+#define DEFAULT_UPDATE_LEASE 7200
// Entry points into unicast-specific routines
Change History (most recent first):
$Log: Mac\040OS\040Test\040Responder.c,v $
+Revision 1.24 2004/12/16 20:49:34 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.23 2004/09/17 01:08:50 cheshire
Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
{
switch (result)
{
- case mStatus_NoError: debugf("Callback: %##s Name Registered", sr->RR_SRV.resrec.name.c); break;
- case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", sr->RR_SRV.resrec.name.c); break;
- case mStatus_MemFree: debugf("Callback: %##s Memory Free", sr->RR_SRV.resrec.name.c); break;
- default: debugf("Callback: %##s Unknown Result %d", sr->RR_SRV.resrec.name.c, result); break;
+ case mStatus_NoError: debugf("Callback: %##s Name Registered", sr->RR_SRV.resrec.name->c); break;
+ case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", sr->RR_SRV.resrec.name->c); break;
+ case mStatus_MemFree: debugf("Callback: %##s Memory Free", sr->RR_SRV.resrec.name->c); break;
+ default: debugf("Callback: %##s Unknown Result %d", sr->RR_SRV.resrec.name->c, result); break;
}
if (result == mStatus_NameConflict) mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
mDNSInterface_Any, // Interface ID
Callback, mDNSNULL); // Callback and context
- ConvertDomainNameToCString(&recordset->RR_SRV.resrec.name, buffer);
+ ConvertDomainNameToCString(recordset->RR_SRV.resrec.name, buffer);
printf("Made Service Records for %s\n", buffer);
}
Change History (most recent first):
$Log: Mac\040OS\040Test\040Searcher.c,v $
+Revision 1.21 2004/12/16 20:49:34 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.20 2004/10/19 21:33:18 cheshire
<rdar://problem/3844991> Cannot resolve non-local registrations using the mach API
Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name
// These don't have to be globals, but their memory does need to remain valid for as
// long as the search is going on. They are declared as globals here for simplicity.
#define RR_CACHE_SIZE 1000
-static CacheRecord rrcachestorage[RR_CACHE_SIZE];
+static CacheEntity rrcachestorage[RR_CACHE_SIZE];
static mDNS mDNSStorage;
static mDNS_PlatformSupport PlatformSupportStorage;
static SearcherServices services;
SearcherServices *services = (SearcherServices *)question->QuestionContext;
linkedServiceInfo *info;
- debugf("FoundInstance %##s PTR %##s", answer->name.c, answer->rdata->u.name.c);
+ debugf("FoundInstance %##s PTR %##s", answer->name->c, answer->rdata->u.name.c);
if (answer->rrtype != kDNSType_PTR) return;
if (!services) { debugf("FoundInstance: services is NULL"); return; }
SearcherServices *services = (SearcherServices *)question->QuestionContext;
linkedServiceInfo *info;
- debugf("FoundDomain %##s PTR %##s", answer->name.c, answer->rdata->u.name.c);
+ debugf("FoundDomain %##s PTR %##s", answer->name->c, answer->rdata->u.name.c);
if (answer->rrtype != kDNSType_PTR) return;
if (!services) { debugf("FoundDomain: services is NULL"); return; }
Change History (most recent first):
$Log: SubTypeTester.c,v $
+Revision 1.6 2004/12/16 20:49:35 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.5 2004/09/17 01:08:50 cheshire
Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
mDNSInterface_Any, // Interface ID
Callback, mDNSNULL); // Callback and context
- ConvertDomainNameToCString(&recordset->RR_SRV.resrec.name, buffer);
+ ConvertDomainNameToCString(recordset->RR_SRV.resrec.name, buffer);
printf("Made Service Records for %s\n", buffer);
}
// 3. Set target of subtype PTR record to point to our SRV record (exactly the same as the main service PTR record)
// 4. And register it
mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_Any, kDNSType_PTR, 2*3600, kDNSRecordTypeShared, AvailCallback, &availRec2Active);
- MakeDomainNameFromDNSNameString(&rr->resrec.name, "a._sub._raop._tcp.local.");
- AssignDomainName(rr->resrec.rdata->u.name, sr->RR_SRV.resrec.name);
+ MakeDomainNameFromDNSNameString(rr->resrec.name, "a._sub._raop._tcp.local.");
+ AssignDomainName(&rr->resrec.rdata->u.name, sr->RR_SRV.resrec.name);
return(mDNS_Register(m, rr));
}
Change History (most recent first):
$Log: mDNSLibrary.c,v $
+Revision 1.3 2004/12/16 20:49:35 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.2 2004/09/17 01:08:50 cheshire
Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
mDNS mDNSStorage;
static mDNS_PlatformSupport PlatformSupportStorage;
-#define RR_CACHE_SIZE 64
-static CacheRecord rrcachestorage[RR_CACHE_SIZE];
+// Start off with a default cache of 16K (about 100 records)
+#define RR_CACHE_SIZE ((16*1024) / sizeof(CacheRecord))
+static CacheEntity rrcachestorage[RR_CACHE_SIZE];
mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
{
if (result == mStatus_GrowCache)
{
- // If we've run out of cache space, then double the total cache size and give the memory to mDNSCore
- mDNSu32 numrecords = m->rrcache_size;
- CacheRecord *storage = OTAllocMem(sizeof(CacheRecord) * numrecords);
- LogMsg("mStatus_GrowCache %d", numrecords);
- if (storage) mDNS_GrowCache(m, storage, numrecords);
+ // Allocate another chunk of cache storage
+ CacheEntity *storage = OTAllocMem(sizeof(CacheEntity) * RR_CACHE_SIZE);
+ if (storage) mDNS_GrowCache(m, storage, RR_CACHE_SIZE);
}
}
Change History (most recent first):
$Log: mDNSLibraryResources.r,v $
+Revision 1.25 2005/01/28 00:04:16 cheshire
+mDNSResponder-98
+
+Revision 1.24 2005/01/22 01:15:14 ksekar
+Update version string to 1.0a97
+
+Revision 1.23 2005/01/13 19:50:17 ksekar
+Update version string to 1.0a94
+
+Revision 1.22 2005/01/10 16:33:26 ksekar
+Update version string to 1.0a93
+
+Revision 1.21 2004/12/23 23:50:59 ksekar
+Update version string to 1.0a92
+
+Revision 1.20 2004/12/20 23:26:47 cheshire
+mDNSResponder-90
+
+Revision 1.19 2004/12/16 20:52:38 cheshire
+mDNSResponder-89
+
+Revision 1.18 2004/12/15 20:25:49 cheshire
+mDNSResponder-88
+
Revision 1.17 2004/12/13 21:54:30 cheshire
mDNSResponder-87
resource 'vers' (1, purgeable)
{
- 0x01, 0x00, alpha, 87, verUS,
- "1.0a87",
- "Multicast DNS & DNS Service Discovery 1.0a87"
+ 0x01, 0x00, alpha, 98, verUS,
+ "1.0a98",
+ "Multicast DNS & DNS Service Discovery 1.0a98"
};
resource 'vers' (2, purgeable)
{
- 0x01, 0x00, alpha, 87, verUS,
- "1.0a87",
+ 0x01, 0x00, alpha, 98, verUS,
+ "1.0a98",
"developer.apple.com/darwin/projects/rendezvous/"
};
Change History (most recent first):
$Log: mDNSMacOS9.c,v $
+Revision 1.43 2004/12/17 23:37:49 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+(and other repetitive configuration changes)
+
+Revision 1.42 2004/12/16 20:43:39 cheshire
+interfaceinfo.fMask should be interfaceinfo.fNetmask
+
Revision 1.41 2004/10/16 00:17:00 cheshire
<rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
m->p->interface.ip .type = mDNSAddrType_IPv4;
m->p->interface.ip .ip.v4.NotAnInteger = interfaceinfo.fAddress;
m->p->interface.mask.type = mDNSAddrType_IPv4;
- m->p->interface.mask.ip.v4.NotAnInteger = interfaceinfo.fMask;
+ m->p->interface.mask.ip.v4.NotAnInteger = interfaceinfo.fNetmask;
m->p->interface.ifname[0] = 0;
m->p->interface.Advertise = m->AdvertiseLocalAddresses;
m->p->interface.McastTxRx = mDNStrue;
case mOT_Bind: OTBind(m->p->ep, (TBind*)&mDNSbindReq, NULL); break;
case mOT_Ready: mDNSinitComplete(m, mStatus_NoError);
// Can't do mDNS_RegisterInterface until *after* mDNSinitComplete has set m->mDNSPlatformStatus to mStatus_NoError
- mDNS_RegisterInterface(m, &m->p->interface);
+ mDNS_RegisterInterface(m, &m->p->interface, 0);
break;
default: LogMsg("Unexpected m->p->mOTstate %d", m->p->mOTstate-1);
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.apple.mDNSResponder</string>
+ <key>OnDemand</key>
+ <false/>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/sbin/mDNSResponder</string>
+ <string>-launchdaemon</string>
+ </array>
+ <key>ServiceIPC</key>
+ <false/>
+</dict>
+</plist>
Change History (most recent first):
$Log: daemon.c,v $
+Revision 1.244 2005/01/28 00:34:49 cheshire
+Turn off "Starting time value" log message
+
+Revision 1.243 2005/01/27 17:46:58 cheshire
+Added comment about CFSocketInvalidate closing the underlying socket
+
+Revision 1.242 2005/01/27 00:10:58 cheshire
+<rdar://problem/3967867> Name change log messages every time machine boots
+
+Revision 1.241 2005/01/25 17:28:06 ksekar
+<rdar://problem/3971467> Should not return "local" twice for domain enumeration
+
+Revision 1.240 2005/01/21 02:39:18 cheshire
+Rename FoundDomain() to DomainEnumFound() to avoid order-file symbol clash with other routine called FoundDomain()
+
+Revision 1.239 2005/01/20 00:25:01 cheshire
+Improve validatelists() log message generation
+
+Revision 1.238 2005/01/19 19:15:35 ksekar
+Refinement to <rdar://problem/3954575> - Simplify mDNS_PurgeResultsForDomain logic and move into daemon layer
+
+Revision 1.237 2005/01/19 03:33:09 cheshire
+<rdar://problem/3945652> When changing Computer Name, we drop our own Goobye Packets
+
+Revision 1.236 2005/01/19 03:16:38 cheshire
+<rdar://problem/3961051> CPU Spin in mDNSResponder
+Improve detail of "Task Scheduling Error" diagnostic messages
+
+Revision 1.235 2005/01/15 00:56:41 ksekar
+<rdar://problem/3954575> Unicast services don't disappear when logging
+out of VPN
+
+Revision 1.234 2005/01/10 03:42:30 ksekar
+Clarify debugf
+
+Revision 1.233 2004/12/18 00:53:46 cheshire
+Use symbolic constant mDNSInterface_LocalOnly instead of (mDNSInterfaceID)~0
+
+Revision 1.232 2004/12/17 23:37:48 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+(and other repetitive configuration changes)
+
+Revision 1.231 2004/12/17 04:13:38 cheshire
+Removed debugging check
+
+Revision 1.230 2004/12/17 04:09:30 cheshire
+<rdar://problem/3191011> Switch mDNSResponder to launchd
+
+Revision 1.229 2004/12/16 21:51:36 cheshire
+Remove some startup messages
+
+Revision 1.228 2004/12/16 20:13:01 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.227 2004/12/10 13:52:57 cheshire
<rdar://problem/3909995> Turn off SIGPIPE signals
#include "DNSServiceDiscoveryRequestServer.h"
#include "DNSServiceDiscoveryReply.h"
-#include "mDNSEmbeddedAPI.h" // Defines the interface to the client layer above
+#include "DNSCommon.h"
#include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
#include "uds_daemon.h" // Interface to the server side implementation of dns_sd.h
#define LOCAL_DEFAULT_REG 1 // empty string means register in the local domain
#define DEFAULT_REG_DOMAIN "apple.com." // used if the above flag is turned off
static mDNS_PlatformSupport PlatformStorage;
-#define RR_CACHE_SIZE 64
-static CacheRecord rrcachestorage[RR_CACHE_SIZE];
+
+// Start off with a default cache of 16K (about 100 records)
+#define RR_CACHE_SIZE ((16*1024) / sizeof(CacheRecord))
+static CacheEntity rrcachestorage[RR_CACHE_SIZE];
static const char kmDNSBootstrapName[] = "com.apple.mDNSResponderRestart";
static mach_port_t client_death_port = MACH_PORT_NULL;
#define MDNS_MM_TIMEOUT 250
static int restarting_via_mach_init = 0;
+static int started_via_launchdaemon = 0;
//*************************************************************************************************************
// Active client list structures
DNSServiceResolver *l;
DNSServiceRegistration *r;
AuthRecord *rr;
+ CacheGroup *cg;
CacheRecord *cr;
DNSQuestion *q;
mDNSu32 slot;
LogMsg("!!!! DNSServiceRegistrationList: %p is garbage (%X) !!!!", r, r->ClientMachPort);
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);
+ if (rr->resrec.name != &rr->namestorage)
+ LogMsg("!!!! 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)
if (q->ThisQInterval == (mDNSs32)~0)
LogMsg("!!!! Questions list: %p is garbage (%lX) !!!!", q, q->ThisQInterval);
- for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
- for (cr = m->rrcache_hash[slot]; cr; cr=cr->next)
- if (cr->resrec.RecordType == 0 || cr->resrec.RecordType == 0xFF)
- LogMsg("!!!! Cache slot %lu: %p is garbage (%X) !!!!", slot, rr, rr->resrec.RecordType);
+ 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);
for (i = m->p->InterfaceList; i; i = i->next)
if (!i->ifa_name)
ServiceInstance *instance = si;
si = si->next;
instance->autorename = mDNSfalse;
- if (m && m != x) LogMsg("%5d: DNSServiceRegistration(%##s, %u) STOP; WARNING m %p != x %p", ClientMachPort, instance->srs.RR_SRV.resrec.name.c, SRS_PORT(&instance->srs), m, x);
- else LogOperation("%5d: DNSServiceRegistration(%##s, %u) STOP", ClientMachPort, instance->srs.RR_SRV.resrec.name.c, SRS_PORT(&instance->srs));
+ if (m && m != x) LogMsg("%5d: DNSServiceRegistration(%##s, %u) STOP; WARNING m %p != x %p", ClientMachPort, instance->srs.RR_SRV.resrec.name->c, SRS_PORT(&instance->srs), m, x);
+ else LogOperation("%5d: DNSServiceRegistration(%##s, %u) STOP", ClientMachPort, instance->srs.RR_SRV.resrec.name->c, SRS_PORT(&instance->srs));
// If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list,
// is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory.
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);
+ 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);
LogMsg("%5d: Browser(%##s) already exists!", c, qptr->q.qname.c);
}
if (l) LogMsg("%5d: Resolver(%##s) already exists!", c, l->i.name.c);
- if (r) LogMsg("%5d: Registration(%##s) already exists!", c, r->regs ? r->regs->srs.RR_SRV.resrec.name.c : NULL);
+ if (r) LogMsg("%5d: Registration(%##s) already exists!", c, r->regs ? r->regs->srs.RR_SRV.resrec.name->c : NULL);
return(e || b || l || r);
}
//*************************************************************************************************************
// Domain Enumeration
-mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void DomainEnumFound(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
{
kern_return_t status;
#pragma unused(m)
DNSServiceDomainEnumerationReplyResultType rt;
DNSServiceDomainEnumeration *x = (DNSServiceDomainEnumeration *)question->QuestionContext;
- debugf("FoundDomain: %##s PTR %##s", answer->name.c, answer->rdata->u.name.c);
+ debugf("DomainEnumFound: %##s PTR %##s", answer->name->c, answer->rdata->u.name.c);
if (answer->rrtype != kDNSType_PTR) return;
- if (!x) { debugf("FoundDomain: DNSServiceDomainEnumeration is NULL"); return; }
+ if (!x) { debugf("DomainEnumFound: DNSServiceDomainEnumeration is NULL"); return; }
if (AddRecord)
{
mDNS_DomainType dt1 = regDom ? mDNS_DomainTypeRegistration : mDNS_DomainTypeBrowse;
mDNS_DomainType dt2 = regDom ? mDNS_DomainTypeRegistrationDefault : mDNS_DomainTypeBrowseDefault;
- const DNSServiceDomainEnumerationReplyResultType rt = DNSServiceDomainEnumerationReplyAddDomainDefault;
// Allocate memory, and handle failure
DNSServiceDomainEnumeration *x = mallocL("DNSServiceDomainEnumeration", sizeof(*x));
x->next = DNSServiceDomainEnumerationList;
DNSServiceDomainEnumerationList = x;
- // Generate initial response
verbosedebugf("%5d: Enumerate %s Domains", client, regDom ? "Registration" : "Browsing");
- // We always give local. as the initial default browse domain, and then look for more
- kern_return_t status = DNSServiceDomainEnumerationReply_rpc(x->ClientMachPort, rt, "local.", 0, MDNS_MM_TIMEOUT);
- if (status == MACH_SEND_TIMED_OUT)
- { AbortBlockedClient(x->ClientMachPort, "local enumeration", x); return(mStatus_UnknownErr); }
// Do the operation
- err = mDNS_GetDomains(&mDNSStorage, &x->dom, dt1, NULL, mDNSInterface_LocalOnly, FoundDomain, x);
- if (!err) err = mDNS_GetDomains(&mDNSStorage, &x->def, dt2, NULL, mDNSInterface_LocalOnly, FoundDomain, x);
+ err = mDNS_GetDomains(&mDNSStorage, &x->dom, dt1, NULL, mDNSInterface_LocalOnly, DomainEnumFound, x);
+ if (!err) err = mDNS_GetDomains(&mDNSStorage, &x->def, dt2, NULL, mDNSInterface_LocalOnly, DomainEnumFound, x);
if (err) { AbortClient(client, x); errormsg = "mDNS_GetDomains"; goto fail; }
// Succeeded: Wrap up and return
if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain))
{
LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
- answer->name.c, answer->rdata->u.name.c);
+ answer->name->c, answer->rdata->u.name.c);
return;
}
if (!x) { LogMsg("FoundInstance: Failed to allocate memory for result %##s", answer->rdata->u.name.c); return; }
verbosedebugf("FoundInstance: %s %##s", AddRecord ? "Add" : "Rmv", answer->rdata->u.name.c);
- AssignDomainName(x->result, answer->rdata->u.name);
+ AssignDomainName(&x->result, &answer->rdata->u.name);
if (AddRecord)
x->resultType = DNSServiceBrowserReplyAddInstance;
else x->resultType = DNSServiceBrowserReplyRemoveInstance;
question = mallocL("DNSServiceBrowserQuestion", sizeof(DNSServiceBrowserQuestion));
if (!question) { LogMsg("Error: malloc"); return mStatus_NoMemoryErr; }
- AssignDomainName(question->domain, *d);
+ AssignDomainName(&question->domain, d);
question->next = browser->qlist;
browser->qlist = question;
LogOperation("%5d: DNSServiceBrowse(%##s%##s) START", browser->ClientMachPort, browser->type.c, d->c);
{
DNSServiceBrowser *ptr;
- debugf("%s default browse domain %##s", add ? "Adding" : "Removing", d->c);
+ debugf("DefaultBrowseDomainChanged: %s default browse domain %##s", add ? "Adding" : "Removing", d->c);
for (ptr = DNSServiceBrowserList; ptr; ptr = ptr->next)
{
if (ptr->DefaultDomain)
}
else
{
-#if 0
- /*
- * By cancelling the browse immediately, we may lose remove events.
- * Instead, we allow the browse to run. If our previous results are no longer valid (e.g. because we
- * moved out from behind a firewall) we will get remove events for those names.
- */
- // find the question for this domain
- DNSServiceBrowserQuestion *q = ptr->qlist, *prev = NULL;
- while (q)
- {
- if (SameDomainName(&q->domain, d))
- {
- if (prev) prev->next = q->next;
- else ptr->qlist = q->next;
- mDNS_StopBrowse(&mDNSStorage, &q->q);
- freeL("DNSServiceBrowserQuestion", q);
- break;
- }
- prev = q;
- q = q->next;
- }
- if (!q) LogMsg("Requested removal of default domain %##s not in client %5d's list", d->c, ptr->ClientMachPort);
-#endif
- }
+ DNSServiceBrowserQuestion **q = &ptr->qlist;
+ while (*q)
+ {
+ if (SameDomainName(&(*q)->domain, d))
+ {
+ DNSServiceBrowserQuestion *remove = *q;
+ *q = (*q)->next;
+ if (remove->q.LongLived)
+ {
+ // give goodbyes for known answers. note that since events are sent to client via udns_execute(),
+ // we don't need to worry about the question being cancelled mid-loop
+ CacheRecord *ka = remove->q.uDNS_info.knownAnswers;
+ while (ka) { remove->q.QuestionCallback(&mDNSStorage, &remove->q, &ka->resrec, mDNSfalse); ka = ka->next; }
+ }
+ mDNS_StopBrowse(&mDNSStorage, &remove->q);
+ freeL("DNSServiceBrowserQuestion", remove );
+ return;
+ }
+ q = &(*q)->next;
+ }
+ LogMsg("Requested removal of default domain %##s not in client %5d's list", d->c, ptr->ClientMachPort);
+ }
}
}
}
if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
// Set up object, and link into list
- AssignDomainName(x->type, t);
+ AssignDomainName(&x->type, &t);
x->ClientMachPort = client;
x->results = NULL;
x->lastsuccess = 0;
//*************************************************************************************************************
// Resolve Service Info
- mDNSlocal void FoundInstanceInfo(mDNS *const m, ServiceInfoQuery *query)
+mDNSlocal void FoundInstanceInfo(mDNS *const m, ServiceInfoQuery *query)
{
kern_return_t status;
DNSServiceResolver *x = (DNSServiceResolver *)query->ServiceInfoQueryContext;
NetworkInterfaceInfoOSX *ifx = (NetworkInterfaceInfoOSX *)query->info->InterfaceID;
- if (query->info->InterfaceID == (mDNSInterfaceID)~0) ifx = mDNSNULL;
+ if (query->info->InterfaceID == mDNSInterface_LocalOnly) ifx = mDNSNULL;
struct sockaddr_storage interface;
struct sockaddr_storage address;
char cstring[1024];
if (result == mStatus_NoError)
{
kern_return_t status;
- LogOperation("%5d: DNSServiceRegistration(%##s, %u) Name Registered", si->ClientMachPort, srs->RR_SRV.resrec.name.c, SRS_PORT(srs));
+ LogOperation("%5d: DNSServiceRegistration(%##s, %u) Name Registered", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs));
status = DNSServiceRegistrationReply_rpc(si->ClientMachPort, result, MDNS_MM_TIMEOUT);
if (status == MACH_SEND_TIMED_OUT)
AbortBlockedClient(si->ClientMachPort, "registration success", si);
else if (result == mStatus_NameConflict)
{
- LogOperation("%5d: DNSServiceRegistration(%##s, %u) Name Conflict", si->ClientMachPort, srs->RR_SRV.resrec.name.c, SRS_PORT(srs));
+ LogOperation("%5d: DNSServiceRegistration(%##s, %u) Name Conflict", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs));
// Note: By the time we get the mStatus_NameConflict message, the service is already deregistered
// and the memory is free, so we don't have to wait for an mStatus_MemFree message as well.
if (si->autoname && CountPeerRegistrations(m, srs) == 0)
{
if (sp == si)
{
- LogMsg("RegCallback: %##s Still in DNSServiceRegistration list; removing now", srs->RR_SRV.resrec.name.c);
+ LogMsg("RegCallback: %##s Still in DNSServiceRegistration list; removing now", srs->RR_SRV.resrec.name->c);
if (prev) prev->next = sp->next;
else r->regs = sp->next;
break;
}
else if (result != mStatus_NATTraversal)
- LogMsg("%5d: DNSServiceRegistration(%##s, %u) Unknown Result %ld", si->ClientMachPort, srs->RR_SRV.resrec.name.c, SRS_PORT(srs), result);
+ LogMsg("%5d: DNSServiceRegistration(%##s, %u) Unknown Result %ld", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs), result);
}
mDNSlocal mStatus AddServiceInstance(DNSServiceRegistration *x, const domainname *domain)
{
if (!SameDomainLabel(si->name.c, m->nicelabel.c))
{
- debugf("NetworkChanged renaming %##s to %#s", si->srs.RR_SRV.resrec.name.c, m->nicelabel.c);
+ debugf("NetworkChanged renaming %##s to %#s", si->srs.RR_SRV.resrec.name->c, m->nicelabel.c);
si->autorename = mDNStrue;
if (mDNS_DeregisterService(m, &si->srs)) // If service deregistered already, we can re-register immediately
RegCallback(m, &si->srs, mStatus_MemFree);
}
else if (result == mStatus_GrowCache)
{
- // If we've run out of cache space, then double the total cache size and give the memory to mDNSCore
- mDNSu32 numrecords = m->rrcache_size;
- CacheRecord *storage = mallocL("mStatus_GrowCache", sizeof(CacheRecord) * numrecords);
- if (storage) mDNS_GrowCache(m, storage, numrecords);
+ // Allocate another chunk of cache storage
+ CacheEntity *storage = mallocL("mStatus_GrowCache", sizeof(CacheEntity) * RR_CACHE_SIZE);
+ if (storage) mDNS_GrowCache(m, storage, RR_CACHE_SIZE);
}
}
// Do the operation
LogOperation("%5d: DNSServiceRegistrationAddRecord(%##s, type %d, length %d) REF %p",
- client, si->srs.RR_SRV.resrec.name.c, type, data_len, extra);
+ client, si->srs.RR_SRV.resrec.name->c, type, data_len, extra);
err = mDNS_AddRecordToService(&mDNSStorage, &si->srs, extra, &extra->r.rdatastorage, ttl);
if (err)
const char *errormsg = "Unknown";
domainname *name = (domainname *)"";
- name = &srs->RR_SRV.resrec.name;
+ name = srs->RR_SRV.resrec.name;
unsigned int size = sizeof(RDataBody);
if (size < data_len)
// Do the operation
LogOperation("%5d: DNSServiceRegistrationUpdateRecord(%##s, new length %d)",
- client, srs->RR_SRV.resrec.name.c, data_len);
+ client, srs->RR_SRV.resrec.name->c, data_len);
err = mDNS_Update(&mDNSStorage, rr, ttl, data_len, newrdata, UpdateCallback);
if (err)
mDNSlocal mStatus RemoveRecord(ServiceRecordSet *srs, ExtraResourceRecord *extra, mach_port_t client)
{
- domainname *name = &srs->RR_SRV.resrec.name;
+ domainname *name = srs->RR_SRV.resrec.name;
mStatus err = mStatus_NoError;
// Do the operation
- LogOperation("%5d: DNSServiceRegistrationRemoveRecord(%##s)", client, srs->RR_SRV.resrec.name.c);
+ LogOperation("%5d: DNSServiceRegistrationRemoveRecord(%##s)", client, srs->RR_SRV.resrec.name->c);
err = mDNS_RemoveRecordFromService(&mDNSStorage, srs, extra, FreeExtraRR, extra);
if (err) LogMsg("%5d: DNSServiceRegistrationRemoveRecord (%##s) failed: %d", client, name->c, err);
mDNSlocal void ExitCallback(int signal)
{
-#if 0
- CacheRecord *rr;
- int rrcache_active = 0;
- for (rr = mDNSStorage.rrcache; rr; rr=rr->next) if (CacheRRActive(&mDNSStorage, rr)) rrcache_active++;
- debugf("ExitCallback: RR Cache now using %d records, %d active", mDNSStorage.rrcache_used, rrcache_active);
-#endif
-
LogMsgIdent(mDNSResponderVersionString, "stopping");
- debugf("ExitCallback: destroyBootstrapService");
- if (!mDNS_DebugMode && signal != SIGHUP)
+ debugf("ExitCallback");
+ if (!mDNS_DebugMode && !started_via_launchdaemon && signal != SIGHUP)
destroyBootstrapService();
debugf("ExitCallback: Aborting MIG clients");
mDNSlocal void INFOCallback(void)
{
+ mDNSs32 utc = mDNSPlatformUTC();
DNSServiceDomainEnumeration *e;
DNSServiceBrowser *b;
DNSServiceResolver *l;
NetworkInterfaceInfoOSX *i;
LogMsgIdent(mDNSResponderVersionString, "---- BEGIN STATE LOG ----");
-
+
udsserver_info(&mDNSStorage);
for (e = DNSServiceDomainEnumerationList; e; e=e->next)
{
ServiceInstance *si;
for (si = r->regs; si; si = si->next)
- LogMsgNoIdent("%5d: Mach ServiceInstance %##s %u", si->ClientMachPort, si->srs.RR_SRV.resrec.name.c, mDNSVal16(si->srs.RR_SRV.resrec.rdata->u.srv.port));
+ LogMsgNoIdent("%5d: Mach ServiceInstance %##s %u", si->ClientMachPort, si->srs.RR_SRV.resrec.name->c, mDNSVal16(si->srs.RR_SRV.resrec.rdata->u.srv.port));
}
for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
{
if (!i->Exists)
- LogMsgNoIdent("Interface: %s %5s(%lu) %.6a DORMANT",
- i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifa_name, i->scope_id, &i->BSSID);
+ LogMsgNoIdent("Interface: %s %5s(%lu) %.6a DORMANT %d",
+ i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifa_name, i->scope_id, &i->BSSID, utc - i->LastSeen);
else
LogMsgNoIdent("Interface: %s %5s(%lu) %.6a %s %s %2d %s %2d InterfaceID %p %s %s %#a",
i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifa_name, i->scope_id, &i->BSSID,
CFRelease(s_rls);
CFRelease(i_rls);
if (mDNS_DebugMode) printf("Service registered with Mach Port %d\n", m_port);
- err = udsserver_init();
- if (err) { LogMsg("Daemon start: udsserver_init failed"); return err; }
return(err);
}
mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
{
- // 1. Call mDNS_Execute() to let mDNSCore do what it needs to do
+ mDNSs32 now = mDNS_TimeNow(m);
+
+ // 1. If we have network change events to handle, do them FIRST, before calling mDNS_Execute()
+ // Detailed reason:
+ // mDNSMacOSXNetworkChanged() currently closes and re-opens its sockets. If there are received packets waiting, they are lost.
+ // mDNS_Execute() generates packets, including multicasts that are looped back to ourself.
+ // If we call mDNS_Execute() first, and generate packets, and then call mDNSMacOSXNetworkChanged() immediately afterwards
+ // we then systematically lose our own looped-back packets.
+ if (m->p->NetworkChanged && now - m->p->NetworkChanged >= 0) { m->p->NetworkChanged = 0; mDNSMacOSXNetworkChanged(m); }
+
+ // 2. Call mDNS_Execute() to let mDNSCore do what it needs to do
mDNSs32 nextevent = mDNS_Execute(m);
- mDNSs32 now = mDNS_TimeNow(m);
+ if (m->p->NetworkChanged)
+ if (nextevent - m->p->NetworkChanged > 0)
+ nextevent = m->p->NetworkChanged;
- // 2. Deliver any waiting browse messages to clients
+ // 3. Deliver any waiting browse messages to clients
DNSServiceBrowser *b = DNSServiceBrowserList;
while (b)
nextevent = m->p->NotifyUser;
}
- if (m->p->NetworkChanged)
- {
- if (m->p->NetworkChanged - now < 0)
- {
- m->p->NetworkChanged = 0;
- mDNSMacOSXNetworkChanged(m);
- }
- else
- if (nextevent - m->p->NetworkChanged > 0)
- nextevent = m->p->NetworkChanged;
- }
-
return(nextevent);
}
+mDNSlocal void ShowTaskSchedulingError(mDNS *const m)
+ {
+ mDNS_Lock(m);
+
+ LogMsg("Task Scheduling Error: Continuously busy for more than a second");
+
+ if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0))
+ LogMsg("Task Scheduling Error: NewQuestion %##s (%s)",
+ m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
+ if (m->NewLocalOnlyQuestions)
+ LogMsg("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)",
+ m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
+ if (m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords))
+ LogMsg("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, m->NewLocalRecords));
+ if (m->SuppressSending && m->timenow - m->SuppressSending >= 0)
+ LogMsg("Task Scheduling Error: m->SuppressSending %d", m->timenow - m->SuppressSending);
+#ifndef UNICAST_DISABLED
+ if (m->timenow - m->uDNS_info.nextevent >= 0)
+ LogMsg("Task Scheduling Error: m->uDNS_info.nextevent %d", m->timenow - m->uDNS_info.nextevent);
+#endif
+ if (m->timenow - m->NextCacheCheck >= 0)
+ LogMsg("Task Scheduling Error: m->NextCacheCheck %d", m->timenow - m->NextCacheCheck);
+ if (m->timenow - m->NextScheduledQuery >= 0)
+ LogMsg("Task Scheduling Error: m->NextScheduledQuery %d", m->timenow - m->NextScheduledQuery);
+ if (m->timenow - m->NextScheduledProbe >= 0)
+ LogMsg("Task Scheduling Error: m->NextScheduledProbe %d", m->timenow - m->NextScheduledProbe);
+ if (m->timenow - m->NextScheduledResponse >= 0)
+ LogMsg("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse);
+
+ mDNS_Unlock(&mDNSStorage);
+ }
+
mDNSexport int main(int argc, char **argv)
{
int i;
for (i=1; i<argc; i++)
{
if (!strcmp(argv[i], "-d")) mDNS_DebugMode = mDNStrue;
+ if (!strcmp(argv[i], "-launchdaemon")) started_via_launchdaemon = mDNStrue;
}
signal(SIGHUP, HandleSIG); // (Debugging) Exit cleanly and let mach_init restart us (for debugging)
signal(SIGUSR1, HandleSIG); // (Debugging) Simulate network change notification from System Configuration Framework
// Register the server with mach_init for automatic restart only during normal (non-debug) mode
- if (!mDNS_DebugMode) registerBootstrapService();
-
- if (!mDNS_DebugMode && !restarting_via_mach_init)
- exit(0); /* mach_init will restart us immediately as a daemon */
-
- if (!mDNS_DebugMode)
- {
+ if (!mDNS_DebugMode && !started_via_launchdaemon)
+ {
+ registerBootstrapService();
+ if (!restarting_via_mach_init) exit(0); // mach_init will restart us immediately as a daemon
int fd = open(_PATH_DEVNULL, O_RDWR, 0);
if (fd < 0) LogMsg("open(_PATH_DEVNULL, O_RDWR, 0) failed errno %d (%s)", errno, strerror(errno));
else
}
}
+ // Make our PID file and Unix Domain Socket first, because launchd waits for those before it starts launching other daemons.
+ // The sooner we do this, the faster the machine will boot.
+ status = udsserver_init();
+ if (status) { LogMsg("Daemon start: udsserver_init failed"); return(status); }
+
// First do the all the initialization we need root privilege for, before we change to user "nobody"
LogMsgIdent(mDNSResponderVersionString, "starting");
status = mDNSDaemonInitialize();
if (status == 0)
{
- LogMsg("Starting time value 0x%08lX (%ld)", (mDNSu32)mDNSStorage.timenow_last, mDNSStorage.timenow_last);
+ LogOperation("Starting time value 0x%08lX (%ld)", (mDNSu32)mDNSStorage.timenow_last, mDNSStorage.timenow_last);
int numevents = 0;
int RunLoopStatus = kCFRunLoopRunTimedOut;
else
{
ticks = 1;
- if (++RepeatedBusy >= mDNSPlatformOneSecond * 10)
- { LogMsg("Task Scheduling Error: Continuously busy for the last ten seconds"); RepeatedBusy = 0; }
+ if (++RepeatedBusy >= mDNSPlatformOneSecond) { ShowTaskSchedulingError(&mDNSStorage); RepeatedBusy = 0; }
}
CFAbsoluteTime interval = (CFAbsoluteTime)ticks / (CFAbsoluteTime)mDNSPlatformOneSecond;
mDNS_Close(&mDNSStorage);
}
- if (!mDNS_DebugMode) destroyBootstrapService();
+ if (!mDNS_DebugMode && !started_via_launchdaemon) destroyBootstrapService();
+ LogMsgIdent(mDNSResponderVersionString, "exiting");
return(status);
}
{
if (newSource->cfs)
{
- CFSocketInvalidate(newSource->cfs); // automatically closes socket
+ CFSocketInvalidate(newSource->cfs); // Note: Also closes the underlying socket
CFRelease(newSource->cfs);
}
return mStatus_NoMemoryErr;
return mStatus_NoError;
}
-mStatus udsSupportRemoveFDFromEventLoop(int fd)
+mStatus udsSupportRemoveFDFromEventLoop(int fd) // Note: This also CLOSES the file descriptor
// Reverse what was done in udsSupportAddFDToEventLoop().
{
CFSocketEventSource *iSource;
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), iSource->RLS, kCFRunLoopDefaultMode);
CFRunLoopSourceInvalidate(iSource->RLS);
CFRelease(iSource->RLS);
- CFSocketInvalidate(iSource->cfs);
+ CFSocketInvalidate(iSource->cfs); // Note: Also closes the underlying socket
CFRelease(iSource->cfs);
free(iSource);
return mStatus_NoError;
Change History (most recent first):
$Log: mDNSMacOSX.c,v $
+Revision 1.294 2005/01/27 21:30:23 cheshire
+<rdar://problem/3952067> "Can't assign requested address" message after AirPort turned off
+Don't write syslog messages for EADDRNOTAVAIL if we know network configuration changes are happening
+
+Revision 1.293 2005/01/27 19:15:41 cheshire
+Remove extraneous LogMsg() call
+
+Revision 1.292 2005/01/27 17:48:38 cheshire
+Added comment about CFSocketInvalidate closing the underlying socket
+
+Revision 1.291 2005/01/27 00:10:58 cheshire
+<rdar://problem/3967867> Name change log messages every time machine boots
+
+Revision 1.290 2005/01/25 23:18:30 ksekar
+fix for <rdar://problem/3971467> requires that local-only ".local" registration record be created
+
+Revision 1.289 2005/01/25 18:08:31 ksekar
+Removed redundant debug output
+
+Revision 1.288 2005/01/25 17:42:26 ksekar
+Renamed FoundDefBrowseDomain -> FoundLegacyBrowseDomain,
+cleaned up duplicate log messages when adding/removing browse domains
+
+Revision 1.287 2005/01/25 16:59:23 ksekar
+<rdar://problem/3971138> sa_len not set checking reachability for TCP connections
+
+Revision 1.286 2005/01/25 02:02:37 cheshire
+<rdar://problem/3970673> mDNSResponder leaks
+GetSearchDomains() was not calling dns_configuration_free().
+
+Revision 1.285 2005/01/22 00:07:54 ksekar
+<rdar://problem/3960546> mDNSResponder should look at all browse domains in SCPreferences
+
+Revision 1.284 2005/01/21 23:07:17 ksekar
+<rdar://problem/3960795> mDNSResponder causes Dial on Demand
+
+Revision 1.283 2005/01/19 21:16:16 cheshire
+Make sure when we set NetworkChanged that we don't set it to zero
+
+Revision 1.282 2005/01/19 19:19:21 ksekar
+<rdar://problem/3960191> Need a way to turn off domain discovery
+
+Revision 1.281 2005/01/18 18:10:55 ksekar
+<rdar://problem/3954575> Use 10.4 resolver API to get search domains
+
+Revision 1.280 2005/01/17 22:48:52 ksekar
+No longer need to call MarkSearchListElem for registration domain
+
+Revision 1.279 2005/01/17 20:40:34 ksekar
+SCPreferences changes should remove exactly one browse and one legacy browse domain for each remove event
+
+Revision 1.278 2005/01/17 19:53:34 ksekar
+Refinement to previous fix - register _legacy._browse records for SCPreference domains to achieve correct reference counting
+
+Revision 1.277 2005/01/12 00:17:50 ksekar
+<rdar://problem/3933573> Update LLQs *after* setting DNS
+
+Revision 1.276 2005/01/10 17:39:10 ksekar
+Refinement to 1.272 - avoid spurious warnings when registration and browse domains are set to same value and toggled on/off
+
+Revision 1.275 2005/01/10 04:02:22 ksekar
+Refinement to <rdar://problem/3891628> - strip trailing dot before writing hostname status to dynamic store
+
+Revision 1.274 2005/01/10 03:41:36 ksekar
+Correction to checkin 1.272 - check that registration domain is set
+before trying to remove it as an implicit browse domain
+
+Revision 1.273 2005/01/08 00:42:18 ksekar
+<rdar://problem/3922758> Clean up syslog messages
+
+Revision 1.272 2005/01/07 23:21:42 ksekar
+<rdar://problem/3891628> Clean up SCPreferences format
+
+Revision 1.271 2004/12/20 23:18:12 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+One more refinement: When an interface with a v6LL address gets a v4 address too, that's not a flap
+
+Revision 1.270 2004/12/20 21:28:14 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+Additional refinements to handle sleep/wake better
+
+Revision 1.269 2004/12/20 20:48:11 cheshire
+Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xxx) or later
+
+Revision 1.268 2004/12/18 03:19:04 cheshire
+Show netmask in error log
+
+Revision 1.267 2004/12/18 00:51:52 cheshire
+Use symbolic constant kDNSServiceInterfaceIndexLocalOnly instead of (mDNSu32) ~0
+
+Revision 1.266 2004/12/17 23:49:38 cheshire
+<rdar://problem/3922754> Computer Name change is slow
+Also treat changes to "Setup:/Network/DynamicDNS" the same way
+
+Revision 1.265 2004/12/17 23:37:47 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+(and other repetitive configuration changes)
+
+Revision 1.264 2004/12/17 19:03:05 cheshire
+Update debugging messages to show netmask a simple CIDR-style numeric value (0-128)
+
+Revision 1.263 2004/12/17 05:25:46 cheshire
+<rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
+
+Revision 1.262 2004/12/17 04:48:32 cheshire
+<rdar://problem/3922754> Computer Name change is slow
+
+Revision 1.261 2004/12/17 02:40:08 cheshire
+Undo last change -- it was too strict
+
+Revision 1.260 2004/12/16 22:17:16 cheshire
+Only accept multicast packets on interfaces that have McastTxRx set
+
+Revision 1.259 2004/12/16 20:13:01 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.258 2004/12/14 00:18:05 cheshire
Don't log dns_configuration_copy() failures in the first three minutes after boot
static ARListElem *SCPrefBrowseDomains = NULL; // manually generated local-only PTR records for browse domains we get from SCPreferences
static domainname DynDNSRegDomain; // Default wide-area zone for service registration
-static domainname DynDNSBrowseDomain; // Default wide-area zone for legacy ("empty string") browses
+static CFArrayRef DynDNSBrowseDomains = NULL; // Default wide-area zones for legacy ("empty string") browses
static domainname DynDNSHostname;
+static mDNSBool DomainDiscoveryDisabled = mDNSfalse;
+
#define CONFIG_FILE "/etc/mDNSResponder.conf"
#define DYNDNS_KEYCHAIN_SERVICE "DynDNS Shared Secret"
#define SYS_KEYCHAIN_PATH "/Library/Keychains/System.keychain"
newelem = mallocL("DNameListElem", sizeof(*newelem));
if (!newelem) { LogMsg("Error - malloc"); return; }
- AssignDomainName(newelem->name, *d);
+ AssignDomainName(&newelem->name, d);
newelem->next = DefRegList;
DefRegList = newelem;
mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index)
{
NetworkInterfaceInfoOSX *i;
- if (index == (uint32_t)~0) return(mDNSInterface_LocalOnly);
+ if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
if (index)
for (i = m->p->InterfaceList; i; i = i->next)
// Don't get tricked by inactive interfaces with no InterfaceID set
mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(const mDNS *const m, mDNSInterfaceID id)
{
NetworkInterfaceInfoOSX *i;
- if (id == mDNSInterface_LocalOnly) return((mDNSu32)~0);
+ if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
if (id)
for (i = m->p->InterfaceList; i; i = i->next)
// Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces, which have no InterfaceID set
return 0;
}
+mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr)
+ {
+ mDNSBool result = mDNSfalse;
+ SCNetworkConnectionFlags flags;
+ SCNetworkReachabilityRef ReachRef = NULL;
+
+ ReachRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, addr);
+ if (!ReachRef) { LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithAddress"); goto end; }
+ if (!SCNetworkReachabilityGetFlags(ReachRef, &flags)) { LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); goto end; }
+ result = flags & kSCNetworkFlagsConnectionRequired;
+
+ end:
+ if (ReachRef) CFRelease(ReachRef);
+ return result;
+ }
+
// NOTE: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
// NOTE: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
// OR send via our primary v4 unicast socket
if ((m->h.flags.b[0] & kDNSFlag0_QR_Mask) == kDNSFlag0_QR_Query)
LogMsg("mDNSPlatformSendUDP: ERROR: Sending query OP from mDNS port to non-mDNS destination %#a:%d", dst, mDNSVal16(dstPort));
}
-
+
if (dst->type == mDNSAddrType_IPv4)
{
struct sockaddr_in *sin_to = (struct sockaddr_in*)&to;
return mStatus_BadParamErr;
}
+ // Don't send if it would cause dial on demand connection initiation. As an optimization,
+ // don't bother consulting reachability API / routing table when sending Multicast DNS
+ // since we ignore PPP interfaces for mDNS traffic
+ if (!mDNSAddrIsDNSMulticast(dst) && AddrRequiresPPPConnection((struct sockaddr *)&to))
+ {
+ debugf("mDNSPlatformSendUDP: Surpressing sending to avoid dial-on-demand connection");
+ return mStatus_NoError;
+ }
+
if (s >= 0)
verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s);
// This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
// but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(err);
+ // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
+ if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(err);
LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %5s/%ld to %#a:%d skt %d error %d errno %d (%s) %lu",
InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
return(err);
// 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 option to find the name of the interface
// on which the packet arrived, and ignore the packet if it really arrived on some other interface.
- if (!ss->info)
+ if (!ss->info || !ss->info->Exists)
{
verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on unicast socket (Ignored)", &senderAddr, &destAddr);
return;
return mStatus_UnknownErr;
}
+ bzero(&saddr, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = dstport.NotAnInteger;
+ saddr.sin_len = sizeof(saddr);
+ memcpy(&saddr.sin_addr, &dst->ip.v4.NotAnInteger, sizeof(saddr.sin_addr));
+
+ // Don't send if it would cause dial on demand connection initiation.
+ if (AddrRequiresPPPConnection((struct sockaddr *)&saddr))
+ {
+ debugf("mDNSPlatformTCPConnect: Surpressing sending to avoid dial-on-demand connection");
+ return mStatus_UnknownErr;
+ }
+
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 3) { LogMsg("mDNSPlatformTCPConnect: socket error %d errno %d (%s)", sd, errno, strerror(errno)); return mStatus_UnknownErr; }
CFRelease(rls);
// initiate connection wth peer
- bzero(&saddr, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_port = dstport.NotAnInteger;
- memcpy(&saddr.sin_addr, &dst->ip.v4.NotAnInteger, sizeof(saddr.sin_addr));
if (connect(sd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
{
if (errno == EINPROGRESS)
}
LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: %s", strerror(errno));
freeL("mDNSPlatformTCPConnect", info);
- CFSocketInvalidate(sr);
+ CFSocketInvalidate(sr); // Note: Also closes the underlying socket
return mStatus_ConnFailed;
}
info->connected = 1;
}
}
-mDNSlocal void GetUserSpecifiedDDNSConfig(domainname *const fqdn, domainname *const regDomain, domainname *const browseDomain)
+mDNSlocal mDNSBool DDNSSettingEnabled(CFDictionaryRef dict)
+ {
+ mDNSs32 val;
+ CFNumberRef state = CFDictionaryGetValue(dict, CFSTR("Enabled"));
+ if (!state) return mDNSfalse;
+ if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val)) { LogMsg("ERROR: DDNSSettingEnabled - CFNumberGetValue"); return mDNSfalse; }
+ return val ? mDNStrue : mDNSfalse;
+ }
+
+mDNSlocal void GetUserSpecifiedDDNSConfig(domainname *const fqdn, domainname *const regDomain, CFArrayRef *const browseDomains)
{
char buf[MAX_ESCAPED_DOMAIN_NAME];
fqdn->c[0] = 0;
regDomain->c[0] = 0;
- browseDomain->c[0] = 0;
buf[0] = 0;
+ *browseDomains = NULL;
SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetUserSpecifiedDDNSConfig"), NULL, NULL);
if (store)
CFDictionaryRef dict = SCDynamicStoreCopyValue(store, CFSTR("Setup:/Network/DynamicDNS"));
if (dict)
{
- CFArrayRef fqdnArray = CFDictionaryGetValue(dict, CFSTR("FQDN"));
- CFArrayRef regArray = CFDictionaryGetValue(dict, CFSTR("DefaultRegistrationDomain"));
- CFArrayRef browseArray = CFDictionaryGetValue(dict, CFSTR("DefaultBrowseDomain"));
+ CFArrayRef fqdnArray = CFDictionaryGetValue(dict, CFSTR("HostNames"));
if (fqdnArray)
- {
- CFStringRef name = CFArrayGetValueAtIndex(fqdnArray, 0);
- if (name)
- {
- if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
- !MakeDomainNameFromDNSNameString(fqdn, buf) || !fqdn->c[0])
- LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf[0] ? buf : "(unknown)");
- else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf);
+ {
+ CFDictionaryRef fqdnDict = CFArrayGetValueAtIndex(fqdnArray, 0); // for now, we only look at the first array element. if we ever support multiple configurations, we will walk the list
+ if (fqdnDict && DDNSSettingEnabled(fqdnDict))
+ {
+ CFStringRef name = CFDictionaryGetValue(fqdnDict, CFSTR("Domain"));
+ if (name)
+ {
+ if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
+ !MakeDomainNameFromDNSNameString(fqdn, buf) || !fqdn->c[0])
+ LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf[0] ? buf : "(unknown)");
+ else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf);
+ }
}
- }
+ }
+
+ CFArrayRef regArray = CFDictionaryGetValue(dict, CFSTR("RegistrationDomains"));
if (regArray)
{
- CFStringRef name = CFArrayGetValueAtIndex(regArray, 0);
- if (name)
+ CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
+ if (regDict && DDNSSettingEnabled(regDict))
{
- if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
- !MakeDomainNameFromDNSNameString(regDomain, buf) || !regDomain->c[0])
- LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf[0] ? buf : "(unknown)");
- else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration zone: %s", buf);
+ CFStringRef name = CFDictionaryGetValue(regDict, CFSTR("Domain"));
+ if (name)
+ {
+ if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
+ !MakeDomainNameFromDNSNameString(regDomain, buf) || !regDomain->c[0])
+ LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf[0] ? buf : "(unknown)");
+ else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration zone: %s", buf);
+ }
}
}
+ CFArrayRef browseArray = CFDictionaryGetValue(dict, CFSTR("BrowseDomains"));
if (browseArray)
{
- CFStringRef name = CFArrayGetValueAtIndex(browseArray, 0);
- if (name)
- {
- if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
- !MakeDomainNameFromDNSNameString(browseDomain, buf) || !browseDomain->c[0])
- LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS browse domain: %s", buf[0] ? buf : "(unknown)");
- else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS browse zone: %s", buf);
- }
- }
+ CFRetain(browseArray);
+ *browseDomains = browseArray;
+ }
CFRelease(dict);
}
CFRelease(store);
char uname[MAX_ESCAPED_DOMAIN_NAME];
ConvertDomainNameToCString(dname, uname);
char *p = uname;
- while (*p) { *p = tolower(*p); p++; }
- const void *n1 = CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8); // CFStringRef
- const void *v1 = CFNumberCreate(NULL, kCFNumberSInt32Type, &status); // CFNumberRef
- const void *n2 = CFSTR("FQDN"); // CFStringRef
- const void *v2 = CFDictionaryCreate(NULL, &n1, &v1, 1, NULL, NULL); // CFDictionaryRef
- CFDictionaryRef dict = CFDictionaryCreate(NULL, &n2, &v2, 1, NULL, NULL);
- SCDynamicStoreSetValue(store, CFSTR("State:/Network/DynamicDNS"), dict);
- CFRelease(dict);
- CFRelease(v2);
- CFRelease(n2);
- CFRelease(v1);
- CFRelease(n1);
+
+ while (*p)
+ {
+ *p = tolower(*p);
+ if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
+ p++;
+ }
+
+ const void *StatusKey = CFSTR("Status");
+ const void *StatusVal = CFNumberCreate(NULL, kCFNumberSInt32Type, &status); // CFNumberRef
+ const void *StatusDict = CFDictionaryCreate(NULL, &StatusKey, &StatusVal, 1, NULL, NULL);
+
+ const void *HostKey = CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8);
+ const void *HostDict = CFDictionaryCreate(NULL, &HostKey, &StatusDict, 1, NULL, NULL);
+
+ const void *StateKey = CFSTR("HostNames"); // CFStringRef
+ CFDictionaryRef StateDict = CFDictionaryCreate(NULL, &StateKey, &HostDict, 1, NULL, NULL);
+ SCDynamicStoreSetValue(store, CFSTR("State:/Network/DynamicDNS"), StateDict);
+
+ CFRelease(StateDict);
+ CFRelease(StateKey);
+ CFRelease(HostDict);
+ CFRelease(HostKey);
+ CFRelease(StatusDict);
+ CFRelease(StatusVal);
+ CFRelease(StatusKey);
CFRelease(store);
}
}
return(eth);
}
-mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa)
+mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa, mDNSs32 utc)
{
mDNSu32 scope_id = if_nametoindex(ifa->ifa_name);
mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
i->next = mDNSNULL;
i->Exists = mDNStrue;
+ i->LastSeen = utc;
i->scope_id = scope_id;
i->BSSID = bssid;
i->sa_family = ifa->ifa_addr->sa_family;
return(mDNSNULL);
}
-mDNSlocal mStatus UpdateInterfaceList(mDNS *const m)
+mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
{
mDNSBool foundav4 = mDNSfalse;
mDNSBool foundav6 = mDNSfalse;
{
#if LIST_ALL_INTERFACES
if (ifa->ifa_addr->sa_family == AF_APPLETALK)
- debugf("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
else if (ifa->ifa_addr->sa_family == AF_LINK)
- debugf("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
else if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)
- debugf("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
if (!(ifa->ifa_flags & IFF_UP))
- debugf("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
if (!(ifa->ifa_flags & IFF_MULTICAST))
- debugf("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
if (ifa->ifa_flags & IFF_POINTOPOINT)
- debugf("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
if (ifa->ifa_flags & IFF_LOOPBACK)
- debugf("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
#endif
else v6Loopback = ifa;
else
{
- AddInterfaceToList(m, ifa);
+ AddInterfaceToList(m, ifa, utc);
if (ifa->ifa_addr->sa_family == AF_INET) foundav4 = mDNStrue;
else foundav6 = mDNStrue;
}
}
// For efficiency, we don't register a loopback interface when other interfaces of that family are available
- if (!foundav4 && v4Loopback) AddInterfaceToList(m, v4Loopback);
- if (!foundav6 && v6Loopback) AddInterfaceToList(m, v6Loopback);
+ if (!foundav4 && v4Loopback) AddInterfaceToList(m, v4Loopback, utc);
+ if (!foundav6 && v6Loopback) AddInterfaceToList(m, v6Loopback, utc);
// Now the list is complete, set the McastTxRx setting for each interface.
// We always send and receive using IPv4.
domainlabel nicelabel;
nicelabel.c[0] = 0;
GetUserSpecifiedFriendlyComputerName(&nicelabel);
- if (nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&nicelabel, defaultname);
+ if (nicelabel.c[0] == 0)
+ {
+ LogMsg("Couldn't read user-specified Computer Name; using default “%s” instead", defaultname);
+ MakeDomainLabelFromLiteralString(&nicelabel, defaultname);
+ }
// Set up the RFC 1034-compliant label
domainlabel hostlabel;
hostlabel.c[0] = 0;
GetUserSpecifiedLocalHostName(&hostlabel);
- if (hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&hostlabel, defaultname);
+ if (hostlabel.c[0] == 0)
+ {
+ LogMsg("Couldn't read user-specified local hostname; using default “%s.local” instead", defaultname);
+ MakeDomainLabelFromLiteralString(&hostlabel, defaultname);
+ }
if (SameDomainLabel(m->p->usernicelabel.c, nicelabel.c))
debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m->p->usernicelabel.c, m->nicelabel.c);
return(mStatus_NoError);
}
+mDNSlocal int CountMaskBits(mDNSAddr *mask)
+ {
+ int i = 0, bits = 0;
+ int bytes = mask->type == mDNSAddrType_IPv4 ? 4 : mask->type == mDNSAddrType_IPv6 ? 16 : 0;
+ while (i < bytes)
+ {
+ mDNSu8 b = mask->ip.v6.b[i++];
+ while (b & 0x80) { bits++; b <<= 1; }
+ if (b) return(-1);
+ }
+ while (i < bytes) if (mask->ip.v6.b[i++]) return(-1);
+ return(bits);
+ }
+
// returns count of non-link local V4 addresses registered
-mDNSlocal int SetupActiveInterfaces(mDNS *const m)
+mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
{
NetworkInterfaceInfoOSX *i;
int count = 0;
// so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
// If n->InterfaceID is NOT set, then we haven't registered it and we should not try to deregister it
n->InterfaceID = (mDNSInterfaceID)primary;
- mDNS_RegisterInterface(m, n);
+ // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
+ // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
+ // If the interface is an old one that went away and came back in less than a minute, then we're in a flapping scenario.
+ mDNSBool flapping = (utc - i->LastSeen > 0 && utc - i->LastSeen < 60);
+ mDNS_RegisterInterface(m, n, flapping ? mDNSPlatformOneSecond * 5 : 0);
if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && (i->ifinfo.ip.ip.v4.b[0] != 169 || i->ifinfo.ip.ip.v4.b[1] != 254)) count++;
- LogOperation("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p %#a/%#a%s",
- i->ifa_name, i->scope_id, &i->BSSID, primary, &n->ip, &n->mask, n->InterfaceActive ? " (Primary)" : "");
+ LogOperation("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s",
+ i->ifa_name, i->scope_id, &i->BSSID, primary, &n->ip, CountMaskBits(&n->mask),
+ flapping ? " (Flapping)" : "", n->InterfaceActive ? " (Primary)" : "");
}
if (!n->McastTxRx)
if (i->sa_family == AF_INET && primary->ss.sktv4 == -1)
{
mStatus err = SetupSocket(m, &primary->ss, mDNStrue, &i->ifinfo.ip, AF_INET);
- if (err == 0) debugf("SetupActiveInterfaces: v4 socket%2d %5s(%lu) %.6a InterfaceID %p %#a", primary->ss.sktv4, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip);
- else LogMsg("SetupActiveInterfaces: v4 socket%2d %5s(%lu) %.6a InterfaceID %p %#a FAILED", primary->ss.sktv4, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip);
+ if (err == 0) debugf("SetupActiveInterfaces: v4 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d", primary->ss.sktv4, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip, CountMaskBits(&n->mask));
+ else LogMsg("SetupActiveInterfaces: v4 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d FAILED", primary->ss.sktv4, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip, CountMaskBits(&n->mask));
}
if (i->sa_family == AF_INET6 && primary->ss.sktv6 == -1)
{
mStatus err = SetupSocket(m, &primary->ss, mDNStrue, &i->ifinfo.ip, AF_INET6);
- if (err == 0) debugf("SetupActiveInterfaces: v6 socket%2d %5s(%lu) %.6a InterfaceID %p %#a", primary->ss.sktv6, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip);
- else LogMsg("SetupActiveInterfaces: v6 socket%2d %5s(%lu) %.6a InterfaceID %p %#a FAILED", primary->ss.sktv6, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip);
+ if (err == 0) debugf("SetupActiveInterfaces: v6 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d", primary->ss.sktv6, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip, CountMaskBits(&n->mask));
+ else LogMsg("SetupActiveInterfaces: v6 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d FAILED", primary->ss.sktv6, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip, CountMaskBits(&n->mask));
}
}
}
return count;
}
-mDNSlocal void MarkAllInterfacesInactive(mDNS *const m)
+mDNSlocal void MarkAllInterfacesInactive(mDNS *const m, mDNSs32 utc)
{
NetworkInterfaceInfoOSX *i;
for (i = m->p->InterfaceList; i; i = i->next)
+ {
+ if (i->Exists) i->LastSeen = utc;
i->Exists = mDNSfalse;
+ }
}
mDNSlocal void CloseRunLoopSourceSocket(CFRunLoopSourceRef rls, CFSocketRef cfs)
{
+ // Note: CFSocketInvalidate also closes the underlying socket for us
// Comments show retain counts (obtained via CFGetRetainCount()) after each call. rls 3 cfs 3
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); // rls 2 cfs 3
CFRelease(rls); // rls ? cfs 3
}
// returns count of non-link local V4 addresses deregistered
-mDNSlocal int ClearInactiveInterfaces(mDNS *const m)
+mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
{
// First pass:
// If an interface is going away, then deregister this from the mDNSCore.
if (i->ifinfo.InterfaceID)
if (i->Exists == 0 || i->Exists == 2 || i->ifinfo.InterfaceID != (mDNSInterfaceID)primary)
{
- LogOperation("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a%s",
- i->ifa_name, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, &i->ifinfo.ip, i->ifinfo.InterfaceActive ? " (Primary)" : "");
+ LogOperation("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s",
+ i->ifa_name, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID,
+ &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask), i->ifinfo.InterfaceActive ? " (Primary)" : "");
mDNS_DeregisterInterface(m, &i->ifinfo);
- if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && (i->ifinfo.ip.ip.v4.b[0] != 169 || i->ifinfo.ip.ip.v4.b[1] != 254)) count++;
+ if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && (i->ifinfo.ip.ip.v4.b[0] != 169 || i->ifinfo.ip.ip.v4.b[1] != 254)) count++;
i->ifinfo.InterfaceID = mDNSNULL;
// NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
// so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
// (We may have previously had both v4 and v6, and we may not need both any more.)
CloseSocketSet(&i->ss);
// 3. If no longer active, delete interface from list and free memory
- if (!i->Exists && NumCacheRecordsForInterfaceID(m, (mDNSInterfaceID)i) == 0)
+ if (!i->Exists)
{
- debugf("ClearInactiveInterfaces: Deleting %#a", &i->ifinfo.ip);
- *p = i->next;
- if (i->ifa_name) freeL("NetworkInterfaceInfoOSX name", i->ifa_name);
- freeL("NetworkInterfaceInfoOSX", i);
+ if (i->LastSeen == utc) i->LastSeen = utc - 1;
+ mDNSBool delete = (NumCacheRecordsForInterfaceID(m, (mDNSInterfaceID)i) == 0) && (utc - i->LastSeen >= 60);
+ LogOperation("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
+ i->ifa_name, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID,
+ &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask), utc - i->LastSeen,
+ i->ifinfo.InterfaceActive ? " (Primary)" : "");
+ if (delete)
+ {
+ *p = i->next;
+ if (i->ifa_name) freeL("NetworkInterfaceInfoOSX name", i->ifa_name);
+ freeL("NetworkInterfaceInfoOSX", i);
+ continue; // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
+ }
}
- else
- p = &i->next;
+ p = &i->next;
}
return count;
}
-mDNSlocal mStatus RegisterSplitDNS(mDNS *m)
+mDNSlocal mStatus GetDNSConfig(void **result)
{
#ifndef MAC_OS_X_VERSION_10_4
static int MessageShown = 0;
- (void)m;
if (!MessageShown) { MessageShown = 1; LogMsg("Note: Compiled without Apple-specific split DNS support"); }
- return mStatus_UnsupportedErr;
+ *result = NULL;
+ return mStatus_UnsupportedErr;
#else
- int i;
- dns_config_t *config = dns_configuration_copy();
- if (!config)
+ *result = dns_configuration_copy();
+
+ if (!*result)
{
// When running on 10.3 (build 7xxx) and earlier, we don't expect dns_configuration_copy() to succeed
if (mDNSMacOSXSystemBuildNumber(NULL) < 8) return mStatus_UnsupportedErr;
// Apparently this is expected behaviour -- "not a bug".
// Accordingly, we suppress syslog messages for the first three minutes after boot.
// If we are still getting failures after three minutes, then we log them.
- if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return mStatus_UnknownErr;
+ if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return mStatus_NoError;
- LogMsg("RegisterSplitDNS: Error: dns_configuration_copy returned NULL");
+ LogMsg("GetDNSConfig: Error: dns_configuration_copy returned NULL");
return mStatus_UnknownErr;
}
- mDNS_DeleteDNSServers(m);
+ return mStatus_NoError;
+#endif // MAC_OS_X_VERSION_10_4
+ }
- LogOperation("RegisterSplitDNS: Registering %d resolvers", config->n_resolver);
- for (i = 0; i < config->n_resolver; i++)
+mDNSlocal mStatus RegisterSplitDNS(mDNS *m)
+ {
+ (void)m; // unused on 10.3 systems
+ void *v;
+ mStatus err = GetDNSConfig(&v);
+ if (!err && v)
{
- int j, n;
- domainname d;
- dns_resolver_t *r = config->resolver[i];
- if (r->port == MulticastDNSPort.NotAnInteger) continue; // ignore configurations for .local
- if (r->search_order == DEFAULT_SEARCH_ORDER || !r->domain || !*r->domain) d.c[0] = 0; // we ignore domain for "default" resolver
- else if (!MakeDomainNameFromDNSNameString(&d, r->domain)) { LogMsg("RegisterSplitDNS: bad domain %s", r->domain); continue; }
-
- // check if this is the lowest-weighted server for the domain
- for (j = 0; j < config->n_resolver; j++)
+#ifdef MAC_OS_X_VERSION_10_4
+ int i;
+ dns_config_t *config = v; // use void * to allow compilation on 10.3 systems
+ mDNS_DeleteDNSServers(m);
+
+ LogOperation("RegisterSplitDNS: Registering %d resolvers", config->n_resolver);
+ for (i = 0; i < config->n_resolver; i++)
{
- dns_resolver_t *p = config->resolver[j];
- if (p->port == MulticastDNSPort.NotAnInteger) continue;
- if (p->search_order <= r->search_order)
+ int j, n;
+ domainname d;
+ dns_resolver_t *r = config->resolver[i];
+ if (r->port == MulticastDNSPort.NotAnInteger) continue; // ignore configurations for .local
+ if (r->search_order == DEFAULT_SEARCH_ORDER || !r->domain || !*r->domain) d.c[0] = 0; // we ignore domain for "default" resolver
+ else if (!MakeDomainNameFromDNSNameString(&d, r->domain)) { LogMsg("RegisterSplitDNS: bad domain %s", r->domain); continue; }
+
+ // check if this is the lowest-weighted server for the domain
+ for (j = 0; j < config->n_resolver; j++)
{
- domainname tmp;
- if (p->search_order == DEFAULT_SEARCH_ORDER || !p->domain || !*p->domain) tmp.c[0] = '\0';
- else if (!MakeDomainNameFromDNSNameString(&tmp, p->domain)) { LogMsg("RegisterSplitDNS: bad domain %s", p->domain); continue; }
- if (SameDomainName(&d, &tmp))
- if (p->search_order < r->search_order || j < i) break; // if equal weights, pick first in list, otherwise pick lower-weight (p)
+ dns_resolver_t *p = config->resolver[j];
+ if (p->port == MulticastDNSPort.NotAnInteger) continue;
+ if (p->search_order <= r->search_order)
+ {
+ domainname tmp;
+ if (p->search_order == DEFAULT_SEARCH_ORDER || !p->domain || !*p->domain) tmp.c[0] = '\0';
+ else if (!MakeDomainNameFromDNSNameString(&tmp, p->domain)) { LogMsg("RegisterSplitDNS: bad domain %s", p->domain); continue; }
+ if (SameDomainName(&d, &tmp))
+ if (p->search_order < r->search_order || j < i) break; // if equal weights, pick first in list, otherwise pick lower-weight (p)
+ }
}
- }
- if (j < config->n_resolver) // found a lower-weighted resolver for this domain
- { debugf("Rejecting DNS server in slot %d domain %##s (slot %d outranks)", i, d.c, j); continue; }
- // we're using this resolver - find the first IPv4 address
- for (n = 0; n < r->n_nameserver; n++)
- {
- if (r->nameserver[n]->sa_family == AF_INET)
+ if (j < config->n_resolver) // found a lower-weighted resolver for this domain
+ { debugf("Rejecting DNS server in slot %d domain %##s (slot %d outranks)", i, d.c, j); continue; }
+ // we're using this resolver - find the first IPv4 address
+ for (n = 0; n < r->n_nameserver; n++)
{
- mDNSAddr saddr;
- if (SetupAddr(&saddr, r->nameserver[n])) { LogMsg("RegisterSplitDNS: bad IP address"); continue; }
- debugf("Adding dns server from slot %d %d.%d.%d.%d for domain %##s", i, saddr.ip.v4.b[0], saddr.ip.v4.b[1], saddr.ip.v4.b[2], saddr.ip.v4.b[3], d.c);
- mDNS_AddDNSServer(m, &saddr, &d);
- break; // !!!KRS if we ever support round-robin servers, don't break here
+ if (r->nameserver[n]->sa_family == AF_INET && !AddrRequiresPPPConnection(r->nameserver[n]))
+ {
+ mDNSAddr saddr;
+ if (SetupAddr(&saddr, r->nameserver[n])) { LogMsg("RegisterSplitDNS: bad IP address"); continue; }
+ debugf("Adding dns server from slot %d %d.%d.%d.%d for domain %##s", i, saddr.ip.v4.b[0], saddr.ip.v4.b[1], saddr.ip.v4.b[2], saddr.ip.v4.b[3], d.c);
+ mDNS_AddDNSServer(m, &saddr, &d);
+ break; // !!!KRS if we ever support round-robin servers, don't break here
+ }
}
}
+ dns_configuration_free(config);
+#endif
}
- dns_configuration_free(config);
- return mStatus_NoError;
-#endif
+ return err;
}
mDNSlocal mStatus RegisterNameServers(mDNS *const m, CFDictionaryRef dict)
SearchListElem *slElem = question->QuestionContext;
ARListElem *arElem, *ptr, *prev;
AuthRecord *dereg;
- char *name;
+ const char *name;
mStatus err;
if (AddRecord)
arElem = mallocL("FoundDomain - arElem", sizeof(ARListElem));
if (!arElem) { LogMsg("ERROR: malloc"); return; }
mDNS_SetupResourceRecord(&arElem->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, arElem);
- if (question == &slElem->BrowseQ) name = "_browse._dns-sd._udp.local.";
- else if (question == &slElem->DefBrowseQ) name = "_default._browse._dns-sd._udp.local.";
- else if (question == &slElem->LegacyBrowseQ) name = "_legacy._browse._dns-sd._udp.local.";
- else if (question == &slElem->RegisterQ) name = "_register._dns-sd._udp.local.";
- else if (question == &slElem->DefRegisterQ) name = "_default._register._dns-sd._udp.local.";
+ if (question == &slElem->BrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowse];
+ else if (question == &slElem->DefBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseDefault];
+ else if (question == &slElem->LegacyBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseLegacy];
+ else if (question == &slElem->RegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistration];
+ else if (question == &slElem->DefRegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistrationDefault];
else { LogMsg("FoundDomain - unknown question"); return; }
- MakeDomainNameFromDNSNameString(&arElem->ar.resrec.name, name);
- AssignDomainName(arElem->ar.resrec.rdata->u.name, answer->rdata->u.name);
+ MakeDomainNameFromDNSNameString(arElem->ar.resrec.name, name);
+ AppendDNSNameString (arElem->ar.resrec.name, "local");
+ AssignDomainName(&arElem->ar.resrec.rdata->u.name, &answer->rdata->u.name);
err = mDNS_Register(m, &arElem->ar);
if (err)
{
{
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;
}
}
-mDNSlocal void MarkSearchListElem(domainname *domain)
+mDNSlocal void MarkSearchListElem(const char *d)
{
SearchListElem *new, *ptr;
+ domainname domain;
+ if (!MakeDomainNameFromDNSNameString(&domain, d))
+ { LogMsg("ERROR: MarkSearchListElem - bad domain %##s", d); return; }
+
+ if (SameDomainName(&domain, &localdomain) || SameDomainName(&domain, &LocalReverseMapomain))
+ { debugf("MarkSearchListElem - ignoring local domain %##s", domain.c); return; }
+
// if domain is in list, mark as pre-existent (0)
for (ptr = SearchList; ptr; ptr = ptr->next)
- if (SameDomainName(&ptr->domain, domain))
+ if (SameDomainName(&ptr->domain, &domain))
{
if (ptr->flag != 1) ptr->flag = 0; // gracefully handle duplicates - if it is already marked as add, don't bump down to preexistent
break;
new = mallocL("MarkSearchListElem - SearchListElem", sizeof(SearchListElem));
if (!new) { LogMsg("ERROR: MarkSearchListElem - malloc"); return; }
bzero(new, sizeof(SearchListElem));
- AssignDomainName(new->domain, *domain);
+ AssignDomainName(&new->domain, &domain);
new->flag = 1; // add
new->next = SearchList;
SearchList = new;
}
}
-mDNSlocal mStatus RegisterSearchDomains(mDNS *const m, CFDictionaryRef dict)
+// Get the search domains via OS X resolver routines. Returns mStatus_UnsupporterErr if compiled or run on 10.3 systems
+mDNSlocal mStatus GetSearchDomains(void)
{
- struct ifaddrs *ifa = NULL;
+ void *v;
+ mStatus err = GetDNSConfig(&v);
+ if (!err && v)
+ {
+#ifdef MAC_OS_X_VERSION_10_4
+ int i;
+ dns_config_t *config = v;
+ if (!config->n_resolver) return err;
+ dns_resolver_t *resolv = config->resolver[0]; // use the first slot for search domains
+
+ for (i = 0; i < resolv->n_search; i++) MarkSearchListElem(resolv->search[i]);
+ if (resolv->domain) MarkSearchListElem(resolv->domain);
+ dns_configuration_free(config);
+#endif
+ }
+ return err;
+ }
+
+// Get search domains from dynamic store - used as a fallback mechanism on 10.3 systems, if GetSearchDomains (above) fails.
+mDNSlocal void GetDSSearchDomains(CFDictionaryRef dict)
+ {
+ char buf[MAX_ESCAPED_DOMAIN_NAME];
int i, count;
- domainname domain;
- char buf[MAX_ESCAPED_DOMAIN_NAME];
+
CFStringRef s;
- SearchListElem *ptr, *prev, *freeSLPtr;
- ARListElem *arList;
- mStatus err;
-
- // step 1: mark each elem for removal (-1), unless we aren't passed a dictionary in which case we mark as preexistent
- for (ptr = SearchList; ptr; ptr = ptr->next) ptr->flag = dict ? -1 : 0;
// get all the domains from "Search Domains" field of sharing prefs
if (dict)
for (i = 0; i < count; i++)
{
s = CFArrayGetValueAtIndex(searchdomains, i);
- if (!s) { LogMsg("ERROR: RegisterSearchDomains - CFArrayGetValueAtIndex"); break; }
+ if (!s) { LogMsg("ERROR: GetDSSearchDomains - CFArrayGetValueAtIndex"); break; }
if (!CFStringGetCString(s, buf, MAX_ESCAPED_DOMAIN_NAME, kCFStringEncodingUTF8))
{
- LogMsg("ERROR: RegisterSearchDomains - CFStringGetCString");
+ LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
continue;
}
- if (!MakeDomainNameFromDNSNameString(&domain, buf))
- {
- LogMsg("ERROR: RegisterSearchDomains - invalid search domain %s", buf);
- continue;
- }
- MarkSearchListElem(&domain);
+ MarkSearchListElem(buf);
}
}
+
+ // get DHCP domain field
CFStringRef dname = CFDictionaryGetValue(dict, kSCPropNetDNSDomainName);
if (dname)
{
if (CFStringGetCString(dname, buf, MAX_ESCAPED_DOMAIN_NAME, kCFStringEncodingUTF8))
- {
- if (MakeDomainNameFromDNSNameString(&domain, buf)) MarkSearchListElem(&domain);
- else LogMsg("ERROR: RegisterSearchDomains - invalid domain %s", buf);
- }
- else LogMsg("ERROR: RegisterSearchDomains - CFStringGetCString");
+ MarkSearchListElem(buf);
+ else LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
}
}
+ }
+
+mDNSlocal mStatus RegisterSearchDomains(mDNS *const m, CFDictionaryRef dict)
+ {
+ struct ifaddrs *ifa = NULL;
+ SearchListElem *ptr, *prev, *freeSLPtr;
+ ARListElem *arList;
+ mStatus err;
+
+ if (DomainDiscoveryDisabled) return mStatus_NoError;
+ // step 1: mark each elem for removal (-1), unless we aren't passed a dictionary in which case we mark as preexistent
+ for (ptr = SearchList; ptr; ptr = ptr->next) ptr->flag = dict ? -1 : 0;
+
+ // Get search domains from resolver library (available in OS X 10.4 and later), reverting to dynamic store on 10.3 systems
+ if (GetSearchDomains() == mStatus_UnsupportedErr) GetDSSearchDomains(dict);
+
// Construct reverse-map search domains
ifa = myGetIfAddrs(1);
while (ifa)
addr.ip.v4.b[2] & netmask.ip.v4.b[2],
addr.ip.v4.b[1] & netmask.ip.v4.b[1],
addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
- MakeDomainNameFromDNSNameString(&domain, buffer);
- MarkSearchListElem(&domain);
+ MarkSearchListElem(buffer);
}
}
ifa = ifa->ifa_next;
}
-
- if (DynDNSRegDomain.c[0]) MarkSearchListElem(&DynDNSRegDomain); // implicitly browse reg domain too (no-op if same as BrowseDomain)
// delete elems marked for removal, do queries for elems marked add
prev = NULL;
{
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);
}
mDNSlocal void SCPrefsDynDNSCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
{
(void)m; // unused
- debugf("SCPrefsDynDNSCallback: result %d for registration of name %##s", result, rr->resrec.name.c);
- SetDDNSNameStatus(&rr->resrec.name, result);
+ debugf("SCPrefsDynDNSCallback: result %d for registration of name %##s", result, rr->resrec.name->c);
+ SetDDNSNameStatus(rr->resrec.name, result);
}
mDNSlocal void SetSecretForDomain(mDNS *m, const domainname *domain)
}
}
+mDNSlocal void SetSCPrefsBrowseDomainsFromCFArray(mDNS *m, CFArrayRef browseDomains, mDNSBool add)
+ {
+ if (browseDomains)
+ {
+ CFIndex count = CFArrayGetCount(browseDomains);
+ CFDictionaryRef browseDict;
+ char buf[MAX_ESCAPED_DOMAIN_NAME];
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ browseDict = (CFDictionaryRef)CFArrayGetValueAtIndex(browseDomains, i);
+ if (browseDict && DDNSSettingEnabled(browseDict))
+ {
+ CFStringRef name = CFDictionaryGetValue(browseDict, CFSTR("Domain"));
+ if (name)
+ {
+ domainname BrowseDomain;
+ if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) || !MakeDomainNameFromDNSNameString(&BrowseDomain, buf) || !BrowseDomain.c[0])
+ LogMsg("SetSCPrefsBrowseDomainsFromCFArray SCDynamicStore bad DDNS browse domain: %s", buf[0] ? buf : "(unknown)");
+ else SetSCPrefsBrowseDomain(m, &BrowseDomain, add);
+ }
+ }
+ }
+ }
+ }
+
+
mDNSlocal void DynDNSConfigChanged(mDNS *const m)
{
static mDNSBool LegacyNATInitialized = mDNSfalse;
uDNS_GlobalInfo *u = &m->uDNS_info;
CFDictionaryRef dict;
CFStringRef key;
- domainname BrowseDomain, RegDomain, fqdn;
+ domainname RegDomain, fqdn;
+ CFArrayRef NewBrowseDomains = NULL;
// get fqdn, zone from SCPrefs
- GetUserSpecifiedDDNSConfig(&fqdn, &RegDomain, &BrowseDomain);
- if (!fqdn.c[0] && !RegDomain.c[0]) ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &fqdn, &RegDomain);
+ GetUserSpecifiedDDNSConfig(&fqdn, &RegDomain, &NewBrowseDomains);
+ ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, fqdn.c[0] ? NULL : &fqdn, RegDomain.c[0] ? NULL : &RegDomain, &DomainDiscoveryDisabled);
- if (!SameDomainName(&BrowseDomain, &DynDNSBrowseDomain))
- {
- if (DynDNSBrowseDomain.c[0]) SetSCPrefsBrowseDomain(m, &DynDNSBrowseDomain, mDNSfalse);
- AssignDomainName(DynDNSBrowseDomain, BrowseDomain);
- if (DynDNSBrowseDomain.c[0]) SetSCPrefsBrowseDomain(m, &DynDNSBrowseDomain, mDNStrue);
- }
-
if (!SameDomainName(&RegDomain, &DynDNSRegDomain))
{
- if (DynDNSRegDomain.c[0]) RemoveDefRegDomain(&DynDNSRegDomain);
- AssignDomainName(DynDNSRegDomain, RegDomain);
- if (DynDNSRegDomain.c[0]) { SetSecretForDomain(m, &DynDNSRegDomain); AddDefRegDomain(&DynDNSRegDomain); }
+ if (DynDNSRegDomain.c[0])
+ {
+ RemoveDefRegDomain(&DynDNSRegDomain);
+ SetSCPrefsBrowseDomain(m, &DynDNSRegDomain, mDNSfalse); // if we were automatically browsing in our registration domain, stop
+ }
+ AssignDomainName(&DynDNSRegDomain, &RegDomain);
+ if (DynDNSRegDomain.c[0])
+ {
+ SetSecretForDomain(m, &DynDNSRegDomain);
+ AddDefRegDomain(&DynDNSRegDomain);
+ SetSCPrefsBrowseDomain(m, &DynDNSRegDomain, mDNStrue);
+ }
}
+
+ // Add new browse domains to internal list
+ if (NewBrowseDomains) SetSCPrefsBrowseDomainsFromCFArray(m, NewBrowseDomains, mDNStrue);
+
+ // Remove old browse domains from internal list
+ if (DynDNSBrowseDomains)
+ {
+ SetSCPrefsBrowseDomainsFromCFArray(m, DynDNSBrowseDomains, mDNSfalse);
+ CFRelease(DynDNSBrowseDomains);
+ }
+
+ // Replace the old browse domains array with the new array
+ DynDNSBrowseDomains = NewBrowseDomains;
if (!SameDomainName(&fqdn, &DynDNSHostname))
{
if (DynDNSHostname.c[0]) mDNS_RemoveDynDNSHostName(m, &DynDNSHostname);
- AssignDomainName(DynDNSHostname, fqdn);
+ AssignDomainName(&DynDNSHostname, &fqdn);
if (DynDNSHostname.c[0])
{
SetSecretForDomain(m, &fqdn); // no-op if "zone" secret, above, is to be used for hostname
CFStringRef router = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
if (router)
{
+ struct sockaddr_in saddr;
+
if (!CFStringGetCString(router, buf, 256, kCFStringEncodingUTF8))
LogMsg("Could not convert router to CString");
- else inet_aton(buf, (struct in_addr *)&r.ip.v4);
+ else
+ {
+ saddr.sin_len = sizeof(saddr);
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = 0;
+ inet_aton(buf, &saddr.sin_addr);
+ if (AddrRequiresPPPConnection((struct sockaddr *)&saddr)) { debugf("Ignoring router %s (requires PPP connection)", buf); }
+ else *(in_addr_t *)&r.ip.v4 = saddr.sin_addr.s_addr;
+ }
}
// handle primary interface changes
r.ip.v4.NotAnInteger != u->Router.ip.v4.NotAnInteger)
{
if (LegacyNATInitialized) { LegacyNATDestroy(); LegacyNATInitialized = mDNSfalse; }
- if (IsPrivateV4Addr(&ip))
+ if (r.ip.v4.NotAnInteger && IsPrivateV4Addr(&ip))
{
mStatus err = LegacyNATInit();
if (err) LogMsg("ERROR: LegacyNATInit");
ifa = ifa->ifa_next;
}
}
-
+
error:
CFRelease(dict);
}
mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
- {
+ {
LogOperation("*** Network Configuration Change ***");
- MarkAllInterfacesInactive(m);
- UpdateInterfaceList(m);
- int nDeletions = ClearInactiveInterfaces(m);
- int nAdditions = SetupActiveInterfaces(m);
- if (nDeletions || nAdditions) mDNS_UpdateLLQs(m);
- DynDNSConfigChanged(m);
+ mDNSs32 utc = mDNSPlatformUTC();
+ MarkAllInterfacesInactive(m, utc);
+ UpdateInterfaceList(m, utc);
+ int nDeletions = ClearInactiveInterfaces(m, utc);
+ int nAdditions = SetupActiveInterfaces(m, utc);
+ DynDNSConfigChanged(m); // note - call DynDNSConfigChanged *before* mDNS_UpdateLLQs
+ if (nDeletions || nAdditions) mDNS_UpdateLLQs(m); // so that LLQs are restarted against the up to date name servers
if (m->MainCallback)
m->MainCallback(m, mStatus_ConfigChanged);
{
(void)store; // Parameter not used
(void)changedKeys; // Parameter not used
- LogOperation("*** NetworkChanged ***");
mDNS *const m = (mDNS *const)context;
mDNS_Lock(m);
- m->p->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
+
+ mDNSs32 delay = mDNSPlatformOneSecond * 2; // Start off assuming a two-second delay
+
+ int c = CFArrayGetCount(changedKeys); // Count changes
+ CFRange range = { 0, c };
+ CFStringRef k1 = SCDynamicStoreKeyCreateComputerName(NULL);
+ CFStringRef k2 = SCDynamicStoreKeyCreateHostNames(NULL);
+ if (k1 && k2)
+ {
+ int c1 = (CFArrayContainsValue(changedKeys, range, k1) != 0); // See if ComputerName changed
+ int c2 = (CFArrayContainsValue(changedKeys, range, k2) != 0); // See if Local Hostname changed
+ int c3 = (CFArrayContainsValue(changedKeys, range, CFSTR("Setup:/Network/DynamicDNS")) != 0);
+ if (c && c - c1 - c2 - c3 == 0) delay = mDNSPlatformOneSecond/10; // If these were the only changes, shorten delay
+ }
+ if (k1) CFRelease(k1);
+ if (k2) CFRelease(k2);
+
+ LogOperation("*** NetworkChanged *** %d change%s, delay %d", c, c>1?"s":"", delay);
+
+ if (!m->p->NetworkChanged ||
+ m->p->NetworkChanged - NonZeroTime(m->timenow + delay) < 0)
+ m->p->NetworkChanged = NonZeroTime(m->timenow + delay);
+
if (!m->SuppressSending ||
m->SuppressSending - m->p->NetworkChanged < 0)
m->SuppressSending = m->p->NetworkChanged;
switch(messageType)
{
case kIOMessageCanSystemPowerOff: debugf("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240
- case kIOMessageSystemWillPowerOff: debugf("PowerChanged kIOMessageSystemWillPowerOff"); mDNSCoreMachineSleep(m, true); break; // E0000250
+ case kIOMessageSystemWillPowerOff: debugf("PowerChanged kIOMessageSystemWillPowerOff");
+ mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000250
case kIOMessageSystemWillNotPowerOff: debugf("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
case kIOMessageCanSystemSleep: debugf("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270
- case kIOMessageSystemWillSleep: debugf("PowerChanged kIOMessageSystemWillSleep"); mDNSCoreMachineSleep(m, true); break; // E0000280
+ case kIOMessageSystemWillSleep: debugf("PowerChanged kIOMessageSystemWillSleep");
+ mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000280
case kIOMessageSystemWillNotSleep: debugf("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290
case kIOMessageSystemHasPoweredOn: debugf("PowerChanged kIOMessageSystemHasPoweredOn");
// If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
}
// Callback for the _legacy._browse queries - add answer to list of domains to search for empty-string browses
-mDNSlocal void FoundDefBrowseDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void FoundLegacyBrowseDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
{
DNameListElem *ptr, *prev, *new;
(void)m; // unused;
(void)question; // unused
+ LogMsg("%s browse domain %##s", AddRecord ? "Adding" : "Removing", answer->rdata->u.name.c);
+
if (AddRecord)
{
- new = mallocL("FoundDefBrowseDomain", sizeof(DNameListElem));
+ new = mallocL("FoundLegacyBrowseDomain", sizeof(DNameListElem));
if (!new) { LogMsg("ERROR: malloc"); return; }
- AssignDomainName(new->name, answer->rdata->u.name);
+ AssignDomainName(&new->name, &answer->rdata->u.name);
new->next = DefBrowseList;
DefBrowseList = new;
DefaultBrowseDomainChanged(&new->name, mDNStrue);
udsserver_default_browse_domain_changed(&ptr->name, mDNSfalse);
if (prev) prev->next = ptr->next;
else DefBrowseList = ptr->next;
- freeL("FoundDefBrowseDomain", ptr);
+ freeL("FoundLegacyBrowseDomain", ptr);
return;
}
prev = ptr;
ptr = ptr->next;
}
- LogMsg("FoundDefBrowseDomain: Got remove event for domain %s not in list", answer->rdata->u.name.c);
+ LogMsg("FoundLegacyBrowseDomain: Got remove event for domain %s not in list", answer->rdata->u.name.c);
+ }
+ }
+
+mDNSlocal void RegisterBrowseDomainPTR(mDNS *m, const domainname *d, int type)
+ {
+ // allocate/register legacy and non-legacy _browse PTR record
+ ARListElem *browse = mallocL("ARListElem", sizeof(*browse));
+ mDNS_SetupResourceRecord(&browse->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, browse);
+ MakeDomainNameFromDNSNameString(browse->ar.resrec.name, mDNS_DomainTypeNames[type]);
+ AppendDNSNameString (browse->ar.resrec.name, "local");
+ AssignDomainName(&browse->ar.resrec.rdata->u.name, d);
+ mStatus err = mDNS_Register(m, &browse->ar);
+ if (err)
+ {
+ LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
+ freeL("ARListElem", browse);
+ }
+ else
+ {
+ browse->next = SCPrefBrowseDomains;
+ SCPrefBrowseDomains = browse;
+ }
+ }
+
+mDNSlocal void DeregisterBrowseDomainPTR(mDNS *m, const domainname *d, int type)
+ {
+ ARListElem *remove, **ptr = &SCPrefBrowseDomains;
+ domainname lhs; // left-hand side of PTR, for comparison
+
+ MakeDomainNameFromDNSNameString(&lhs, mDNS_DomainTypeNames[type]);
+ AppendDNSNameString (&lhs, "local");
+
+ while (*ptr)
+ {
+ if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, d) && SameDomainName((*ptr)->ar.resrec.name, &lhs))
+ {
+ remove = *ptr;
+ *ptr = (*ptr)->next;
+ mDNS_Deregister(m, &remove->ar);
+ return;
+ }
+ else ptr = &(*ptr)->next;
}
}
// Also register a non-legacy _browse PTR record so that the domain appears in enumeration lists
mDNSlocal void SetSCPrefsBrowseDomain(mDNS *m, const domainname *d, mDNSBool add)
{
- AuthRecord rec;
+ debugf("SetSCPrefsBrowseDomain: %s default browse domain %##s", add ? "Adding" : "Removing", d->c);
- // Create dummy record pointing to the domain to be added/removed
- mDNS_SetupResourceRecord(&rec, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, mDNSNULL, mDNSNULL);
- AssignDomainName(rec.resrec.rdata->u.name, *d);
-
- // add/remove the "_legacy" entry
- MakeDomainNameFromDNSNameString(&rec.resrec.name, "_legacy._browse._dns-sd._udp.local.");
- FoundDefBrowseDomain(m, &LegacyBrowseDomainQ, &rec.resrec, add);
-
if (add)
{
- // allocate/register a non-legacy _browse PTR record
- ARListElem *ptr = mallocL("ARListElem", sizeof(*ptr));
- mDNS_SetupResourceRecord(&ptr->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, ptr);
- MakeDomainNameFromDNSNameString(&ptr->ar.resrec.name, "_browse._dns-sd._udp.local.");
- AssignDomainName(ptr->ar.resrec.rdata->u.name, *d);
- mStatus err = mDNS_Register(m, &ptr->ar);
- if (err)
- {
- LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
- freeL("ARListElem", ptr);
- }
- else
- {
- ptr->next = SCPrefBrowseDomains;
- SCPrefBrowseDomains = ptr;
- }
+ RegisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowse);
+ RegisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowseLegacy);
}
else
{
- ARListElem **remove = &SCPrefBrowseDomains;
- while (*remove && !SameDomainName(&(*remove)->ar.resrec.rdata->u.name, d)) remove = &(*remove)->next;
- if (!*remove) { LogMsg("SetSCPrefsBrowseDomain (remove) - domain %##s not found!", d->c); return; }
- mDNS_Deregister(m, &(*remove)->ar);
- *remove = (*remove)->next;
+ DeregisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowse);
+ DeregisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowseLegacy);
}
}
-
// Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
-// 1) query for _browse._dns-sd._udp.local on LocalOnly interface
+// 1) query for b._dns-sd._udp.local on LocalOnly interface
// (.local manually generated via explicit callback)
-// 2) for each search domain (from prefs pane), query for _browse._dns-sd._udp.<searchdomain>.
-// 3) for each result from (2), register LocalOnly PTR record_browse._dns-sd._udp.local. -> <result>
+// 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
+// 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
// 4) result above should generate a callback from question in (1). result added to global list
// 5) global list delivered to client via GetSearchDomainList()
// 6) client calls to enumerate domains now go over LocalOnly interface
mDNSlocal mStatus 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);
+ err = mDNS_GetDomains(m, &LegacyBrowseDomainQ, mDNS_DomainTypeBrowseLegacy, NULL, mDNSInterface_LocalOnly, FoundLegacyBrowseDomain, NULL);
- // provide .local automatically
+ // provide browse domain "local" automatically
SetSCPrefsBrowseDomain(m, &localdomain, mDNStrue);
- return mStatus_NoError;
+
+ // 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: InitDNSConfig - mDNS_Register returned error %d", err);
+
+ return mStatus_NoError;
}
mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
{
+ // In 10.4, mDNSResponder is launched very early in the boot process, while other subsystems are still in the process of starting up.
+ // If we can't read the user's preferences, then we sleep a bit and try again, for up to five seconds before we give up.
+ int i;
+ for (i=0; i<100; i++)
+ {
+ domainlabel testlabel;
+ testlabel.c[0] = 0;
+ GetUserSpecifiedLocalHostName(&testlabel);
+ if (testlabel.c[0]) break;
+ usleep(50000);
+ }
+
mStatus err;
m->hostlabel.c[0] = 0;
m->p->userhostlabel.c[0] = 0;
m->p->usernicelabel.c[0] = 0;
m->p->NotifyUser = 0;
- UpdateInterfaceList(m);
- SetupActiveInterfaces(m);
+ mDNSs32 utc = mDNSPlatformUTC();
+ UpdateInterfaceList(m, utc);
+ SetupActiveInterfaces(m, utc);
err = WatchForNetworkChanges(m);
if (err) return(err);
if (err) return err;
DynDNSRegDomain.c[0] = '\0';
- DynDNSBrowseDomain.c[0] = '\0';
DynDNSConfigChanged(m); // Get initial DNS configuration
InitDNSConfig(m);
m->p->StoreRLS = NULL;
}
- MarkAllInterfacesInactive(m);
- ClearInactiveInterfaces(m);
+ mDNSs32 utc = mDNSPlatformUTC();
+ MarkAllInterfacesInactive(m, utc);
+ ClearInactiveInterfaces(m, utc);
CloseSocketSet(&m->p->unicastsockets);
}
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;
- NotifyOfElusiveBug("mach_absolute_time went backwards!", 3438376, "");
+ // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xxx) or later
+ if (mDNSMacOSXSystemBuildNumber(NULL) >= 8)
+ NotifyOfElusiveBug("mach_absolute_time went backwards!", 3438376, "");
}
last_mach_absolute_time = this_mach_absolute_time;
Change History (most recent first):
$Log: mDNSMacOSX.h,v $
+Revision 1.49 2004/12/17 23:37:47 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+(and other repetitive configuration changes)
+
Revision 1.48 2004/12/07 01:31:31 cheshire
mDNSMacOSXSystemBuildNumber() returns int, not mDNSBool
#include <sys/socket.h>
#include <netinet/in.h>
#include "mDNSEmbeddedAPI.h" // for domain name structure
-
typedef struct NetworkInterfaceInfoOSX_struct NetworkInterfaceInfoOSX;
NetworkInterfaceInfoOSX *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
char *ifa_name; // Memory for this is allocated using malloc
mDNSu32 scope_id; // interface index / IPv6 scope ID
mDNSEthAddr BSSID; // BSSID of 802.11 base station, if applicable
--- /dev/null
+no_module:start
+no_module:__call_mod_init_funcs
+no_module:__start
+no_module:__dyld_func_lookup
+no_module:dyld_stub_binding_helper
+no_module:_main
+no_module:_LogMsgIdent
+no_module:_mDNS_vsnprintf
+no_module:_WriteLogMsg
+no_module:_mDNSDaemonInitialize
+no_module:_mDNSMacOSXSystemBuildNumber
+no_module:_mDNS_Init
+no_module:_mDNSPlatformTimeInit
+no_module:___udivdi3
+no_module:_mDNSRandom
+no_module:_mDNSPlatformRandomSeed
+no_module:_mDNSPlatformRawTime
+no_module:_mDNS_GrowCache_internal
+no_module:_LogMsg
+no_module:_uDNS_Init
+no_module:_mDNSPlatformMemZero
+no_module:_mDNSPlatformInit
+no_module:_mDNSPlatformInit_setup
+no_module:_mDNS_snprintf
+no_module:_mDNSPlatformInit_CanReceiveUnicast
+no_module:_mDNSPlatformStrLen
+no_module:_mDNSPlatformMemCopy
+no_module:_SetupSocket
+no_module:_mDNSPlatformUTC
+no_module:_UpdateInterfaceList
+no_module:_myGetIfAddrs
+no_module:_AddInterfaceToList
+no_module:_GetBSSID
+no_module:_SetupAddr
+no_module:_mallocL
+no_module:_validatelists
+no_module:_mDNSSameAddress
+no_module:_FindRoutableIPv4
+no_module:_GetUserSpecifiedFriendlyComputerName
+no_module:_GetUserSpecifiedLocalHostName
+no_module:_SameDomainLabel
+no_module:_mDNS_SetFQDN
+no_module:_AppendDomainLabel
+no_module:_DomainNameLength
+no_module:_AppendLiteralLabelString
+no_module:_SameDomainName
+no_module:_mDNS_Lock
+no_module:_mDNSPlatformLock
+no_module:_mDNS_Unlock
+no_module:_GetNextScheduledEvent
+no_module:_mDNSPlatformUnlock
+no_module:_SetupActiveInterfaces
+no_module:_SearchForInterfaceByName
+no_module:_mDNS_RegisterInterface
+no_module:_AdvertiseInterface
+no_module:_FindFirstAdvertisedInterface
+no_module:_mDNS_SetupResourceRecord
+no_module:_MakeDomainNameFromDNSNameString
+no_module:_AppendDNSNameString
+no_module:_mDNS_Register_internal
+no_module:_IsLocalDomain
+no_module:_InitializeLastAPTime
+no_module:_SetNextAnnounceProbeTime
+no_module:_GetRDLength
+no_module:_ValidateRData
+no_module:_DomainNameHashValue
+no_module:_RDataHashValue
+no_module:_SetTargetToHostName
+no_module:_SetNewRData
+no_module:_CompressedDomainNameLength
+no_module:_AcknowledgeRecord
+no_module:_IdenticalResourceRecord
+no_module:_CountMaskBits
+no_module:_SameRData
+no_module:_mDNSPlatformMemSame
+no_module:_WatchForNetworkChanges
+no_module:_WatchForPowerChanges
+no_module:_DynDNSConfigChanged
+no_module:_GetUserSpecifiedDDNSConfig
+no_module:_ReadDDNSSettingsFromConfFile
+no_module:_RegisterSplitDNS
+no_module:_GetDNSConfig
+no_module:_RegisterSearchDomains
+no_module:_GetSearchDomains
+no_module:_GetDSSearchDomains
+no_module:_IsPrivateV4Addr
+no_module:_mDNS_SetPrimaryInterfaceInfo
+no_module:_InitDNSConfig
+no_module:_mDNS_GetDomains
+no_module:_AppendDomainName
+no_module:_mDNS_StartQuery
+no_module:_mDNS_StartQuery_internal
+no_module:_CheckForSoonToExpireRecords
+no_module:_CacheGroupForName
+no_module:_FindDuplicateQuestion
+no_module:_SetSCPrefsBrowseDomain
+no_module:_RegisterBrowseDomainPTR
+no_module:_mDNS_Register
+no_module:_FreeARElemCallback
+no_module:_mDNSCoreInitComplete
+no_module:_mDNS_StatusCallback
+no_module:_RecordUpdatedNiceLabel
+no_module:_udsserver_init
+no_module:_udsSupportAddFDToEventLoop
+no_module:_InitLinkedList
+no_module:_AddToTail
+no_module:_mDNSDaemonIdle
+no_module:_mDNS_TimeNow
+no_module:_mDNS_Execute
+no_module:_AnswerNewLocalOnlyQuestion
+no_module:_uDNS_Execute
+no_module:_mDNSPlatformTimeNow
+no_module:_CheckNATMappings
+no_module:_CheckQueries
+no_module:_CheckRecordRegistrations
+no_module:_CheckServiceRegistrations
+no_module:_udsserver_idle
+no_module:_cf_callback
+no_module:_connect_callback
+no_module:_request_callback
+no_module:_read_msg
+no_module:_ConvertHeaderBytes
+no_module:_validate_message
+no_module:_handle_regservice_request
+no_module:_get_long
+no_module:_mDNSPlatformInterfaceIDfromInterfaceIndex
+no_module:_get_string
+no_module:_get_short
+no_module:_get_rdata
+no_module:_ChopSubTypes
+no_module:_FindFirstSubType
+no_module:_ConstructServiceName
+no_module:_CountExistingRegistrations
+no_module:_register_service_instance
+no_module:_AllocateSubTypes
+no_module:_mDNS_RegisterService
+no_module:_ServiceCallback
+no_module:_mDNSPlatformGetRegDomainList
+no_module:_mDNS_CopyDNameList
+no_module:_mDNS_FreeDNameList
+no_module:_deliver_error
+no_module:_dnssd_htonl
+no_module:_put_long
+no_module:_reset_connected_rstate
+no_module:_freeL
+no_module:_SendQueries
+no_module:_GetFirstActiveInterface
+no_module:_InitializeDNSMessage
+no_module:_putQuestion
+no_module:_putDomainNameAsLabels
+no_module:_FindCompressionPointer
+no_module:_GetNextActiveInterfaceID
+no_module:_PutResourceRecordTTLWithLimit
+no_module:_putRData
+no_module:_mDNSSendDNSMessage
+no_module:_mDNSPlatformSendUDP
+no_module:_mDNSAddrIsDNSMulticast
+no_module:_myCFSocketCallBack
+no_module:_myrecvfrom
+no_module:_mDNSCoreReceive
+no_module:_mDNSCoreReceiveQuery
+no_module:_ProcessQuery
+no_module:_AddressIsLocalSubnet
+no_module:_getQuestion
+no_module:_getDomainName
+no_module:_ResourceRecordAnswersQuestion
+no_module:_ResolveSimultaneousProbe
+no_module:_LocateAuthorities
+no_module:_LocateAnswers
+no_module:_skipQuestion
+no_module:_skipDomainName
+no_module:_GetLargeResourceRecord
+no_module:_PacketRRConflict
+no_module:_MatchDependentOn
+no_module:_FindRRSet
+no_module:_AddAdditionalsToResponseList
+no_module:_NetworkChanged
+no_module:_MakeDomainLabelFromLiteralString
+no_module:_mDNSMacOSXNetworkChanged
+no_module:_MarkAllInterfacesInactive
+no_module:_ClearInactiveInterfaces
+no_module:_mDNS_DeregisterInterface
+no_module:_UpdateInterfaceProtocols
+no_module:_DeadvertiseInterface
+no_module:_mDNS_Deregister_internal
+no_module:_mDNS_HostNameCallback
+no_module:_CloseSocketSet
+no_module:_CloseRunLoopSourceSocket
+no_module:_NumCacheRecordsForInterfaceID
+no_module:_RegisterNameServers
+no_module:_mDNS_DeleteDNSServers
+no_module:_mDNS_AddDNSServer
+no_module:_mDNSPlatformMemAllocate
+no_module:_MarkSearchListElem
+no_module:_uDNS_StartQuery
+no_module:_startQuery
+no_module:_newMessageID
+no_module:_constructQueryMsg
+no_module:_initializeQuery
+no_module:_LinkActiveQuestion
+no_module:_uDNS_IsActiveQuery
+no_module:_GetServerForName
+no_module:_CountLabels
+no_module:_UpdateHostnameRegistrations
+no_module:_UpdateSRVRecords
+no_module:_GetStaticHostname
+no_module:_mDNS_UpdateLLQs
+no_module:_SuspendLLQs
+no_module:_CheckForUnreferencedLLQMapping
+no_module:_RestartQueries
+no_module:_udsserver_handle_configchange
+no_module:_rename_service
+no_module:_AnswerLocalQuestions
+no_module:_AnswerLocalOnlyQuestionWithResourceRecord
+no_module:_FoundDefBrowseDomain
+no_module:_DefaultBrowseDomainChanged
+no_module:_udsserver_default_browse_domain_changed
+no_module:_SendResponses
+no_module:_uDNS_ReceiveMsg
+no_module:_recvLLQResponse
+no_module:_simpleResponseHndlr
+no_module:_pktResponseHndlr
+no_module:_deriveGoodbyes
+no_module:_mDNSCoreReceiveResponse
+no_module:_kaListContainsAnswer
+no_module:_addKnownAnswer
+no_module:_FoundDomain
+no_module:_SameResourceRecord
+no_module:_mDNSPlatformMemFree
+no_module:_FoundStaticHostname
+no_module:_PacketRRMatchesSignature
+no_module:_CacheGroupForRecord
+no_module:_GetCacheGroup
+no_module:_GetCacheEntity
+no_module:_GetCacheRecord
+no_module:_CacheRecordAdd
+no_module:_SetNextCacheCheckTime
+no_module:_SameResourceRecordSignature
+no_module:_CacheRecordDeferredAdd
+no_module:_regservice_callback
+no_module:_process_service_registration
+no_module:_gen_rr_response
+no_module:_DeconstructServiceName
+no_module:_ConvertDomainLabelToCString_withescape
+no_module:_ConvertDomainNameToCString_withescape
+no_module:_create_reply
+no_module:_mDNSPlatformInterfaceIndexfromInterfaceID
+no_module:_put_string
+no_module:_send_msg
+no_module:_CountPeerRegistrations
+no_module:_CheckCacheExpiration
+no_module:_FindIdenticalRecordInCache
+no_module:_handle_browse_request
+no_module:_mDNSPlatformGetSearchDomainList
+no_module:_add_domain_to_browser
+no_module:_mDNS_StartBrowse
+no_module:_SetNextQueryTime
+no_module:_startLLQ
+no_module:_startGetZoneData
+no_module:_getZoneData
+no_module:_hndlLookupSOA
+no_module:_startInternalQuery
+no_module:_AnswerNewQuestion
+no_module:_ExpireDupSuppressInfo
+no_module:_SuppressOnThisInterface
+no_module:_BuildQuestion
+no_module:_uDNS_StopQuery
+no_module:_processSOA
+no_module:_confirmNS
+no_module:_lookupNSAddr
+no_module:_LocateAdditionals
+no_module:_skipResourceRecord
+no_module:_hndlLookupPorts
+no_module:_lookupDNSPort
+no_module:_startLLQHandshakeCallback
+no_module:_mDNS_GrowCache
+no_module:_AnswerQuestionWithResourceRecord
+no_module:_browse_result_callback
+no_module:_DNSTypeName
+no_module:_GetRRDisplayString_rdb
+no_module:_append_reply
+no_module:_llqResponseHndlr
+no_module:_AccelerateThisQuery
+no_module:_ReconfirmAntecedents
+no_module:_handle_enum_request
+no_module:_format_enumeration_reply
+no_module:_enum_result_callback
+no_module:_ReleaseCacheRecord
+no_module:_ReleaseCacheEntity
+no_module:_AddRecordToResponseList
+no_module:_ShouldSuppressKnownAnswer
+no_module:_RecordDupSuppressInfo
+no_module:_ReleaseCacheGroup
+no_module:_CacheRecordRmv
+no_module:_hndlTruncatedAnswer
+no_module:_mDNSPlatformTCPConnect
+no_module:_tcpCFSocketCallback
+no_module:_conQueryCallback
+no_module:_mDNSPlatformWriteTCP
+no_module:_mDNSPlatformReadTCP
+no_module:_mDNSPlatformTCPCloseConnection
+no_module:_handle_add_request
+no_module:_add_record_to_service
+no_module:_mDNS_AddRecordToService
+no_module:_handle_update_request
+no_module:_update_record
+no_module:_mDNS_Update
+no_module:_handle_query_request
+no_module:_question_result_callback
+no_module:_put_short
+no_module:_put_rdata
+no_module:_abort_request
+no_module:_question_termination_callback
+no_module:_mDNS_StopQuery
+no_module:_mDNS_StopQuery_internal
+no_module:_UpdateQuestionDuplicates
+no_module:_udsSupportRemoveFDFromEventLoop
+no_module:_RemoveFromList
+no_module:_unlink_request
+no_module:_DNSserverCallback
+no_module:_DNSServiceDiscoveryRequest_server
+no_module:__XDNSServiceResolverResolve_rpc
+no_module:___MIG_check__Request__DNSServiceResolverResolve_rpc_t
+no_module:_provide_DNSServiceResolverResolve_rpc
+no_module:_CheckForExistingClient
+no_module:_mDNS_StartResolveService
+no_module:_EnableDeathNotificationForClient
+no_module:_FoundServiceInfoSRV
+no_module:_MachineHasActiveIPv6
+no_module:_FoundServiceInfoTXT
+no_module:_FoundServiceInfo
+no_module:_FoundInstanceInfo
+no_module:_DNSServiceResolverReply_rpc
+no_module:_ExpireDupSuppressInfoOnInterface
+no_module:_CompleteRDataUpdate
+no_module:_update_callback
+no_module:_GenerateUnicastResponse
+no_module:_PutResourceRecordCappedTTL
+no_module:_ClientDeathCallback
+no_module:_AbortClient
+no_module:_mDNS_StopResolveService
+no_module:_mDNS_Reconfirm_internal
+no_module:_browse_termination_callback
+no_module:_stopLLQ
+no_module:_GrantUpdateCredit
+no_module:__XDNSServiceBrowserCreate_rpc
+no_module:___MIG_check__Request__DNSServiceBrowserCreate_rpc_t
+no_module:_provide_DNSServiceBrowserCreate_rpc
+no_module:_AddDomainToBrowser
+no_module:_FoundInstance
+no_module:_DNSServiceBrowserReply_rpc
+no_module:__XDNSServiceRegistrationCreate_rpc
+no_module:___MIG_check__Request__DNSServiceRegistrationCreate_rpc_t
+no_module:_provide_DNSServiceRegistrationCreate_rpc
+no_module:_AddServiceInstance
+no_module:_RegCallback
+no_module:_DNSServiceRegistrationReply_rpc
+no_module:_mDNS_DeregisterService
+no_module:_CompleteDeregistration
+no_module:_FreeServiceInstance
+no_module:_PowerChanged
+no_module:_mDNSCoreMachineSleep
+no_module:_uDNS_Sleep
+no_module:_SleepServiceRegistrations
+no_module:_SleepRecordRegistrations
+no_module:_PurgeCacheResourceRecord
+no_module:_regservice_termination_callback
+no_module:_free_service_instance
+no_module:_FreeExtraRR
+no_module:_mDNS_Deregister
+no_module:_uDNS_Wake
+no_module:_WakeServiceRegistrations
+no_module:_WakeRecordRegistrations
+no_module:_SendDelayedUnicastResponse
+no_module:_mDNS_RenameAndReregisterService
+no_module:_FindNextSubType
+no_module:_handle_removerecord_request
OTHER_REZFLAGS = "";
PRODUCT_NAME = mDNSResponder.debug;
REZ_EXECUTABLE = YES;
- SECTORDER_FLAGS = "";
+ SECTORDER_FLAGS = "-sectorder __TEXT __text mDNSResponder.order";
STRIPFLAGS = "-S";
WARNING_CFLAGS = "-W -Wall -Wmissing-prototypes -Wno-four-char-constants -Wno-unknown-pragmas";
};
08FB77A3FE84155DC02AAC07,
08FB77A5FE84155DC02AAC07,
FF5A0AE705632EA600743C27,
+ FF5585E507790732008D1C14,
);
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = mDNSResponder;
REZ_EXECUTABLE = YES;
- SECTORDER_FLAGS = "";
+ SECTORDER_FLAGS = "-sectorder __TEXT __text mDNSResponder.order";
STRIPFLAGS = "-S";
WARNING_CFLAGS = "-W -Wall -Wmissing-prototypes -Wno-four-char-constants -Wno-unknown-pragmas";
};
path = ../mDNSShared/mDNSResponder.8;
refType = 2;
};
+ FF5585E507790732008D1C14 = {
+ buildActionMask = 8;
+ files = (
+ );
+ generatedFileNames = (
+ );
+ isa = PBXShellScriptBuildPhase;
+ neededFileNames = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "mkdir -p ${DSTROOT}/System/Library/LaunchDaemons\ncp ${SRCROOT}/LaunchDaemonInfo.plist ${DSTROOT}/System/Library/LaunchDaemons/com.apple.mDNSResponder.plist";
+ };
FF5A0AE705632EA600743C27 = {
buildActionMask = 8;
dstPath = /usr/share/man/man8;
Change History (most recent first):
$Log: Client.c,v $
+Revision 1.15 2004/12/16 20:17:11 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.14 2004/11/30 22:37:00 cheshire
Update copyright dates and add "Mode: C; tab-width: 4" headers
static mDNS mDNSStorage; // mDNS core uses this to store its globals
static mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals
#define RR_CACHE_SIZE 500
-static CacheRecord gRRCache[RR_CACHE_SIZE];
+static CacheEntity gRRCache[RR_CACHE_SIZE];
static const char *gProgramName = "mDNSResponderPosix";
Change History (most recent first):
$Log: Identify.c,v $
+Revision 1.34 2004/12/16 20:17:11 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.33 2004/11/30 22:37:00 cheshire
Update copyright dates and add "Mode: C; tab-width: 4" headers
static mDNS mDNSStorage; // mDNS core uses this to store its globals
static mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals
#define RR_CACHE_SIZE 500
-static CacheRecord gRRCache[RR_CACHE_SIZE];
+static CacheEntity gRRCache[RR_CACHE_SIZE];
static volatile int StopNow; // 0 means running, 1 means stop because we got an answer, 2 means stop because of Ctrl-C
static volatile int NumAnswers, NumAddr, NumAAAA, NumHINFO;
{
ConvertDomainNameToCString(&answer->rdata->u.name, hostname);
StopNow = 1;
- mprintf("%##s %s %##s\n", answer->name.c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
+ mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
}
}
if (!id.NotAnInteger) id = lastid;
NumAnswers++;
NumAddr++;
- mprintf("%##s %s %.4a\n", answer->name.c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv4);
+ mprintf("%##s %s %.4a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv4);
hostaddr.type = mDNSAddrType_IPv4; // Prefer v4 target to v6 target, for now
hostaddr.ip.v4 = answer->rdata->u.ipv4;
}
if (!id.NotAnInteger) id = lastid;
NumAnswers++;
NumAAAA++;
- mprintf("%##s %s %.16a\n", answer->name.c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv6);
+ mprintf("%##s %s %.16a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv6);
if (!hostaddr.type) // Prefer v4 target to v6 target, for now
{
hostaddr.type = mDNSAddrType_IPv6;
{
NumAnswers++;
NumAddr++;
- mprintf("%##s %s %##s\n", answer->name.c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
+ mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
StopNow = 1;
}
}
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $Log: Makefile,v $
+# Revision 1.55 2005/01/27 22:55:00 cheshire
+# Add "make os=tiger" target which uses gcc4 and "-Wdeclaration-after-statement"
+#
+# Revision 1.54 2004/12/17 19:33:03 cheshire
+# Add "-lresolv" for Solaris
+#
# Revision 1.53 2004/12/01 20:04:31 cheshire
# Tidy up alignment
#
-DLOG_PERROR=0 -D_XPG4_2 -D__EXTENSIONS__ -DHAVE_BROKEN_RECVIF_NAME -DUSE_TCP_LOOPBACK
CC = gcc
LD = gcc -shared
-LIBFLAGS = -lsocket -lnsl
+LIBFLAGS = -lsocket -lnsl -lresolv
JAVACFLAGS_OS += -I$(JDK)/include/solaris
ifneq ($(DEBUG),1)
STRIP = strip
JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Headers -framework JavaVM
else
-$(error ERROR: Must specify target OS on command-line, e.g. "make os=panther [target]".\
+ifeq ($(os),tiger)
+CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Wdeclaration-after-statement
+CC = @gcc-4.0
+LD = libtool -dynamic
+LIBFLAGS = -lSystem
+LDSUFFIX = dylib
+JDK = /System/Library/Frameworks/JavaVM.framework/Home
+JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Headers -framework JavaVM
+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)
endif
endif
endif
endif
endif
+endif
NSSLIBNAME := libnss_mdns
NSSVERSION := 0.2
Change History (most recent first):
$Log: NetMonitor.c,v $
+Revision 1.71 2004/12/16 20:17:11 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.70 2004/12/04 02:13:20 cheshire
Pass proper record type in GetLargeResourceRecord() calls
{
// Should really check that the rdata in the address record matches the source address of this packet
entry->NumQueries = 0;
- AssignDomainName(entry->hostname, pktrr->name);
+ AssignDomainName(&entry->hostname, pktrr->name);
}
if (pktrr->rrtype == kDNSType_PTR)
- if (SameDomainName(&entry->revname, &pktrr->name))
+ if (SameDomainName(&entry->revname, pktrr->name))
{
entry->NumQueries = 0;
- AssignDomainName(entry->hostname, pktrr->rdata->u.name);
+ AssignDomainName(&entry->hostname, &pktrr->rdata->u.name);
}
}
else if (pktrr->rrtype == kDNSType_HINFO)
mDNSu8 *sw = hw + 1 + (mDNSu32)hw[0];
if (sw + 1 + sw[0] <= rdend)
{
- AssignDomainName(entry->hostname, pktrr->name);
+ AssignDomainName(&entry->hostname, pktrr->name);
mDNSPlatformMemCopy(hw, entry->HIHardware.c, 1 + (mDNSu32)hw[0]);
mDNSPlatformMemCopy(sw, entry->HISoftware.c, 1 + (mDNSu32)sw[0]);
}
RDataBody *rd = &pktrr->rdata->u;
mDNSu8 *rdend = (mDNSu8 *)rd + pktrr->rdlength;
- int n = mprintf("%#-16a %-5s %-5s%5lu %##s -> ", srcaddr, op, DNSTypeName(pktrr->rrtype), pktrr->rroriginalttl, pktrr->name.c);
+ int n = mprintf("%#-16a %-5s %-5s%5lu %##s -> ", srcaddr, op, DNSTypeName(pktrr->rrtype), pktrr->rroriginalttl, pktrr->name->c);
switch(pktrr->rrtype)
{
// the same as a single query, to more accurately reflect the burden on the network
// (A query with a six-packet KA list is *at least* six times the burden on the network as a single-packet query.)
if (msg->h.numQuestions == 0 && i == 0)
- recordstat(entry, &pkt.r.resrec.name, OP_query, pkt.r.resrec.rrtype);
+ recordstat(entry, pkt.r.resrec.name, OP_query, pkt.r.resrec.rrtype);
}
for (i=0; i<msg->h.numAuthorities; i++)
{
NumAnswers++;
DisplayResourceRecord(srcaddr, (pkt.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? "(AN)" : "(AN+)", &pkt.r.resrec);
- if (msg->h.id.NotAnInteger != 0xFFFF) recordstat(entry, &pkt.r.resrec.name, OP_answer, pkt.r.resrec.rrtype);
+ if (msg->h.id.NotAnInteger != 0xFFFF) recordstat(entry, pkt.r.resrec.name, OP_answer, pkt.r.resrec.rrtype);
if (entry) RecordHostInfo(entry, &pkt.r.resrec);
}
else
{
NumGoodbyes++;
DisplayResourceRecord(srcaddr, "(DE)", &pkt.r.resrec);
- recordstat(entry, &pkt.r.resrec.name, OP_goodbye, pkt.r.resrec.rrtype);
+ recordstat(entry, pkt.r.resrec.name, OP_goodbye, pkt.r.resrec.rrtype);
}
}
ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &pkt);
if (!ptr) { DisplayError(srcaddr, ep, end, "AUTHORITY"); return; }
mprintf("%#-16a (?) **** ERROR: SHOULD NOT HAVE AUTHORITY IN mDNS RESPONSE **** %-5s %##s\n",
- srcaddr, DNSTypeName(pkt.r.resrec.rrtype), pkt.r.resrec.name.c);
+ srcaddr, DNSTypeName(pkt.r.resrec.rrtype), pkt.r.resrec.name->c);
}
for (i=0; i<msg->h.numAdditionals; i++)
Change History (most recent first):
$Log: PosixDaemon.c,v $
+Revision 1.25 2005/01/27 20:01:50 cheshire
+udsSupportRemoveFDFromEventLoop() needs to close the file descriptor as well
+
+Revision 1.24 2005/01/19 19:20:49 ksekar
+<rdar://problem/3960191> Need a way to turn off domain discovery
+
+Revision 1.23 2004/12/16 20:17:11 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.22 2004/12/10 13:12:08 cheshire
Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
static domainname DynDNSHostname;
#define RR_CACHE_SIZE 500
-static CacheRecord gRRCache[RR_CACHE_SIZE];
+static CacheEntity gRRCache[RR_CACHE_SIZE];
extern const char mDNSResponderVersionString[];
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);
+ 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);
return mDNSPosixAddFDToEventLoop(fd, callback, context);
}
-mStatus udsSupportRemoveFDFromEventLoop(int fd)
+mStatus udsSupportRemoveFDFromEventLoop(int fd) // Note: This also CLOSES the file descriptor
{
return mDNSPosixRemoveFDFromEventLoop(fd);
+ close(fd);
}
mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
Change History (most recent first):
$Log: ProxyResponder.c,v $
+Revision 1.35 2004/12/16 20:17:11 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.34 2004/12/01 04:27:28 cheshire
<rdar://problem/3872803> Darwin patches for Solaris and Suse
Don't use uint32_t, etc. -- they require stdint.h, which doesn't exist on FreeBSD 4.x, Solaris, etc.
{
ProxyHost *f = (ProxyHost*)rr->RecordContext;
if (result == mStatus_NoError)
- debugf("Host name successfully registered: %##s", rr->resrec.name.c);
+ debugf("Host name successfully registered: %##s", rr->resrec.name->c);
else
{
- debugf("Host name conflict for %##s", rr->resrec.name.c);
+ debugf("Host name conflict for %##s", rr->resrec.name->c);
mDNS_Deregister(m, &f->RR_A);
mDNS_Deregister(m, &f->RR_PTR);
exit(-1);
mDNS_SetupResourceRecord(&p->RR_A, mDNSNULL, mDNSInterface_Any, kDNSType_A, 60, kDNSRecordTypeUnique, HostNameCallback, p);
mDNS_SetupResourceRecord(&p->RR_PTR, mDNSNULL, mDNSInterface_Any, kDNSType_PTR, 60, kDNSRecordTypeKnownUnique, HostNameCallback, p);
- p->RR_A.resrec.name.c[0] = 0;
- AppendDomainLabel(&p->RR_A.resrec.name, &p->hostlabel);
- AppendLiteralLabelString(&p->RR_A.resrec.name, "local");
+ p->RR_A.resrec.name->c[0] = 0;
+ AppendDomainLabel(p->RR_A.resrec.name, &p->hostlabel);
+ AppendLiteralLabelString(p->RR_A.resrec.name, "local");
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);
+ MakeDomainNameFromDNSNameString(p->RR_PTR.resrec.name, buffer);
p->RR_A. resrec.rdata->u.ipv4 = p->ip;
- p->RR_PTR.resrec.rdata->u.name = p->RR_A.resrec.name;
+ AssignDomainName(&p->RR_PTR.resrec.rdata->u.name, p->RR_A.resrec.name);
mDNS_Register(m, &p->RR_A);
mDNS_Register(m, &p->RR_PTR);
- debugf("Made Proxy Host Records for %##s", p->RR_A.resrec.name.c);
+ debugf("Made Proxy Host Records for %##s", p->RR_A.resrec.name->c);
return(mStatus_NoError);
}
{
switch (result)
{
- case mStatus_NoError: debugf("Callback: %##s Name Registered", sr->RR_SRV.resrec.name.c); break;
- case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", sr->RR_SRV.resrec.name.c); break;
- case mStatus_MemFree: debugf("Callback: %##s Memory Free", sr->RR_SRV.resrec.name.c); break;
- default: debugf("Callback: %##s Unknown Result %ld", sr->RR_SRV.resrec.name.c, result); break;
+ case mStatus_NoError: debugf("Callback: %##s Name Registered", sr->RR_SRV.resrec.name->c); break;
+ case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", sr->RR_SRV.resrec.name->c); break;
+ case mStatus_MemFree: debugf("Callback: %##s Memory Free", sr->RR_SRV.resrec.name->c); break;
+ default: debugf("Callback: %##s Unknown Result %ld", sr->RR_SRV.resrec.name->c, result); break;
}
if (result == mStatus_NoError)
{
char buffer[MAX_ESCAPED_DOMAIN_NAME];
- ConvertDomainNameToCString(&sr->RR_SRV.resrec.name, buffer);
+ ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer);
printf("Service %s now registered and active\n", buffer);
}
if (result == mStatus_NameConflict)
{
char buffer1[MAX_ESCAPED_DOMAIN_NAME], buffer2[MAX_ESCAPED_DOMAIN_NAME];
- ConvertDomainNameToCString(&sr->RR_SRV.resrec.name, buffer1);
+ ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer1);
mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
- ConvertDomainNameToCString(&sr->RR_SRV.resrec.name, buffer2);
+ ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer2);
printf("Name Conflict! %s renamed as %s\n", buffer1, buffer2);
}
}
mDNSInterface_Any, // Interface ID
ServiceCallback, mDNSNULL); // Callback and context
- ConvertDomainNameToCString(&recordset->RR_SRV.resrec.name, buffer);
+ ConvertDomainNameToCString(recordset->RR_SRV.resrec.name, buffer);
printf("Made Service Records for %s\n", buffer);
}
domainname *proxyhostname = (domainname *)rr->RecordContext;
switch (result)
{
- case mStatus_NoError: debugf("Callback: %##s Name Registered", rr->resrec.name.c); break;
- case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", rr->resrec.name.c); break;
- case mStatus_MemFree: debugf("Callback: %##s Memory Free", rr->resrec.name.c); break;
- default: debugf("Callback: %##s Unknown Result %ld", rr->resrec.name.c, result); break;
+ case mStatus_NoError: debugf("Callback: %##s Name Registered", rr->resrec.name->c); break;
+ case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", rr->resrec.name->c); break;
+ case mStatus_MemFree: debugf("Callback: %##s Memory Free", rr->resrec.name->c); break;
+ default: debugf("Callback: %##s Unknown Result %ld", rr->resrec.name->c, result); break;
}
if (result == mStatus_NoError)
{
char buffer[MAX_ESCAPED_DOMAIN_NAME];
- ConvertDomainNameToCString(&rr->resrec.name, buffer);
+ ConvertDomainNameToCString(rr->resrec.name, buffer);
printf("Non-existence assertion %s now registered and active\n", buffer);
}
domainlabel n;
domainname t, d;
char buffer1[MAX_ESCAPED_DOMAIN_NAME], buffer2[MAX_ESCAPED_DOMAIN_NAME];
- ConvertDomainNameToCString(&rr->resrec.name, buffer1);
- DeconstructServiceName(&rr->resrec.name, &n, &t, &d);
+ ConvertDomainNameToCString(rr->resrec.name, buffer1);
+ DeconstructServiceName(rr->resrec.name, &n, &t, &d);
IncrementLabelSuffix(&n, mDNStrue);
mDNS_RegisterNoSuchService(m, rr, &n, &t, &d, proxyhostname, mDNSInterface_Any, NoSuchServiceCallback, mDNSNULL);
- ConvertDomainNameToCString(&rr->resrec.name, buffer2);
+ ConvertDomainNameToCString(rr->resrec.name, buffer2);
printf("Name Conflict! %s renamed as %s\n", buffer1, buffer2);
}
}
MakeDomainNameFromDNSNameString(&t, type);
MakeDomainNameFromDNSNameString(&d, domain);
mDNS_RegisterNoSuchService(m, rr, &n, &t, &d, proxyhostname, mDNSInterface_Any, NoSuchServiceCallback, proxyhostname);
- ConvertDomainNameToCString(&rr->resrec.name, buffer);
+ ConvertDomainNameToCString(rr->resrec.name, buffer);
printf("Made Non-existence Record for %s\n", buffer);
}
if (argc >=6)
RegisterService(&mDNSStorage, &proxyservice, argv[3], argv[4], "local.",
- &proxyhost.RR_A.resrec.name, atoi(argv[5]), argc-6, &argv[6]);
+ proxyhost.RR_A.resrec.name, atoi(argv[5]), argc-6, &argv[6]);
}
do
Change History (most recent first):
$Log: Responder.c,v $
+Revision 1.28 2005/01/11 01:55:26 ksekar
+Fix compile errors in Posix debug build
+
Revision 1.27 2004/12/01 04:28:43 cheshire
<rdar://problem/3872803> Darwin patches for Solaris and Suse
Use version of daemon() provided in mDNSUNP.c instead of local copy
switch (status) {
case mStatus_NoError:
- debugf("Callback: %##s Name Registered", thisRegistration->RR_SRV.resrec.name.c);
+ debugf("Callback: %##s Name Registered", thisRegistration->RR_SRV.resrec.name->c);
// Do nothing; our name was successfully registered. We may
// get more call backs in the future.
break;
case mStatus_NameConflict:
- debugf("Callback: %##s Name Conflict", thisRegistration->RR_SRV.resrec.name.c);
+ debugf("Callback: %##s Name Conflict", thisRegistration->RR_SRV.resrec.name->c);
// In the event of a conflict, this sample RegistrationCallback
// just calls mDNS_RenameAndReregisterService to automatically
break;
case mStatus_MemFree:
- debugf("Callback: %##s Memory Free", thisRegistration->RR_SRV.resrec.name.c);
+ debugf("Callback: %##s Memory Free", thisRegistration->RR_SRV.resrec.name->c);
// When debugging is enabled, make sure that thisRegistration
// is not on our gServiceList.
break;
default:
- debugf("Callback: %##s Unknown Status %ld", thisRegistration->RR_SRV.resrec.name.c, status);
+ debugf("Callback: %##s Unknown Status %ld", thisRegistration->RR_SRV.resrec.name->c, status);
break;
}
}
Change History (most recent first):
$Log: dnsextd.c,v $
+Revision 1.30 2005/01/27 22:57:56 cheshire
+Fix compile errors on gcc4
+
+Revision 1.29 2004/12/22 00:13:50 ksekar
+<rdar://problem/3873993> Change version, port, and polling interval for LLQ
+
+Revision 1.28 2004/12/17 00:30:00 ksekar
+<rdar://problem/3924045> dnsextd memory leak
+
+Revision 1.27 2004/12/17 00:27:32 ksekar
+Ignore SIGPIPE
+
+Revision 1.26 2004/12/17 00:21:33 ksekar
+Fixes for new CacheRecord structure with indirect name pointer
+
+Revision 1.25 2004/12/16 20:13:02 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
+Revision 1.24 2004/12/14 17:09:06 ksekar
+fixed incorrect usage instructions
+
Revision 1.23 2004/12/06 20:24:31 ksekar
<rdar://problem/3907303> dnsextd leaks sockets
#define LOOPBACK "127.0.0.1"
#define NS_PORT 53
-#define DAEMON_PORT 5355 // default, may be overridden via command line argument
+#define DAEMON_PORT 5352 // default, may be overridden via command line argument
#define LISTENQ 128 // tcp connection backlog
#define RECV_BUFLEN 9000
#define LEASETABLE_INIT_NBUCKETS 256 // initial hashtable size (doubles as table fills)
struct sockaddr_in cli; // client's source address
long expire; // expiration time, in seconds since epoch
domainname zone; // from zone field of update message
+ domainname name; // name of the record
CacheRecord rr; // last field in struct allows for allocation of oversized RRs
} RRTableElem;
// Verbose Logging (conditional on -v option)
mDNSlocal void VLog(const char *format, ...)
{
- unsigned char buffer[512];
+ char buffer[512];
va_list ptr;
if (!verbose) return;
// Unconditional Logging
mDNSlocal void Log(const char *format, ...)
{
- unsigned char buffer[512];
+ char buffer[512];
va_list ptr;
va_start(ptr,format);
int nread, allocsize;
mDNSu16 msglen = 0;
PktMsg *pkt = NULL;
- int srclen;
+ unsigned int srclen;
nread = my_recv(sd, &msglen, sizeof(msglen));
if (nread < 0) { LogErr("TCPRequestForkFn", "recv"); goto error; }
return mDNSfalse;
}
-// Allocate an appropriately sized CacheRecord and copy data from original
-mDNSlocal CacheRecord *CopyCacheRecord(CacheRecord *orig)
+// Allocate an appropriately sized CacheRecord and copy data from original.
+// Name pointer in CacheRecord object is set to point to the name specified
+//
+mDNSlocal CacheRecord *CopyCacheRecord(const CacheRecord *orig, domainname *name)
{
CacheRecord *cr;
size_t size = sizeof(*cr);
if (!cr) { LogErr("CopyCacheRecord", "malloc"); return NULL; }
memcpy(cr, orig, size);
cr->resrec.rdata = (RData*)&cr->rdatastorage;
+ cr->resrec.name = name;
+
return cr;
}
// delete all RRS of a given name/type
mDNSlocal mDNSu8 *putRRSetDeletion(DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit, ResourceRecord *rr)
{
- ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->name);
+ ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name);
if (!ptr || ptr + 10 >= limit) return NULL; // out of space
ptr[0] = (mDNSu8)(rr->rrtype >> 8);
ptr[1] = (mDNSu8)(rr->rrtype & 0xFF);
if (!gethostname(hostname, 1024) < 0 || MakeDomainNameFromDNSNameString(&rr.resrec.rdata->u.srv.target, hostname))
rr.resrec.rdata->u.srv.target.c[0] = '\0';
- MakeDomainNameFromDNSNameString(&rr.resrec.name, regtype);
- strcpy(rr.resrec.name.c + strlen(rr.resrec.name.c), d->zone.c);
+ MakeDomainNameFromDNSNameString(rr.resrec.name, regtype);
+ AppendDomainName(rr.resrec.name, &d->zone);
VLog("%s %s", registration ? "Registering SRV record" : "Deleting existing RRSet",
GetRRDisplayString_rdb(&rr.resrec, &rr.resrec.rdata->u, buf));
if (registration) ptr = PutResourceRecord(&pkt->msg, ptr, &pkt->msg.h.mDNS_numUpdates, &rr.resrec);
mDNSlocal int ReadAuthKey(int argc, char *argv[], DaemonInfo *d)
{
uDNS_AuthInfo *auth = NULL;
- char keybuf[512];
+ unsigned char keybuf[512];
mDNSs32 keylen;
auth = malloc(sizeof(*auth));
mDNSlocal void PrintUsage(void)
{
- fprintf(stderr, "Usage: dnsextd -z <zone> [-vf] [ -s server ] [-k zone keyname secret] ...\n"
+ fprintf(stderr, "Usage: dnsextd -z <zone> [-vf] [ -s server ] [-k keyname secret] ...\n"
"Use \"dnsextd -h\" for help\n");
}
}
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
+ if (d->AuthInfo) AssignDomainName(&d->AuthInfo->zone, &d->zone); // if we have a shared secret, use it for the entire zone
return 0;
arg_error:
if (!new) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; }
memcpy(&new->rr, &lcr.r, sizeof(CacheRecord) + lcr.r.resrec.rdlength - InlineCacheRDSize);
new->rr.resrec.rdata = (RData *)&new->rr.rdatastorage;
+ AssignDomainName(&new->name, lcr.r.resrec.name);
+ new->rr.resrec.name = &new->name;
new->expire = time.tv_sec + (unsigned)lease;
new->cli.sin_addr = pkt->src.sin_addr;
- strcpy(new->zone.c, zone.qname.c);
+ AssignDomainName(&new->zone, &zone.qname);
new->next = d->table[bucket];
d->table[bucket] = new;
d->nelems++;
mDNSlocal void FormatLLQOpt(AuthRecord *opt, int opcode, mDNSu8 *id, mDNSs32 lease)
{
bzero(opt, sizeof(*opt));
- opt->resrec.rdata = &opt->rdatastorage;
- opt->resrec.RecordType = kDNSRecordTypeKnownUnique; // to suppress warnings from other layers
- opt->resrec.rrtype = kDNSType_OPT;
+ mDNS_SetupResourceRecord(opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
opt->resrec.rdlength = LLQ_OPT_SIZE;
opt->resrec.rdestimate = LLQ_OPT_SIZE;
opt->resrec.rdata->u.opt.opt = kDNSOpt_LLQ;
//if (!rr) { LogErr("AnswerQuestion", "malloc"); goto end; }
ansptr = GetLargeResourceRecord(NULL, &reply->msg, ansptr, end, 0, kDNSRecordTypePacketAns, &lcr);
if (!ansptr) { Log("AnswerQuestions: GetLargeResourceRecord returned NULL"); goto end; }
- if (lcr.r.resrec.rrtype != e->qtype || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(&lcr.r.resrec.name, &e->qname))
+ if (lcr.r.resrec.rrtype != e->qtype || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->qname))
{
Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d. Discarding",
- lcr.r.resrec.name.c, lcr.r.resrec.rrtype, e->qname.c, e->qtype);
+ lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->qname.c, e->qtype);
}
else
{
- CacheRecord *cr = CopyCacheRecord(&lcr.r);
+ CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->qname);
if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; }
cr->next = AnswerList;
AnswerList = cr;
if (!ka)
{
// answer is not in KA list
- CacheRecord *cr = CopyCacheRecord(na);
+ CacheRecord *cr = CopyCacheRecord(na, &e->qname);
if (!cr) { Log("Error: UpdateAnswerList - CopyCacheRecord returned NULL"); return; }
cr->resrec.rroriginalttl = 1; // 1 means add
cr->next = e->KnownAnswers;
}
else
{
- CacheRecord *answers = AnswerQuestion(d, e, sd);
+ CacheRecord *tmp, *answers = AnswerQuestion(d, e, sd);
UpdateAnswerList(d, e, answers);
+ while (answers) { tmp = answers; answers = answers->next; free(tmp); }
e = e->next;
}
}
mDNSs32 serial = 0;
mDNSBool SerialInitialized = mDNSfalse;
int sd;
- LargeCacheRecord lcr;
+ LargeCacheRecord lcr;
ResourceRecord *rr = &lcr.r.resrec;
int i, sleeptime = 0;
domainname zone;
// create question
id.NotAnInteger = 0;
InitializeDNSMessage(&q.msg.h, id, flags);
- AssignDomainName(zone, d->zone);
+ 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);
{
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 (rr->rrtype != kDNSType_SOA || rr->rrclass != kDNSClass_IN || !SameDomainName(rr->name, &zone)) continue;
if (!SerialInitialized)
{
// first time through loop
// initialize structure
e->cli = cli;
- AssignDomainName(e->qname, *qname);
+ AssignDomainName(&e->qname, qname);
e->qtype = qtype;
memset(e->id, 0, 8);
e->state = RequestReceived;
{
UDPRequestArgs *req;
pthread_t tid;
- int clisize = sizeof(req->cliaddr);
+ unsigned int clisize = sizeof(req->cliaddr);
req = malloc(sizeof(UDPRequestArgs));
if (!req) { LogErr("RecvUDPRequest", "malloc"); return -1; }
{
TCPRequestArgs *req;
pthread_t tid;
- int clilen = sizeof(req->cliaddr);
+ unsigned int clilen = sizeof(req->cliaddr);
req = malloc(sizeof(TCPRequestArgs));
if (!req) { LogErr("RecvTCPRequest", "malloc"); return -1; }
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");
if (ProcessArgs(argc, argv, &d) < 0) exit(1);
Change History (most recent first):
$Log: mDNSPosix.c,v $
+Revision 1.69 2004/12/18 02:03:28 cheshire
+Need to #include "dns_sd.h"
+
+Revision 1.68 2004/12/18 00:51:52 cheshire
+Use symbolic constant kDNSServiceInterfaceIndexLocalOnly instead of (mDNSu32) ~0
+
+Revision 1.67 2004/12/17 23:37:48 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+(and other repetitive configuration changes)
+
Revision 1.66 2004/12/01 04:27:28 cheshire
<rdar://problem/3872803> Darwin patches for Solaris and Suse
Don't use uint32_t, etc. -- they require stdint.h, which doesn't exist on FreeBSD 4.x, Solaris, etc.
#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
#include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform
+#include "dns_sd.h"
#include <assert.h>
#include <stdio.h>
assert(m != NULL);
- if (index == (mDNSu32)~0) return(mDNSInterface_LocalOnly);
+ if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
intf = (PosixNetworkInterface*)(m->HostInterfaces);
while ( (intf != NULL) && (mDNSu32) intf->index != index)
assert(m != NULL);
- if (id == mDNSInterface_LocalOnly) return((mDNSu32)~0);
+ if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
intf = (PosixNetworkInterface*)(m->HostInterfaces);
while ( (intf != NULL) && (mDNSInterfaceID) intf != id)
// The interface is all ready to go, let's register it with the mDNS core.
if (err == 0)
- err = mDNS_RegisterInterface(m, &intf->coreIntf);
+ err = mDNS_RegisterInterface(m, &intf->coreIntf, 0);
// Clean up.
if (err == 0)
Change History (most recent first):
$Log: mDNSUNP.h,v $
+Revision 1.17 2004/12/17 19:32:43 cheshire
+Add missing semicolon
+
Revision 1.16 2004/12/01 04:25:05 cheshire
<rdar://problem/3872803> Darwin patches for Solaris and Suse
Provide daemon() for platforms that don't have it
extern void free_ifi_info(struct ifi_info *);
#ifdef NOT_HAVE_DAEMON
-extern int daemon(int nochdir, int noclose)
+extern int daemon(int nochdir, int noclose);
#endif
#ifdef __cplusplus
Change History (most recent first):
$Log: PlatformCommon.c,v $
+Revision 1.4 2005/01/19 19:19:21 ksekar
+<rdar://problem/3960191> Need a way to turn off domain discovery
+
Revision 1.3 2004/12/13 17:46:52 cheshire
Use sizeof(buf) instead of fixed constant 1024
a->ip.v4.NotAnInteger = addr.sin_addr.s_addr;
}
-// dst must be at least MAX_ESCAPED_DOMAIN_NAME bytes, and option must be less than 20 bytes in length
+// dst must be at least MAX_ESCAPED_DOMAIN_NAME bytes, and option must be less than 32 bytes in length
mDNSlocal mDNSBool GetConfigOption(char *dst, const char *option, FILE *f)
{
- char buf[20+1+MAX_ESCAPED_DOMAIN_NAME]; // Option name, one space, option value
+ char buf[32+1+MAX_ESCAPED_DOMAIN_NAME]; // Option name, one space, option value
unsigned int len = strlen(option);
if (len + 1 + MAX_ESCAPED_DOMAIN_NAME > sizeof(buf)-1) { LogMsg("GetConfigOption: option %s too long", option); return mDNSfalse; }
fseek(f, 0, SEEK_SET); // set position to beginning of stream
return mDNSfalse;
}
-mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain)
+mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled)
{
- char zone [MAX_ESCAPED_DOMAIN_NAME];
- char fqdn [MAX_ESCAPED_DOMAIN_NAME];
+ char buf [MAX_ESCAPED_DOMAIN_NAME];
char secret[MAX_ESCAPED_DOMAIN_NAME] = "";
int slen;
mStatus err;
FILE *f = fopen(filename, "r");
- hostname->c[0] = 0;
- domain->c[0] = 0;
+ if (hostname) hostname->c[0] = 0;
+ if (domain) domain->c[0] = 0;
+ if (DomainDiscoveryDisabled) *DomainDiscoveryDisabled = mDNSfalse;
if (f)
{
- if (GetConfigOption(fqdn, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, fqdn)) goto badf;
- if (GetConfigOption(zone, "zone", f) && !MakeDomainNameFromDNSNameString(domain, zone)) goto badf;
- GetConfigOption(secret, "secret-64", f); // failure means no authentication
+ if (DomainDiscoveryDisabled && GetConfigOption(buf, "DomainDiscoveryDisabled", f) && !strcasecmp(buf, "true")) *DomainDiscoveryDisabled = mDNStrue;
+ if (hostname && GetConfigOption(buf, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, buf)) goto badf;
+ if (domain && GetConfigOption(buf, "zone", f) && !MakeDomainNameFromDNSNameString(domain, buf)) goto badf;
+ GetConfigOption(secret, "secret-64", f); // failure means no authentication
fclose(f);
f = NULL;
}
return;
}
- if (secret[0])
+ if (domain && domain->c[0] && secret[0])
{
// for now we assume keyname = service reg domain and we use same key for service and hostname registration
slen = strlen(secret);
Change History (most recent first):
$Log: PlatformCommon.h,v $
+Revision 1.3 2005/01/19 19:19:21 ksekar
+<rdar://problem/3960191> Need a way to turn off domain discovery
+
Revision 1.2 2004/12/01 03:30:29 cheshire
<rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
*/
extern void FindDefaultRouteIP(mDNSAddr *a);
-extern void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain);
+extern void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled);
* by renaming the service. NoAutoRename overrides this behavior - with this
* flag set, name conflicts will result in a callback. The NoAutorename flag
* is only valid if a name is explicitly specified when registering a service
- * (ie the default name is not used.)
+ * (i.e. the default name is not used.)
*/
kDNSServiceFlagsShared = 0x10,
kDNSServiceErr_NoAuth = -65555,
kDNSServiceErr_NoSuchKey = -65556,
kDNSServiceErr_NATTraversal = -65557,
- kDNSServiceErr_DblNAT = -65558,
+ kDNSServiceErr_DoubleNAT = -65558,
kDNSServiceErr_BadTime = -65559
/* mDNS Error codes are in the range
* FFFE FF00 (-65792) to FFFE FFFF (-65537) */
*
* If the client passes kDNSServiceInterfaceIndexLocalOnly when registering
* a service, then that service will be found *only* by other local clients
- * on the same machine that pass kDNSServiceInterfaceIndexLocalOnly when browsing.
+ * on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly
+ * or kDNSServiceInterfaceIndexAny.
* If a client has a 'private' service, accessible only to other processes
* running on the same machine, this allows the client to advertise that service
* in a way such that it does not inadvertently appear in service lists on
* all the other machines on the network.
- * Note that to discover these special non-public services, the browsing
- * client also has to explicitly use kDNSServiceInterfaceIndexLocalOnly in its
- * DNSServiceBrowse() call. These special non-public services are not reported to
- * other clients on the same machine using interface index 0 or other index values.
*
* If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing
- * then it will find only records registered on that same local machine.
- * Note that this is *not* exactly symmetrical with the registering case:
- * Services advertised using LocalOnly are ONLY discovered by clients browsing
- * on LocalOnly; in contrast, clients browsing on LocalOnly find ALL services
- * advertised by this machine, not only those advertised on LocalOnly.
- * Clients explicitly wishing to discover only LocalOnly services can
+ * then it will find *all* records registered on that same local machine.
+ * Clients explicitly wishing to discover *only* LocalOnly services can
* accomplish this by inspecting the interfaceIndex of each service reported
* to their DNSServiceBrowseReply() callback function, and discarding those
* where the interface index is not kDNSServiceInterfaceIndexLocalOnly.
Change History (most recent first):
$Log: dnssd_clientshim.c,v $
+Revision 1.8 2004/12/16 20:47:34 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.7 2004/12/10 04:08:43 cheshire
Added comments about autoname and autorename
char namestr[MAX_DOMAIN_LABEL+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
char typestr[MAX_ESCAPED_DOMAIN_NAME];
char domstr [MAX_ESCAPED_DOMAIN_NAME];
- if (!DeconstructServiceName(&sr->RR_SRV.resrec.name, &name, &type, &dom)) return;
+ if (!DeconstructServiceName(sr->RR_SRV.resrec.name, &name, &type, &dom)) return;
if (!ConvertDomainLabelToCString_unescaped(&name, namestr)) return;
if (!ConvertDomainNameToCString(&type, typestr)) return;
if (!ConvertDomainNameToCString(&dom, domstr)) return;
if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain))
{
LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
- answer->name.c, answer->rdata->u.name.c);
+ answer->name->c, answer->rdata->u.name.c);
return;
}
if (x->SRV && x->TXT && x->callback)
{
char fullname[MAX_ESCAPED_DOMAIN_NAME], targethost[MAX_ESCAPED_DOMAIN_NAME];
- ConvertDomainNameToCString(&answer->name, fullname);
+ ConvertDomainNameToCString(answer->name, fullname);
ConvertDomainNameToCString(&x->SRV->rdata->u.srv.target, targethost);
x->callback((DNSServiceRef)x, 0, 0, kDNSServiceErr_NoError, fullname, targethost,
x->SRV->rdata->u.srv.port.NotAnInteger, x->TXT->rdlength, (char*)x->TXT->rdata->u.txt.c, x->context);
x->qSRV.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
x->qSRV.InterfaceID = mDNSInterface_Any;
x->qSRV.Target = zeroAddr;
- AssignDomainName(x->qSRV.qname, srv);
+ AssignDomainName(&x->qSRV.qname, &srv);
x->qSRV.qtype = kDNSType_SRV;
x->qSRV.qclass = kDNSClass_IN;
x->qSRV.LongLived = mDNSfalse;
x->qTXT.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
x->qTXT.InterfaceID = mDNSInterface_Any;
x->qTXT.Target = zeroAddr;
- AssignDomainName(x->qTXT.qname, srv);
+ AssignDomainName(&x->qTXT.qname, &srv);
x->qTXT.qtype = kDNSType_TXT;
x->qTXT.qclass = kDNSClass_IN;
x->qTXT.LongLived = mDNSfalse;
mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)question->QuestionContext;
char fullname[MAX_ESCAPED_DOMAIN_NAME];
(void)m; // Unused
- ConvertDomainNameToCString(&answer->name, fullname);
+ ConvertDomainNameToCString(answer->name, fullname);
x->callback((DNSServiceRef)x, AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0, 0, kDNSServiceErr_NoError,
fullname, answer->rrtype, answer->rrclass, answer->rdlength, answer->rdata->u.data, answer->rroriginalttl, x->context);
}
Change History (most recent first):
$Log: dnssd_clientstub.c,v $
+Revision 1.44 2005/01/27 22:57:56 cheshire
+Fix compile errors on gcc4
+
+Revision 1.43 2005/01/27 00:02:29 cheshire
+<rdar://problem/3947461> Handle case where client runs before daemon has finished launching
+
+Revision 1.42 2005/01/11 02:01:02 shersche
+Use dnssd_close() rather than close() for Windows compatibility
+
+Revision 1.41 2004/12/23 17:34:26 ksekar
+<rdar://problem/3931319> Rendevzous calls leak sockets if mDNSResponder is not running
+
Revision 1.40 2004/11/23 03:39:47 cheshire
Let interface name/index mapping capability live directly in JNISupport.c,
instead of having to call through to the daemon via IPC to get this information.
{
dnssd_sockaddr_t saddr;
DNSServiceRef sdr;
+ int NumTries = 0;
#if defined(_WIN32)
if (!g_initWinsock)
saddr.sun_family = AF_LOCAL;
strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH);
#endif
- if (connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) { free(sdr); return NULL; }
+ while (1)
+ {
+ int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr));
+ if (!err) break; // If we succeeded, return sdr
+ // If we failed, then it may be because the daemon is still launching.
+ // This can happen for processes that launch early in the boot process, while the
+ // daemon is still coming up. Rather than fail here, we'll wait a bit and try again.
+ // If, after ten seconds, we still can't connect to the daemon,
+ // then we give up and return a failure code.
+ if (++NumTries < 10)
+ sleep(1); // Sleep a bit, then try again
+ else
+ {
+ dnssd_close(sdr->sockfd);
+ sdr->sockfd = dnssd_InvalidSocket;
+ free(sdr);
+ return NULL;
+ }
+ }
return sdr;
}
dnssd_sockaddr_t caddr, daddr; // (client and daemon address structs)
char *data = (char *)msg + sizeof(ipc_msg_hdr);
dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
- int ret, len = sizeof(caddr);
+ int ret;
+ unsigned int len = sizeof(caddr);
DNSServiceErrorType err = kDNSServiceErr_Unknown;
if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown;
Change History (most recent first):
$Log: dnssd_ipc.c,v $
+Revision 1.15 2005/01/27 22:57:56 cheshire
+Fix compile errors on gcc4
+
Revision 1.14 2004/10/06 02:22:20 cheshire
Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
return overrun;
}
-void put_rdata(const int rdlen, const char *rdata, char **ptr)
+void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr)
{
memcpy(*ptr, rdata, rdlen);
*ptr += rdlen;
Change History (most recent first):
$Log: dnssd_ipc.h,v $
+Revision 1.18 2005/01/27 22:57:56 cheshire
+Fix compile errors on gcc4
+
Revision 1.17 2004/11/23 03:39:47 cheshire
Let interface name/index mapping capability live directly in JNISupport.c,
instead of having to call through to the daemon via IPC to get this information.
int put_string(const char *str, char **ptr);
int get_string(char **ptr, char *buffer, int buflen);
-void put_rdata(const int rdlen, const char *rdata, char **ptr);
+void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr);
char *get_rdata(char **ptr, int rdlen); // return value is rdata pointed to by *ptr -
// rdata is not copied from buffer.
Change History (most recent first):
$Log: mDNSDebug.c,v $
+Revision 1.6 2005/01/27 22:57:56 cheshire
+Fix compile errors on gcc4
+
Revision 1.5 2004/09/17 01:08:55 cheshire
Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
// Log message with default "mDNSResponder" ident string at the start
mDNSexport void LogMsg(const char *format, ...)
{
- unsigned char buffer[512];
+ char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
// Log message with specified ident string at the start
mDNSexport void LogMsgIdent(const char *ident, const char *format, ...)
{
- unsigned char buffer[512];
+ char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
// Log message with no ident string at the start
mDNSexport void LogMsgNoIdent(const char *format, ...)
{
- unsigned char buffer[512];
+ char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
Change History (most recent first):
$Log: uds_daemon.c,v $
+Revision 1.164 2005/01/28 06:07:55 cheshire
+Don't use deliver_error() from within handle_regrecord_request()
+
+Revision 1.163 2005/01/28 01:39:16 cheshire
+Include file descriptor number in "broken pipe" message
+
+Revision 1.162 2005/01/27 23:59:20 cheshire
+Remove extraneous LogMsg
+
+Revision 1.161 2005/01/27 22:57:56 cheshire
+Fix compile errors on gcc4
+
+Revision 1.160 2005/01/27 20:52:11 cheshire
+<rdar://problem/3972566> mDNSResponder leaks sockets for add/update/remove record calls
+
+Revision 1.159 2005/01/27 01:45:25 cheshire
+<rdar://problem/3976147> mDNSResponder should never call exit(1);
+
+Revision 1.158 2005/01/25 17:28:07 ksekar
+<rdar://problem/3971467> Should not return "local" twice for domain enumeration
+
+Revision 1.157 2005/01/21 02:20:39 cheshire
+Fix mistake in LogOperation() format string
+
+Revision 1.156 2005/01/19 19:15:36 ksekar
+Refinement to <rdar://problem/3954575> - Simplify mDNS_PurgeResultsForDomain logic and move into daemon layer
+
+Revision 1.155 2005/01/19 03:00:47 cheshire
+Show Add/Rmv in DNSServiceBrowse LogOperation() message
+
+Revision 1.154 2005/01/15 00:56:42 ksekar
+<rdar://problem/3954575> Unicast services don't disappear when logging
+out of VPN
+
+Revision 1.153 2005/01/14 18:44:28 ksekar
+<rdar://problem/3954609> mDNSResponder is crashing when changing domains
+
+Revision 1.152 2005/01/13 17:16:38 ksekar
+Back out checkin 1.150 - correct fix is on clientstub side
+
+Revision 1.151 2005/01/11 21:06:29 ksekar
+Changed now-benign LogMsg to debugf
+
+Revision 1.150 2005/01/07 23:59:15 ksekar
+<rdar://problem/3942900> dnd-sd shows the wrong port numbers
+
+Revision 1.149 2004/12/20 23:20:35 cheshire
+<rdar://problem/3928361> mDNSResponder crashes repeatedly when printer sharing is enabled
+Make sure to call mDNS_SetupResourceRecord() for all newly created AuthRecords
+
+Revision 1.148 2004/12/20 20:37:35 cheshire
+AllowRemoteQuery not set for the extras in a ServiceRecordSet
+
+Revision 1.147 2004/12/20 00:15:41 cheshire
+Include client file descriptor numbers in udsserver_info() output
+
+Revision 1.146 2004/12/17 05:25:47 cheshire
+<rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
+
+Revision 1.145 2004/12/16 21:39:46 cheshire
+Include CacheGroup objects in CacheUsed count
+
+Revision 1.144 2004/12/16 21:27:38 ksekar
+Fixed build failures when compiled with verbose debugging messages
+
+Revision 1.143 2004/12/16 20:13:02 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
+Revision 1.142 2004/12/16 08:07:33 shersche
+Fix compiler error (mixed declarations and code) on Windows
+
+Revision 1.141 2004/12/16 01:56:21 cheshire
+Improve DNSServiceEnumerateDomains syslog message
+
+Revision 1.140 2004/12/14 03:02:10 ksekar
+<rdar://problem/3919016> Rare race condition can cause crash
+
Revision 1.139 2004/12/13 21:18:45 ksekar
Include uDNS registrations in CountPeerRegistrations
// to facilitate cleanup, when instances and parent may be deallocated at different times.
typedef struct service_instance
{
- struct service_instance *next;
+ struct service_instance *next;
mDNSBool autoname; // Set if this name is tied to the Computer Name
mDNSBool autorename; // Set if this client wants us to automatically rename on conflict
mDNSBool allowremotequery; // Respond to unicast queries from outside the local link?
struct request_state *request;
int sd;
AuthRecord *subtypes;
- ServiceRecordSet srs; // note - must be last field in struct
+ ServiceRecordSet srs; // note - must be last field in struct
} service_instance;
// A client-created service. May reference several service_info objects if default
browser_t *browsers;
} browser_info_t;
-typedef struct
+typedef struct
{
mStatus err; // Note: This field is in NETWORK byte order
int nwritten;
typedef struct request_state
{
// connection structures
- dnssd_sock_t sd, errfd;
-
- // state of read (in case message is read over several recv() calls)
+ dnssd_sock_t sd;
+
+ // state of read (in case message is read over several recv() calls)
transfer_state ts;
uint32_t hdr_bytes; // bytes of header already read
ipc_msg_hdr hdr;
undelivered_error_t *u_err;
void *termination_context;
req_termination_fn terminate;
-
+
//!!!KRS toss these pointers in a union
// registration context associated with this request (null if not applicable)
registered_record_entry *reg_recs; // muliple registrations for a connection-oriented request
uint32_t ifi; // Note: This field is in NETWORK byte order
DNSServiceErrorType error; // Note: This field is in NETWORK byte order
} reply_hdr;
-
typedef struct reply_state
{
reply_hdr *rhdr;
char *sdata; // pointer to start of call-specific data
// pointer to malloc'd buffer
- char *msgbuf;
+ char *msgbuf;
} reply_state;
-
// domain enumeration and resolv calls require 2 mDNSCore calls, so we need separate interconnected
// structures to handle callbacks
typedef struct
mDNSu16 txtlen;
mDNSu8 txtdata[AbsoluteMaxDNSMessageData];
} resolve_termination_t;
-
+
#ifdef _HAVE_SETDOMAIN_SUPPORT_
typedef struct default_browse_list_t
{
mDNSexport mDNS mDNSStorage;
#define gmDNS (&mDNSStorage)
-static dnssd_sock_t listenfd = dnssd_InvalidSocket;
-static request_state * all_requests = NULL;
+static dnssd_sock_t listenfd = dnssd_InvalidSocket;
+static request_state * all_requests = NULL;
#define MAX_TIME_BLOCKED 60 * mDNSPlatformOneSecond // try to send data to a blocked client for 60 seconds before
// terminating connection
#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
+ // 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 void regservice_termination_callback(void *context);
static void process_service_registration(ServiceRecordSet *const srs);
static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
-static void handle_add_request(request_state *rstate);
-static void handle_update_request(request_state *rstate);
+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 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 void handle_regrecord_request(request_state *rstate);
+static mStatus handle_regrecord_request(request_state *rstate);
static void regrecord_callback(mDNS *const m, AuthRecord *const 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 void handle_removerecord_request(request_state *rstate);
+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);
#define PID_FILE "/var/run/mDNSResponder.pid"
#endif
+static 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
+ abort(); // On platforms where writing to zero doesn't generate an exception, abort instead
+ }
+
int udsserver_init(void)
- {
+ {
dnssd_sockaddr_t laddr;
int ret;
#if defined(_WIN32)
bzero(&laddr, sizeof(laddr));
-#if defined(USE_TCP_LOOPBACK)
+ #if defined(USE_TCP_LOOPBACK)
{
laddr.sin_family = AF_INET;
laddr.sin_port = htons(MDNS_TCP_SERVERPORT);
if (ret < 0)
goto error;
}
-#else
+ #else
{
mode_t mask = umask(0);
unlink(MDNS_UDS_SERVERPATH); //OK if this fails
laddr.sun_family = AF_LOCAL;
-# ifndef NOT_HAVE_SA_LEN
- // According to Stevens (section 3.2), there is no portable way to
- // determine whether sa_len is defined on a particular platform.
+ #ifndef NOT_HAVE_SA_LEN
+ // According to Stevens (section 3.2), there is no portable way to
+ // determine whether sa_len is defined on a particular platform.
laddr.sun_len = sizeof(struct sockaddr_un);
-# endif
+ #endif
strcpy(laddr.sun_path, MDNS_UDS_SERVERPATH);
ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
umask(mask);
if (ret < 0)
goto error;
}
-#endif
+ #endif
-#if defined(_WIN32)
+ #if defined(_WIN32)
//
// SEH: do we even need to do this on windows? this socket
// will be given to WSAEventSelect which will automatically
// set it to non-blocking
//
if (ioctlsocket(listenfd, FIONBIO, &opt) != 0)
-#else
+ #else
if (fcntl(listenfd, F_SETFL, O_NONBLOCK) != 0)
-#endif
+ #endif
{
my_perror("ERROR: could not set listen socket to non-blocking mode");
goto error;
return 0;
}
-
mDNSs32 udsserver_idle(mDNSs32 nextevent)
{
request_state *req = all_requests, *tmp, *prev = NULL;
reply_state *fptr;
- transfer_state result;
+ transfer_state result;
mDNSs32 now = mDNS_TimeNow(&mDNSStorage);
while(req)
{
result = t_uninitialized;
- if (req->u_err)
+ if (req->u_err)
result = send_undelivered_error(req);
if (result != t_error && result != t_morecoming && // don't try to send msg if send_error failed
(req->ts == t_complete || req->ts == t_morecoming))
}
}
if (result == t_morecoming)
- {
+ {
if (!req->time_blocked) req->time_blocked = now;
debugf("udsserver_idle: client has been blocked for %ld seconds", (now - req->time_blocked) / mDNSPlatformOneSecond);
if (now - req->time_blocked >= MAX_TIME_BLOCKED)
}
else if (nextevent - now > mDNSPlatformOneSecond) nextevent = now + mDNSPlatformOneSecond; // try again in a second
}
- if (result == t_terminated || result == t_error)
+ 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()
{
tmp = req;
req = req->next;
freeL("udsserver_idle", tmp);
}
- else
+ else
{
prev = req;
req = req->next;
mDNSs32 now = mDNS_TimeNow(m);
mDNSu32 CacheUsed = 0, CacheActive = 0;
mDNSu32 slot;
+ CacheGroup *cg;
+ CacheRecord *rr;
request_state *req;
LogMsgNoIdent("Timenow 0x%08lX (%ld)", (mDNSu32)now, now);
for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
- {
- mDNSu32 SlotUsed = 0;
- CacheRecord *rr;
- for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
+ for(cg = m->rrcache_hash[slot]; cg; cg=cg->next)
{
- mDNSs32 remain = rr->resrec.rroriginalttl - (now - rr->TimeRcvd) / mDNSPlatformOneSecond;
- CacheUsed++;
- SlotUsed++;
- if (rr->CRActiveQuestion) CacheActive++;
- LogMsgNoIdent("%s%6ld %s%-6s%-6s%s",
- rr->CRActiveQuestion ? "*" : " ", remain,
- (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? "-" : " ", DNSTypeName(rr->resrec.rrtype),
- ((NetworkInterfaceInfo *)rr->resrec.InterfaceID)->ifname, CRDisplayString(m, rr));
- usleep(1000); // Limit rate a little so we don't flood syslog too fast
+ CacheUsed++; // Count one cache entity for the CacheGroup object
+ for (rr = cg->members; rr; rr=rr->next)
+ {
+ mDNSs32 remain = rr->resrec.rroriginalttl - (now - rr->TimeRcvd) / mDNSPlatformOneSecond;
+ CacheUsed++;
+ if (rr->CRActiveQuestion) CacheActive++;
+ LogMsgNoIdent("%s%6ld %s%-6s%-6s%s",
+ rr->CRActiveQuestion ? "*" : " ", remain,
+ (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? "-" : " ", DNSTypeName(rr->resrec.rrtype),
+ ((NetworkInterfaceInfo *)rr->resrec.InterfaceID)->ifname, CRDisplayString(m, rr));
+ usleep(1000); // Limit rate a little so we don't flood syslog too fast
+ }
}
- if (m->rrcache_used[slot] != SlotUsed)
- LogMsgNoIdent("Cache use mismatch: rrcache_used[slot] is %lu, true count %lu", m->rrcache_used[slot], SlotUsed);
- }
+
if (m->rrcache_totalused != CacheUsed)
LogMsgNoIdent("Cache use mismatch: rrcache_totalused is %lu, true count %lu", m->rrcache_totalused, CacheUsed);
if (m->rrcache_active != CacheActive)
{
service_instance *ptr;
for (ptr = ((service_info *)t)->instances; ptr; ptr = ptr->next)
- LogMsgNoIdent("DNSServiceRegister %##s %u", ptr->srs.RR_SRV.resrec.name.c, SRS_PORT(&ptr->srs));
+ LogMsgNoIdent("%3d: DNSServiceRegister %##s %u", req->sd, ptr->srs.RR_SRV.resrec.name->c, SRS_PORT(&ptr->srs));
}
else if (req->terminate == browse_termination_callback)
{
browser_t *blist;
for (blist = req->browser_info->browsers; blist; blist = blist->next)
- LogMsgNoIdent("DNSServiceBrowse %##s", blist->q.qname.c);
+ LogMsgNoIdent("%3d: DNSServiceBrowse %##s", req->sd, blist->q.qname.c);
}
else if (req->terminate == resolve_termination_callback)
- LogMsgNoIdent("DNSServiceResolve %##s", ((resolve_termination_t *)t)->qsrv.qname.c);
+ LogMsgNoIdent("%3d: DNSServiceResolve %##s", req->sd, ((resolve_termination_t *)t)->qsrv.qname.c);
else if (req->terminate == question_termination_callback)
- LogMsgNoIdent("DNSServiceQueryRecord %##s", ((DNSQuestion *) t)->qname.c);
+ LogMsgNoIdent("%3d: DNSServiceQueryRecord %##s", req->sd, ((DNSQuestion *) t)->qname.c);
else if (req->terminate == enum_termination_callback)
- LogMsgNoIdent("DNSServiceEnumerateDomains %##s", ((enum_termination_t *) t)->all->question.qname.c);
+ LogMsgNoIdent("%3d: DNSServiceEnumerateDomains %##s", req->sd, ((enum_termination_t *) t)->all->question.qname.c);
}
now = mDNS_TimeNow(m);
srv->rename_on_memfree = 1;
if (mDNS_DeregisterService(gmDNS, &srv->srs)) // If service deregistered already, we can re-register immediately
regservice_callback(gmDNS, &srv->srs, mStatus_MemFree);
- }
+ }
}
void udsserver_handle_configchange(void)
static void connect_callback(void *info)
{
dnssd_sock_t sd;
- int len;
+ unsigned int len;
unsigned long optval;
dnssd_sockaddr_t cliaddr;
request_state *rstate;
if (sd == dnssd_InvalidSocket)
{
- if (dnssd_errno() == dnssd_EWOULDBLOCK) return;
+ if (dnssd_errno() == dnssd_EWOULDBLOCK) return;
my_perror("ERROR: accept");
return;
}
// Some environments (e.g. OS X) support turning off SIGPIPE for a socket
if (setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
{
- my_perror("ERROR: setsockopt - SOL_NOSIGPIPE - aborting client");
+ my_perror("ERROR: setsockopt - SO_NOSIGPIPE - aborting client");
dnssd_close(sd);
return;
}
if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0)
#endif
{
- my_perror("ERROR: setsockopt - SOL_NOSIGPIPE - aborting client");
+ my_perror("ERROR: fcntl(sd, F_SETFL, O_NONBLOCK) - aborting client");
dnssd_close(sd);
return;
}
// allocate a request_state struct that will live with the socket
rstate = mallocL("connect_callback", sizeof(request_state));
- if (!rstate)
- {
- my_perror("ERROR: malloc");
- exit(1);
- }
+ if (!rstate) FatalError("ERROR: malloc");
bzero(rstate, sizeof(request_state));
rstate->ts = t_morecoming;
rstate->sd = sd;
all_requests = rstate;
}
-
// handler
static void request_callback(void *info)
- {
- request_state *rstate = info;
- transfer_state result;
- dnssd_sockaddr_t cliaddr;
+ {
+ request_state *rstate = info;
+ transfer_state result;
+ dnssd_sockaddr_t cliaddr;
+ int dedicated_error_socket;
#if defined(_WIN32)
- u_long opt = 1;
+ u_long opt = 1;
#endif
-
- result = read_msg(rstate);
- if (result == t_morecoming)
- {
- return;
- }
- if (result == t_terminated)
- {
- abort_request(rstate);
- unlink_request(rstate);
- return;
- }
- if (result == t_error)
- {
- abort_request(rstate);
- unlink_request(rstate);
- return;
- }
-
- if (rstate->hdr.version != VERSION)
- {
- LogMsg("ERROR: client incompatible with daemon (client version = %d, "
- "daemon version = %d)\n", rstate->hdr.version, VERSION);
- abort_request(rstate);
- unlink_request(rstate);
- return;
- }
-
- if (validate_message(rstate) < 0)
- {
- // note that we cannot deliver an error message if validation fails, since the path to the error socket
- // may be contained in the (invalid) message body for some message types
- abort_request(rstate);
- unlink_request(rstate);
- LogMsg("Invalid message sent by client - may indicate a malicious program running on this machine!");
- return;
- }
-
- // check if client wants silent operation
- if (rstate->hdr.flags & IPC_FLAGS_NOREPLY) rstate->no_reply = 1;
-
- // check if primary socket is to be used for synchronous errors, else open new socket
- if (rstate->hdr.flags & IPC_FLAGS_REUSE_SOCKET)
- rstate->errfd = rstate->sd;
- else
+
+ result = read_msg(rstate);
+ if (result == t_morecoming)
{
- if ((rstate->errfd = socket(AF_DNSSD, SOCK_STREAM, 0)) == dnssd_InvalidSocket)
- {
- my_perror("ERROR: socket");
- exit(1);
- }
+ return;
+ }
+ if (result == t_terminated)
+ {
+ abort_request(rstate);
+ unlink_request(rstate);
+ return;
+ }
+ if (result == t_error)
+ {
+ abort_request(rstate);
+ unlink_request(rstate);
+ return;
+ }
-#if defined(USE_TCP_LOOPBACK)
+ if (rstate->hdr.version != VERSION)
{
- mDNSOpaque16 port;
- port.b[0] = rstate->msgdata[0];
- port.b[1] = rstate->msgdata[1];
- rstate->msgdata += 2;
- cliaddr.sin_family = AF_INET;
- cliaddr.sin_port = port.NotAnInteger;
- cliaddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
+ LogMsg("ERROR: client incompatible with daemon (client version = %d, "
+ "daemon version = %d)\n", rstate->hdr.version, VERSION);
+ abort_request(rstate);
+ unlink_request(rstate);
+ return;
}
-#else
+
+ if (validate_message(rstate) < 0)
{
- char ctrl_path[MAX_CTLPATH];
- get_string(&rstate->msgdata, ctrl_path, 256); // path is first element in message buffer
- bzero(&cliaddr, sizeof(cliaddr));
- cliaddr.sun_family = AF_LOCAL;
- strcpy(cliaddr.sun_path, ctrl_path);
+ // note that we cannot deliver an error message if validation fails, since the path to the error socket
+ // may be contained in the (invalid) message body for some message types
+ abort_request(rstate);
+ unlink_request(rstate);
+ LogMsg("Invalid message sent by client - may indicate a malicious program running on this machine!");
+ return;
}
-#endif
- if (connect(rstate->errfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0)
- {
- my_perror("ERROR: connect");
- abort_request(rstate);
- unlink_request(rstate);
+
+ // check if client wants silent operation
+ if (rstate->hdr.flags & IPC_FLAGS_NOREPLY) rstate->no_reply = 1;
+
+ dedicated_error_socket = (rstate->hdr.op == reg_record_request || rstate->hdr.op == add_record_request ||
+ rstate->hdr.op == update_record_request || rstate->hdr.op == remove_record_request);
+
+ if (((rstate->hdr.flags & IPC_FLAGS_REUSE_SOCKET) == 0) != dedicated_error_socket)
+ LogMsg("WARNING: client request %d with incorrect flags setting 0x%X", rstate->hdr.op, rstate->hdr.flags);
+
+ // check if primary socket is to be used for synchronous errors, else open new socket
+ if (dedicated_error_socket)
+ {
+ mStatus err = 0;
+ int nwritten;
+ int errfd = socket(AF_DNSSD, SOCK_STREAM, 0);
+ if (errfd == dnssd_InvalidSocket)
+ {
+ my_perror("ERROR: socket");
+ abort_request(rstate);
+ unlink_request(rstate);
return;
- }
+ }
+
+ #if defined(USE_TCP_LOOPBACK)
+ {
+ mDNSOpaque16 port;
+ port.b[0] = rstate->msgdata[0];
+ port.b[1] = rstate->msgdata[1];
+ rstate->msgdata += 2;
+ cliaddr.sin_family = AF_INET;
+ cliaddr.sin_port = port.NotAnInteger;
+ cliaddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
+ }
+ #else
+ {
+ char ctrl_path[MAX_CTLPATH];
+ get_string(&rstate->msgdata, ctrl_path, 256); // path is first element in message buffer
+ bzero(&cliaddr, sizeof(cliaddr));
+ cliaddr.sun_family = AF_LOCAL;
+ strcpy(cliaddr.sun_path, ctrl_path);
+ }
+ #endif
+ if (connect(errfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0)
+ {
+ my_perror("ERROR: connect");
+ abort_request(rstate);
+ unlink_request(rstate);
+ return;
+ }
#if defined(_WIN32)
- if (ioctlsocket(rstate->errfd, FIONBIO, &opt) != 0)
+ if (ioctlsocket(errfd, FIONBIO, &opt) != 0)
#else
- if (fcntl(rstate->errfd, F_SETFL, O_NONBLOCK) != 0)
+ if (fcntl(errfd, F_SETFL, O_NONBLOCK) != 0)
#endif
- {
- my_perror("ERROR: could not set control socket to non-blocking mode");
- abort_request(rstate);
- unlink_request(rstate);
- return;
- }
- }
+ {
+ my_perror("ERROR: could not set control socket to non-blocking mode");
+ abort_request(rstate);
+ unlink_request(rstate);
+ return;
+ }
- switch(rstate->hdr.op)
- {
- case resolve_request: handle_resolve_request(rstate); break;
- case query_request: handle_query_request(rstate); break;
- case browse_request: handle_browse_request(rstate); break;
- case reg_service_request: handle_regservice_request(rstate); break;
- case enumeration_request: handle_enum_request(rstate); break;
- case reg_record_request: handle_regrecord_request(rstate); break;
- case add_record_request: handle_add_request(rstate); break;
- case update_record_request: handle_update_request(rstate); break;
- case remove_record_request: handle_removerecord_request(rstate); break;
- case reconfirm_record_request: handle_reconfirm_request(rstate); break;
- case setdomain_request: handle_setdomain_request(rstate); break;
- default:
- LogMsg("%3d: ERROR: udsserver_recv_request - unsupported request type: %d", rstate->sd, rstate->hdr.op);
- }
- }
+ switch(rstate->hdr.op)
+ {
+ case reg_record_request: err = handle_regrecord_request (rstate); break;
+ case add_record_request: err = handle_add_request (rstate); break;
+ case update_record_request: err = handle_update_request (rstate); break;
+ case remove_record_request: err = handle_removerecord_request(rstate); break;
+ default: LogMsg("%3d: ERROR: udsserver_recv_request - unsupported request type: %d", rstate->sd, rstate->hdr.op);
+ }
+
+ err = dnssd_htonl(err);
+ nwritten = send(errfd, &err, sizeof(err), 0);
+ // On a freshly-created Unix Domain Socket, the kernel should *never* fail to buffer a four-byte write for us.
+ // If not, we don't attempt to handle this failure, but we do log it.
+ if (nwritten < (int)sizeof(err))
+ LogMsg("ERROR: failed to write error response back to caller: %d %d %s",
+ nwritten, dnssd_errno(), dnssd_strerror(dnssd_errno()));
+ dnssd_close(errfd);
+ reset_connected_rstate(rstate); // Reset ready to accept the next request on this pipe
+ }
+ else
+ {
+ switch(rstate->hdr.op)
+ {
+ case resolve_request: handle_resolve_request (rstate); break;
+ case query_request: handle_query_request (rstate); break;
+ case browse_request: handle_browse_request (rstate); break;
+ case reg_service_request: handle_regservice_request(rstate); break;
+ case enumeration_request: handle_enum_request (rstate); break;
+ case reconfirm_record_request: handle_reconfirm_request (rstate); break;
+ case setdomain_request: handle_setdomain_request (rstate); break;
+ default: LogMsg("%3d: ERROR: udsserver_recv_request - unsupported request type: %d", rstate->sd, rstate->hdr.op);
+ }
+ }
+ }
// mDNS operation functions. Each operation has 3 associated functions - a request handler that parses
// the client's request and makes the appropriate mDNSCore call, a result handler (passed as a callback
// to the mDNSCore routine) that sends results back to the client, and a termination routine that aborts
// the mDNSCore operation if the client dies or closes its socket.
-
// query and resolve calls have separate request handlers that parse the arguments from the client and
// 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.
if (ifi && !InterfaceID) goto bad_param;
q = mallocL("DNSQuestion", sizeof(DNSQuestion));
- if (!q)
- {
- my_perror("ERROR: handle_query - malloc");
- exit(1);
- }
- bzero(q, sizeof(DNSQuestion));
+ if (!q) FatalError("ERROR: handle_query - malloc");
+ bzero(q, sizeof(DNSQuestion));
q->InterfaceID = InterfaceID;
q->Target = zeroAddr;
- if (!MakeDomainNameFromDNSNameString(&q->qname, name)) { freeL("DNSQuestion", q); goto bad_param; }
+ if (!MakeDomainNameFromDNSNameString(&q->qname, name)) { freeL("DNSQuestion", q); goto bad_param; }
q->qtype = rrtype;
q->qclass = rrclass;
q->LongLived = (flags & kDNSServiceFlagsLongLivedQuery) != 0;
// free memory in rstate since we don't need it anymore
freeL("handle_resolve_request", rstate->msgbuf);
rstate->msgbuf = NULL;
-
+
if (build_domainname_from_strings(&fqdn, name, regtype, domain) < 0)
{ LogMsg("ERROR: handle_resolve_request - Couldn't build_domainname_from_strings “%s” “%s” “%s”", name, regtype, domain); goto bad_param; }
// set up termination info
term = mallocL("handle_resolve_request", sizeof(resolve_termination_t));
bzero(term, sizeof(*term));
- if (!term) goto malloc_error;
+ if (!term) FatalError("ERROR: malloc");
// format questions
term->qsrv.InterfaceID = InterfaceID;
freeL("handle_resolve_request", term);
rstate->terminate = NULL; // prevent abort_request() from invoking termination callback
}
- if (deliver_error(rstate, err) < 0 || err)
+ if (deliver_error(rstate, err) < 0 || err)
{
abort_request(rstate);
unlink_request(rstate);
deliver_error(rstate, mStatus_BadParamErr);
abort_request(rstate);
unlink_request(rstate);
- return;
-
-malloc_error:
- my_perror("ERROR: malloc");
- exit(1);
}
static void resolve_termination_callback(void *context)
resolve_termination_t *term = context;
request_state *rs;
- if (!term)
+ if (!term)
{
LogMsg("ERROR: resolve_termination_callback: double termination");
return;
if (answer->rrtype == kDNSType_SRV)
{
- AssignDomainName(res->target, answer->rdata->u.srv.target);
+ AssignDomainName(&res->target, &answer->rdata->u.srv.target);
res->port = answer->rdata->u.srv.port;
res->srv = mDNStrue;
}
if (!res->txt || !res->srv) return; // only deliver result to client if we have both answers
- ConvertDomainNameToCString(&answer->name, fullname);
+ ConvertDomainNameToCString(answer->name, fullname);
ConvertDomainNameToCString(&res->target, target);
// calculate reply length
// write reply data to message
put_string(fullname, &data);
put_string(target, &data);
- *data++ = res->port.b[0];
- *data++ = res->port.b[1];
+ *data++ = res->port.b[0];
+ *data++ = res->port.b[1];
put_short(res->txtlen, &data);
put_rdata(res->txtlen, res->txtdata, &data);
result = send_msg(rep);
- if (result == t_error || result == t_terminated)
- {
- abort_request(rs);
+ if (result == t_error || result == t_terminated)
+ {
+ abort_request(rs);
unlink_request(rs);
- freeL("resolve_result_callback", rep);
+ freeL("resolve_result_callback", rep);
}
else if (result == t_complete) freeL("resolve_result_callback", rep);
else append_reply(rs, rep);
}
-
+
// 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)
{
len += sizeof(DNSServiceErrorType);
len += 3 * sizeof(uint16_t); // type, class, rdlen
len += answer->rdlength;
- ConvertDomainNameToCString(&answer->name, name);
+ ConvertDomainNameToCString(answer->name, name);
len += strlen(name) + 1;
rep = create_reply(query_reply, len, req);
put_short(answer->rrtype, &data);
put_short(answer->rrclass, &data);
put_short(answer->rdlength, &data);
- put_rdata(answer->rdlength, (char *)&answer->rdata->u, &data);
+ put_rdata(answer->rdlength, answer->rdata->u.data, &data);
put_long(AddRecord ? answer->rroriginalttl : 0, &data);
append_reply(req, rep);
if (!st) return(mDNSNULL);
for (i = 0; i < NumSubTypes; i++)
{
+ mDNS_SetupResourceRecord(&st[i], mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, mDNSNULL, mDNSNULL);
while (*p) p++;
p++;
- if (!MakeDomainNameFromDNSNameString(&st[i].resrec.name, p))
+ if (!MakeDomainNameFromDNSNameString(st[i].resrec.name, p))
{ freeL("ServiceSubTypes", st); return(mDNSNULL); }
}
}
return(st);
}
-
#ifdef _HAVE_SETDOMAIN_SUPPORT_
static void free_defdomain(mDNS *const m, AuthRecord *const rr, mStatus result)
{
// extract flags/domain from message
ptr = request->msgdata;
flags = get_flags(&ptr);
- if (get_string(&ptr, domainstr, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
+ if (get_string(&ptr, domainstr, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
!MakeDomainNameFromDNSNameString(&domain, domainstr))
{ err = mStatus_BadParamErr; goto end; }
if (getsockopt(request->sd, 0, LOCAL_PEERCRED, &xuc, &xuclen))
{ my_perror("ERROR: getsockopt, LOCAL_PEERCRED"); err = mStatus_UnknownErr; goto end; }
if (xuc.cr_version != XUCRED_VERSION) { LogMsg("getsockopt, LOCAL_PEERCRED - bad version"); err = mStatus_UnknownErr; goto end; }
- LogMsg("Default domain %s %s for UID %d", domainstr, flags & kDNSServiceFlagsAdd ? "set" : "removed", xuc.cr_uid);
+ LogMsg("Default domain %s %s for UID %d", domainstr, flags & kDNSServiceFlagsAdd ? "set" : "removed", xuc.cr_uid);
if (flags & kDNSServiceFlagsAdd)
{
default_browse_list_t *newelem = malloc(sizeof(default_browse_list_t));
if (!newelem) { LogMsg("ERROR: malloc"); err = mStatus_NoMemoryErr; goto end; }
mDNS_SetupResourceRecord(&newelem->ptr_rec, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, free_defdomain, newelem);
- MakeDomainNameFromDNSNameString(&newelem->ptr_rec.resrec.name, "_default._browse._dns-sd._udp.local.");
- AssignDomainName(newelem->ptr_rec.resrec.rdata->u.name, domain);
+ MakeDomainNameFromDNSNameString(&newelem->ptr_rec.resrec.name, mDNS_DomainTypeNames[mDNS_DomainTypeBrowseDefault]);
+ AppendDNSNameString (&newelem->ptr_rec.resrec.name, "local");
+ AssignDomainName(&newelem->ptr_rec.resrec.rdata->u.name, &domain);
newelem->uid = xuc.cr_uid;
err = mDNS_Register(gmDNS, &newelem->ptr_rec);
if (err) free(newelem);
ptr = ptr->next;
}
if (!ptr) { LogMsg("Attempt to remove nonexistent domain %s for UID %d", domainstr, xuc.cr_uid); err = mStatus_Invalid; }
- }
+ }
#else
err = mStatus_NoError;
#endif // _HAVE_SETDOMAIN_SUPPORT_
for (p = info->browsers; p; p = p->next)
{
if (SameDomainName(&p->domain, d))
- { LogMsg("add_domain_to_browser - attempt to add domain %##d already in list", d->c); return mStatus_AlreadyRegistered; }
+ { debugf("add_domain_to_browser - attempt to add domain %##d already in list", d->c); return mStatus_AlreadyRegistered; }
}
b = mallocL("browser_t", sizeof(*b));
if (!b) return mStatus_NoMemoryErr;
- AssignDomainName(b->domain, *d);
+ AssignDomainName(&b->domain, d);
err = mDNS_StartBrowse(gmDNS, &b->q, &info->regtype, d, info->interface_id, info->ForceMCast, browse_result_callback, info->rstate);
if (err)
{
ptr = request->msgdata;
flags = get_flags(&ptr);
interfaceIndex = get_long(&ptr);
- if (get_string(&ptr, regtype, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
+ if (get_string(&ptr, regtype, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
get_string(&ptr, domain, MAX_ESCAPED_DOMAIN_NAME) < 0)
{ err = mStatus_BadParamErr; goto error; }
freeL("handle_browse_request", request->msgbuf);
request->browser_info = info;
info->ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0;
info->interface_id = InterfaceID;
- AssignDomainName(info->regtype, typedn);
+ AssignDomainName(&info->regtype, &typedn);
info->rstate = request;
info->default_domain = !domain[0];
info->browsers = NULL;
reply_state *rep;
mStatus err;
(void)m; // Unused
- LogOperation("%3d: DNSServiceBrowse(%##s, %s) RESULT %s", req->sd, question->qname.c, DNSTypeName(question->qtype), RRDisplayString(m, answer));
+ LogOperation("%3d: DNSServiceBrowse(%##s, %s) RESULT %s %s",
+ req->sd, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "Add" : "Rmv", RRDisplayString(m, answer));
err = gen_rr_response(&answer->rdata->u.name, answer->InterfaceID, req, &rep);
if (err)
{
- if (deliver_async_error(req, browse_reply, err) < 0)
+ if (deliver_async_error(req, browse_reply, err) < 0)
{
abort_request(req);
unlink_request(req);
mDNSexport void udsserver_default_browse_domain_changed(const domainname *d, mDNSBool add)
{
request_state *r;
-
- for (r = all_requests; r; r = r->next)
+
+ for (r = all_requests; r; r = r->next)
{
browser_info_t *info = r->browser_info;
if (add) add_domain_to_browser(info, d);
else
{
- browser_t *ptr = info->browsers, *prev = NULL;
- while (ptr)
+ browser_t **ptr = &info->browsers;
+ while (*ptr)
{
- if (SameDomainName(&ptr->domain, d))
+ if (SameDomainName(&(*ptr)->domain, d))
{
- if (prev) prev->next = ptr->next;
- else info->browsers = ptr->next;
- mDNS_StopBrowse(gmDNS, &ptr->q);
- freeL("browser_t", ptr);
- break;
+ browser_t *remove = *ptr;
+ *ptr = (*ptr)->next;
+ if (remove->q.LongLived)
+ {
+ // give goodbyes for known answers.
+ // note that since events are sent to client via udsserver_idle(), we don't need to worry about the question being cancelled mid-loop
+ CacheRecord *ka = remove->q.uDNS_info.knownAnswers;
+ while (ka) { remove->q.QuestionCallback(gmDNS, &remove->q, &ka->resrec, mDNSfalse); ka = ka->next; }
+ }
+ mDNS_StopBrowse(gmDNS, &remove->q);
+ freeL("browser_t", remove);
+ return;
}
- prev = ptr;
- ptr = ptr->next;
+ ptr = &(*ptr)->next;
}
- if (!ptr) LogMsg("Requested removal of default domain %##s not in list for sd %s", d->c, r->sd);
+ LogMsg("Requested removal of default domain %##s not in list for sd %d", d->c, r->sd);
}
}
}
ServiceRecordSet *s;
for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (rr->resrec.rrtype == kDNSType_SRV && SameDomainName(&rr->resrec.name, &r->name) && !SameRData(&rr->resrec, r))
+ if (rr->resrec.rrtype == kDNSType_SRV && SameDomainName(rr->resrec.name, r->name) && !SameRData(&rr->resrec, r))
count++;
for (rr = m->uDNS_info.RecordRegistrations; rr; rr=rr->next)
- if (rr->uDNS_info.state != regState_Unregistered && rr->resrec.rrtype == kDNSType_SRV && SameDomainName(&rr->resrec.name, &r->name) && !SameRData(&rr->resrec, r))
+ if (rr->uDNS_info.state != regState_Unregistered && rr->resrec.rrtype == kDNSType_SRV && SameDomainName(rr->resrec.name, r->name) && !SameRData(&rr->resrec, r))
count++;
for (s = m->uDNS_info.ServiceRegistrations; s; s = s->next)
- if (s->uDNS_info.state != regState_Unregistered && SameDomainName(&s->RR_SRV.resrec.name, &r->name) && !SameRData(&s->RR_SRV.resrec, r))
+ if (s->uDNS_info.state != regState_Unregistered && SameDomainName(s->RR_SRV.resrec.name, r->name) && !SameRData(&s->RR_SRV.resrec, r))
count++;
- verbosedebugf("%d peer registrations for %##s", count, r->name.c);
+ verbosedebugf("%d peer registrations for %##s", count, r->name->c);
return(count);
}
for (rr = gmDNS->ResourceRecords; rr; rr=rr->next)
if (rr->resrec.rrtype == kDNSType_SRV &&
rr->resrec.rdata->u.srv.port.NotAnInteger == port.NotAnInteger &&
- SameDomainName(&rr->resrec.name, srv))
+ SameDomainName(rr->resrec.name, srv))
count++;
return(count);
}
{ LogMsg("register_service_instance: domain %##s already registered", domain->c); return mStatus_AlreadyRegistered; }
}
- instance_size = sizeof(*instance);
+ instance_size = sizeof(*instance);
if (info->txtlen > sizeof(RDataBody)) instance_size += (info->txtlen - sizeof(RDataBody));
instance = mallocL("service_instance", instance_size);
- if (!instance) { my_perror("ERROR: malloc"); return mStatus_NoMemoryErr; }
+ if (!instance) { my_perror("ERROR: malloc"); return mStatus_NoMemoryErr; }
instance->subtypes = AllocateSubTypes(info->num_subtypes, info->type_as_string);
if (info->num_subtypes && !instance->subtypes)
- { free_service_instance(instance); instance = NULL; goto malloc_error; }
+ { free_service_instance(instance); instance = NULL; FatalError("ERROR: malloc"); }
instance->request = request;
instance->sd = request->sd;
instance->autoname = info->autoname;
instance->allowremotequery = info->allowremotequery;
instance->rename_on_memfree = 0;
instance->name = info->name;
- AssignDomainName(instance->domain, *domain);
+ AssignDomainName(&instance->domain, domain);
instance->default_local = (info->default_domain && SameDomainName(domain, &localdomain));
result = mDNS_RegisterService(gmDNS, &instance->srs, &instance->name, &info->type, domain, info->host.c[0] ? &info->host : NULL, info->port,
info->txtdata, info->txtlen, instance->subtypes, info->num_subtypes, info->InterfaceID, regservice_callback, instance);
info->instances = instance;
}
return result;
-
-malloc_error:
- my_perror("ERROR: malloc");
- exit(1);
}
mDNSexport void udsserver_default_reg_domain_changed(const domainname *d, mDNSBool add)
{
if (SameDomainName(&si->domain, d))
{
- mStatus err;
+ mStatus err;
if (prev) prev->next = si->next;
else info->instances = si->next;
err = mDNS_DeregisterService(gmDNS, &si->srs);
if (ifi && !service->InterfaceID)
{ LogMsg("ERROR: handle_regservice_request - Couldn't find InterfaceID for interfaceIndex %d", ifi); goto bad_param; }
if (get_string(&ptr, name, 256) < 0 ||
- get_string(&ptr, service->type_as_string, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
+ get_string(&ptr, service->type_as_string, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
get_string(&ptr, domain, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
get_string(&ptr, host, MAX_ESCAPED_DOMAIN_NAME) < 0)
{ LogMsg("ERROR: handle_regservice_request - Couldn't read name/regtype/domain"); goto bad_param; }
- service->port.b[0] = *ptr++;
- service->port.b[1] = *ptr++;
+ service->port.b[0] = *ptr++;
+ service->port.b[1] = *ptr++;
+
service->txtlen = get_short(&ptr);
service->txtdata = get_rdata(&ptr, service->txtlen);
finish:
deliver_error(request, result);
- if (result != mStatus_NoError)
+ if (result != mStatus_NoError)
{
abort_request(request);
unlink_request(request);
}
- else
- reset_connected_rstate(request); // reset to receive add/remove messages
+ else
+ reset_connected_rstate(request); // prepare to receive add/remove messages
return;
if (!instance) { LogMsg("regservice_callback: srs->ServiceContext is NULL %d", result); return; }
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));
+ LogOperation("%3d: DNSServiceRegister(%##s, %u) REGISTERED ", instance->sd, srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port));
else if (result == mStatus_MemFree)
- LogOperation("%3d: DNSServiceRegister(%##s, %u) DEREGISTERED", instance->sd, srs->RR_SRV.resrec.name.c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port));
+ LogOperation("%3d: DNSServiceRegister(%##s, %u) DEREGISTERED", instance->sd, srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port));
else if (result == mStatus_NameConflict)
- LogOperation("%3d: DNSServiceRegister(%##s, %u) NAME CONFLICT", instance->sd, srs->RR_SRV.resrec.name.c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port));
+ LogOperation("%3d: DNSServiceRegister(%##s, %u) NAME CONFLICT", instance->sd, srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port));
else
- LogOperation("%3d: DNSServiceRegister(%##s, %u) CALLBACK %d", instance->sd, srs->RR_SRV.resrec.name.c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port), result);
+ LogOperation("%3d: DNSServiceRegister(%##s, %u) CALLBACK %d", instance->sd, srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port), result);
if (result == mStatus_NoError)
{
if (instance->allowremotequery)
{
+ ExtraResourceRecord *e;
srs->RR_ADV.AllowRemoteQuery = mDNStrue;
srs->RR_PTR.AllowRemoteQuery = mDNStrue;
srs->RR_SRV.AllowRemoteQuery = mDNStrue;
srs->RR_TXT.AllowRemoteQuery = mDNStrue;
+ for (e = instance->srs.Extras; e; e = e->next) e->r.AllowRemoteQuery = mDNStrue;
}
process_service_registration(srs);
if (instance->autoname && CountPeerRegistrations(m, srs) == 0)
if (err) LogMsg("ERROR: regservice_callback - RenameAndReregisterService returned %ld", err);
// error should never happen - safest to log and continue
}
- else
+ else
{
free_service_instance(instance);
return;
request_state *rs = instance->request;
if (!rs) { LogMsg("ERROR: regservice_callback: received result %ld with a NULL request pointer", result); return; }
free_service_instance(instance);
- if (deliver_async_error(rs, reg_service_reply, result) < 0)
+ if (deliver_async_error(rs, reg_service_reply, result) < 0)
{
abort_request(rs);
unlink_request(rs);
}
return;
}
- }
- else
+ }
+ else
{
request_state *rs = instance->request;
if (!rs) { LogMsg("ERROR: regservice_callback: received result %ld with a NULL request pointer", result); return; }
if (result != mStatus_NATTraversal) LogMsg("ERROR: unknown result in regservice_callback: %ld", result);
free_service_instance(instance);
- if (deliver_async_error(rs, reg_service_reply, result) < 0)
+ if (deliver_async_error(rs, reg_service_reply, result) < 0)
{
abort_request(rs);
unlink_request(rs);
if (result != mStatus_MemFree) { LogMsg("Error: FreeExtraRR invoked with unexpected error %d", result); return; }
- debugf("%##s: MemFree", rr->resrec.name.c);
+ debugf("%##s: MemFree", rr->resrec.name->c);
if (rr->resrec.rdata != &rr->rdatastorage)
freeL("Extra RData", rr->resrec.rdata);
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)
{
ServiceRecordSet *srs = &instance->srs;
return result;
}
-
-static void handle_add_request(request_state *rstate)
+static mStatus handle_add_request(request_state *rstate)
{
uint32_t ttl;
uint16_t rrtype, rdlen;
service_info *srvinfo = rstate->service_registration;
service_instance *i;
- if (!srvinfo) { LogMsg("handle_add_request called with NULL service_registration"); return; }
+ if (!srvinfo) { LogMsg("handle_add_request called with NULL service_registration"); return(-1); }
ptr = rstate->msgdata;
flags = get_flags(&ptr);
if (!ttl) ttl = DefaultTTLforRRType(rrtype);
- LogOperation("%3d: DNSServiceAddRecord(%##s, %s)", rstate->sd,
- (srvinfo->instances) ? srvinfo->instances->srs.RR_SRV.resrec.name.c : NULL, DNSTypeName(rrtype));
+ LogOperation("%3d: DNSServiceAddRecord(%##s, %s)", rstate->sd,
+ (srvinfo->instances) ? srvinfo->instances->srs.RR_SRV.resrec.name->c : NULL, DNSTypeName(rrtype));
for (i = srvinfo->instances; i; i = i->next)
{
else result = mStatus_NoError; // suppress non-local default errors
}
- deliver_error(rstate, result);
- reset_connected_rstate(rstate);
+ return(result);
}
static mStatus update_record(AuthRecord *rr, uint16_t rdlen, char *rdata, uint32_t ttl)
- {
+ {
int rdsize;
RData *newrd;
mStatus result;
if (rdlen > sizeof(RDataBody)) rdsize = rdlen;
else rdsize = sizeof(RDataBody);
newrd = mallocL("handle_update_request", sizeof(RData) - sizeof(RDataBody) + rdsize);
- if (!newrd)
- {
- my_perror("ERROR: malloc");
- exit(1);
- }
+ if (!newrd) FatalError("ERROR: malloc");
newrd->MaxRDLength = (mDNSu16) rdsize;
memcpy(&newrd->u, rdata, rdlen);
result = mDNS_Update(gmDNS, rr, ttl, rdlen, newrd, update_callback);
return result;
}
-static void handle_update_request(request_state *rstate)
+static mStatus handle_update_request(request_state *rstate)
{
uint16_t rdlen;
char *ptr, *rdata;
get_flags(&ptr); // flags unused
rdlen = get_short(&ptr);
rdata = get_rdata(&ptr, rdlen);
- ttl = get_long(&ptr);
+ ttl = get_long(&ptr);
if (rstate->reg_recs)
{
{
ExtraResourceRecord *e;
for (e = i->srs.Extras; e; e = e->next)
- if (e->ClientID == rstate->hdr.reg_index) { rr = &e->r; break; }
+ if (e->ClientID == rstate->hdr.reg_index) { rr = &e->r; break; }
}
if (!rr) { result = mStatus_BadReferenceErr; goto end; }
end:
LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s)", rstate->sd,
- (srvinfo->instances) ? srvinfo->instances->srs.RR_SRV.resrec.name.c : NULL,
+ (srvinfo->instances) ? srvinfo->instances->srs.RR_SRV.resrec.name->c : NULL,
rr ? DNSTypeName(rr->resrec.rrtype) : "<NONE>");
- deliver_error(rstate, result);
- reset_connected_rstate(rstate);
+ return(result);
}
static void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd)
- {
+ {
(void)m; // Unused
if (oldrd != &rr->rdatastorage) freeL("update_callback", oldrd);
}
service_instance *instance = srs->ServiceContext;
request_state *req = instance->request;
-
- err = gen_rr_response(&srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, req, &rep);
- if (err)
+ if (!req) { LogMsg("ERROR: process_service_registration - null request object"); return; }
+ err = gen_rr_response(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, req, &rep);
+ if (err)
{
if (deliver_async_error(req, reg_service_reply, err) < 0)
{
return;
}
send_result = send_msg(rep);
- if (send_result == t_error || send_result == t_terminated)
- {
- abort_request(req);
+ if (send_result == t_error || send_result == t_terminated)
+ {
+ abort_request(req);
unlink_request(req);
- freeL("process_service_registration", rep);
+ freeL("process_service_registration", rep);
}
else if (send_result == t_complete) freeL("process_service_registration", rep);
else append_reply(req, rep);
p = i;
i = i->next;
p->request = NULL; // clear back pointer
- // only safe to free memory if registration is not valid, ie deregister fails (which invalidates p)
- LogOperation("%3d: DNSServiceRegister(%##s, %u) STOP", info->request->sd, p->srs.RR_SRV.resrec.name.c, mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port));
+ // only safe to free memory if registration is not valid, i.e. deregister fails (which invalidates p)
+ LogOperation("%3d: DNSServiceRegister(%##s, %u) STOP", info->request->sd, p->srs.RR_SRV.resrec.name->c, mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port));
if (mDNS_DeregisterService(gmDNS, &p->srs)) free_service_instance(p);
}
info->request->service_registration = NULL; // clear pointer from request back to info
freeL("service_info", info);
}
-static void handle_regrecord_request(request_state *rstate)
+static mStatus handle_regrecord_request(request_state *rstate)
{
AuthRecord *rr;
registered_record_entry *re;
LogMsg("ERROR: handle_regrecord_request - transfer state != t_complete");
abort_request(rstate);
unlink_request(rstate);
- return;
+ return(-1);
}
rr = read_rr_from_ipc_msg(rstate->msgdata, 1, 1);
- if (!rr)
- {
- deliver_error(rstate, mStatus_BadParamErr);
- return;
- }
+ if (!rr) return(mStatus_BadParamErr);
// allocate registration entry, link into list
re = mallocL("handle_regrecord_request", sizeof(registered_record_entry));
- if (!re) goto malloc_error;
+ if (!re) FatalError("ERROR: malloc");
re->key = rstate->hdr.reg_index;
re->rr = rr;
re->rstate = rstate;
LogOperation("%3d: DNSServiceRegisterRecord %s", rstate->sd, RRDisplayString(gmDNS, &rr->resrec));
result = mDNS_Register(gmDNS, rr);
- deliver_error(rstate, result);
- reset_connected_rstate(rstate);
- return;
-
-malloc_error:
- my_perror("ERROR: malloc");
- return;
+ return(result);
}
static void regrecord_callback(mDNS *const m, AuthRecord * rr, mStatus result)
{
if (result != mStatus_MemFree) LogMsg("regrecord_callback: error %d received after parent termination", result);
freeL("regrecord_callback", rr);
- }
+ }
return;
}
if (result)
{
// unlink from list, free memory
- registered_record_entry **ptr = &re->rstate->reg_recs;
+ registered_record_entry **ptr = &re->rstate->reg_recs;
while (*ptr && (*ptr) != re) ptr = &(*ptr)->next;
- if (!*ptr) { LogMsg("regrecord_callback - record not in list!"); return; }
+ if (!*ptr) { LogMsg("regrecord_callback - record not in list!"); return; }
*ptr = (*ptr)->next;
freeL("regrecord_callback", re->rr);
re->rr = rr = NULL;
ptr = ptr->next;
shared = fptr->rr->resrec.RecordType == kDNSRecordTypeShared;
fptr->rr->RecordContext = NULL;
- mDNS_Deregister(gmDNS, fptr->rr);
+ mDNS_Deregister(gmDNS, fptr->rr);
freeL("connected_registration_termination", fptr);
}
}
-static void handle_removerecord_request(request_state *rstate)
+static mStatus handle_removerecord_request(request_state *rstate)
{
mStatus err = mStatus_BadReferenceErr;
char *ptr;
else if (!srvinfo) LogOperation("%3d: DNSServiceRemoveRecord (bad ref)", rstate->sd);
else
{
- LogOperation("%3d: DNSServiceRemoveRecord(%##s, %s)", rstate->sd,
- (srvinfo->instances) ? srvinfo->instances->srs.RR_SRV.resrec.name.c : NULL);
service_instance *i;
+ LogOperation("%3d: DNSServiceRemoveRecord(%##s)", rstate->sd,
+ (srvinfo->instances) ? srvinfo->instances->srs.RR_SRV.resrec.name->c : NULL);
for (i = srvinfo->instances; i; i = i->next)
{
err = remove_extra(rstate, i);
}
}
- reset_connected_rstate(rstate);
- if (deliver_error(rstate, err) < 0)
- {
- abort_request(rstate);
- unlink_request(rstate);
- }
+ return(err);
}
// remove a resource record registered via DNSServiceRegisterRecord()
e = *ptr;
*ptr = e->next; // unlink
- LogOperation("%3d: DNSServiceRemoveRecord(%#s)", rstate->sd, e->rr->resrec.name.c);
+ LogOperation("%3d: DNSServiceRemoveRecord(%#s)", rstate->sd, e->rr->resrec.name->c);
shared = e->rr->resrec.RecordType == kDNSRecordTypeShared;
e->rr->RecordContext = NULL;
err = mDNS_Deregister(gmDNS, e->rr);
return err;
}
-
static mStatus remove_extra(request_state *rstate, service_instance *serv)
{
mStatus err = mStatus_BadReferenceErr;
// domain enumeration
static void handle_enum_request(request_state *rstate)
{
- DNSServiceFlags flags, add_default;
+ DNSServiceFlags flags;
uint32_t ifi;
mDNSInterfaceID InterfaceID;
char *ptr = rstate->msgdata;
domain_enum_t *def, *all;
enum_termination_t *term;
- reply_state *reply; // initial default reply
- transfer_state tr;
mStatus err;
int result;
def = mallocL("handle_enum_request", sizeof(domain_enum_t));
all = mallocL("handle_enum_request", sizeof(domain_enum_t));
term = mallocL("handle_enum_request", sizeof(enum_termination_t));
- if (!def || !all || !term)
- {
- my_perror("ERROR: malloc");
- exit(1);
- }
+ if (!def || !all || !term) FatalError("ERROR: malloc");
// enumeration requires multiple questions, so we must link all the context pointers so that
// necessary context can be reached from the callbacks
rstate->termination_context = term;
rstate->terminate = enum_termination_callback;
def->question.QuestionContext = def;
- def->type = (flags & kDNSServiceFlagsRegistrationDomains) ?
+ def->type = (flags & kDNSServiceFlagsRegistrationDomains) ?
mDNS_DomainTypeRegistrationDefault: mDNS_DomainTypeBrowseDefault;
all->question.QuestionContext = all;
- all->type = (flags & kDNSServiceFlagsRegistrationDomains) ?
+ all->type = (flags & kDNSServiceFlagsRegistrationDomains) ?
mDNS_DomainTypeRegistration : mDNS_DomainTypeBrowse;
// if the caller hasn't specified an explicit interface, we use local-only to get the system-wide list.
if (!InterfaceID) InterfaceID = mDNSInterface_LocalOnly;
// make the calls
- LogOperation("%3d: DNSServiceEnumerateDomains(%X)", rstate->sd, flags);
+ LogOperation("%3d: DNSServiceEnumerateDomains(%X=%s)", rstate->sd, flags,
+ (flags & kDNSServiceFlagsBrowseDomains ) ? "kDNSServiceFlagsBrowseDomains" :
+ (flags & kDNSServiceFlagsRegistrationDomains) ? "kDNSServiceFlagsRegistrationDomains" : "<<Unknown>>");
err = mDNS_GetDomains(gmDNS, &all->question, all->type, NULL, InterfaceID, enum_result_callback, all);
if (err == mStatus_NoError)
err = mDNS_GetDomains(gmDNS, &def->question, def->type, NULL, InterfaceID, enum_result_callback, def);
unlink_request(rstate);
return;
}
-
- // provide local. as the first domain automatically
- add_default = kDNSServiceFlagsDefault | kDNSServiceFlagsAdd;
- reply = format_enumeration_reply(rstate, "local.", add_default, ifi, 0);
- tr = send_msg(reply);
- if (tr == t_error || tr == t_terminated)
- {
- freeL("handle_enum_request", def);
- freeL("handle_enum_request", all);
- abort_request(rstate);
- unlink_request(rstate);
- return;
- }
- if (tr == t_complete) freeL("handle_enum_request", reply);
- if (tr == t_morecoming) append_reply(rstate, reply); // couldn't send whole reply because client is blocked - link into list
}
static void enum_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
reply = create_reply(enumeration_reply, len, rstate);
reply->rhdr->flags = dnssd_htonl(flags);
- reply->rhdr->ifi = dnssd_htonl(ifi);
+ reply->rhdr->ifi = dnssd_htonl(ifi);
reply->rhdr->error = dnssd_htonl(err);
data = reply->sdata;
put_string(domain, &data);
freeL("handle_reconfirm_request", rr);
}
-
// setup rstate to accept new reg/dereg requests
static void reset_connected_rstate(request_state *rstate)
{
rstate->bufsize = 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
LogMsg("ERROR: read_rr_from_ipc_msg - get_string");
return NULL;
}
- type = get_short(&msgbuf);
+ type = get_short(&msgbuf);
class = get_short(&msgbuf);
rdlen = get_short(&msgbuf);
else storage_size = sizeof(RDataBody);
rr = mallocL("read_rr_from_ipc_msg", sizeof(AuthRecord) - sizeof(RDataBody) + storage_size);
- if (!rr)
- {
- my_perror("ERROR: malloc");
- exit(1);
- }
+ if (!rr) FatalError("ERROR: malloc");
bzero(rr, sizeof(AuthRecord)); // ok if oversized rdata not zero'd
mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSPlatformInterfaceIDfromInterfaceIndex(gmDNS, interfaceIndex),
type, 0, (flags & kDNSServiceFlagsShared) ? kDNSRecordTypeShared : kDNSRecordTypeUnique, mDNSNULL, mDNSNULL);
- if (!MakeDomainNameFromDNSNameString(&rr->resrec.name, name))
+ if (!MakeDomainNameFromDNSNameString(rr->resrec.name, name))
{
LogMsg("ERROR: bad name: %s", name);
freeL("read_rr_from_ipc_msg", rr);
rr->resrec.rdata->MaxRDLength = rdlen;
rdata = get_rdata(&msgbuf, rdlen);
memcpy(rr->resrec.rdata->u.data, rdata, rdlen);
- if (GetTTL)
+ if (GetTTL)
{
rr->resrec.rroriginalttl = get_long(&msgbuf);
}
return rr;
}
-
// generate a response message for a browse result, service registration result, or any other call with the
// 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.
return mStatus_NoError;
}
-
static int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain)
{
domainlabel n;
return 0;
}
-
// append a reply to the list in a request object
static void append_reply(request_state *req, reply_state *rep)
{
rep->next = NULL;
}
-
// 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
{
uint32_t nleft;
int nread;
- char buf[4]; // dummy for death notification
+ char buf[4]; // dummy for death notification
if (rs->ts == t_terminated || rs->ts == t_error)
{
return rs->ts;
rerror:
- if (dnssd_errno() == dnssd_EWOULDBLOCK || dnssd_errno() == dnssd_EINTR) return t_morecoming;
+ if (dnssd_errno() == dnssd_EWOULDBLOCK || dnssd_errno() == dnssd_EINTR) return t_morecoming;
my_perror("ERROR: read_msg");
rs->ts = t_error;
return t_error;
}
-
static int send_msg(reply_state *rs)
{
ssize_t nwriten;
#if !defined(PLATFORM_NO_EPIPE)
if (dnssd_errno() == EPIPE)
{
- LogMsg("broken pipe - cleanup should be handled by run-loop read wakeup");
+ LogMsg("%3d: broken pipe - cleanup will be handled by run-loop read wakeup", rs->sd);
rs->ts = t_terminated;
rs->request->ts = t_terminated;
- return t_terminated;
+ return t_terminated;
}
else
#endif
return rs->ts;
}
-
-
static reply_state *create_reply(reply_op_t op, size_t datalen, request_state *request)
{
reply_state *reply;
totallen = (int) (datalen + sizeof(ipc_msg_hdr));
reply = mallocL("create_reply", sizeof(reply_state));
- if (!reply)
- {
- my_perror("ERROR: malloc");
- exit(1);
- }
+ if (!reply) FatalError("ERROR: malloc");
bzero(reply, sizeof(reply_state));
reply->ts = t_morecoming;
reply->sd = request->sd;
reply->request = request;
reply->len = totallen;
reply->msgbuf = mallocL("create_reply", totallen);
- if (!reply->msgbuf)
- {
- my_perror("ERROR: malloc");
- exit(1);
- }
+ if (!reply->msgbuf) FatalError("ERROR: malloc");
bzero(reply->msgbuf, totallen);
reply->mhdr = (ipc_msg_hdr *)reply->msgbuf;
reply->rhdr = (reply_hdr *)(reply->msgbuf + sizeof(ipc_msg_hdr));
return reply;
}
-
static int deliver_error(request_state *rstate, mStatus err)
- {
- int nwritten = -1;
- undelivered_error_t *undeliv;
-
- err = dnssd_htonl(err);
- nwritten = send(rstate->errfd, &err, sizeof(mStatus), 0);
- if (nwritten < (int)sizeof(mStatus))
- {
- if (dnssd_errno() == dnssd_EINTR || dnssd_errno() == dnssd_EWOULDBLOCK)
- nwritten = 0;
- if (nwritten < 0)
- {
- my_perror("ERROR: send - unable to deliver error to client");
- goto error;
- }
- //client blocked - store result and come backr
- undeliv = mallocL("deliver_error", sizeof(undelivered_error_t));
- if (!undeliv)
- {
- my_perror("ERROR: malloc");
- exit(1);
- }
- undeliv->err = err;
- undeliv->nwritten = nwritten;
- undeliv->sd = rstate->errfd;
- rstate->u_err = undeliv;
- return 0;
- }
- return 0;
-
-error:
- return -1;
-
- }
-
+ {
+ int nwritten = -1;
+ undelivered_error_t *undeliv;
+
+ err = dnssd_htonl(err);
+ nwritten = send(rstate->sd, &err, sizeof(mStatus), 0);
+ if (nwritten < (int)sizeof(mStatus))
+ {
+ if (dnssd_errno() == dnssd_EINTR || dnssd_errno() == dnssd_EWOULDBLOCK)
+ nwritten = 0;
+ if (nwritten < 0)
+ {
+ my_perror("ERROR: send - unable to deliver error to client");
+ return(-1);
+ }
+ else
+ {
+ //client blocked - store result and come backr
+ undeliv = mallocL("deliver_error", sizeof(undelivered_error_t));
+ if (!undeliv) FatalError("ERROR: malloc");
+ undeliv->err = err;
+ undeliv->nwritten = nwritten;
+ undeliv->sd = rstate->sd;
+ rstate->u_err = undeliv;
+ return 0;
+ }
+ }
+ return 0;
+ }
// 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)
- {
- int nwritten;
-
- nwritten = send(rs->u_err->sd, (char *)(&rs->u_err->err) + rs->u_err->nwritten, sizeof(mStatus) - rs->u_err->nwritten, 0);
- if (nwritten < 0)
- {
- if (dnssd_errno() == dnssd_EINTR || dnssd_errno() == dnssd_EWOULDBLOCK)
- nwritten = 0;
- else
- {
- my_perror("ERROR: send - unable to deliver error to client\n");
- return t_error;
- }
- }
- if (nwritten + rs->u_err->nwritten == sizeof(mStatus))
- {
- freeL("send_undelivered_error", rs->u_err);
- rs->u_err = NULL;
- return t_complete;
- }
- rs->u_err->nwritten += nwritten;
- return t_morecoming;
- }
-
+ {
+ int nwritten;
+
+ nwritten = send(rs->u_err->sd, (char *)(&rs->u_err->err) + rs->u_err->nwritten, sizeof(mStatus) - rs->u_err->nwritten, 0);
+ if (nwritten < 0)
+ {
+ if (dnssd_errno() == dnssd_EINTR || dnssd_errno() == dnssd_EWOULDBLOCK)
+ nwritten = 0;
+ else
+ {
+ my_perror("ERROR: send - unable to deliver error to client\n");
+ return t_error;
+ }
+ }
+ if ((unsigned int)(nwritten + rs->u_err->nwritten) >= sizeof(mStatus))
+ {
+ freeL("send_undelivered_error", rs->u_err);
+ rs->u_err = NULL;
+ return t_complete;
+ }
+ rs->u_err->nwritten += nwritten;
+ return t_morecoming;
+ }
// send bogus data along with an error code to the app callback
// returns 0 on success (linking reply into list of not fully delivered),
return 0;
}
-
static void abort_request(request_state *rs)
{
reply_state *rep, *ptr;
if (rs->terminate) rs->terminate(rs->termination_context); // terminate field may not be set yet
if (rs->msgbuf) freeL("abort_request", rs->msgbuf);
LogOperation("%3d: Removing FD", rs->sd);
- udsSupportRemoveFDFromEventLoop(rs->sd);
+ udsSupportRemoveFDFromEventLoop(rs->sd); // Note: This also closes file descriptor rs->sd for us
rs->sd = dnssd_InvalidSocket;
- if (rs->errfd != rs->sd && rs->errfd != dnssd_InvalidSocket) dnssd_close(rs->errfd);
- rs->errfd = dnssd_InvalidSocket;
// free pending replies
rep = rs->replies;
}
}
-
static void unlink_request(request_state *rs)
{
request_state *ptr;
return;
}
}
-
-
//hack to search-replace perror's to LogMsg's
static void my_perror(char *errmsg)
case resolve_request: min_size = sizeof(DNSServiceFlags) + // flags
sizeof(uint32_t) + // interface
(3 * sizeof(char)); // name, regtype, domain
- break;
+ break;
case query_request: min_size = sizeof(DNSServiceFlags) + // flags
sizeof(uint32_t) + // interface
sizeof(char) + // fullname
case reg_service_request: min_size = sizeof(DNSServiceFlags) + // flags
sizeof(uint32_t) + // interface
(4 * sizeof(char)) + // name, type, domain, host
- (2 * sizeof(uint16_t)); // port, textlen
- break;
+ (2 * sizeof(uint16_t)); // port, textlen
+ break;
case enumeration_request: min_size = sizeof(DNSServiceFlags) + // flags
sizeof(uint32_t); // interface
break;
(3 * sizeof(uint16_t)); // type, class, rdlen
break;
case setdomain_request: min_size = sizeof(DNSServiceFlags) + sizeof(char); // flags + domain
- break;
+ break;
default:
- LogMsg("ERROR: validate_message - unsupported request type: %d", rstate->hdr.op);
+ LogMsg("ERROR: validate_message - unsupported request type: %d", rstate->hdr.op);
return -1;
- }
+ }
return (rstate->data_bytes >= min_size ? 0 : -1);
}
-
static uint32_t dnssd_htonl(uint32_t l)
{
uint32_t ret;
return ret;
}
-
#if defined(_WIN32)
static char * win32_strerror(int inErrorCode)
memset(buffer, 0, sizeof(buffer));
- n = FormatMessageA(
- FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
+ n = FormatMessageA(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
(DWORD) inErrorCode,
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
buffer,
Change History (most recent first):
$Log: uds_daemon.h,v $
+Revision 1.14 2005/01/27 17:48:39 cheshire
+Added comment about CFSocketInvalidate closing the underlying socket
+
Revision 1.13 2004/12/10 05:27:26 cheshire
<rdar://problem/3909147> Guard against multiple autoname services of the same type on the same machine
typedef void (*udsEventCallback)(void *context);
extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback callback, void *context);
-extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd);
+extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd); // Note: This also CLOSES the file descriptor as well
// RecordUpdatedNiceLabel() can be a no-op on platforms that don't care about updating the machine's
// global default service name (was OS X calls the "Computer Name") in response to name conflicts.
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
item->hostSet.Advertise = inMDNS->AdvertiseLocalAddresses;
item->hostSet.McastTxRx = mDNStrue;
- err = mDNS_RegisterInterface( inMDNS, &item->hostSet );
+ err = mDNS_RegisterInterface( inMDNS, &item->hostSet, 0 );
require_noerr( err, exit );
item->hostRegistered = mDNStrue;
Change History (most recent first):
$Log: dnssd_NET.h,v $
+Revision 1.7 2004/12/16 19:56:12 cheshire
+Update comments
+
Revision 1.6 2004/09/20 22:47:06 cheshire
Add cautionary comment
* by renaming the service. NoAutoRename overrides this behavior - with this
* flag set, name conflicts will result in a callback. The NoAutorename flag
* is only valid if a name is explicitly specified when registering a service
- * (ie the default name is not used.)
+ * (i.e. the default name is not used.)
*/
Shared = 16,
VALUE "FileDescription", "dnssd.NET Dynamic Link Library"
VALUE "FileVersion", MASTER_PROD_VERS_STR
VALUE "InternalName", "dnssd.NET"
- VALUE "LegalCopyright", "Copyright (C) 2004"
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "dnssd.NET.dll"
VALUE "ProductName", MASTER_PROD_NAME
VALUE "ProductVersion", MASTER_PROD_VERS_STR
AdditionalDependencies="../DLL/Release/dnssd.lib mscoree.lib ws2_32.lib msvcrt.lib"\r
OutputFile="$(OutDir)\dnssd.NET.dll"\r
LinkIncremental="1"\r
- GenerateDebugInformation="TRUE"/>\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"/>\r
<Tool\r
Name="VCMIDLTool"/>\r
<Tool\r
VALUE "FileDescription", "dnssd Dynamic Link Library"
VALUE "FileVersion", MASTER_PROD_VERS_STR
VALUE "InternalName", "dnssd"
- VALUE "LegalCopyright", "Copyright (C) 2004"
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "dnssd.dll"
VALUE "ProductName", MASTER_PROD_NAME
VALUE "ProductVersion", MASTER_PROD_VERS_STR
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.00"
- Name="DLL"
- ProjectGUID="{AB581101-18F0-46F6-B56A-83A6B1EA657E}"
- Keyword="Win32Proj">
- <Platforms>
- <Platform
- Name="Win32"/>
- </Platforms>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory=".\Debug"
- IntermediateDirectory=".\Debug"
- ConfigurationType="2"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="../../mDNSCore;../../mDNSShared;../"
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DEBUG=1;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK"
- StringPooling="TRUE"
- MinimalRebuild="TRUE"
- ExceptionHandling="FALSE"
- BasicRuntimeChecks="3"
- SmallerTypeCheck="TRUE"
- RuntimeLibrary="1"
- BufferSecurityCheck="TRUE"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="4"
- CallingConvention="2"
- CompileAs="0"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib iphlpapi.lib"
- OutputFile="$(OutDir)/dnssd.dll"
- LinkIncremental="2"
- ModuleDefinitionFile="dnssd.def"
- GenerateDebugInformation="TRUE"
- ProgramDatabaseFile="$(OutDir)/dnssd.pdb"
- SubSystem="2"
- ImportLibrary="$(OutDir)/dnssd.lib"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- AdditionalIncludeDirectories="../"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="2"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="../../mDNSCore;../../mDNSShared;../"
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK"
- RuntimeLibrary="0"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="3"
- CallingConvention="2"
- CompileAs="0"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib iphlpapi.lib"
- OutputFile="$(OutDir)/dnssd.dll"
- LinkIncremental="1"
- ModuleDefinitionFile="dnssd.def"
- GenerateDebugInformation="TRUE"
- SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- ImportLibrary="$(OutDir)/dnssd.lib"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- AdditionalIncludeDirectories="../"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- </Configurations>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
- <File
- RelativePath="..\DebugServices.c">
- </File>
- <File
- RelativePath="..\..\mDNSShared\GenLinkedList.c">
- </File>
- <File
- RelativePath=".\dllmain.c">
- </File>
- <File
- RelativePath=".\dnssd.def">
- </File>
- <File
- RelativePath="..\..\mDNSShared\dnssd_clientlib.c">
- </File>
- <File
- RelativePath="..\..\mDNSShared\dnssd_clientstub.c">
- </File>
- <File
- RelativePath="..\..\mDNSShared\dnssd_ipc.c">
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
- <File
- RelativePath="..\CommonServices.h">
- </File>
- <File
- RelativePath="..\DebugServices.h">
- </File>
- <File
- RelativePath="..\..\mDNSShared\GenLinkedList.h">
- </File>
- <File
- RelativePath="..\..\mDNSShared\dns_sd.h">
- </File>
- <File
- RelativePath="..\..\mDNSShared\dnssd_ipc.h">
- </File>
- <File
- RelativePath="..\..\mDNSShared\dnssd_sock.h">
- </File>
- <File
- RelativePath=".\resource.h">
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
- <File
- RelativePath=".\dll.rc">
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding = "Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="DLL"\r
+ ProjectGUID="{AB581101-18F0-46F6-B56A-83A6B1EA657E}"\r
+ Keyword="Win32Proj">\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="2"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="../../mDNSCore;../../mDNSShared;../"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DEBUG=1;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK"\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="TRUE"\r
+ ExceptionHandling="FALSE"\r
+ BasicRuntimeChecks="3"\r
+ SmallerTypeCheck="TRUE"\r
+ RuntimeLibrary="1"\r
+ BufferSecurityCheck="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="4"\r
+ CallingConvention="2"\r
+ CompileAs="0"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
+ OutputFile="$(OutDir)/dnssd.dll"\r
+ LinkIncremental="2"\r
+ ModuleDefinitionFile="dnssd.def"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(OutDir)/dnssd.pdb"\r
+ SubSystem="2"\r
+ ImportLibrary="$(IntDir)\dnssd.lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files\bin"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="2"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ AdditionalIncludeDirectories="../../mDNSCore;../../mDNSShared;../"\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MDNS_DEBUGMSGS=0;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK"\r
+ RuntimeLibrary="0"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"\r
+ CallingConvention="2"\r
+ CompileAs="0"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
+ OutputFile="$(OutDir)/dnssd.dll"\r
+ LinkIncremental="1"\r
+ ModuleDefinitionFile="dnssd.def"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+ SubSystem="2"\r
+ OptimizeReferences="2"\r
+ EnableCOMDATFolding="2"\r
+ ImportLibrary=".\Release\dnssd.lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\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="..\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=".\dnssd.def">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\dnssd_clientlib.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\dnssd_clientstub.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\dnssd_ipc.c">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+ <File\r
+ RelativePath="..\CommonServices.h">\r
+ </File>\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_ipc.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\dnssd_sock.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\resource.h">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
+ <File\r
+ RelativePath=".\dll.rc">\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
Change History (most recent first):
$Log: DNSServices.c,v $
+Revision 1.32 2004/12/16 20:13:02 cheshire
+<rdar://problem/3324626> Cache memory management improvements
+
Revision 1.31 2004/10/19 21:33:23 cheshire
<rdar://problem/3844991> Cannot resolve non-local registrations using the mach API
Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name
objectPtr->callback = inCallBack;
objectPtr->callbackContext = inCallBackContext;
objectPtr->owner = inOwner;
- AssignDomainName( objectPtr->info.name, fullName );
+ AssignDomainName( &objectPtr->info.name, &fullName );
objectPtr->info.InterfaceID = mDNSInterface_Any;
// Save off the resolve info so the callback can get it.
mDNS_SetupResourceRecord( &object->RR_PTR, mDNSNULL, interfaceID, kDNSType_PTR, 60, kDNSRecordTypeKnownUnique,
DNSHostRegistrationPrivateCallBack, object );
- AssignDomainName( object->RR_A.resrec.name, name );
+ AssignDomainName( &object->RR_A.resrec.name, &name );
mDNS_snprintf( buffer, sizeof( buffer ), "%d.%d.%d.%d.in-addr.arpa.", ip.b[ 3 ], ip.b[ 2 ], ip.b[ 1 ], ip.b[ 0 ] );
MakeDomainNameFromDNSNameString( &object->RR_PTR.resrec.name, buffer );
object->RR_A.resrec.rdata->u.ipv4 = ip;
- AssignDomainName( object->RR_PTR.resrec.rdata->u.name, object->RR_A.resrec.name );
+ AssignDomainName( &object->RR_PTR.resrec.rdata->u.name, &object->RR_A.resrec.name );
// Add the object to the list.
name.c[ 0 ] = 0;
AppendDomainLabel( &name, &object->name );
AppendDomainLabel( &name, &object->domain );
- AssignDomainName( object->RR_PTR.resrec.name, name );
+ AssignDomainName( &object->RR_PTR.resrec.name, &name );
err = mDNS_Register( gMDNSPtr, &object->RR_A );
check_noerr( err );
# @APPLE_LICENSE_HEADER_END@
#
# $Log: makefile,v $
+# Revision 1.4 2004/12/16 22:38:00 shersche
+# Compile DNSSDException.java first to avoid build errors, copy output to appropriate "buildroot" folder
+#
# Revision 1.3 2004/11/23 08:13:07 shersche
# Link to the iphlpapi.lib for GetAdaptersInfo
#
#############################################################################
-all: setup Java
+all: setup Java postbuild
# 'setup' sets up the build directory structure the way we want
setup:
@if not exist $(OBJDIR) mkdir $(OBJDIR)
@if not exist $(BUILDDIR) mkdir $(BUILDDIR)
+!if DEFINED(DNSSD_BUILD_ROOT)
+!if $(DEBUG) == 1
+postbuild:
+ copy $(BUILDDIR)\dns_sd.jar $(DNSSD_BUILD_ROOT)\Debug\Root\"Program Files"\bin
+ copy $(BUILDDIR)\jdns_sd.dll $(DNSSD_BUILD_ROOT)\Debug\Root\"Program Files"\bin
+!else
+postbuild:
+ copy $(BUILDDIR)\dns_sd.jar $(DNSSD_BUILD_ROOT)\Release\Root\"Program Files"\bin
+ copy $(BUILDDIR)\jdns_sd.dll $(DNSSD_BUILD_ROOT)\Release\Root\"Program Files"\bin
+!endif
+!else
+postbuild:
+!endif
+
# clean removes targets and objects
clean:
@if exist $(OBJDIR) $(RMDIR) $(OBJDIR)
# The following targets build Java wrappers for the dns-sd.h API.
-Java: setup $(BUILDDIR)\dns_sd.jar $(BUILDDIR)\jdns_sd.dll
+Java: setup $(BUILDDIR)\dns_sd.jar $(BUILDDIR)\jdns_sd.dll postbuild
@echo "Java wrappers done"
JAVASRC = $(SHAREDDIR)\Java
JARCONTENTS = $(OBJDIR)\com\apple\dnssd\DNSSDService.class \
- $(OBJDIR)\com\apple\dnssd\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 \
// Generated from the TEXTINCLUDE 2 resource.\r
//\r
#include "afxres.h"\r
+#include "WinVersRes.h"\r
\r
/////////////////////////////////////////////////////////////////////////////\r
#undef APSTUDIO_READONLY_SYMBOLS\r
//\r
\r
VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 1,0,0,5\r
- PRODUCTVERSION 1,0,0,5\r
+ FILEVERSION MASTER_PROD_VERS\r
+ PRODUCTVERSION MASTER_PROD_VERS\r
FILEFLAGSMASK 0x17L\r
#ifdef _DEBUG\r
FILEFLAGS 0x1L\r
BEGIN\r
VALUE "CompanyName", "Apple Computer, Inc."\r
VALUE "FileDescription", "NSPTool Application"\r
- VALUE "FileVersion", "1, 0, 0, 5"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
VALUE "InternalName", "NSPTool"\r
- VALUE "LegalCopyright", "Copyright (C) 2004"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
VALUE "OriginalFilename", "NSPTool.exe"\r
- VALUE "ProductName", " NSPTool Application"\r
- VALUE "ProductVersion", "1, 0, 0, 5"\r
+ VALUE "ProductName", MASTER_PROD_NAME\r
+ VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
END\r
END\r
BLOCK "VarFileInfo"\r
<Tool\r
Name="VCPreLinkEventTool"/>\r
<Tool\r
- Name="VCResourceCompilerTool"/>\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="..\"/>\r
<Tool\r
Name="VCWebServiceProxyGeneratorTool"/>\r
<Tool\r
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory="Release"\r
- IntermediateDirectory="Release"\r
+ OutputDirectory=".\Release\Root\InstallTools"\r
+ IntermediateDirectory=".\Release"\r
ConfigurationType="1"\r
CharacterSet="2">\r
<Tool\r
OutputFile="$(OutDir)/NSPTool.exe"\r
LinkIncremental="1"\r
GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
SubSystem="1"\r
OptimizeReferences="2"\r
EnableCOMDATFolding="2"\r
<Tool\r
Name="VCPreLinkEventTool"/>\r
<Tool\r
- Name="VCResourceCompilerTool"/>\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="..\"/>\r
<Tool\r
Name="VCWebServiceProxyGeneratorTool"/>\r
<Tool\r
Change History (most recent first):
$Log: Service.c,v $
+Revision 1.24 2005/01/27 20:02:43 cheshire
+udsSupportRemoveFDFromEventLoop() needs to close the SocketRef as well
+
+Revision 1.23 2005/01/25 08:14:15 shersche
+Change CacheRecord to CacheEntity
+
Revision 1.22 2004/12/10 13:18:40 cheshire
Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
#define kDNSServiceCacheEntryCountDefault 512
#define RR_CACHE_SIZE 500
-static CacheRecord gRRCache[RR_CACHE_SIZE];
+static CacheEntity gRRCache[RR_CACHE_SIZE];
#if 0
#pragma mark == Structures ==
#endif
mStatus
-udsSupportRemoveFDFromEventLoop( SocketRef fd)
+udsSupportRemoveFDFromEventLoop( SocketRef fd) // Note: This also CLOSES the socket
{
Win32EventSource * source;
mStatus err = mStatus_NoError;
// done with the list
//
EventSourceUnlock();
+
+ closesocket(fd);
return err;
}
VALUE "FileDescription", "mDNSResponder"
VALUE "FileVersion", MASTER_PROD_VERS_STR
VALUE "InternalName", "mDNSResponder"
- VALUE "LegalCopyright", "Copyright (C) 2003-2004 Apple Computer, Inc."
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "mDNSResponder.exe"
VALUE "ProductName", MASTER_PROD_NAME
VALUE "ProductVersion", MASTER_PROD_VERS_STR
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.00"
- Name="mDNSResponder"
- ProjectGUID="{C1D98254-BA27-4427-A3BE-A68CA2CC5F69}"
- 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;../../mDNSShared;"C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include""
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;DEBUG=1;MDNS_DEBUGMSGS=0;UNICAST_DISABLED;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE="""""
- StringPooling="TRUE"
- MinimalRebuild="TRUE"
- ExceptionHandling="FALSE"
- BasicRuntimeChecks="3"
- SmallerTypeCheck="TRUE"
- RuntimeLibrary="1"
- BufferSecurityCheck="TRUE"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="4"
- CallingConvention="2"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib iphlpapi.lib"
- OutputFile="$(OutDir)/mDNSResponder.exe"
- LinkIncremental="2"
- IgnoreAllDefaultLibraries="FALSE"
- GenerateDebugInformation="TRUE"
- ProgramDatabaseFile="$(OutDir)/mDNSResponder.pdb"
- SubSystem="1"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- AdditionalIncludeDirectories="../"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="1"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;"C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include""
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;UNICAST_DISABLED;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE="""""
- RuntimeLibrary="0"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="3"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib iphlpapi.lib"
- OutputFile="$(OutDir)/mDNSResponder.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"
- AdditionalIncludeDirectories="../"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- </Configurations>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
- <File
- RelativePath="..\..\mDNSCore\DNSCommon.c">
- </File>
- <File
- RelativePath="..\..\mDNSCore\DNSDigest.c">
- </File>
- <File
- RelativePath="..\DebugServices.c">
- </File>
- <File
- RelativePath="Firewall.cpp">
- </File>
- <File
- RelativePath="..\..\mDNSShared\GenLinkedList.c">
- </File>
- <File
- RelativePath=".\Service.c">
- </File>
- <File
- RelativePath="..\..\mDNSShared\dnssd_ipc.c">
- </File>
- <File
- RelativePath="..\..\mDNSCore\mDNS.c">
- </File>
- <File
- RelativePath="..\..\mDNSShared\mDNSDebug.c">
- </File>
- <File
- RelativePath="..\mDNSWin32.c">
- </File>
- <File
- RelativePath="..\..\mDNSCore\uDNS.c">
- </File>
- <File
- RelativePath="..\..\mDNSShared\uds_daemon.c">
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
- <File
- RelativePath="..\CommonServices.h">
- </File>
- <File
- RelativePath="..\..\mDNSCore\DNSCommon.h">
- </File>
- <File
- RelativePath="..\DebugServices.h">
- </File>
- <File
- RelativePath="..\..\mDNSShared\GenLinkedList.h">
- </File>
- <File
- RelativePath=".\Resource.h">
- </File>
- <File
- RelativePath="..\..\mDNSShared\dnssd_ipc.h">
- </File>
- <File
- RelativePath="..\..\mDNSCore\mDNSClientAPI.h">
- </File>
- <File
- RelativePath="..\..\mDNSCore\mDNSDebug.h">
- </File>
- <File
- RelativePath="..\mDNSWin32.h">
- </File>
- <File
- RelativePath="..\..\mDNSCore\uDNS.h">
- </File>
- <File
- RelativePath="..\..\mDNSShared\uds_daemon.h">
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
- <File
- RelativePath=".\Service.rc">
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding = "Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="mDNSResponder"\r
+ ProjectGUID="{C1D98254-BA27-4427-A3BE-A68CA2CC5F69}"\r
+ Keyword="Win32Proj">\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="1"\r
+ CharacterSet="2">\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="""""\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="TRUE"\r
+ ExceptionHandling="FALSE"\r
+ BasicRuntimeChecks="3"\r
+ SmallerTypeCheck="TRUE"\r
+ RuntimeLibrary="1"\r
+ BufferSecurityCheck="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="4"\r
+ CallingConvention="2"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="ws2_32.lib iphlpapi.lib crypt32.lib"\r
+ OutputFile="$(OutDir)/mDNSResponder.exe"\r
+ LinkIncremental="2"\r
+ IgnoreAllDefaultLibraries="FALSE"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(OutDir)/mDNSResponder.pdb"\r
+ SubSystem="1"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files\bin"\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="""""\r
+ RuntimeLibrary="0"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="ws2_32.lib iphlpapi.lib"\r
+ OutputFile="$(OutDir)/mDNSResponder.exe"\r
+ LinkIncremental="1"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+ SubSystem="1"\r
+ OptimizeReferences="2"\r
+ EnableCOMDATFolding="2"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\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
+ </File>\r
+ <File\r
+ RelativePath="..\DebugServices.c">\r
+ </File>\r
+ <File\r
+ RelativePath="Firewall.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\GenLinkedList.c">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Service.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\dDNS.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\dnssd_ipc.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSCore\mDNS.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\mDNSDebug.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\mDNSWin32.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSCore\uDNS.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\uds_daemon.c">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+ <File\r
+ RelativePath="..\CommonServices.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSCore\DNSCommon.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
+ </File>\r
+ <File\r
+ RelativePath="..\dDNS.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\dnssd_ipc.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSCore\mDNSDebug.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSCore\mDNSEmbeddedAPI.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\mDNSWin32.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSCore\uDNS.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\uds_daemon.h">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
+ <File\r
+ RelativePath=".\Service.rc">\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
Change History (most recent first):
$Log: WinVersRes.h,v $
+Revision 1.22 2005/01/25 17:15:52 shersche
+Bump to 1.0.0.51. Add legal copyright string.
+
+Revision 1.21 2005/01/11 07:09:32 shersche
+Bump to version 1.0.0.51
+
+Revision 1.20 2004/12/17 01:23:24 shersche
+Bump version to 1.0.0.50
+
+Revision 1.19 2004/12/16 08:09:47 shersche
+Revert version number back to 1.0.0.22
+
+Revision 1.18 2004/12/16 02:48:10 shersche
+Bump version number to 1.1.0.0
+
Revision 1.17 2004/10/20 15:37:46 shersche
Bump to Windows-trial-21
#define MASTER_PROD_NAME "Rendezvous"
// Define the product version for mDNSResponder on Windows
-#define MASTER_PROD_VERS 1,0,0,21
-#define MASTER_PROD_VERS_STR "1,0,0,21"
-#define MASTER_PROD_VERS_STR2 "1.0.0.21"
-#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.0.21"
+#define MASTER_PROD_VERS 1,0,0,52
+#define MASTER_PROD_VERS_STR "1,0,0,52"
+#define MASTER_PROD_VERS_STR2 "1.0.0.52"
+#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.0.52"
+
+// Define the legal copyright
+#define MASTER_LEGAL_COPYRIGHT "Copyright (C) 2003-2005 Apple Computer, Inc."
#endif // WINRESVERS_H
--- /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):
+
+*/
+
+#include "dDNS.h"
+#include "DNSCommon.h"
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <ws2tcpip.h>
+
+typedef struct SearchListElem
+ {
+ struct SearchListElem *next;
+ domainname domain;
+ int flag;
+ DNSQuestion BrowseQ;
+ DNSQuestion DefBrowseQ;
+ DNSQuestion LegacyBrowseQ;
+ DNSQuestion RegisterQ;
+ DNSQuestion DefRegisterQ;
+ ARListElem *AuthRecs;
+ } SearchListElem;
+// for domain enumeration and default browsing/registration
+static SearchListElem *SearchList = mDNSNULL; // where we search for _browse domains
+static DNSQuestion LegacyBrowseDomainQ; // our local enumeration query for _legacy._browse domains
+static DNameListElem *DefBrowseList = mDNSNULL; // cache of answers to above query (where we search for empty string browses)
+static DNameListElem *DefRegList = mDNSNULL; // manually generated list of domains where we register for empty string registrations
+static ARListElem *SCPrefBrowseDomains = mDNSNULL; // manually generated local-only PTR records for browse domains we get from SCPreferences
+
+static domainname dDNSRegDomain; // Default wide-area zone for service registration
+static domainname dDNSBrowseDomain; // Default wide-area zone for legacy ("empty string") browses
+static domainname dDNSHostname;
+
+
+mStatus dDNS_SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
+ {
+ if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
+
+ if (sa->sa_family == AF_INET)
+ {
+ struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
+ ip->type = mDNSAddrType_IPv4;
+ ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
+ return(mStatus_NoError);
+ }
+
+ if (sa->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
+ ip->type = mDNSAddrType_IPv6;
+#if !defined(_WIN32)
+ if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
+#else
+ if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.u.Word[1] = 0;
+#endif
+ ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
+ return(mStatus_NoError);
+ }
+
+ LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
+ return(mStatus_Invalid);
+ }
+
+mDNSlocal void MarkSearchListElem(domainname *domain)
+ {
+ SearchListElem *new, *ptr;
+
+ // if domain is in list, mark as pre-existent (0)
+ for (ptr = SearchList; ptr; ptr = ptr->next)
+ if (SameDomainName(&ptr->domain, domain))
+ {
+ if (ptr->flag != 1) ptr->flag = 0; // gracefully handle duplicates - if it is already marked as add, don't bump down to preexistent
+ break;
+ }
+
+ // if domain not in list, add to list, mark as add (1)
+ if (!ptr)
+ {
+ new = mallocL("MarkSearchListElem - SearchListElem", sizeof(SearchListElem));
+ if (!new) { LogMsg("ERROR: MarkSearchListElem - malloc"); return; }
+ bzero(new, sizeof(SearchListElem));
+ AssignDomainName(&new->domain, domain);
+ new->flag = 1; // add
+ new->next = SearchList;
+ SearchList = new;
+ }
+ }
+
+//!!!KRS here is where we will give success/failure notification to the UI
+mDNSlocal void SCPrefsdDNSCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
+ {
+ (void)m; // unused
+ debugf("SCPrefsdDNSCallback: result %d for registration of name %##s", result, rr->resrec.name->c);
+ dDNSPlatformSetNameStatus(rr->resrec.name, result);
+ }
+
+mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
+ {
+ ARListElem *elem = rr->RecordContext;
+
+ (void)m; // unused
+
+ if (result == mStatus_MemFree) freeL("FreeARElemCallback", elem);
+ }
+
+mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+ {
+ SearchListElem *slElem = question->QuestionContext;
+ ARListElem *arElem, *ptr, *prev;
+ AuthRecord *dereg;
+ const char *name;
+ mStatus err;
+
+ if (AddRecord)
+ {
+ arElem = mallocL("FoundDomain - arElem", sizeof(ARListElem));
+ if (!arElem) { LogMsg("ERROR: malloc"); return; }
+ mDNS_SetupResourceRecord(&arElem->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, arElem);
+ if (question == &slElem->BrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowse];
+ else if (question == &slElem->DefBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseDefault];
+ else if (question == &slElem->LegacyBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseLegacy];
+ else if (question == &slElem->RegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistration];
+ else if (question == &slElem->DefRegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistrationDefault];
+ else { LogMsg("FoundDomain - unknown question"); return; }
+
+ MakeDomainNameFromDNSNameString(arElem->ar.resrec.name, name);
+ AppendDNSNameString (arElem->ar.resrec.name, "local");
+ AssignDomainName(&arElem->ar.resrec.rdata->u.name, &answer->rdata->u.name);
+ err = mDNS_Register(m, &arElem->ar);
+ if (err)
+ {
+ LogMsg("ERROR: FoundDomain - mDNS_Register returned %d", err);
+ freeL("FoundDomain - arElem", arElem);
+ return;
+ }
+ arElem->next = slElem->AuthRecs;
+ slElem->AuthRecs = arElem;
+ }
+ else
+ {
+ ptr = slElem->AuthRecs;
+ prev = NULL;
+ while (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);
+ dereg = &ptr->ar;
+ if (prev) prev->next = ptr->next;
+ else slElem->AuthRecs = ptr->next;
+ ptr = ptr->next;
+ err = mDNS_Deregister(m, dereg);
+ if (err) LogMsg("ERROR: FoundDomain - mDNS_Deregister returned %d", err);
+ }
+ else
+ {
+ prev = ptr;
+ ptr = ptr->next;
+ }
+ }
+ }
+ }
+
+mDNSexport DNameListElem *mDNSPlatformGetSearchDomainList(void)
+ {
+ return mDNS_CopyDNameList(DefBrowseList);
+ }
+
+mDNSexport DNameListElem *mDNSPlatformGetRegDomainList(void)
+ {
+ return mDNS_CopyDNameList(DefRegList);
+ }
+
+mDNSlocal void AddDefRegDomain(domainname *d)
+ {
+ DNameListElem *newelem = NULL, *ptr;
+
+ // make sure name not already in list
+ for (ptr = DefRegList; ptr; ptr = ptr->next)
+ {
+ if (SameDomainName(&ptr->name, d))
+ { debugf("duplicate addition of default reg domain %##s", d->c); return; }
+ }
+
+ newelem = mallocL("DNameListElem", sizeof(*newelem));
+ if (!newelem) { LogMsg("Error - malloc"); return; }
+ AssignDomainName(&newelem->name, d);
+ newelem->next = DefRegList;
+ DefRegList = newelem;
+
+ dDNSPlatformDefaultRegDomainChanged(d, mDNStrue);
+ udsserver_default_reg_domain_changed(d, mDNStrue);
+ }
+
+mDNSlocal void RemoveDefRegDomain(domainname *d)
+ {
+ DNameListElem *ptr = DefRegList, *prev = NULL;
+
+ while (ptr)
+ {
+ if (SameDomainName(&ptr->name, d))
+ {
+ if (prev) prev->next = ptr->next;
+ else DefRegList = ptr->next;
+ freeL("DNameListElem", ptr);
+ dDNSPlatformDefaultRegDomainChanged(d, mDNSfalse);
+ udsserver_default_reg_domain_changed(d, mDNSfalse);
+ return;
+ }
+ prev = ptr;
+ ptr = ptr->next;
+ }
+ debugf("Requested removal of default registration domain %##s not in contained in list", d->c);
+ }
+
+
+mDNSlocal void FoundDefBrowseDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+ {
+ DNameListElem *ptr, *prev, *new;
+ (void)m; // unused;
+ (void)question; // unused
+
+ if (AddRecord)
+ {
+ new = mallocL("FoundDefBrowseDomain", sizeof(DNameListElem));
+ if (!new) { LogMsg("ERROR: malloc"); return; }
+ AssignDomainName(&new->name, &answer->rdata->u.name);
+ new->next = DefBrowseList;
+ DefBrowseList = new;
+ dDNSPlatformDefaultBrowseDomainChanged(&new->name, mDNStrue);
+ udsserver_default_browse_domain_changed(&new->name, mDNStrue);
+ return;
+ }
+ else
+ {
+ ptr = DefBrowseList;
+ prev = NULL;
+ while (ptr)
+ {
+ if (SameDomainName(&ptr->name, &answer->rdata->u.name))
+ {
+ dDNSPlatformDefaultBrowseDomainChanged(&ptr->name, mDNSfalse);
+ udsserver_default_browse_domain_changed(&ptr->name, mDNSfalse);
+ if (prev) prev->next = ptr->next;
+ else DefBrowseList = ptr->next;
+ freeL("FoundDefBrowseDomain", ptr);
+ return;
+ }
+ prev = ptr;
+ ptr = ptr->next;
+ }
+ LogMsg("FoundDefBrowseDomain: Got remove event for domain %s not in list", answer->rdata->u.name.c);
+ }
+ }
+
+
+mDNSlocal mStatus RegisterNameServers( mDNS *const m )
+ {
+ IPAddrListElem * list;
+ IPAddrListElem * elem;
+
+ mDNS_DeleteDNSServers(m); // deregister orig list
+
+ list = dDNSPlatformGetDNSServers();
+
+ for ( elem = list; elem; elem = elem->next )
+ {
+ LogOperation("RegisterNameServers: Adding %#a", &elem->addr);
+ mDNS_AddDNSServer(m, &elem->addr, NULL);
+ }
+
+ dDNS_FreeIPAddrList( list );
+
+ return mStatus_NoError;
+ }
+
+
+mDNSlocal mStatus RegisterSearchDomains( mDNS *const m )
+ {
+ SearchListElem *ptr, *prev, *freeSLPtr;
+ DNameListElem * elem;
+ DNameListElem * list;
+ ARListElem *arList;
+ mStatus err;
+ mDNSBool dict = 1;
+
+ // step 1: mark each elem for removal (-1), unless we aren't passed a dictionary in which case we mark as preexistent
+ for (ptr = SearchList; ptr; ptr = ptr->next) ptr->flag = dict ? -1 : 0;
+
+ // get all the domains from "Search Domains" field of sharing prefs
+
+ list = dDNSPlatformGetSearchDomainList();
+
+ for ( elem = list; elem; elem = elem->next )
+ {
+ MarkSearchListElem(&elem->name);
+ }
+
+ mDNS_FreeDNameList( list );
+
+ list = dDNSPlatformGetDomainName();
+
+ if ( list )
+ {
+ MarkSearchListElem( &list->name );
+ mDNS_FreeDNameList( list );
+ }
+
+ list = dDNSPlatformGetReverseMapSearchDomainList( );
+
+ for ( elem = list; elem; elem = elem->next )
+ {
+ MarkSearchListElem(&elem->name);
+ }
+
+ mDNS_FreeDNameList( list );
+
+ if (dDNSRegDomain.c[0]) MarkSearchListElem(&dDNSRegDomain); // implicitly browse reg domain too (no-op if same as BrowseDomain)
+
+ // delete elems marked for removal, do queries for elems marked add
+ prev = mDNSNULL;
+ ptr = SearchList;
+ while (ptr)
+ {
+ if (ptr->flag == -1) // remove
+ {
+ mDNS_StopQuery(m, &ptr->BrowseQ);
+ mDNS_StopQuery(m, &ptr->RegisterQ);
+ mDNS_StopQuery(m, &ptr->DefBrowseQ);
+ mDNS_StopQuery(m, &ptr->DefRegisterQ);
+ mDNS_StopQuery(m, &ptr->LegacyBrowseQ);
+
+ // deregister records generated from answers to the query
+ arList = ptr->AuthRecs;
+ ptr->AuthRecs = mDNSNULL;
+ while (arList)
+ {
+ AuthRecord *dereg = &arList->ar;
+ arList = arList->next;
+ 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);
+ }
+
+ // remove elem from list, delete
+ if (prev) prev->next = ptr->next;
+ else SearchList = ptr->next;
+ freeSLPtr = ptr;
+ ptr = ptr->next;
+ freeL("RegisterSearchDomains - freeSLPtr", freeSLPtr);
+ continue;
+ }
+
+ if (ptr->flag == 1) // add
+ {
+ mStatus err1, err2, err3, err4, err5;
+ err1 = mDNS_GetDomains(m, &ptr->BrowseQ, mDNS_DomainTypeBrowse, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+ err2 = mDNS_GetDomains(m, &ptr->DefBrowseQ, mDNS_DomainTypeBrowseDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+ err3 = mDNS_GetDomains(m, &ptr->RegisterQ, mDNS_DomainTypeRegistration, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+ err4 = mDNS_GetDomains(m, &ptr->DefRegisterQ, mDNS_DomainTypeRegistrationDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+ err5 = mDNS_GetDomains(m, &ptr->LegacyBrowseQ, mDNS_DomainTypeBrowseLegacy, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
+ if (err1 || err2 || err3 || err4 || err5)
+ LogMsg("GetDomains for domain %##s returned error(s):\n"
+ "%d (mDNS_DomainTypeBrowse)\n"
+ "%d (mDNS_DomainTypeBrowseDefault)\n"
+ "%d (mDNS_DomainTypeRegistration)\n"
+ "%d (mDNS_DomainTypeRegistrationDefault)"
+ "%d (mDNS_DomainTypeBrowseLegacy)\n",
+ ptr->domain.c, err1, err2, err3, err4, err5);
+ ptr->flag = 0;
+ }
+
+ if (ptr->flag) { LogMsg("RegisterSearchDomains - unknown flag %d. Skipping.", ptr->flag); }
+
+ prev = ptr;
+ ptr = ptr->next;
+ }
+
+ return mStatus_NoError;
+ }
+
+// Add or remove a user-specified domain to the list of empty-string browse domains
+// Also register a non-legacy _browse PTR record so that the domain appears in enumeration lists
+mDNSlocal void SetSCPrefsBrowseDomain(mDNS *m, const domainname *d, mDNSBool add)
+ {
+ AuthRecord rec;
+
+ LogMsg("%s default browse domain %##s", add ? "Adding" : "Removing", d->c);
+
+ // Create dummy record pointing to the domain to be added/removed
+ mDNS_SetupResourceRecord(&rec, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, mDNSNULL, mDNSNULL);
+ AssignDomainName(&rec.resrec.rdata->u.name, d);
+
+ // add/remove the "_legacy" entry
+ MakeDomainNameFromDNSNameString(rec.resrec.name, mDNS_DomainTypeNames[mDNS_DomainTypeBrowseLegacy]);
+ AppendDNSNameString (rec.resrec.name, "local");
+ FoundDefBrowseDomain(m, &LegacyBrowseDomainQ, &rec.resrec, add);
+
+ if (add)
+ {
+ mStatus err;
+
+ // allocate/register a non-legacy _browse PTR record
+ ARListElem *ptr = mallocL("ARListElem", sizeof(*ptr));
+ mDNS_SetupResourceRecord(&ptr->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, ptr);
+ MakeDomainNameFromDNSNameString(ptr->ar.resrec.name, mDNS_DomainTypeNames[mDNS_DomainTypeBrowse]);
+ AppendDNSNameString (ptr->ar.resrec.name, "local");
+ AssignDomainName(&ptr->ar.resrec.rdata->u.name, d);
+ err = mDNS_Register(m, &ptr->ar);
+ if (err)
+ {
+ LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
+ freeL("ARListElem", ptr);
+ }
+ else
+ {
+ ptr->next = SCPrefBrowseDomains;
+ SCPrefBrowseDomains = ptr;
+ }
+ }
+ else
+ {
+ ARListElem **remove = &SCPrefBrowseDomains;
+ while (*remove && !SameDomainName(&(*remove)->ar.resrec.rdata->u.name, d)) remove = &(*remove)->next;
+ if (!*remove) { LogMsg("SetSCPrefsBrowseDomain (remove) - domain %##s not found!", d->c); return; }
+ mDNS_Deregister(m, &(*remove)->ar);
+ *remove = (*remove)->next;
+ }
+ }
+
+
+mStatus dDNS_Setup( mDNS *const m )
+ {
+ static mDNSBool LegacyNATInitialized = mDNSfalse;
+ mDNSBool dict = mDNStrue;
+ mDNSAddr ip;
+ mDNSAddr r;
+ // YO CFDictionaryRef dict;
+ // YO CFStringRef key;
+ domainname BrowseDomain, RegDomain, fqdn;
+
+ // get fqdn, zone from SCPrefs
+ dDNSPlatformGetConfig(&fqdn, &RegDomain, &BrowseDomain);
+
+ // YO if (!fqdn.c[0] && !RegDomain.c[0]) ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &fqdn, &RegDomain);
+
+ if (!SameDomainName(&RegDomain, &dDNSRegDomain))
+ {
+ if (dDNSRegDomain.c[0])
+ {
+ RemoveDefRegDomain(&dDNSRegDomain);
+ SetSCPrefsBrowseDomain(m, &dDNSRegDomain, mDNSfalse); // if we were automatically browsing in our registration domain, stop
+ }
+
+ AssignDomainName(&dDNSRegDomain, &RegDomain);
+
+ if (dDNSRegDomain.c[0])
+ {
+ dDNSPlatformSetSecretForDomain(m, &dDNSRegDomain);
+ AddDefRegDomain(&dDNSRegDomain);
+ SetSCPrefsBrowseDomain(m, &dDNSRegDomain, mDNStrue);
+ }
+ }
+
+ if (!SameDomainName(&BrowseDomain, &dDNSBrowseDomain))
+ {
+ if (dDNSBrowseDomain.c[0]) SetSCPrefsBrowseDomain(m, &dDNSBrowseDomain, mDNSfalse);
+ AssignDomainName(&dDNSBrowseDomain, &BrowseDomain);
+ if (dDNSBrowseDomain.c[0]) SetSCPrefsBrowseDomain(m, &dDNSBrowseDomain, mDNStrue);
+ }
+
+ if (!SameDomainName(&fqdn, &dDNSHostname))
+ {
+ if (dDNSHostname.c[0]) mDNS_RemoveDynDNSHostName(m, &dDNSHostname);
+ AssignDomainName(&dDNSHostname, &fqdn);
+ if (dDNSHostname.c[0])
+ {
+ dDNSPlatformSetSecretForDomain(m, &fqdn); // no-op if "zone" secret, above, is to be used for hostname
+ mDNS_AddDynDNSHostName(m, &dDNSHostname, SCPrefsdDNSCallback, mDNSNULL);
+ dDNSPlatformSetNameStatus(&dDNSHostname, 1);
+ }
+ }
+
+ // get DNS settings
+ // YO SCDynamicStoreRef store = SCDynamicStoreCreate(mDNSNULL, CFSTR("mDNSResponder:dDNSConfigChanged"), mDNSNULL, mDNSNULL);
+ // YO if (!store) return;
+
+ // YO key = SCDynamicStoreKeyCreateNetworkGlobalEntity(mDNSNULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
+ // YO if (!key) { LogMsg("ERROR: DNSConfigChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store); return; }
+ // YO dict = SCDynamicStoreCopyValue(store, key);
+ // 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 (dict) CFRelease(dict);
+
+ // get IPv4 settings
+ // YO key = SCDynamicStoreKeyCreateNetworkGlobalEntity(mDNSNULL,kSCDynamicStoreDomainState, kSCEntNetIPv4);
+ // YO if (!key) { LogMsg("ERROR: RouterChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store); return; }
+ // YO dict = SCDynamicStoreCopyValue(store, key);
+ // YO CFRelease(key);
+ // YO CFRelease(store);
+ // YO if (!dict)
+ // YO { mDNS_SetPrimaryInterfaceInfo(m, mDNSNULL, mDNSNULL); return; } // lost v4
+
+ // handle router changes
+ // YO mDNSAddr r;
+ // YO char buf[256];
+ // YO r.type = mDNSAddrType_IPv4;
+ // YO r.ip.v4.NotAnInteger = 0;
+ // YO CFStringRef router = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
+ // YO if (router)
+ // YO {
+ // YO if (!CFStringGetCString(router, buf, 256, kCFStringEncodingUTF8))
+ // YO LogMsg("Could not convert router to CString");
+ // YO else inet_aton(buf, (struct in_addr *)&r.ip.v4);
+ // YO }
+
+ // handle router and primary interface changes
+
+ ip.type = r.type = mDNSAddrType_IPv4;
+ ip.ip.v4.NotAnInteger = r.ip.v4.NotAnInteger = 0;
+
+ if ( dDNSPlatformGetPrimaryInterface( m, &ip, &r ) == mStatus_NoError )
+ {
+ mDNS_SetPrimaryInterfaceInfo(m, &ip, r.ip.v4.NotAnInteger ? &r : mDNSNULL);
+ }
+
+ return mStatus_NoError;
+}
+
+
+// Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
+// 1) query for b._dns-sd._udp.local on LocalOnly interface
+// (.local manually generated via explicit callback)
+// 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
+// 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
+// 4) result above should generate a callback from question in (1). result added to global list
+// 5) global list delivered to client via GetSearchDomainList()
+// 6) client calls to enumerate domains now go over LocalOnly interface
+// (!!!KRS may add outgoing interface in addition)
+
+mStatus dDNS_InitDNSConfig(mDNS *const m)
+ {
+ mStatus err;
+
+ // 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);
+ return mStatus_NoError;
+}
+
+void
+dDNS_FreeIPAddrList(IPAddrListElem * list)
+{
+ IPAddrListElem * fptr;
+
+ while (list)
+ {
+ fptr = list;
+ list = list->next;
+ mDNSPlatformMemFree(fptr);
+ }
+}
--- /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):
+
+*/
+
+
+#ifndef __dDNS_h
+#define __dDNS_h
+
+#include "mDNSEmbeddedAPI.h"
+#include "dns_sd.h"
+
+#if 0
+#pragma mark - DynDNS structures
+#endif
+
+typedef struct IPAddrListElem
+ {
+ mDNSAddr addr;
+ struct IPAddrListElem *next;
+ } IPAddrListElem;
+
+extern void dDNS_FreeIPAddrList( IPAddrListElem * list );
+
+
+// ***************************************************************************
+#if 0
+#pragma mark - Main Client Functions
+#endif
+
+extern mStatus dDNS_Setup( mDNS *const m );
+extern mStatus dDNS_InitDNSConfig( mDNS *const m );
+extern mStatus dDNS_SetupAddr( mDNSAddr *ip, const struct sockaddr * const sa );
+
+
+// ***************************************************************************
+#if 0
+#pragma mark - PlatformSupport interface
+#endif
+
+// This section defines the interface to the DynDNS Platform Support layer.
+
+extern void dDNSPlatformGetConfig(domainname *const fqdn, domainname *const regDomain, domainname *const browseDomain);
+extern void dDNSPlatformSetNameStatus(domainname *const dname, mStatus status);
+extern void dDNSPlatformSetSecretForDomain( mDNS *m, const domainname *domain );
+extern DNameListElem * dDNSPlatformGetSearchDomainList( void );
+extern DNameListElem * dDNSPlatformGetReverseMapSearchDomainList( void );
+extern IPAddrListElem * dDNSPlatformGetDNSServers( void );
+extern DNameListElem * dDNSPlatformGetDomainName( void );
+extern mStatus dDNSPlatformRegisterSplitDNS( mDNS *m );
+extern mStatus dDNSPlatformGetPrimaryInterface( mDNS * m, mDNSAddr * primary, mDNSAddr * router );
+extern void dDNSPlatformDefaultBrowseDomainChanged( const domainname *d, mDNSBool add );
+extern void dDNSPlatformDefaultRegDomainChanged(const domainname *d, mDNSBool add);
+
+#endif
+
--- /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):
+
+*/
+
+/* isocode.h */
+/* ----------------------------------------------------------------------*/
+/* THIS FILE HAS BEEN AUTO-GENERATED. DO NOT EDIT DIRECTLY */
+/* If a language needs to be added, edit isocode.txt, and run isocode.pl */
+/* to generate a new version of this file */
+/* ----------------------------------------------------------------------*/
+/* ----------------------------------------------------------------------*/
+
+
+unsigned char ISOCODES[] = {
+12, 9, 'e','n', 0 , 0 , 0 , 0 ,
+40, 9, 'e','n', 0 , 0 , 0 , 0 ,
+16, 9, 'e','n', 0 , 0 , 0 , 0 ,
+36, 9, 'e','n', 0 , 0 , 0 , 0 ,
+24, 9, 'e','n', 0 , 0 , 0 , 0 ,
+32, 9, 'e','n', 0 , 0 , 0 , 0 ,
+20, 9, 'e','n', 0 , 0 , 0 , 0 ,
+52, 9, 'e','n', 0 , 0 , 0 , 0 ,
+28, 9, 'e','n', 0 , 0 , 0 , 0 ,
+44, 9, 'e','n', 0 , 0 , 0 , 0 ,
+8, 9, 'e','n', 0 , 0 , 0 , 0 ,
+4, 9, 'e','n', 0 , 0 , 0 , 0 ,
+48, 9, 'e','n', 0 , 0 , 0 , 0 ,
+8, 12, 'f','r', 0 , 0 , 0 , 0 ,
+44, 12, 'f','r', 0 , 0 , 0 , 0 ,
+12, 12, 'f','r', 0 , 0 , 0 , 0 ,
+36, 12, 'f','r', 0 , 0 , 0 , 0 ,
+48, 12, 'f','r', 0 , 0 , 0 , 0 ,
+4, 12, 'f','r', 0 , 0 , 0 , 0 ,
+20, 12, 'f','r', 0 , 0 , 0 , 0 ,
+52, 12, 'f','r', 0 , 0 , 0 , 0 ,
+24, 12, 'f','r', 0 , 0 , 0 , 0 ,
+40, 12, 'f','r', 0 , 0 , 0 , 0 ,
+16, 12, 'f','r', 0 , 0 , 0 , 0 ,
+28, 12, 'f','r', 0 , 0 , 0 , 0 ,
+4, 98, 'f','r', 0 , 0 , 0 , 0 ,
+12, 7, 'd','e', 0 , 0 , 0 , 0 ,
+4, 7, 'd','e', 0 , 0 , 0 , 0 ,
+20, 7, 'd','e', 0 , 0 , 0 , 0 ,
+16, 7, 'd','e', 0 , 0 , 0 , 0 ,
+8, 7, 'd','e', 0 , 0 , 0 , 0 ,
+4, 17, 'j','a', 0 , 0 , 0 , 0 ,
+8, 19, 'n','l', 0 , 0 , 0 , 0 ,
+4, 19, 'n','l', 0 , 0 , 0 , 0 ,
+4, 16, 'i','t', 0 , 0 , 0 , 0 ,
+8, 16, 'i','t', 0 , 0 , 0 , 0 ,
+44, 10, 'e','s', 0 , 0 , 0 , 0 ,
+64, 10, 'e','s', 0 , 0 , 0 , 0 ,
+52, 10, 'e','s', 0 , 0 , 0 , 0 ,
+36, 10, 'e','s', 0 , 0 , 0 , 0 ,
+20, 10, 'e','s', 0 , 0 , 0 , 0 ,
+28, 10, 'e','s', 0 , 0 , 0 , 0 ,
+48, 10, 'e','s', 0 , 0 , 0 , 0 ,
+68, 10, 'e','s', 0 , 0 , 0 , 0 ,
+16, 10, 'e','s', 0 , 0 , 0 , 0 ,
+72, 10, 'e','s', 0 , 0 , 0 , 0 ,
+12, 10, 'e','s', 0 , 0 , 0 , 0 ,
+8, 10, 'e','s', 0 , 0 , 0 , 0 ,
+76, 10, 'e','s', 0 , 0 , 0 , 0 ,
+24, 10, 'e','s', 0 , 0 , 0 , 0 ,
+60, 10, 'e','s', 0 , 0 , 0 , 0 ,
+40, 10, 'e','s', 0 , 0 , 0 , 0 ,
+80, 10, 'e','s', 0 , 0 , 0 , 0 ,
+4, 10, 'e','s', 0 , 0 , 0 , 0 ,
+56, 10, 'e','s', 0 , 0 , 0 , 0 ,
+32, 10, 'e','s', 0 , 0 , 0 , 0 ,
+8, 4, 'z','h','_','C','N', 0 ,
+16, 4, 'z','h','_','C','N', 0 ,
+12, 4, 'z','h','_','T','W', 0 ,
+20, 4, 'z','h','_','T','W', 0 ,
+4, 4, 'z','h','_','T','W', 0 ,
+4, 6, 'd','a', 0 , 0 , 0 , 0 ,
+4, 11, 'f','i', 0 , 0 , 0 , 0 ,
+4, 18, 'k','o', 0 , 0 , 0 , 0 ,
+4, 20, 'n','o', 0 , 0 , 0 , 0 ,
+8, 20, 'n','o', 0 , 0 , 0 , 0 ,
+4, 22, 'p','t', 0 , 0 , 0 , 0 ,
+4, 29, 's','v', 0 , 0 , 0 , 0 ,
+8, 29, 's','v', 0 , 0 , 0 , 0 ,
+20, 1, 'a','r', 0 , 0 , 0 , 0 ,
+60, 1, 'a','r', 0 , 0 , 0 , 0 ,
+12, 1, 'a','r', 0 , 0 , 0 , 0 ,
+8, 1, 'a','r', 0 , 0 , 0 , 0 ,
+44, 1, 'a','r', 0 , 0 , 0 , 0 ,
+52, 1, 'a','r', 0 , 0 , 0 , 0 ,
+48, 1, 'a','r', 0 , 0 , 0 , 0 ,
+16, 1, 'a','r', 0 , 0 , 0 , 0 ,
+24, 1, 'a','r', 0 , 0 , 0 , 0 ,
+32, 1, 'a','r', 0 , 0 , 0 , 0 ,
+64, 1, 'a','r', 0 , 0 , 0 , 0 ,
+4, 1, 'a','r', 0 , 0 , 0 , 0 ,
+40, 1, 'a','r', 0 , 0 , 0 , 0 ,
+28, 1, 'a','r', 0 , 0 , 0 , 0 ,
+56, 1, 'a','r', 0 , 0 , 0 , 0 ,
+36, 1, 'a','r', 0 , 0 , 0 , 0 ,
+4, 2, 'b','g', 0 , 0 , 0 , 0 ,
+4, 26, 'h','r', 0 , 0 , 0 , 0 ,
+4, 5, 'c','s', 0 , 0 , 0 , 0 ,
+4, 8, 'e','l', 0 , 0 , 0 , 0 ,
+4, 13, 'i','w', 0 , 0 , 0 , 0 ,
+4, 14, 'h','u', 0 , 0 , 0 , 0 ,
+4, 15, 'i','s', 0 , 0 , 0 , 0 ,
+4, 21, 'p','l', 0 , 0 , 0 , 0 ,
+8, 22, 'p','t','_','P','T', 0 ,
+4, 24, 'r','o', 0 , 0 , 0 , 0 ,
+8, 24, 'r','o', 0 , 0 , 0 , 0 ,
+4, 15, 'r','u', 0 , 0 , 0 , 0 ,
+8, 25, 'r','u', 0 , 0 , 0 , 0 ,
+4, 30, 't','h', 0 , 0 , 0 , 0 ,
+4, 31, 't','r', 0 , 0 , 0 , 0 ,
+4, 34, 'u','k', 0 , 0 , 0 , 0 ,
+};
+
+#define NUM_ISOCODES 101
+#define LANG_CODE_LEN 5
+#define MODULO_ISOCODES 8
+
+
--- /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):
+
+ */
+
+/* loclibrary.c
+ * ----------------------------------------------------------------------
+ * Source for localization library
+ * Originally created by jsantamaria: 3 may 2004
+ * ----------------------------------------------------------------------
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include "isocode.h"
+#include "loclibrary.h"
+#include "Shlwapi.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <wchar.h>
+
+#ifdef __cplusplus
+extern "c" {
+#endif
+
+#ifdef _MSC_VER
+#define swprintf _snwprintf
+#define snprintf _snprintf
+#endif
+
+
+
+#define DEFAULT_LANG_CODE "en"
+
+// gets the user language
+static LANGID _getUserLanguage( void ) {
+
+ return GetUserDefaultUILanguage();
+
+}
+
+
+// gets the ISO mapping
+static int _getISOCode(LANGID wLangID, char *isoLangCode, int codeLen) {
+ int i;
+ unsigned short langCode;
+
+ for (i = 0; i < NUM_ISOCODES; i++) {
+ int startIndex = i * MODULO_ISOCODES;
+
+ langCode = (ISOCODES[startIndex] << 8);
+ langCode += ( (unsigned short) (ISOCODES[startIndex + 1]) );
+
+ if (langCode == wLangID) {
+ char *langStr = (char *)&(ISOCODES[startIndex+2]);
+ strncpy(isoLangCode, langStr, codeLen);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static char isoLangCode[LANG_CODE_LEN + 1] = "";
+static LANGID wLangID = (LANGID) -1;
+
+static void _setLanguageIfNeeded(void) {
+
+ // get the language code if we don't have it cached
+ if (!strncmp(isoLangCode,"",LANG_CODE_LEN + 1)) {
+
+ // if we haven't cached the language id, do the lookup
+ if (wLangID == (LANGID) -1) {
+ wLangID = _getUserLanguage();
+ }
+
+ // if no ISOCode, set it to DEFAULT_LANG_CODE
+ if (_getISOCode(wLangID, isoLangCode, LANG_CODE_LEN + 1)) {
+ strncpy(isoLangCode, DEFAULT_LANG_CODE, LANG_CODE_LEN+1);
+ }
+ }
+
+}
+
+//// PathForResource
+
+// Gets the PathForResource for handle 0 for the current process
+
+
+static char appPathNameA[MAX_PATH] = "";
+
+int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locFileLen) {
+ if (!strcmp(appPathNameA,"")) {
+ GetModuleFileNameA(module, appPathNameA, MAX_PATH);
+ }
+
+ return PathForResourceWithPathA (appPathNameA, name, locFile, locFileLen);
+
+}
+
+static wchar_t appPathNameW[MAX_PATH] = L"";
+
+int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, int locFileLen) {
+ if (!wcscmp(appPathNameW,L"")) {
+ GetModuleFileNameW( module, appPathNameW, MAX_PATH);
+ }
+
+OutputDebugString( appPathNameW );
+
+ return PathForResourceWithPathW (appPathNameW, name, locFile, locFileLen);
+}
+
+
+//// PathForResourceWithPath
+
+#define TMP_BUF_SIZE MAX_PATH
+
+int PathForResourceWithPathA (const char *path, const char *nm,
+ char *locFile, int locFileLen) {
+ char tmpBuffer[TMP_BUF_SIZE];
+
+ // build the path to the executable in the generic
+ // resources folder, check there first
+ snprintf(tmpBuffer, MAX_PATH, "%s.Resources\\%s", path, nm);
+
+ if (!PathFileExistsA(tmpBuffer)) {
+
+ // didn't hit generic resource folder, so need to get language codes
+ _setLanguageIfNeeded();
+
+ // test to see if localized directory exists,
+ // if so, we don't fall back if we don't find the file.
+ snprintf(tmpBuffer, TMP_BUF_SIZE,
+ "%s.Resources\\%s.lproj", path, isoLangCode);
+
+ if (PathFileExistsA(tmpBuffer)) {
+ snprintf(tmpBuffer, TMP_BUF_SIZE, "%s\\%s", tmpBuffer, nm);
+
+ if (!PathFileExistsA(tmpBuffer)) return 0;
+
+ strncpy(locFile, tmpBuffer, locFileLen);
+ return (int) strlen(locFile);
+ }
+
+ // fall back on DEFAULT_LANG_CODE if still no good
+ snprintf(tmpBuffer, TMP_BUF_SIZE, "%s.Resources\\%s.lproj\\%s",
+ path, DEFAULT_LANG_CODE, nm);
+
+ // we can't find the resource, so return 0
+ if (!PathFileExistsA(tmpBuffer)) return 0;
+ }
+
+ strncpy(locFile, tmpBuffer, locFileLen);
+ return (int) strlen(locFile);
+
+}
+
+
+int PathForResourceWithPathW (const wchar_t *path, const wchar_t *nm,
+ wchar_t *locFile, int locFileLen) {
+
+ wchar_t tmpBuffer[TMP_BUF_SIZE];
+
+ // build the path to the executable in the generic
+ // resources folder, check there first
+ swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls.Resources\\%ls", path, nm);
+
+ if (!PathFileExistsW(tmpBuffer)) {
+ // didn't hit generic resource folder, so need to get language codes
+ _setLanguageIfNeeded();
+
+ // test to see if localized directory exists,
+ // if so, we don't fall back if we don't find the file.
+ swprintf(tmpBuffer, TMP_BUF_SIZE,
+ L"%ls.Resources\\%S.lproj", path, isoLangCode);
+
+ if (PathFileExistsW(tmpBuffer)) {
+ swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls\\%ls", tmpBuffer, nm);
+
+ if (!PathFileExistsW(tmpBuffer)) return 0;
+
+ wcsncpy(locFile, tmpBuffer, locFileLen);
+ return (int) wcslen(locFile);
+ }
+
+ // fall back on DEFAULT_LANG_CODE if still no good
+ swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls.Resources\\%s.lproj\\%ls",
+ path, DEFAULT_LANG_CODE, nm);
+
+ // we can't find the resource, so return 0
+ if (!PathFileExistsW(tmpBuffer)) return 0;
+ }
+
+ wcsncpy(locFile, tmpBuffer, locFileLen);
+ return (int) wcslen(locFile);
+
+
+}
+
+
+
+#ifdef __cplusplus
+}
+#endif
--- /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):
+
+ */
+
+/* loclibrary.h
+ * ----------------------------------------------------------------------
+ * Header file for localization library
+ * Originally created by jsantamaria: 3 may 2004
+ * ----------------------------------------------------------------------
+ */
+
+#ifndef _loclibrary_h_
+#define _loclibrary_h_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, int locFileLen);
+int PathForResourceWithPathW ( const wchar_t *path, const wchar_t *name, wchar_t *locFile, int locFileLen);
+
+int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locFileLen);
+int PathForResourceWithPathA ( const char *path, const char *name, char *locFile, int locFileLen);
+
+
+#ifdef UNICODE
+#define PathForResource PathForResourceW
+#define PathForResourceWithPath PathForResourceWithPathW
+#else
+#define PathForResource PathForResourceA
+#define PathForResourceWithPath PathForResourceWithPathA
+#endif // UNICODE
+
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+
+#endif // _loclibrary_h_
Change History (most recent first):
$Log: mDNSWin32.c,v $
+Revision 1.71 2005/01/27 22:57:57 cheshire
+Fix compile errors on gcc4
+
+Revision 1.70 2005/01/25 08:12:52 shersche
+<rdar://problem/3947417> Enable Unicast and add Dynamic DNS support.
+Bug #: 3947417
+
+Revision 1.69 2005/01/11 04:39:48 shersche
+Workaround for GetAdaptersAddresses() bug in iphlpapi.dll
+
+Revision 1.68 2005/01/11 02:04:48 shersche
+Gracefully handle when IPv6 is not installed on a user's machine
+
+Revision 1.67 2004/12/18 00:51:52 cheshire
+Use symbolic constant kDNSServiceInterfaceIndexLocalOnly instead of (mDNSu32) ~0
+
+Revision 1.66 2004/12/17 23:37:49 cheshire
+<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
+(and other repetitive configuration changes)
+
+Revision 1.65 2004/12/15 07:34:45 shersche
+Add platform support for IPv4 and IPv6 unicast sockets
+
+Revision 1.64 2004/12/15 06:06:15 shersche
+Fix problem in obtaining IPv6 subnet mask
+
Revision 1.63 2004/11/23 03:39:47 cheshire
Let interface name/index mapping capability live directly in JNISupport.c,
instead of having to call through to the daemon via IPC to get this information.
#include "CommonServices.h"
#include "DebugServices.h"
+#include <dns_sd.h>
#include <Iphlpapi.h>
#if( !TARGET_OS_WINDOWS_CE )
#include <mswsock.h>
#include <process.h>
+ #include <ntsecapi.h>
#endif
#include "mDNSEmbeddedAPI.h"
#define MDNS_WINDOWS_ENABLE_IPV6 1
#define MDNS_WINDOWS_EXCLUDE_IPV4_ROUTABLE_IPV6 1
#define MDNS_WINDOWS_AAAA_OVER_IPV4 1
+#define MDNS_FIX_IPHLPAPI_PREFIX_BUG 1
#define kMDNSDefaultName "My Computer"
#define kWaitListCancelEvent ( WAIT_OBJECT_0 + 0 )
#define kWaitListInterfaceListChangedEvent ( WAIT_OBJECT_0 + 1 )
#define kWaitListWakeupEvent ( WAIT_OBJECT_0 + 2 )
-#define kWaitListRegEvent ( WAIT_OBJECT_0 + 3 )
-#define kWaitListFixedItemCount 4
+#define kWaitListComputerDescriptionEvent ( WAIT_OBJECT_0 + 3 )
+#define kWaitListDynDNSEvent ( WAIT_OBJECT_0 + 4 )
+#define kWaitListFixedItemCount 5 + MDNS_WINDOWS_ENABLE_IPV4 + MDNS_WINDOWS_ENABLE_IPV6
+
#if( !TARGET_OS_WINDOWS_CE )
static GUID kWSARecvMsgGUID = WSAID_WSARECVMSG;
#endif
+
#if 0
#pragma mark == Prototypes ==
#endif
mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS );
mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD );
mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD );
-mDNSlocal mStatus SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, SocketRef *outSocketRef );
+mDNSlocal mStatus SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef );
mDNSlocal mStatus SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort );
mDNSlocal mStatus SetupNotifications( mDNS * const inMDNS );
mDNSlocal mStatus TearDownNotifications( mDNS * const inMDNS );
mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **outWaitList, int *outWaitListCount );
mDNSlocal void ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *inIFD, SocketRef inSock );
mDNSlocal void ProcessingThreadInterfaceListChanged( mDNS *inMDNS );
-mDNSlocal void ProcessingThreadRegistryChanged( mDNS * inMDNS );
+mDNSlocal void ProcessingThreadComputerDescriptionChanged( mDNS * inMDNS );
+mDNSlocal void ProcessingThreadDynDNSConfigChanged( mDNS * inMDNS );
+
// Platform Accessors
#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
mDNSlocal int getifaddrs_ipv6( struct ifaddrs **outAddrs );
- mDNSlocal int getifnetmask_ipv6( struct ifaddrs * ifa );
#endif
#if( !TARGET_OS_WINDOWS_CE )
mDNSlocal mDNSBool CanReceiveUnicast( void );
+mDNSlocal mStatus StringToAddress( mDNSAddr * ip, const char * string );
+mDNSlocal mStatus RegQueryString( HKEY key, const char * param, char ** string, DWORD * stringLen, DWORD * enabled );
+mDNSlocal struct ifaddrs* myGetIfAddrs(int refresh);
+mDNSlocal OSStatus ConvertUTF8ToLsaString( const char * input, PLSA_UNICODE_STRING output );
+mDNSlocal OSStatus ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char ** output );
+
#ifdef __cplusplus
}
#endif
mStatus err;
WSADATA wsaData;
int supported;
+ struct sockaddr_in sa4;
+ struct sockaddr_in6 sa6;
dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" );
inMDNS->HISoftware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HISoftware.c[ 1 ] );
dlog( kDebugLevelInfo, DEBUG_NAME "HISoftware: %#s\n", inMDNS->HISoftware.c );
+ // Set up the IPv4 unicast socket
+
+ inMDNS->p->unicastSock4 = INVALID_SOCKET;
+ inMDNS->p->unicastSock4ReadEvent = NULL;
+ inMDNS->p->unicastSock4RecvMsgPtr = NULL;
+
+#if ( MDNS_WINDOWS_ENABLE_IPV4 )
+
+ sa4.sin_family = AF_INET;
+ sa4.sin_addr.s_addr = INADDR_ANY;
+ err = SetupSocket( inMDNS, (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4 );
+ check_noerr( err );
+ inMDNS->p->unicastSock4ReadEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( inMDNS->p->unicastSock4ReadEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+ err = WSAEventSelect( inMDNS->p->unicastSock4, inMDNS->p->unicastSock4ReadEvent, FD_READ );
+ require_noerr( err, exit );
+#if( !TARGET_OS_WINDOWS_CE )
+ {
+ DWORD size;
+
+ err = WSAIoctl( inMDNS->p->unicastSock4, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID,
+ sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock4RecvMsgPtr, sizeof( inMDNS->p->unicastSock4RecvMsgPtr ), &size, NULL, NULL );
+
+ if ( err != 0 )
+ {
+ inMDNS->p->unicastSock4RecvMsgPtr = NULL;
+ }
+ }
+#endif
+
+#endif
+
+ // Set up the IPv6 unicast socket
+
+ inMDNS->p->unicastSock6 = INVALID_SOCKET;
+ inMDNS->p->unicastSock6ReadEvent = NULL;
+ inMDNS->p->unicastSock6RecvMsgPtr = NULL;
+
+#if ( MDNS_WINDOWS_ENABLE_IPV6 )
+
+ sa6.sin6_family = AF_INET6;
+ sa6.sin6_addr = in6addr_any;
+ sa6.sin6_scope_id = 0;
+
+ // This call will fail if the machine hasn't installed IPv6. In that case,
+ // the error will be WSAEAFNOSUPPORT.
+
+ err = SetupSocket( inMDNS, (const struct sockaddr*) &sa6, zeroIPPort, &inMDNS->p->unicastSock6 );
+ require_action( !err || ( err == WSAEAFNOSUPPORT ), exit, err = (mStatus) WSAGetLastError() );
+ inMDNS->p->unicastSock6ReadEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( inMDNS->p->unicastSock6ReadEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ // If we weren't able to create the socket (because IPv6 hasn't been installed) don't do this
+
+ if ( inMDNS->p->unicastSock6 != INVALID_SOCKET )
+ {
+ err = WSAEventSelect( inMDNS->p->unicastSock6, inMDNS->p->unicastSock6ReadEvent, FD_READ );
+ require_noerr( err, exit );
+
+#if( !TARGET_OS_WINDOWS_CE )
+ {
+ DWORD size;
+
+ err = WSAIoctl( inMDNS->p->unicastSock6, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID,
+ sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock6RecvMsgPtr, sizeof( inMDNS->p->unicastSock6RecvMsgPtr ), &size, NULL, NULL );
+
+ if ( err != 0 )
+ {
+ inMDNS->p->unicastSock6RecvMsgPtr = NULL;
+ }
+ }
+#endif
+ }
+
+#endif
+
// Set up the mDNS thread.
err = SetupSynchronizationObjects( inMDNS );
err = TearDownSynchronizationObjects( inMDNS );
check_noerr( err );
+#if ( MDNS_WINDOWS_ENABLE_IPV4 )
+
+ if ( inMDNS->p->unicastSock4ReadEvent )
+ {
+ CloseHandle( inMDNS->p->unicastSock4ReadEvent );
+ inMDNS->p->unicastSock4ReadEvent = 0;
+ }
+
+ if ( IsValidSocket( inMDNS->p->unicastSock4 ) )
+ {
+ close_compat( inMDNS->p->unicastSock4 );
+ }
+
+#endif
+
+#if ( MDNS_WINDOWS_ENABLE_IPV6 )
+
+ if ( inMDNS->p->unicastSock6ReadEvent )
+ {
+ CloseHandle( inMDNS->p->unicastSock6ReadEvent );
+ inMDNS->p->unicastSock6ReadEvent = 0;
+ }
+
+ if ( IsValidSocket( inMDNS->p->unicastSock6 ) )
+ {
+ close_compat( inMDNS->p->unicastSock6 );
+ }
+
+#endif
+
// Free the DLL needed for IPv6 support.
#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
const mDNSAddr * inDstIP,
mDNSIPPort inDstPort )
{
- mStatus err;
- mDNSInterfaceData * ifd;
+ SOCKET sendingsocket = INVALID_SOCKET;
+ mStatus err = mStatus_NoError;
+ mDNSInterfaceData * ifd = (mDNSInterfaceData*) inInterfaceID;
struct sockaddr_storage addr;
int n;
check( inMDNS );
check( inMsg );
check( inMsgEnd );
- check( inInterfaceID );
check( inDstIP );
- ifd = (mDNSInterfaceData *) inInterfaceID;
- require_action_quiet( ifd->interfaceInfo.McastTxRx, exit, err = mStatus_Invalid ); // Silent Interface
- require_action_quiet( inDstIP->type == ifd->interfaceInfo.ip.type, exit, err = mStatus_NoError ); // Wrong Type
- check( IsValidSocket( ifd->sock ) );
-
dlog( kDebugLevelChatty, DEBUG_NAME "platform send %d bytes to %#a:%u\n", n, inDstIP, ntohs( inDstPort.NotAnInteger ) );
if( inDstIP->type == mDNSAddrType_IPv4 )
sa4->sin_family = AF_INET;
sa4->sin_port = inDstPort.NotAnInteger;
sa4->sin_addr.s_addr = inDstIP->ip.v4.NotAnInteger;
+ sendingsocket = ifd ? ifd->sock : inMDNS->p->unicastSock4;
}
else if( inDstIP->type == mDNSAddrType_IPv6 )
{
sa6->sin6_flowinfo = 0;
sa6->sin6_addr = *( (struct in6_addr *) &inDstIP->ip.v6 );
sa6->sin6_scope_id = 0; // Windows requires the scope ID to be zero. IPV6_MULTICAST_IF specifies interface.
+ sendingsocket = ifd ? ifd->sock : inMDNS->p->unicastSock6;
}
else
{
goto exit;
}
- n = sendto( ifd->sock, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
- err = translate_errno( n > 0, errno_compat(), kWriteErr );
- require_noerr( err, exit );
+ if (IsValidSocket(sendingsocket))
+ {
+ n = sendto( sendingsocket, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
+ err = translate_errno( n > 0, errno_compat(), kWriteErr );
+ require_noerr( err, exit );
+ }
exit:
return( err );
mDNSInterfaceID id;
id = mDNSNULL;
- if( inIndex == (mDNSu32) ~0 )
+ if( inIndex == kDNSServiceInterfaceIndexLocalOnly )
{
id = mDNSInterface_LocalOnly;
}
index = 0;
if( inID == mDNSInterface_LocalOnly )
{
- index = (mDNSu32) ~0;
+ index = (mDNSu32) kDNSServiceInterfaceIndexLocalOnly;
}
else if( inID )
{
//===========================================================================================================================
-// mDNSPlatformGetSearchDomainList
+// dDNSPlatformGetConfig
+//===========================================================================================================================
+
+void
+dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, domainname *const browseDomain)
+{
+ char * name = NULL;
+ DWORD dwSize;
+ DWORD enabled;
+ HKEY key;
+ OSStatus err;
+
+ // Initialize
+
+ fqdn->c[0] = regDomain->c[0] = browseDomain->c[0] = 0;
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSHostNames, &key );
+ require_noerr( err, exit );
+
+ err = RegQueryString( key, "", &name, &dwSize, &enabled );
+ if ( !err && ( name[0] != '\0' ) && enabled )
+ {
+ if ( !MakeDomainNameFromDNSNameString( fqdn, name ) || !fqdn->c[0] )
+ {
+ dlog( kDebugLevelError, "bad DDNS host name in registry: %s", name[0] ? name : "(unknown)");
+ }
+ }
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ key = NULL;
+ }
+
+ if ( name )
+ {
+ free( name );
+ name = NULL;
+ }
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key );
+ require_noerr( err, exit );
+
+ err = RegQueryString( key, "", &name, &dwSize, &enabled );
+ if ( !err && ( name[0] != '\0' ) && enabled )
+ {
+ if ( !MakeDomainNameFromDNSNameString( browseDomain, name ) || !browseDomain->c[0] )
+ {
+ dlog( kDebugLevelError, "bad DDNS browse domain in registry: %s", name[0] ? name : "(unknown)");
+ }
+ }
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ key = NULL;
+ }
+
+ if ( name )
+ {
+ free( name );
+ name = NULL;
+ }
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key );
+ require_noerr( err, exit );
+
+ err = RegQueryString( key, "", &name, &dwSize, &enabled );
+ if ( !err && ( name[0] != '\0' ) && enabled )
+ {
+ if ( !MakeDomainNameFromDNSNameString( regDomain, name ) || !regDomain->c[0] )
+ {
+ dlog( kDebugLevelError, "bad DDNS registration domain in registry: %s", name[0] ? name : "(unknown)");
+ }
+ }
+
+exit:
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+
+ if ( name )
+ {
+ free( name );
+ }
+}
+
+
+//===========================================================================================================================
+// dDNSPlatformSetNameStatus
+//===========================================================================================================================
+
+void
+dDNSPlatformSetNameStatus(domainname *const dname, mStatus status)
+{
+ char uname[MAX_ESCAPED_DOMAIN_NAME];
+ char name[MAX_ESCAPED_DOMAIN_NAME + 256];
+ HKEY key = NULL;
+ mStatus err;
+ char * p;
+
+ ConvertDomainNameToCString(dname, uname);
+
+ p = uname;
+
+ while (*p)
+ {
+ *p = (char) tolower(*p);
+ if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
+ p++;
+ }
+
+ check( strlen( p ) <= MAX_ESCAPED_DOMAIN_NAME );
+ sprintf( name, "SYSTEM\\CurrentControlSet\\Services\\%s\\Parameters\\DynDNS\\State\\HostNames", kServiceName );
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, name, &key );
+ require_noerr( err, exit );
+
+ err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &status, sizeof(DWORD) );
+ require_noerr( err, exit );
+
+exit:
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+
+ return;
+}
+
+
+//===========================================================================================================================
+// dDNSPlatformSetSecretForDomain
+//===========================================================================================================================
+
+void
+dDNSPlatformSetSecretForDomain( mDNS *m, const domainname * domain )
+{
+ char dstring[MAX_ESCAPED_DOMAIN_NAME];
+ domainname * d;
+ domainname canon;
+ 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;
+
+ // 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++)
+ {
+ dstring[i] = (char) tolower(dstring[i]); // canonicalize -> lower case
+ }
+
+ MakeDomainNameFromDNSNameString(&canon, dstring);
+ d = &canon;
+
+ // attrs are reserved, so initialize to zeroes.
+
+ ZeroMemory(&attrs, sizeof( attrs ) );
+
+ // Get a handle to the Policy object on the local system
+
+ res = LsaOpenPolicy( NULL, &attrs, POLICY_GET_PRIVATE_INFORMATION, &handle );
+ err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+ require_noerr( err, exit );
+
+ // Get the encrypted data
+
+ err = ConvertUTF8ToLsaString( dstring, &keyName );
+ require_noerr( err, exit );
+
+ res = LsaRetrievePrivateData( handle, &keyName, &secret );
+ err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
+ require_noerr_quiet( err, exit );
+
+ // Convert the unicode to string to 8 bit
+
+ err = ConvertLsaStringToUTF8( secret, &converted );
+ require_noerr( err, exit );
+
+ mDNS_SetSecretForZone( m, d, d, converted, (mDNSu32) strlen( converted ) + 1, mDNStrue );
+
+exit:
+
+ if ( converted )
+ {
+ free( converted );
+ converted = NULL;
+ }
+
+ if ( secret )
+ {
+ LsaFreeMemory( secret );
+ secret = NULL;
+ }
+
+ if ( keyName.Buffer )
+ {
+ free( keyName.Buffer );
+ keyName.Buffer = NULL;
+ }
+
+ if ( handle )
+ {
+ LsaClose( handle );
+ handle = NULL;
+ }
+}
+
+
+//===========================================================================================================================
+// dDNSPlatformGetSearchDomainList
+//===========================================================================================================================
+
+DNameListElem*
+dDNSPlatformGetSearchDomainList( void )
+{
+ char * searchList = NULL;
+ DWORD searchListLen;
+ DNameListElem * head = NULL;
+ DNameListElem * current = NULL;
+ char * tok;
+ HKEY key;
+ mStatus err;
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", &key );
+ require_noerr( err, exit );
+
+ err = RegQueryString( key, "SearchList", &searchList, &searchListLen, NULL );
+ require_noerr( err, exit );
+
+ // Windows separates the search domains with ','
+
+ tok = strtok( searchList, "," );
+ while ( tok )
+ {
+ domainname domain;
+
+ if ( MakeDomainNameFromDNSNameString( &domain, tok ) )
+ {
+ 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;
+ }
+ }
+
+ tok = strtok( NULL, "," );
+ }
+
+exit:
+
+ if ( searchList )
+ {
+ free( searchList );
+ }
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+
+ return head;
+}
+
+
+//===========================================================================================================================
+// dDNSPlatformGetReverseMapSearchDomainList
//===========================================================================================================================
+DNameListElem*
+dDNSPlatformGetReverseMapSearchDomainList( void )
+{
+ DNameListElem * head = NULL;
+ DNameListElem * current = NULL;
+ struct ifaddrs * ifa;
+ mStatus err;
+
+ ifa = myGetIfAddrs( 1 );
+ while (ifa)
+ {
+ mDNSAddr addr;
+
+ if (ifa->ifa_addr->sa_family == AF_INET && !dDNS_SetupAddr(&addr, ifa->ifa_addr) && !IsPrivateV4Addr(&addr) && !(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_netmask)
+ {
+ mDNSAddr netmask;
+ domainname domain;
+ char buffer[256];
+
+ if (!dDNS_SetupAddr(&netmask, ifa->ifa_netmask))
+ {
+ sprintf(buffer, "%d.%d.%d.%d.in-addr.arpa.", addr.ip.v4.b[3] & netmask.ip.v4.b[3],
+ addr.ip.v4.b[2] & netmask.ip.v4.b[2],
+ addr.ip.v4.b[1] & netmask.ip.v4.b[1],
+ addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
+
+ if ( MakeDomainNameFromDNSNameString( &domain, buffer ) )
+ {
+ 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;
+ }
+ }
+ }
+ }
+
+ ifa = ifa->ifa_next;
+ }
+
+exit:
+
+ return head;
+}
+
+
+//===========================================================================================================================
+// dDNSPlatformGetDNSServers
+//===========================================================================================================================
+
+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;
+
+ while ( 1 )
+ {
+ if ( fixedInfo )
+ {
+ GlobalFree( fixedInfo );
+ fixedInfo = NULL;
+ }
+
+ fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
+
+ err = GetNetworkParams( fixedInfo, &bufLen );
+
+ if ( ( err != ERROR_BUFFER_OVERFLOW ) || ( i++ == 100 ) )
+ {
+ break;
+ }
+ }
+
+ require_noerr( err, exit );
+
+ for ( ipAddr = &fixedInfo->DnsServerList; ipAddr; ipAddr = ipAddr->Next )
+ {
+ mDNSAddr addr;
+ IPAddrListElem * last = current;
+
+ err = StringToAddress( &addr, ipAddr->IpAddress.String );
+
+ if ( err )
+ {
+ continue;
+ }
+
+ current = (IPAddrListElem*) malloc( sizeof( IPAddrListElem ) );
+ require_action( current, exit, err = mStatus_NoMemoryErr );
+
+ memcpy( ¤t->addr, &addr, sizeof( mDNSAddr ) );
+ current->next = NULL;
+
+ if ( !head )
+ {
+ head = current;
+ }
+
+ if ( last )
+ {
+ last->next = current;
+ }
+ }
+
+exit:
-mDNSexport DNameListElem *mDNSPlatformGetSearchDomainList(void)
+ if ( fixedInfo )
{
- static DNameListElem tmp;
- static int init = 0;
+ GlobalFree( fixedInfo );
+ }
- if (!init)
+ return head;
+}
+
+
+//===========================================================================================================================
+// dDNSPlatformGetDomainName
+//===========================================================================================================================
+
+DNameListElem*
+dDNSPlatformGetDomainName( void )
+{
+ FIXED_INFO * fixedInfo = NULL;
+ ULONG bufLen = sizeof( FIXED_INFO );
+ DNameListElem * head = NULL;
+ int i = 0;
+ mStatus err;
+
+ while ( 1 )
+ {
+ if ( fixedInfo )
+ {
+ GlobalFree( fixedInfo );
+ fixedInfo = NULL;
+ }
+
+ fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
+
+ err = GetNetworkParams( fixedInfo, &bufLen );
+
+ if ( ( err != ERROR_BUFFER_OVERFLOW ) || ( i++ == 100 ) )
{
- MakeDomainNameFromDNSNameString(&tmp.name, "local.");
- tmp.next = NULL;
- init = 1;
+ break;
}
- return mDNS_CopyDNameList(&tmp);
}
+ require_noerr( err, exit );
+
+ if ( fixedInfo->DomainName )
+ {
+ domainname dname;
+
+ if ( MakeDomainNameFromDNSNameString( &dname, fixedInfo->DomainName ) || !dname.c[0] )
+ {
+ head = (DNameListElem*) malloc( sizeof( DNameListElem ) );
+ require_action( head, exit, err = mStatus_NoMemoryErr );
+
+ AssignDomainName( &head->name, &dname );
+ head->next = NULL;
+ }
+ else
+ {
+ dlog( kDebugLevelError, "bad DDNS host name from domain name: %s", fixedInfo->DomainName );
+ }
+ }
+
+exit:
+
+ if ( fixedInfo )
+ {
+ GlobalFree( fixedInfo );
+ }
+
+ return head;
+}
+
+
+//===========================================================================================================================
+// dDNSPlatformRegisterSplitDNS
//===========================================================================================================================
-// mDNSPlatformGetRegDomainList
+
+mStatus
+dDNSPlatformRegisterSplitDNS( mDNS * m )
+{
+ DEBUG_UNUSED( m );
+
+ return mStatus_UnsupportedErr;
+}
+
+
//===========================================================================================================================
+// dDNSPlatformGetPrimaryInterface
+//===========================================================================================================================
+
+mStatus
+dDNSPlatformGetPrimaryInterface( mDNS * m, mDNSAddr * primary, mDNSAddr * router )
+{
+ IP_ADAPTER_INFO * pAdapterInfo = NULL;
+ IP_ADAPTER_INFO * pAdapter;
+ DWORD bufLen = sizeof( IP_ADAPTER_INFO );
+ int i;
+ BOOL found;
+ mStatus err = mStatus_NoError;
+
+ DEBUG_UNUSED( m );
+
+ pAdapterInfo = NULL;
+ 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 );
-mDNSexport DNameListElem *mDNSPlatformGetRegDomainList(void)
+ err = GetAdaptersInfo( pAdapterInfo, &bufLen);
+
+ if ( err != ERROR_BUFFER_OVERFLOW )
+ {
+ break;
+ }
+ }
+
+ // 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
+
+ for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
{
- return NULL;
+ if ( pAdapter->IpAddressList.IpAddress.String &&
+ pAdapter->IpAddressList.IpAddress.String[0] &&
+ 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 ) )
+ {
+ // Found one that will work
+
+ found = TRUE;
+ break;
+ }
}
+ 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 )
+ {
+ free( pAdapterInfo );
+ }
+
+ return err;
+}
+
+
+//===========================================================================================================================
+// dDNSPlatformDefaultBrowseDomainChanged
+//===========================================================================================================================
+
+void
+dDNSPlatformDefaultBrowseDomainChanged( const domainname *d, mDNSBool add )
+{
+ DEBUG_UNUSED( d );
+ DEBUG_UNUSED( add );
+
+ // This is a no-op on Windows
+}
+
+
+//===========================================================================================================================
+// dDNSPlatformDefaultRegDomainChanged
+//===========================================================================================================================
+
+void
+dDNSPlatformDefaultRegDomainChanged( const domainname * d, mDNSBool add )
+{
+ DEBUG_UNUSED( d );
+ DEBUG_UNUSED( add );
+
+ // This is a no-op on Windows
+}
+
#if 0
#pragma mark -
tempString[ 0 ] = '\0';
// First try and open the registry key that contains the computer description value
- if (inMDNS->p->regKey == NULL)
+ if (inMDNS->p->descKey == NULL)
{
const char * s = "SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters";
- err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &inMDNS->p->regKey);
+ err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &inMDNS->p->descKey);
check_translated_errno( err == 0, errno_compat(), kNameErr );
if (err)
{
- inMDNS->p->regKey = NULL;
+ inMDNS->p->descKey = NULL;
}
}
// if we opened it...
- if (inMDNS->p->regKey != NULL)
+ if (inMDNS->p->descKey != NULL)
{
DWORD type;
DWORD valueLen = sizeof(tempString);
// look for the computer description
- err = RegQueryValueEx(inMDNS->p->regKey, "srvcomment", 0, &type, (LPBYTE) &tempString, &valueLen);
+ err = RegQueryValueEx(inMDNS->p->descKey, "srvcomment", 0, &type, (LPBYTE) &tempString, &valueLen);
check_translated_errno( err == 0, errno_compat(), kNameErr );
}
struct ifaddrs * loopback;
u_int flagMask;
u_int flagTest;
+ BOOL foundUnicastSock4DestAddr;
+ BOOL foundUnicastSock6DestAddr;
dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list\n" );
check( inMDNS );
check( inMDNS->p );
- addrs = NULL;
+ addrs = NULL;
+ foundUnicastSock4DestAddr = FALSE;
+ foundUnicastSock6DestAddr = FALSE;
// Tear down any existing interfaces that may be set up.
err = SetupInterface( inMDNS, p, &ifd );
require_noerr( err, exit );
-
+
+ // If we're on a platform that doesn't have WSARecvMsg(), there's no way
+ // of determing the destination address of a packet that is sent to us.
+ // For multicast packets, that's easy to determine. But for the unicast
+ // sockets, we'll fake it by taking the address of the first interface
+ // that is successfully setup.
+
+ if ( !foundUnicastSock4DestAddr )
+ {
+ inMDNS->p->unicastSock4DestAddr = ifd->interfaceInfo.ip;
+ foundUnicastSock4DestAddr = TRUE;
+ }
+
*next = ifd;
next = &ifd->next;
++inMDNS->p->interfaceCount;
+
+
}
#endif
err = SetupInterface( inMDNS, p, &ifd );
require_noerr( err, exit );
-
+
+ // If we're on a platform that doesn't have WSARecvMsg(), there's no way
+ // of determing the destination address of a packet that is sent to us.
+ // For multicast packets, that's easy to determine. But for the unicast
+ // sockets, we'll fake it by taking the address of the first interface
+ // that is successfully setup.
+
+ if ( !foundUnicastSock6DestAddr )
+ {
+ inMDNS->p->unicastSock6DestAddr = ifd->interfaceInfo.ip;
+ foundUnicastSock6DestAddr = TRUE;
+ }
+
*next = ifd;
next = &ifd->next;
++inMDNS->p->interfaceCount;
err = SetupInterface( inMDNS, loopback, &ifd );
require_noerr( err, exit );
+#if( MDNS_WINDOWS_ENABLE_IPV4 )
+
+ // If we're on a platform that doesn't have WSARecvMsg(), there's no way
+ // of determing the destination address of a packet that is sent to us.
+ // For multicast packets, that's easy to determine. But for the unicast
+ // sockets, we'll fake it by taking the address of the first interface
+ // that is successfully setup.
+
+ if ( !foundUnicastSock4DestAddr )
+ {
+ inMDNS->p->unicastSock4DestAddr = ifd->defaultAddr;
+ foundUnicastSock4DestAddr = TRUE;
+ }
+#endif
+
*next = ifd;
next = &ifd->next;
++inMDNS->p->interfaceCount;
}
-
+
exit:
if( err )
{
if( ifd->interfaceInfo.McastTxRx )
{
- err = SetupSocket( inMDNS, inIFA->ifa_addr, &sock );
+ err = SetupSocket( inMDNS, inIFA->ifa_addr, MulticastDNSPort, &sock );
require_noerr( err, exit );
ifd->sock = sock;
ifd->defaultAddr = ( inIFA->ifa_addr->sa_family == AF_INET6 ) ? AllDNSLinkGroup_v6 : AllDNSLinkGroup_v4;
ifd->interfaceInfo.Advertise = inMDNS->AdvertiseLocalAddresses;
- err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo );
+ err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, 0 );
require_noerr( err, exit );
ifd->hostRegistered = mDNStrue;
// SetupSocket
//===========================================================================================================================
-mDNSlocal mStatus SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, SocketRef *outSocketRef )
+mDNSlocal mStatus SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef )
{
mStatus err;
SocketRef sock;
err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
require_noerr( err, exit );
- // Turn on reuse address option so multiple servers can listen for Multicast DNS packets.
+ // Turn on reuse address option so multiple servers can listen for Multicast DNS packets,
+ // if we're creating a multicast socket
- option = 1;
- err = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
- check_translated_errno( err == 0, errno_compat(), kOptionErr );
+ if ( port.NotAnInteger )
+ {
+ option = 1;
+ err = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
+ check_translated_errno( err == 0, errno_compat(), kOptionErr );
+ }
if( inAddr->sa_family == AF_INET )
{
struct sockaddr_in sa4;
struct ip_mreq mreqv4;
- // Bind to the multicast DNS port 5353.
+ // Bind the socket to the desired port
ipv4.NotAnInteger = ( (const struct sockaddr_in *) inAddr )->sin_addr.s_addr;
memset( &sa4, 0, sizeof( sa4 ) );
sa4.sin_family = AF_INET;
- sa4.sin_port = MulticastDNSPort.NotAnInteger;
+ sa4.sin_port = port.NotAnInteger;
sa4.sin_addr.s_addr = ipv4.NotAnInteger;
err = bind( sock, (struct sockaddr *) &sa4, sizeof( sa4 ) );
err = setsockopt( sock, IPPROTO_IP, IP_PKTINFO, (char *) &option, sizeof( option ) );
check_translated_errno( err == 0, errno_compat(), kOptionErr );
- // Join the all-DNS multicast group so we receive Multicast DNS packets.
+ if (port.NotAnInteger)
+ {
+ // Join the all-DNS multicast group so we receive Multicast DNS packets
+
+ mreqv4.imr_multiaddr.s_addr = AllDNSLinkGroupv4.NotAnInteger;
+ mreqv4.imr_interface.s_addr = ipv4.NotAnInteger;
+ err = setsockopt( sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreqv4, sizeof( mreqv4 ) );
+ check_translated_errno( err == 0, errno_compat(), kOptionErr );
- mreqv4.imr_multiaddr.s_addr = AllDNSLinkGroupv4.NotAnInteger;
- mreqv4.imr_interface.s_addr = ipv4.NotAnInteger;
- err = setsockopt( sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreqv4, sizeof( mreqv4 ) );
- check_translated_errno( err == 0, errno_compat(), kOptionErr );
+ // Specify the interface to send multicast packets on this socket.
- // Specify the interface to send multicast packets on this socket.
+ sa4.sin_addr.s_addr = ipv4.NotAnInteger;
+ err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_IF, (char *) &sa4.sin_addr, sizeof( sa4.sin_addr ) );
+ check_translated_errno( err == 0, errno_compat(), kOptionErr );
- sa4.sin_addr.s_addr = ipv4.NotAnInteger;
- err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_IF, (char *) &sa4.sin_addr, sizeof( sa4.sin_addr ) );
- check_translated_errno( err == 0, errno_compat(), kOptionErr );
+ // Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
+ option = 1;
+ err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
+ check_translated_errno( err == 0, errno_compat(), kOptionErr );
+ }
+
// Send unicast packets with TTL 255 (helps against spoofing).
option = 255;
err = setsockopt( sock, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) );
check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
+
// Send multicast packets with TTL 255 (helps against spoofing).
option = 255;
err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &option, sizeof( option ) );
check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
- // Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
-
- option = 1;
- err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
- check_translated_errno( err == 0, errno_compat(), kOptionErr );
+
}
else if( inAddr->sa_family == AF_INET6 )
{
sa6p = (struct sockaddr_in6 *) inAddr;
- // Bind to the multicast DNS port 5353.
+ // Bind the socket to the desired port
memset( &sa6, 0, sizeof( sa6 ) );
sa6.sin6_family = AF_INET6;
- sa6.sin6_port = MulticastDNSPort.NotAnInteger;
+ sa6.sin6_port = port.NotAnInteger;
sa6.sin6_flowinfo = 0;
sa6.sin6_addr = sa6p->sin6_addr;
sa6.sin6_scope_id = sa6p->sin6_scope_id;
check_translated_errno( err == 0, errno_compat(), kOptionErr );
#endif
- // Join the all-DNS multicast group so we receive Multicast DNS packets.
+ if ( port.NotAnInteger )
+ {
+ // Join the all-DNS multicast group so we receive Multicast DNS packets.
- mreqv6.ipv6mr_multiaddr = *( (struct in6_addr *) &AllDNSLinkGroupv6 );
- mreqv6.ipv6mr_interface = sa6p->sin6_scope_id;
- err = setsockopt( sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreqv6, sizeof( mreqv6 ) );
- check_translated_errno( err == 0, errno_compat(), kOptionErr );
+ mreqv6.ipv6mr_multiaddr = *( (struct in6_addr *) &AllDNSLinkGroupv6 );
+ mreqv6.ipv6mr_interface = sa6p->sin6_scope_id;
+ err = setsockopt( sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreqv6, sizeof( mreqv6 ) );
+ check_translated_errno( err == 0, errno_compat(), kOptionErr );
- // Specify the interface to send multicast packets on this socket.
+ // Specify the interface to send multicast packets on this socket.
- option = (int) sa6p->sin6_scope_id;
- err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &option, sizeof( option ) );
- check_translated_errno( err == 0, errno_compat(), kOptionErr );
+ option = (int) sa6p->sin6_scope_id;
+ err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &option, sizeof( option ) );
+ check_translated_errno( err == 0, errno_compat(), kOptionErr );
+ // Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
+
+ option = 1;
+ err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
+ check_translated_errno( err == 0, errno_compat(), kOptionErr );
+ }
+
// Send unicast packets with TTL 255 (helps against spoofing).
option = 255;
err = setsockopt( sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *) &option, sizeof( option ) );
check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
+
// Send multicast packets with TTL 255 (helps against spoofing).
-
+
option = 255;
err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &option, sizeof( option ) );
check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
- // Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
-
- option = 1;
- err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
- check_translated_errno( err == 0, errno_compat(), kOptionErr );
}
else
{
err = translate_errno( err == 0, errno_compat(), kUnknownErr );
require_noerr( err, exit );
- inMDNS->p->regEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- err = translate_errno( inMDNS->p->regEvent, (mStatus) GetLastError(), kUnknownErr );
+ inMDNS->p->descChangedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ err = translate_errno( inMDNS->p->descChangedEvent, (mStatus) GetLastError(), kUnknownErr );
require_noerr( err, exit );
- if (inMDNS->p->regKey != NULL)
+ if (inMDNS->p->descKey != NULL)
{
- err = RegNotifyChangeKeyValue(inMDNS->p->regKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->regEvent, TRUE);
+ err = RegNotifyChangeKeyValue(inMDNS->p->descKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->descChangedEvent, TRUE);
require_noerr( err, exit );
}
+ inMDNS->p->ddnsChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ err = translate_errno( inMDNS->p->ddnsChangedEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\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);
+ require_noerr( err, exit );
+
exit:
if( err )
{
{
if( IsValidSocket( inMDNS->p->interfaceListChangedSocket ) )
{
- close_compat( inMDNS->p->interfaceListChangedSocket );
- inMDNS->p->interfaceListChangedSocket = kInvalidSocketRef;
+ close_compat( inMDNS->p->interfaceListChangedSocket );
+ inMDNS->p->interfaceListChangedSocket = kInvalidSocketRef;
+ }
+
+ if ( inMDNS->p->descChangedEvent != NULL )
+ {
+ CloseHandle( inMDNS->p->descChangedEvent );
+ inMDNS->p->descChangedEvent = NULL;
+ }
+
+ if ( inMDNS->p->descKey != NULL )
+ {
+ RegCloseKey( inMDNS->p->descKey );
+ inMDNS->p->descKey = NULL;
}
- if ( inMDNS->p->regEvent != NULL )
+ if ( inMDNS->p->ddnsChangedEvent != NULL )
{
- CloseHandle( inMDNS->p->regEvent );
- inMDNS->p->regEvent = NULL;
+ CloseHandle( inMDNS->p->ddnsChangedEvent );
+ inMDNS->p->ddnsChangedEvent = NULL;
}
- if ( inMDNS->p->regKey != NULL )
+ if ( inMDNS->p->ddnsKey != NULL )
{
- RegCloseKey( inMDNS->p->regKey );
- inMDNS->p->regKey = NULL;
+ RegCloseKey( inMDNS->p->ddnsKey );
+ inMDNS->p->ddnsKey = NULL;
}
return( mStatus_NoError );
dlog( kDebugLevelChatty - 1, DEBUG_NAME "wakeup for mDNS_Execute\n" );
continue;
}
- else if ( result == kWaitListRegEvent )
+ else if ( result == kWaitListComputerDescriptionEvent )
{
//
// The computer description might have changed
//
- ProcessingThreadRegistryChanged( m );
+ ProcessingThreadComputerDescriptionChanged( m );
+ break;
+ }
+ else if ( result == kWaitListDynDNSEvent )
+ {
+ //
+ // The DynDNS config might have changed
+ //
+ ProcessingThreadDynDNSConfigChanged( m );
break;
}
else
if( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) )
{
HANDLE signaledObject;
- int n;
+ int n = 0;
mDNSInterfaceData * ifd;
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;
+ }
+#endif
- n = 0;
for( ifd = m->p->interfaceList; ifd; ifd = ifd->next )
{
if( ifd->readPendingEvent == signaledObject )
++n;
}
}
+
check( n > 0 );
}
else
err = SetupInterfaceList( inMDNS );
require_noerr( err, exit );
+
+ err = dDNS_Setup( inMDNS );
+ require_noerr( err, exit );
+
+ err = dDNS_InitDNSConfig( inMDNS );
+ require_noerr( err, exit );
exit:
+
if( err )
{
TearDownInterfaceList( inMDNS );
*waitItemPtr++ = inMDNS->p->cancelEvent;
*waitItemPtr++ = inMDNS->p->interfaceListChangedEvent;
*waitItemPtr++ = inMDNS->p->wakeupEvent;
- *waitItemPtr++ = inMDNS->p->regEvent;
+ *waitItemPtr++ = inMDNS->p->descChangedEvent;
+ *waitItemPtr++ = inMDNS->p->ddnsChangedEvent;
// Append all the dynamic wait items to the list.
-
+#if ( MDNS_WINDOWS_ENABLE_IPV4 )
+ *waitItemPtr++ = inMDNS->p->unicastSock4ReadEvent;
+#endif
+
+#if ( MDNS_WINDOWS_ENABLE_IPV6 )
+ *waitItemPtr++ = inMDNS->p->unicastSock6ReadEvent;
+#endif
+
for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
{
*waitItemPtr++ = ifd->readPendingEvent;
mDNSlocal void ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *inIFD, SocketRef inSock )
{
OSStatus err;
+ const mDNSInterfaceID iid = inIFD ? inIFD->interfaceInfo.InterfaceID : NULL;
+ LPFN_WSARECVMSG recvMsgPtr;
mDNSAddr srcAddr;
mDNSIPPort srcPort;
mDNSAddr dstAddr;
int n;
check( inMDNS );
- check( inIFD );
check( IsValidSocket( inSock ) );
// Set up the default in case the packet info options are not supported or reported correctly.
- dstAddr = inIFD->defaultAddr;
- dstPort = MulticastDNSPort;
- ttl = 255;
+ if ( inIFD )
+ {
+ recvMsgPtr = inIFD->wsaRecvMsgFunctionPtr;
+ dstAddr = inIFD->defaultAddr;
+ dstPort = MulticastDNSPort;
+ ttl = 255;
+ }
+ else if ( inSock == inMDNS->p->unicastSock4 )
+ {
+ recvMsgPtr = inMDNS->p->unicastSock4RecvMsgPtr;
+ dstAddr = inMDNS->p->unicastSock4DestAddr;
+ dstPort = zeroIPPort;
+ ttl = 255;
+ }
+ else if ( inSock == inMDNS->p->unicastSock6 )
+ {
+ recvMsgPtr = inMDNS->p->unicastSock6RecvMsgPtr;
+ dstAddr = inMDNS->p->unicastSock6DestAddr;
+ dstPort = zeroIPPort;
+ ttl = 255;
+ }
+ else
+ {
+ dlog( kDebugLevelError, DEBUG_NAME "packet received on unknown socket\n" );
+ goto exit;
+ }
#if( !TARGET_OS_WINDOWS_CE )
- if( inIFD->wsaRecvMsgFunctionPtr )
+ if( recvMsgPtr )
{
WSAMSG msg;
WSABUF buf;
msg.Control.len = (u_long) sizeof( controlBuffer );
msg.dwFlags = 0;
- err = inIFD->wsaRecvMsgFunctionPtr( inSock, &msg, &size, NULL, NULL );
+ err = recvMsgPtr( inSock, &msg, &size, NULL, NULL );
err = translate_errno( err == 0, (OSStatus) GetLastError(), kUnknownErr );
require_noerr( err, exit );
n = (int) size;
IN_PKTINFO * ipv4PacketInfo;
ipv4PacketInfo = (IN_PKTINFO *) WSA_CMSG_DATA( header );
- require_action( ipv4PacketInfo->ipi_ifindex == ( inIFD->index >> 8 ), exit, err = kMismatchErr );
-
+
+ if ( inIFD )
+ {
+ require_action( ipv4PacketInfo->ipi_ifindex == ( inIFD->index >> 8 ), exit, err = kMismatchErr );
+ }
+
dstAddr.type = mDNSAddrType_IPv4;
dstAddr.ip.v4.NotAnInteger = ipv4PacketInfo->ipi_addr.s_addr;
}
IN6_PKTINFO * ipv6PacketInfo;
ipv6PacketInfo = (IN6_PKTINFO *) WSA_CMSG_DATA( header );
- require_action( ipv6PacketInfo->ipi6_ifindex == inIFD->index, exit, err = kMismatchErr );
-
+
+ if ( inIFD )
+ {
+ require_action( ipv6PacketInfo->ipi6_ifindex == inIFD->index, exit, err = kMismatchErr );
+ }
+
dstAddr.type = mDNSAddrType_IPv6;
dstAddr.ip.v6 = *( (mDNSv6Addr *) &ipv6PacketInfo->ipi6_addr );
}
else
#endif
{
- int addrSize;
+ int addrSize;
addrSize = sizeof( addr );
n = recvfrom( inSock, (char *) &packet, sizeof( packet ), 0, (struct sockaddr *) &addr, &addrSize );
dlog( kDebugLevelChatty, DEBUG_NAME " size = %d\n", n );
dlog( kDebugLevelChatty, DEBUG_NAME " src = %#a:%u\n", &srcAddr, ntohs( srcPort.NotAnInteger ) );
dlog( kDebugLevelChatty, DEBUG_NAME " dst = %#a:%u\n", &dstAddr, ntohs( dstPort.NotAnInteger ) );
- dlog( kDebugLevelChatty, DEBUG_NAME " interface = %#a (index=0x%08X)\n", &inIFD->interfaceInfo.ip, (int) inIFD->index );
+
+ if ( inIFD )
+ {
+ dlog( kDebugLevelChatty, DEBUG_NAME " interface = %#a (index=0x%08X)\n", &inIFD->interfaceInfo.ip, (int) inIFD->index );
+ }
+
dlog( kDebugLevelChatty, DEBUG_NAME "\n" );
end = ( (mDNSu8 *) &packet ) + n;
- mDNSCoreReceive( inMDNS, &packet, end, &srcAddr, srcPort, &dstAddr, dstPort, inIFD->interfaceInfo.InterfaceID );
+ mDNSCoreReceive( inMDNS, &packet, end, &srcAddr, srcPort, &dstAddr, dstPort, iid );
exit:
return;
//===========================================================================================================================
-// ProcessingThreadRegistryChanged
+// ProcessingThreadComputerDescriptionChanged
//===========================================================================================================================
-mDNSlocal void ProcessingThreadRegistryChanged( mDNS *inMDNS )
+mDNSlocal void ProcessingThreadComputerDescriptionChanged( mDNS *inMDNS )
{
mStatus err;
- dlog( kDebugLevelInfo, DEBUG_NAME "registry has changed\n" );
+ dlog( kDebugLevelInfo, DEBUG_NAME "computer description has changed\n" );
check( inMDNS );
mDNSPlatformLock( inMDNS );
}
// and reset the event handler
- if ((inMDNS->p->regKey != NULL) && (inMDNS->p->regEvent))
+ if ((inMDNS->p->descKey != NULL) && (inMDNS->p->descChangedEvent))
+ {
+ err = RegNotifyChangeKeyValue(inMDNS->p->descKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->descChangedEvent, TRUE);
+ check_noerr( err );
+ }
+
+ mDNSPlatformUnlock( inMDNS );
+}
+
+
+//===========================================================================================================================
+// ProcessingThreadDynDNSConfigChanged
+//===========================================================================================================================
+mDNSlocal void ProcessingThreadDynDNSConfigChanged( mDNS *inMDNS )
+{
+ mStatus err;
+
+ dlog( kDebugLevelInfo, DEBUG_NAME "DynDNS config has changed\n" );
+ check( inMDNS );
+
+ mDNSPlatformLock( inMDNS );
+
+ err = dDNS_Setup( inMDNS );
+ check_noerr( err );
+
+ // and reset the event handler
+ if ((inMDNS->p->ddnsKey != NULL) && (inMDNS->p->ddnsChangedEvent))
{
- err = RegNotifyChangeKeyValue(inMDNS->p->regKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->regEvent, TRUE);
+ err = RegNotifyChangeKeyValue(inMDNS->p->ddnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->ddnsChangedEvent, TRUE);
check_noerr( err );
}
for( iaa = iaaList; iaa; iaa = iaa->Next )
{
- IP_ADAPTER_UNICAST_ADDRESS * addr;
+ int addrIndex;
+ IP_ADAPTER_UNICAST_ADDRESS * addr;
+ DWORD ipv6IfIndex;
+ IP_ADAPTER_PREFIX * firstPrefix;
if( iaa->IfIndex > 0xFFFFFF )
{
{
dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv6 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->Ipv6IfIndex );
}
-
+
+ // For IPv4 interfaces, there seems to be a bug in iphlpapi.dll that causes the
+ // following code to crash when iterating through the prefix list. This seems
+ // to occur when iaa->Ipv6IfIndex != 0 when IPv6 is not installed on the host.
+ // This shouldn't happen according to Microsoft docs which states:
+ //
+ // "Ipv6IfIndex contains 0 if IPv6 is not available on the interface."
+ //
+ // So the data structure seems to be corrupted when we return from
+ // GetAdaptersAddresses(). The bug seems to occur when iaa->Length <
+ // sizeof(IP_ADAPTER_ADDRESSES), so when that happens, we'll manually
+ // modify iaa to have the correct values.
+
+ if ( iaa->Length >= sizeof( IP_ADAPTER_ADDRESSES ) )
+ {
+ ipv6IfIndex = iaa->Ipv6IfIndex;
+ firstPrefix = iaa->FirstPrefix;
+ }
+ else
+ {
+ ipv6IfIndex = 0;
+ firstPrefix = NULL;
+ }
+
// Skip psuedo and tunnel interfaces.
- if( ( iaa->Ipv6IfIndex == 1 ) || ( iaa->IfType == IF_TYPE_TUNNEL ) )
+ if( ( ipv6IfIndex == 1 ) || ( iaa->IfType == IF_TYPE_TUNNEL ) )
{
continue;
}
// Add each address as a separate interface to emulate the way getifaddrs works.
- for( addr = iaa->FirstUnicastAddress; addr; addr = addr->Next )
+ for( addrIndex = 0, addr = iaa->FirstUnicastAddress; addr; ++addrIndex, addr = addr->Next )
{
+ int family;
+ int prefixIndex;
+ IP_ADAPTER_PREFIX * prefix;
+ ULONG prefixLength;
+
+ family = addr->Address.lpSockaddr->sa_family;
+ if( ( family != AF_INET ) && ( family != AF_INET6 ) ) continue;
+
ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
require_action( ifa, exit, err = WSAENOBUFS );
// Get interface flags.
ifa->ifa_flags = 0;
- if( iaa->OperStatus == IfOperStatusUp )
- {
- ifa->ifa_flags |= IFF_UP;
- }
- if( iaa->IfType == IF_TYPE_SOFTWARE_LOOPBACK )
- {
- ifa->ifa_flags |= IFF_LOOPBACK;
- }
- if( !( iaa->Flags & IP_ADAPTER_NO_MULTICAST ) )
+ if( iaa->OperStatus == IfOperStatusUp ) ifa->ifa_flags |= IFF_UP;
+ if( iaa->IfType == IF_TYPE_SOFTWARE_LOOPBACK ) ifa->ifa_flags |= IFF_LOOPBACK;
+ 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.
+
+ switch( family )
{
- ifa->ifa_flags |= IFF_MULTICAST;
+ case AF_INET: ifa->ifa_extra.index = iaa->IfIndex << 8; break;
+ case AF_INET6: ifa->ifa_extra.index = ipv6IfIndex; break;
+ default: break;
}
- // 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 16-bits and IPv6 interface indexes
- // in the lower 16-bits. This allows the IPv6 interface index to be usable as an IPv6 scope ID directly.
+ // Get address.
- switch( addr->Address.lpSockaddr->sa_family )
+ switch( family )
{
case AF_INET:
- ifa->ifa_extra.index = iaa->IfIndex << 8;
- break;
-
case AF_INET6:
- ifa->ifa_extra.index = iaa->Ipv6IfIndex;
+ ifa->ifa_addr = (struct sockaddr *) calloc( 1, (size_t) addr->Address.iSockaddrLength );
+ require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
+ memcpy( ifa->ifa_addr, addr->Address.lpSockaddr, (size_t) addr->Address.iSockaddrLength );
break;
default:
break;
}
+ check( ifa->ifa_addr );
- // Get addresses.
+ // Get subnet mask (IPv4)/link prefix (IPv6). It is specified as a bit length (e.g. 24 for 255.255.255.0).
- switch( addr->Address.lpSockaddr->sa_family )
+ prefixLength = 0;
+ for( prefixIndex = 0, prefix = firstPrefix; prefix; ++prefixIndex, prefix = prefix->Next )
+ {
+ if( prefixIndex == addrIndex )
+ {
+ check_string( prefix->Address.lpSockaddr->sa_family == family, "addr family != netmask family" );
+ prefixLength = prefix->PrefixLength;
+ break;
+ }
+ }
+ switch( family )
{
case AF_INET:
+ {
+ struct sockaddr_in * sa4;
+
+ require_action( prefixLength <= 32, exit, err = ERROR_INVALID_DATA );
+
+ sa4 = (struct sockaddr_in *) calloc( 1, sizeof( *sa4 ) );
+ require_action( sa4, exit, err = WSAENOBUFS );
+
+ sa4->sin_family = AF_INET;
+ if( prefixLength == 0 )
+ {
+ 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 ) );
+ ifa->ifa_netmask = (struct sockaddr *) sa4;
+ break;
+ }
+
case AF_INET6:
- ifa->ifa_addr = (struct sockaddr *) calloc( 1, (size_t) addr->Address.iSockaddrLength );
- require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
- memcpy( ifa->ifa_addr, addr->Address.lpSockaddr, (size_t) addr->Address.iSockaddrLength );
-
- ifa->ifa_netmask = (struct sockaddr *) calloc( 1, sizeof(struct sockaddr) );
- require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
- err = getifnetmask_ipv6(ifa);
- require_noerr(err, exit);
-
+ {
+ struct sockaddr_in6 * sa6;
+ int len;
+ int maskIndex;
+ uint8_t maskByte;
+
+ require_action( prefixLength <= 128, exit, err = ERROR_INVALID_DATA );
+
+ sa6 = (struct sockaddr_in6 *) calloc( 1, sizeof( *sa6 ) );
+ require_action( sa6, exit, err = WSAENOBUFS );
+ sa6->sin6_family = AF_INET6;
+
+ if( prefixLength == 0 )
+ {
+ dlog( kDebugLevelWarning, DEBUG_NAME "%s: IPv6 link prefix 0, defaulting to /128\n", __ROUTINE__ );
+ prefixLength = 128;
+ }
+ maskIndex = 0;
+ for( len = (int) prefixLength; len > 0; len -= 8 )
+ {
+ if( len >= 8 ) maskByte = 0xFF;
+ else maskByte = (uint8_t)( ( 0xFFU << ( 8 - len ) ) & 0xFFU );
+ sa6->sin6_addr.s6_addr[ maskIndex++ ] = maskByte;
+ }
+ ifa->ifa_netmask = (struct sockaddr *) sa6;
break;
+ }
default:
break;
return( (int) err );
}
-mDNSlocal int
-getifnetmask_ipv6( struct ifaddrs * ifa )
-{
- PMIB_IPADDRTABLE pIPAddrTable = NULL;
- DWORD dwSize = 0;
- DWORD dwRetVal;
- DWORD i;
- int err = 0;
-
- // Make an initial call to GetIpAddrTable to get the
- // necessary size into the dwSize variable
-
- dwRetVal = GetIpAddrTable(NULL, &dwSize, 0);
- require_action( dwRetVal == ERROR_INSUFFICIENT_BUFFER, exit, err = WSAENOBUFS );
-
- pIPAddrTable = (MIB_IPADDRTABLE *) malloc ( dwSize );
- require_action( pIPAddrTable != NULL, exit, err = WSAENOBUFS );
-
- // Make a second call to GetIpAddrTable to get the
- // actual data we want
-
- dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
- require_action(dwRetVal == NO_ERROR, exit, err = WSAENOBUFS);
-
- // Now try and find the correct IP Address
-
- for (i = 0; i < pIPAddrTable->dwNumEntries; i++)
- {
- struct sockaddr_in sa;
-
- memset(&sa, 0, sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = pIPAddrTable->table[i].dwAddr;
-
- if (memcmp(ifa->ifa_addr, &sa, sizeof(sa)) == 0)
- {
- // Found the right one, so copy the subnet mask information
-
- sa.sin_addr.s_addr = pIPAddrTable->table[i].dwMask;
- memcpy( ifa->ifa_netmask, &sa, sizeof(sa) );
- break;
- }
- }
-
-exit:
-
- if ( pIPAddrTable != NULL )
- {
- free(pIPAddrTable);
- }
-
- return err;
-}
#endif // MDNS_WINDOWS_USE_IPV6_IF_ADDRS
#if( !TARGET_OS_WINDOWS_CE )
}
return( err );
}
+
+
+//===========================================================================================================================
+// RegQueryString
+//===========================================================================================================================
+
+static mStatus
+RegQueryString( HKEY key, const char * valueName, char ** string, DWORD * stringLen, DWORD * enabled )
+{
+ DWORD type;
+ int i;
+ mStatus err;
+
+ *stringLen = MAX_ESCAPED_DOMAIN_NAME;
+ *string = NULL;
+ i = 0;
+
+ do
+ {
+ if ( *string )
+ {
+ free( *string );
+ }
+
+ *string = (char*) malloc( *stringLen );
+ require_action( *string, exit, err = mStatus_NoMemoryErr );
+
+ err = RegQueryValueEx( key, valueName, 0, &type, (LPBYTE) *string, stringLen );
+
+ i++;
+ }
+ while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) );
+
+ if ( enabled )
+ {
+ DWORD dwSize = sizeof( DWORD );
+
+ err = RegQueryValueEx( key, "Enabled", NULL, NULL, (LPBYTE) enabled, &dwSize );
+ check_noerr( err );
+
+ err = kNoErr;
+ }
+
+exit:
+
+ return err;
+}
+
+
+//===========================================================================================================================
+// StringToAddress
+//===========================================================================================================================
+
+static mStatus StringToAddress( mDNSAddr * ip, const char * string )
+{
+ struct sockaddr_in6 sa6;
+ struct sockaddr_in sa4;
+ INT dwSize;
+ mStatus err;
+
+ sa6.sin6_family = AF_INET6;
+ dwSize = sizeof( sa6 );
+
+ err = WSAStringToAddress( (LPSTR) string, AF_INET6, NULL, (struct sockaddr*) &sa6, &dwSize );
+
+ if ( err == mStatus_NoError )
+ {
+ err = dDNS_SetupAddr( ip, (struct sockaddr*) &sa6 );
+ require_noerr( err, exit );
+ }
+ else
+ {
+ sa4.sin_family = AF_INET;
+ dwSize = sizeof( sa4 );
+
+ err = WSAStringToAddress( (LPSTR) string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize );
+ require_noerr( err, exit );
+
+ err = dDNS_SetupAddr( ip, (struct sockaddr*) &sa4 );
+ require_noerr( err, exit );
+ }
+
+exit:
+
+ return err;
+}
+
+
+//===========================================================================================================================
+// myGetIfAddrs
+//===========================================================================================================================
+
+mDNSlocal struct ifaddrs*
+myGetIfAddrs(int refresh)
+{
+ static struct ifaddrs *ifa = NULL;
+
+ if (refresh && ifa)
+ {
+ freeifaddrs(ifa);
+ ifa = NULL;
+ }
+
+ if (ifa == NULL)
+ {
+ getifaddrs(&ifa);
+ }
+
+ return ifa;
+}
+
+
+//===========================================================================================================================
+// ConvertUTF8ToLsaString
+//===========================================================================================================================
+
+mDNSlocal OSStatus
+ConvertUTF8ToLsaString( const char * input, PLSA_UNICODE_STRING output )
+{
+ int size;
+ OSStatus err;
+
+ check( input );
+ check( output );
+
+ output->Buffer = NULL;
+
+ size = MultiByteToWideChar( CP_UTF8, 0, input, -1, NULL, 0 );
+ err = translate_errno( size > 0, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ output->Length = (USHORT)( size * sizeof( wchar_t ) );
+ output->Buffer = (PWCHAR) malloc( output->Length );
+ require_action( output->Buffer, exit, err = mStatus_NoMemoryErr );
+ size = MultiByteToWideChar( CP_UTF8, 0, input, -1, output->Buffer, size );
+ err = translate_errno( size > 0, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ // We're going to subtrace one wchar_t from the size, because we didn't
+ // include it when we encoded the string
+
+ output->MaximumLength = output->Length;
+ output->Length -= sizeof( wchar_t );
+
+exit:
+
+ if ( err && output->Buffer )
+ {
+ free( output->Buffer );
+ output->Buffer = NULL;
+ }
+
+ return( err );
+}
+
+
+//===========================================================================================================================
+// ConvertLsaStringToUTF8
+//===========================================================================================================================
+
+static OSStatus
+ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char ** output )
+{
+ int 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);
+ err = translate_errno( size != 0, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ // Add one for trailing '\0'
+
+ *output = (char*) malloc( size + 1 );
+ require_action( *output, exit, err = mStatus_NoMemoryErr );
+
+ size = WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), *output, size, NULL, NULL);
+ err = translate_errno( size != 0, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ // have to add the trailing 0 because WideCharToMultiByte doesn't do it,
+ // although it does return the correct size
+
+ (*output)[size] = '\0';
+
+exit:
+
+ if ( err && *output )
+ {
+ free( *output );
+ *output = NULL;
+ }
+
+ return err;
+}
Change History (most recent first):
$Log: mDNSWin32.h,v $
+Revision 1.20 2005/01/25 08:12:52 shersche
+<rdar://problem/3947417> Enable Unicast and add Dynamic DNS support.
+Bug #: 3947417
+
+Revision 1.19 2004/12/15 07:34:45 shersche
+Add platform support for IPv4 and IPv6 unicast sockets
+
Revision 1.18 2004/10/11 21:53:15 shersche
<rdar://problem/3832450> Change GetWindowsVersionString link scoping from static to non-static so that it can be accessed from other compilation units. The information returned in this function will be used to determine what service dependencies to use when calling CreateService().
Bug #: 3832450
#endif
#include "mDNSEmbeddedAPI.h"
+#include "dDNS.h"
#ifdef __cplusplus
extern "C" {
HANDLE cancelEvent;
HANDLE quitEvent;
HANDLE interfaceListChangedEvent;
- HANDLE regEvent;
+ HANDLE descChangedEvent; // Computer description changed event
+ HANDLE ddnsChangedEvent; // DynDNS config changed
HANDLE wakeupEvent;
HANDLE initEvent;
- HKEY regKey;
+ HKEY descKey;
+ HKEY ddnsKey;
mStatus initStatus;
SocketRef interfaceListChangedSocket;
int interfaceCount;
IdleThreadCallback idleThreadCallback;
InterfaceListChangedCallback interfaceListChangedCallback;
HostDescriptionChangedCallback hostDescriptionChangedCallback;
+ SocketRef unicastSock4;
+ HANDLE unicastSock4ReadEvent;
+ mDNSAddr unicastSock4DestAddr;
+#if( !defined( _WIN32_WCE ) )
+ LPFN_WSARECVMSG unicastSock4RecvMsgPtr;
+#endif
+ SocketRef unicastSock6;
+ HANDLE unicastSock6ReadEvent;
+ mDNSAddr unicastSock6DestAddr;
+#if( !defined( _WIN32_WCE ) )
+ LPFN_WSARECVMSG unicastSock6RecvMsgPtr;
+#endif
};
//---------------------------------------------------------------------------------------------------------------------------
void freeifaddrs( struct ifaddrs *inAddrs );
+
+//---------------------------------------------------------------------------------------------------------------------------
+// Registry Constants
+//---------------------------------------------------------------------------------------------------------------------------
+
+#define kServiceName "Apple mDNSResponder"
+#define kServiceDynDNSBrowseDomains "BrowseDomains"
+#define kServiceDynDNSHostNames "HostNames"
+#define kServiceDynDNSRegistrationDomains "RegistrationDomains"
+#define kServiceDynDNSDomains "Domains" // value is comma separated list of domains
+#define kServiceDynDNSEnabled "Enabled"
+#define kServiceDynDNSStatus "Status"
+
+
#ifdef __cplusplus
}
#endif
VALUE "FileDescription", "mdnsNSP Dynamic Link Library"
VALUE "FileVersion", MASTER_PROD_VERS_STR
VALUE "InternalName", "mdnsNSP"
- VALUE "LegalCopyright", "Copyright (C) 2004"
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "mdnsNSP.dll"
VALUE "ProductName", MASTER_PROD_NAME
VALUE "ProductVersion", MASTER_PROD_VERS_STR
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.00"
- Name="mdnsNSP"
- ProjectGUID="{F4F15529-F0EB-402F-8662-73C5797EE557}"
- Keyword="Win32Proj">
- <Platforms>
- <Platform
- Name="Win32"/>
- </Platforms>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory=".\Debug"
- IntermediateDirectory=".\Debug"
- ConfigurationType="2"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=".;../;../../mDNSShared"
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;NSP_EXPORTS;DEBUG;WIN32_LEAN_AND_MEAN"
- StringPooling="TRUE"
- MinimalRebuild="TRUE"
- ExceptionHandling="FALSE"
- BasicRuntimeChecks="3"
- SmallerTypeCheck="TRUE"
- RuntimeLibrary="1"
- BufferSecurityCheck="TRUE"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="4"
- CallingConvention="2"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="../DLL/Debug/dnssd.lib ws2_32.lib iphlpapi.lib"
- OutputFile="$(OutDir)/mdnsNSP.dll"
- LinkIncremental="2"
- ModuleDefinitionFile="mdnsNSP.def"
- GenerateDebugInformation="TRUE"
- ProgramDatabaseFile="$(OutDir)/mdnsNSP.pdb"
- SubSystem="2"
- ImportLibrary="$(OutDir)/mdnsNSP.lib"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- AdditionalIncludeDirectories="../"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="2"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=".;../;../../mDNSShared"
- PreprocessorDefinitions="WIN32;_WINDOWS;_USRDLL;NSP_EXPORTS;WIN32_LEAN_AND_MEAN"
- StringPooling="TRUE"
- MinimalRebuild="TRUE"
- ExceptionHandling="FALSE"
- BasicRuntimeChecks="0"
- SmallerTypeCheck="FALSE"
- RuntimeLibrary="0"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="3"
- CallingConvention="2"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="../DLL/Release/dnssd.lib ws2_32.lib iphlpapi.lib"
- OutputFile="$(OutDir)/mdnsNSP.dll"
- LinkIncremental="1"
- ModuleDefinitionFile="mdnsNSP.def"
- GenerateDebugInformation="TRUE"
- SubSystem="2"
- OptimizeReferences="0"
- EnableCOMDATFolding="0"
- ImportLibrary="$(OutDir)/mdnsNSP.lib"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- AdditionalIncludeDirectories="../"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- </Configuration>
- </Configurations>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
- <File
- RelativePath="..\DebugServices.c">
- </File>
- <File
- RelativePath=".\mdnsNSP.c">
- </File>
- <File
- RelativePath=".\mdnsNSP.def">
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
- <File
- RelativePath="..\CommonServices.h">
- </File>
- <File
- RelativePath="..\DebugServices.h">
- </File>
- <File
- RelativePath="..\..\..\mDNSShared\dns_sd.h">
- </File>
- <File
- RelativePath=".\resource.h">
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
- <File
- RelativePath=".\mdnsNSP.rc">
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding = "Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="mdnsNSP"\r
+ ProjectGUID="{F4F15529-F0EB-402F-8662-73C5797EE557}"\r
+ Keyword="Win32Proj">\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="2"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories=".;../;../../mDNSShared"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;NSP_EXPORTS;DEBUG;WIN32_LEAN_AND_MEAN"\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="TRUE"\r
+ ExceptionHandling="FALSE"\r
+ BasicRuntimeChecks="3"\r
+ SmallerTypeCheck="TRUE"\r
+ RuntimeLibrary="1"\r
+ BufferSecurityCheck="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="4"\r
+ CallingConvention="2"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="../DLL/Debug/dnssd.lib ws2_32.lib iphlpapi.lib"\r
+ OutputFile="$(OutDir)/mdnsNSP.dll"\r
+ LinkIncremental="2"\r
+ ModuleDefinitionFile="mdnsNSP.def"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(OutDir)/mdnsNSP.pdb"\r
+ SubSystem="2"\r
+ ImportLibrary="$(OutDir)/mdnsNSP.lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files\bin"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="2"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ AdditionalIncludeDirectories=".;../;../../mDNSShared"\r
+ PreprocessorDefinitions="WIN32;_WINDOWS;_USRDLL;NSP_EXPORTS;WIN32_LEAN_AND_MEAN"\r
+ StringPooling="TRUE"\r
+ MinimalRebuild="TRUE"\r
+ ExceptionHandling="FALSE"\r
+ BasicRuntimeChecks="0"\r
+ SmallerTypeCheck="FALSE"\r
+ RuntimeLibrary="0"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="4"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"\r
+ CallingConvention="2"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="../DLL/Release/dnssd.lib ws2_32.lib iphlpapi.lib"\r
+ OutputFile="$(OutDir)/mdnsNSP.dll"\r
+ LinkIncremental="1"\r
+ ModuleDefinitionFile="mdnsNSP.def"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
+ SubSystem="2"\r
+ OptimizeReferences="0"\r
+ EnableCOMDATFolding="0"\r
+ ImportLibrary="$(IntDir)/mdnsNSP.lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\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="..\DebugServices.c">\r
+ </File>\r
+ <File\r
+ RelativePath=".\mdnsNSP.c">\r
+ </File>\r
+ <File\r
+ RelativePath=".\mdnsNSP.def">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+ <File\r
+ RelativePath="..\CommonServices.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\DebugServices.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\mDNSShared\dns_sd.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\resource.h">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
+ <File\r
+ RelativePath=".\mdnsNSP.rc">\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r