From 7cb34e5c3616917483a8e75510de0387e51833cc Mon Sep 17 00:00:00 2001 From: Apple Date: Wed, 20 Apr 2005 20:12:20 +0000 Subject: [PATCH] mDNSResponder-107.tar.gz --- Clients/DNS-SD.VisualStudio/dns-sd.rc | 103 ++ Clients/DNS-SD.VisualStudio/dns-sd.vcproj | 132 ++ Clients/DNS-SD.VisualStudio/resource.h | 14 + .../DNSServiceBrowser.cs | 16 +- Clients/ExplorerPlugin/ExplorerBarWindow.cpp | 60 +- Clients/ExplorerPlugin/ExplorerBarWindow.h | 9 +- Clients/ExplorerPlugin/ExplorerPlugin.cpp | 143 ++ Clients/ExplorerPlugin/ExplorerPlugin.rc | 2 +- Clients/ExplorerPlugin/ExplorerPlugin.vcproj | 8 +- .../ExplorerPlugin/ExplorerPluginLocRes.rc | 13 +- .../ExplorerPluginLocRes.vcproj | 19 +- Clients/ExplorerPlugin/ExplorerPluginRes.rc | 2 +- .../ExplorerPlugin/ExplorerPluginRes.vcproj | 17 +- Clients/ExplorerPlugin/res/button-xp.ico | Bin 7574 -> 2462 bytes Clients/ExplorerPlugin/res/globe.bmp | Bin 824 -> 824 bytes Clients/ExplorerPlugin/resource_dll.h | 1 - Clients/ExplorerPlugin/resource_loc_res.h | 1 - Clients/ExplorerPlugin/resource_res.h | 1 - Clients/Java/nmakefile | 4 +- Clients/PrinterSetupWizard/FourthPage.cpp | 5 +- .../PrinterSetupWizard/PrinterSetupWizard.rc | 10 +- .../PrinterSetupWizard.vcproj | 6 +- .../PrinterSetupWizardApp.cpp | 16 +- .../PrinterSetupWizardLocRes.rc | 52 +- .../PrinterSetupWizardLocRes.vcproj | 24 +- .../PrinterSetupWizardRes.rc | 6 +- .../PrinterSetupWizardRes.vcproj | 21 +- .../PrinterSetupWizardSheet.cpp | 1101 ++++++++++++++- .../PrinterSetupWizardSheet.h | 125 ++ Clients/PrinterSetupWizard/SecondPage.cpp | 1118 ++------------- Clients/PrinterSetupWizard/SecondPage.h | 108 +- Clients/PrinterSetupWizard/ThirdPage.cpp | 326 ++++- Clients/PrinterSetupWizard/ThirdPage.h | 16 +- Clients/PrinterSetupWizard/UtilTypes.h | 40 +- Clients/PrinterSetupWizard/resource_exe.h | 2 +- Clients/PrinterSetupWizard/resource_loc_res.h | 4 +- Clients/PrinterSetupWizard/resource_res.h | 2 +- Clients/dns-sd.c | 41 +- Makefile | 2 +- README.txt | 10 +- mDNSCore/DNSCommon.c | 94 +- mDNSCore/DNSCommon.h | 6 +- mDNSCore/mDNS.c | 81 +- mDNSCore/mDNSEmbeddedAPI.h | 56 +- mDNSCore/uDNS.c | 343 ++--- mDNSCore/uDNS.h | 13 +- mDNSMacOS9/mDNSLibraryResources.r | 30 +- .../PreferencePane/Artwork/add_idle.tiff | Bin 0 -> 728 bytes .../PreferencePane/Artwork/add_pressed.tiff | Bin 0 -> 688 bytes .../PreferencePane/Artwork/failure.tiff | Bin 0 -> 638 bytes .../PreferencePane/Artwork/inprogress.tiff | Bin 0 -> 644 bytes .../Artwork/remove_disabled.tiff | Bin 0 -> 698 bytes .../PreferencePane/Artwork/remove_idle.tiff | Bin 0 -> 694 bytes .../Artwork/remove_pressed.tiff | Bin 0 -> 656 bytes .../PreferencePane/Artwork/success.tiff | Bin 0 -> 676 bytes .../PreferencePane/ConfigurationAuthority.c | 193 +++ .../PreferencePane/ConfigurationAuthority.h | 59 + .../PreferencePane/ConfigurationRights.h | 55 + .../PreferencePane/DNSServiceDiscoveryPref.h | 189 +++ .../DNSServiceDiscoveryPref.icns | Bin 0 -> 38889 bytes .../PreferencePane/DNSServiceDiscoveryPref.m | 1204 +++++++++++++++++ .../DNSServiceDiscoveryPref.tiff | Bin 0 -> 17394 bytes .../DNSServiceDiscoveryPref.nib/classes.nib | 59 + .../DNSServiceDiscoveryPref.nib/info.nib | 18 + .../keyedobjects.nib | Bin 0 -> 17441 bytes .../English.lproj/InfoPlist.strings | Bin 0 -> 536 bytes .../PreferencePane/PrivilegedOperations.c | 227 ++++ .../PreferencePane/PrivilegedOperations.h | 84 ++ mDNSMacOSX/PreferencePane/ddnswriteconfig.m | 494 +++++++ mDNSMacOSX/daemon.c | 218 ++- mDNSMacOSX/mDNSMacOSX.c | 255 +++- mDNSMacOSX/mDNSMacOSX.h | 7 +- .../English.lproj/Localizable.strings | 10 + .../French.lproj/Localizable.strings | 10 + .../mDNSResponder.pbproj/project.pbxproj | 569 +++++++- mDNSPosix/Client.c | 17 +- mDNSPosix/Makefile | 5 +- mDNSPosix/PosixDaemon.c | 46 +- mDNSPosix/ReadMe.txt | 4 +- mDNSPosix/Responder.c | 88 +- mDNSPosix/dnsextd.c | 473 ++++--- mDNSPosix/mDNSPosix.c | 57 +- mDNSPosix/mDNSPosix.h | 5 + mDNSResponder.sln | 100 ++ mDNSShared/PlatformCommon.c | 7 +- mDNSShared/dns-sd.1 | 12 +- mDNSShared/dns_sd.h | 66 +- mDNSShared/dnssd_clientstub.c | 9 +- mDNSShared/dnssd_ipc.h | 9 +- mDNSShared/mDNS.1 | 12 +- mDNSShared/mDNSResponder.8 | 7 +- mDNSShared/uds_daemon.c | 210 ++- mDNSWindows/ControlPanel/ConfigDialog.cpp | 73 + mDNSWindows/ControlPanel/ConfigDialog.h | 62 + .../ControlPanel/ConfigPropertySheet.cpp | 578 ++++++++ .../ControlPanel/ConfigPropertySheet.h | 141 ++ mDNSWindows/ControlPanel/ControlPanel.cpp | 390 ++++++ mDNSWindows/ControlPanel/ControlPanel.def | 35 + mDNSWindows/ControlPanel/ControlPanel.h | 98 ++ mDNSWindows/ControlPanel/ControlPanel.rc | 280 ++++ mDNSWindows/ControlPanel/ControlPanel.vcproj | 333 +++++ mDNSWindows/ControlPanel/FirstPage.cpp | 287 ++++ mDNSWindows/ControlPanel/FirstPage.h | 93 ++ mDNSWindows/ControlPanel/SecondPage.cpp | 490 +++++++ mDNSWindows/ControlPanel/SecondPage.h | 120 ++ mDNSWindows/ControlPanel/SharedSecret.cpp | 198 +++ mDNSWindows/ControlPanel/SharedSecret.h | 64 + mDNSWindows/ControlPanel/ThirdPage.cpp | 456 +++++++ mDNSWindows/ControlPanel/ThirdPage.h | 129 ++ mDNSWindows/ControlPanel/res/ControlPanel.rc2 | 13 + mDNSWindows/ControlPanel/res/controlpanel.ico | Bin 0 -> 11854 bytes mDNSWindows/ControlPanel/res/failure.ico | Bin 0 -> 894 bytes mDNSWindows/ControlPanel/res/success.ico | Bin 0 -> 894 bytes mDNSWindows/ControlPanel/resource.h | 41 + mDNSWindows/ControlPanel/stdafx.cpp | 34 + mDNSWindows/ControlPanel/stdafx.h | 72 + mDNSWindows/DLL.NET/Stdafx.cpp | 68 +- mDNSWindows/DLL.NET/Stdafx.h | 79 +- mDNSWindows/DLL.NET/dnssd_NET.cpp | 2 +- mDNSWindows/DLL.NET/dnssd_NET.h | 9 +- mDNSWindows/DLL.NET/dnssd_NET.rc | 4 +- mDNSWindows/DLL/dll.rc | 4 +- mDNSWindows/DLL/dnssd.vcproj | 2 +- .../Windows/Sources/ChooserDialog.cpp | 4 +- mDNSWindows/Java/makefile | 25 +- mDNSWindows/RegNames.h | 62 + mDNSWindows/SystemService/Prefix.h | 2 +- mDNSWindows/SystemService/Service.c | 155 ++- mDNSWindows/SystemService/Service.rc | 4 +- mDNSWindows/SystemService/Service.vcproj | 6 +- mDNSWindows/WinVersRes.h | 34 +- mDNSWindows/dDNS.c | 139 +- mDNSWindows/dDNS.h | 2 +- mDNSWindows/loclibrary.c | 59 +- mDNSWindows/mDNSWin32.c | 651 +++++++-- mDNSWindows/mDNSWin32.h | 21 +- mDNSWindows/mdnsNSP/mdnsNSP.c | 554 +++++++- mDNSWindows/mdnsNSP/mdnsNSP.def | 6 + mDNSWindows/mdnsNSP/mdnsNSP.rc | 4 +- mDNSWindows/mdnsNSP/mdnsNSP.vcproj | 2 +- 140 files changed, 12444 insertions(+), 2422 deletions(-) create mode 100755 Clients/DNS-SD.VisualStudio/dns-sd.rc create mode 100755 Clients/DNS-SD.VisualStudio/dns-sd.vcproj create mode 100755 Clients/DNS-SD.VisualStudio/resource.h create mode 100644 mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff create mode 100644 mDNSMacOSX/PreferencePane/Artwork/add_pressed.tiff create mode 100644 mDNSMacOSX/PreferencePane/Artwork/failure.tiff create mode 100644 mDNSMacOSX/PreferencePane/Artwork/inprogress.tiff create mode 100644 mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff create mode 100644 mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff create mode 100644 mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff create mode 100644 mDNSMacOSX/PreferencePane/Artwork/success.tiff create mode 100644 mDNSMacOSX/PreferencePane/ConfigurationAuthority.c create mode 100644 mDNSMacOSX/PreferencePane/ConfigurationAuthority.h create mode 100644 mDNSMacOSX/PreferencePane/ConfigurationRights.h create mode 100644 mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h create mode 100644 mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns create mode 100644 mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m create mode 100644 mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff create mode 100644 mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib create mode 100644 mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib create mode 100644 mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib create mode 100644 mDNSMacOSX/PreferencePane/English.lproj/InfoPlist.strings create mode 100644 mDNSMacOSX/PreferencePane/PrivilegedOperations.c create mode 100644 mDNSMacOSX/PreferencePane/PrivilegedOperations.h create mode 100644 mDNSMacOSX/PreferencePane/ddnswriteconfig.m create mode 100644 mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings create mode 100644 mDNSMacOSX/mDNSResponder-bundle/Resources/French.lproj/Localizable.strings create mode 100755 mDNSResponder.sln create mode 100755 mDNSWindows/ControlPanel/ConfigDialog.cpp create mode 100755 mDNSWindows/ControlPanel/ConfigDialog.h create mode 100755 mDNSWindows/ControlPanel/ConfigPropertySheet.cpp create mode 100755 mDNSWindows/ControlPanel/ConfigPropertySheet.h create mode 100755 mDNSWindows/ControlPanel/ControlPanel.cpp create mode 100755 mDNSWindows/ControlPanel/ControlPanel.def create mode 100755 mDNSWindows/ControlPanel/ControlPanel.h create mode 100755 mDNSWindows/ControlPanel/ControlPanel.rc create mode 100755 mDNSWindows/ControlPanel/ControlPanel.vcproj create mode 100755 mDNSWindows/ControlPanel/FirstPage.cpp create mode 100755 mDNSWindows/ControlPanel/FirstPage.h create mode 100755 mDNSWindows/ControlPanel/SecondPage.cpp create mode 100755 mDNSWindows/ControlPanel/SecondPage.h create mode 100755 mDNSWindows/ControlPanel/SharedSecret.cpp create mode 100755 mDNSWindows/ControlPanel/SharedSecret.h create mode 100755 mDNSWindows/ControlPanel/ThirdPage.cpp create mode 100755 mDNSWindows/ControlPanel/ThirdPage.h create mode 100755 mDNSWindows/ControlPanel/res/ControlPanel.rc2 create mode 100755 mDNSWindows/ControlPanel/res/controlpanel.ico create mode 100755 mDNSWindows/ControlPanel/res/failure.ico create mode 100755 mDNSWindows/ControlPanel/res/success.ico create mode 100755 mDNSWindows/ControlPanel/resource.h create mode 100755 mDNSWindows/ControlPanel/stdafx.cpp create mode 100755 mDNSWindows/ControlPanel/stdafx.h create mode 100644 mDNSWindows/RegNames.h diff --git a/Clients/DNS-SD.VisualStudio/dns-sd.rc b/Clients/DNS-SD.VisualStudio/dns-sd.rc new file mode 100755 index 0000000..a57a430 --- /dev/null +++ b/Clients/DNS-SD.VisualStudio/dns-sd.rc @@ -0,0 +1,103 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +#include "WinVersRes.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION MASTER_PROD_VERS + PRODUCTVERSION MASTER_PROD_VERS + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Apple Computer, Inc." + VALUE "FileDescription", "Bonjour Console Utility" + VALUE "FileVersion", MASTER_PROD_VERS_STR + VALUE "InternalName", "dns-sd.exe" + VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "dns-sd.exe" + VALUE "ProductName", MASTER_PROD_NAME + VALUE "ProductVersion", MASTER_PROD_VERS_STR + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Clients/DNS-SD.VisualStudio/dns-sd.vcproj b/Clients/DNS-SD.VisualStudio/dns-sd.vcproj new file mode 100755 index 0000000..dda633b --- /dev/null +++ b/Clients/DNS-SD.VisualStudio/dns-sd.vcproj @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Clients/DNS-SD.VisualStudio/resource.h b/Clients/DNS-SD.VisualStudio/resource.h new file mode 100755 index 0000000..7a92526 --- /dev/null +++ b/Clients/DNS-SD.VisualStudio/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by dns-sd.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs b/Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs index 75bbc93..f2cf813 100755 --- a/Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs +++ b/Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs @@ -23,6 +23,9 @@ Change History (most recent first): $Log: DNSServiceBrowser.cs,v $ +Revision 1.6 2005/02/10 22:35:06 cheshire + Update name + Revision 1.5 2004/09/21 16:26:58 shersche Check to make sure browse list selected item is not null before resolving Submitted by: prepin@gmail.com @@ -106,10 +109,14 @@ namespace DNSServiceBrowser_NET this.Load += new System.EventHandler(this.Form1_Load); } - private void Form1_Load(object sender, EventArgs e) - { - typeBox.SelectedItem = "_spike._tcp"; - } + private void Form1_Load(object sender, EventArgs e) + + { + + typeBox.SelectedItem = "_spike._tcp"; + + } + /// /// Clean up any resources being used. @@ -267,7 +274,6 @@ namespace DNSServiceBrowser_NET "_raop._tcp", "_rce._tcp", "_realplayfavs._tcp", - "_rendezvouspong._tcp", "_riousbprint._tcp", "_rfb._tcp", "_rtsp._tcp", diff --git a/Clients/ExplorerPlugin/ExplorerBarWindow.cpp b/Clients/ExplorerPlugin/ExplorerBarWindow.cpp index ea9cdc3..a68880b 100644 --- a/Clients/ExplorerPlugin/ExplorerBarWindow.cpp +++ b/Clients/ExplorerPlugin/ExplorerBarWindow.cpp @@ -23,6 +23,15 @@ Change History (most recent first): $Log: ExplorerBarWindow.cpp,v $ +Revision 1.18 2005/02/26 01:24:05 shersche +Remove display lines in tree control + +Revision 1.17 2005/02/25 19:57:30 shersche + Remove FTP browsing from plugin + +Revision 1.16 2005/02/08 23:31:06 shersche +Move "About ..." item underneath WebSites, change icons for discovered sites and "About ..." item + Revision 1.15 2005/01/27 22:38:27 shersche add About item to tree list @@ -205,12 +214,9 @@ int ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct ) require_noerr( err, exit ); GetClientRect( rect ); - mTree.Create( WS_TABSTOP | WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_NOHSCROLL , rect, this, + mTree.Create( WS_TABSTOP | WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_NOHSCROLL , rect, this, IDC_EXPLORER_TREE ); - s.LoadString( IDS_ABOUT ); - m_about = mTree.InsertItem( s, 0, 0 ); - ServiceHandlerEntry * e; // Web Site Handler @@ -220,48 +226,20 @@ int ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct ) e->type = "_http._tcp"; e->urlScheme = "http://"; e->ref = NULL; - e->treeItem = NULL; - e->treeFirst = true; e->obj = this; e->needsLogin = false; mServiceHandlers.Add( e ); - - s.LoadString( IDS_WEB_SITES ); - e->treeItem = mTree.InsertItem( s, 1, 1 ); - mTree.Expand( e->treeItem, TVE_EXPAND ); - - err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e ); - require_noerr( err, exit ); - - err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(e->ref), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE); - require_noerr( err, exit ); - m_serviceRefs.push_back(e->ref); + s.LoadString( IDS_ABOUT ); + m_about = mTree.InsertItem( s, 1, 1 ); - // FTP Site Handler - - e = new ServiceHandlerEntry; - check( e ); - e->type = "_ftp._tcp"; - e->urlScheme = "ftp://"; - e->ref = NULL; - e->treeItem = NULL; - e->treeFirst = true; - e->obj = this; - e->needsLogin = true; - mServiceHandlers.Add( e ); - - s.LoadString( IDS_FTP_SITES ); - e->treeItem = mTree.InsertItem( s, 1, 1 ); - mTree.Expand( e->treeItem, TVE_EXPAND ); - err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e ); require_noerr( err, exit ); err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(e->ref), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE); require_noerr( err, exit ); - m_serviceRefs.push_back(e->ref); + m_serviceRefs.push_back(e->ref); m_imageList.Create( 16, 16, ILC_COLORDDB, 2, 0); bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_GLOBE ) ) ); @@ -551,18 +529,10 @@ LONG ExplorerBarWindow::OnServiceAdd( ServiceInfo * service ) // Insert the new item in sorted order. - afterItem = ( index > 0 ) ? handler->array[ index - 1 ]->item : TVI_FIRST; + afterItem = ( index > 0 ) ? handler->array[ index - 1 ]->item : m_about; handler->array.InsertAt( index, service ); - service->item = mTree.InsertItem( service->displayName, 1, 1, handler->treeItem, afterItem ); + service->item = mTree.InsertItem( service->displayName, 0, 0, NULL, afterItem ); mTree.SetItemData( service->item, (DWORD_PTR) service ); - - // Make sure the item is visible if this is the first time a service was added. - - if( handler->treeFirst ) - { - handler->treeFirst = false; - mTree.EnsureVisible( service->item ); - } } return( 0 ); } diff --git a/Clients/ExplorerPlugin/ExplorerBarWindow.h b/Clients/ExplorerPlugin/ExplorerBarWindow.h index 34a3345..deade95 100644 --- a/Clients/ExplorerPlugin/ExplorerBarWindow.h +++ b/Clients/ExplorerPlugin/ExplorerBarWindow.h @@ -23,8 +23,11 @@ Change History (most recent first): $Log: ExplorerBarWindow.h,v $ +Revision 1.7 2005/02/25 19:57:30 shersche + Remove FTP browsing from plugin + Revision 1.6 2005/01/27 22:27:03 shersche -Add m_about member for "About Rendezvous" tree item +Add m_about member for "About ..." tree item Revision 1.5 2004/07/26 05:47:31 shersche use TXTRecord APIs, fix bug in locating service to be removed @@ -186,8 +189,6 @@ struct ServiceHandlerEntry const char * urlScheme; DNSServiceRef ref; ServiceInfoArray array; - HTREEITEM treeItem; - bool treeFirst; ExplorerBarWindow * obj; bool needsLogin; @@ -196,8 +197,6 @@ struct ServiceHandlerEntry type = NULL; urlScheme = NULL; ref = NULL; - treeItem = NULL; - treeFirst = true; obj = NULL; needsLogin = false; } diff --git a/Clients/ExplorerPlugin/ExplorerPlugin.cpp b/Clients/ExplorerPlugin/ExplorerPlugin.cpp index 464051a..766c173 100644 --- a/Clients/ExplorerPlugin/ExplorerPlugin.cpp +++ b/Clients/ExplorerPlugin/ExplorerPlugin.cpp @@ -23,6 +23,9 @@ Change History (most recent first): $Log: ExplorerPlugin.cpp,v $ +Revision 1.7 2005/02/23 02:00:45 shersche + Delete all the registry entries when component is unregistered + Revision 1.6 2005/01/25 17:56:45 shersche Load resource DLLs, get icons and bitmaps from resource DLLs Bug #: 3911084 @@ -101,6 +104,8 @@ DEBUG_LOCAL void MFCDLLThreadDetach( HINSTANCE inInstance ); DEBUG_LOCAL OSStatus RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName ); DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister ); +DEBUG_LOCAL OSStatus UnregisterServer( CLSID inCLSID ); +DEBUG_LOCAL OSStatus MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey ); // Stash away pointers to our resource DLLs @@ -274,6 +279,9 @@ STDAPI DllUnregisterServer( void ) err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, FALSE ); require_noerr( err, exit ); + + err = UnregisterServer( CLSID_ExplorerBar ); + require_noerr( err, exit ); exit: return( err ); @@ -590,3 +598,138 @@ DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOO exit: return( err ); } + + +//=========================================================================================================================== +// UnregisterServer +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus UnregisterServer( CLSID inCLSID ) +{ + OSStatus err = 0; + LPWSTR clsidWideString; + TCHAR clsidString[ 64 ]; + HKEY key; + TCHAR keyName[ MAX_PATH * 2 ]; + OSVERSIONINFO versionInfo; + + // Convert the CLSID to a string based on the encoding of this code (ANSI or Unicode). + + err = StringFromIID( inCLSID, &clsidWideString ); + require_noerr( err, exit ); + require_action( clsidWideString, exit, err = kNoMemoryErr ); + + #ifdef UNICODE + lstrcpyn( clsidString, clsidWideString, sizeof_array( clsidString ) ); + CoTaskMemFree( clsidWideString ); + #else + nChars = WideCharToMultiByte( CP_ACP, 0, clsidWideString, -1, clsidString, sizeof_array( clsidString ), NULL, NULL ); + err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr ); + CoTaskMemFree( clsidWideString ); + require_noerr( err, exit ); + #endif + + wsprintf( keyName, L"CLSID\\%s", clsidString ); + MyRegDeleteKey( HKEY_CLASSES_ROOT, keyName ); + + // If running on NT, de-register the extension as approved. + + versionInfo.dwOSVersionInfoSize = sizeof( versionInfo ); + GetVersionEx( &versionInfo ); + if( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) + { + lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved" ), sizeof_array( keyName ) ); + err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL ); + require_noerr( err, exit ); + + RegDeleteValue( key, clsidString ); + + err = RegCloseKey( key ); + require_noerr( err, exit ); + } + + // de-register toolbar button + + lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Internet Explorer\\Extensions\\{7F9DB11C-E358-4ca6-A83D-ACC663939424}"), sizeof_array( keyName ) ); + MyRegDeleteKey( HKEY_LOCAL_MACHINE, keyName ); + +exit: + return( err ); +} + + + +//=========================================================================================================================== +// MyRegDeleteKey +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey ) +{ + LPTSTR lpEnd; + OSStatus err; + DWORD dwSize; + TCHAR szName[MAX_PATH]; + HKEY hKey; + FILETIME ftWrite; + + // First, see if we can delete the key without having to recurse. + + err = RegDeleteKey( hKeyRoot, lpSubKey ); + + if ( !err ) + { + goto exit; + } + + err = RegOpenKeyEx( hKeyRoot, lpSubKey, 0, KEY_READ, &hKey ); + require_noerr( err, exit ); + + // Check for an ending slash and add one if it is missing. + + lpEnd = lpSubKey + lstrlen(lpSubKey); + + if ( *( lpEnd - 1 ) != TEXT( '\\' ) ) + { + *lpEnd = TEXT('\\'); + lpEnd++; + *lpEnd = TEXT('\0'); + } + + // Enumerate the keys + + dwSize = MAX_PATH; + err = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite); + + if ( !err ) + { + do + { + lstrcpy (lpEnd, szName); + + if ( !MyRegDeleteKey( hKeyRoot, lpSubKey ) ) + { + break; + } + + dwSize = MAX_PATH; + + err = RegEnumKeyEx( hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite ); + + } + while ( !err ); + } + + lpEnd--; + *lpEnd = TEXT('\0'); + + RegCloseKey( hKey ); + + // Try again to delete the key. + + err = RegDeleteKey(hKeyRoot, lpSubKey); + require_noerr( err, exit ); + +exit: + + return err; +} diff --git a/Clients/ExplorerPlugin/ExplorerPlugin.rc b/Clients/ExplorerPlugin/ExplorerPlugin.rc index 88dfeaf..1b97397 100644 --- a/Clients/ExplorerPlugin/ExplorerPlugin.rc +++ b/Clients/ExplorerPlugin/ExplorerPlugin.rc @@ -81,7 +81,7 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Apple Computer, Inc." - VALUE "FileDescription", "DNSServices Explorer Bar" + VALUE "FileDescription", "Bonjour Explorer Bar" VALUE "FileVersion", MASTER_PROD_VERS_STR VALUE "InternalName", "ExplorerPlugin.dll" VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT diff --git a/Clients/ExplorerPlugin/ExplorerPlugin.vcproj b/Clients/ExplorerPlugin/ExplorerPlugin.vcproj index 87f3f8e..c0f9af3 100644 --- a/Clients/ExplorerPlugin/ExplorerPlugin.vcproj +++ b/Clients/ExplorerPlugin/ExplorerPlugin.vcproj @@ -85,7 +85,7 @@ - + Name="VCPreLinkEventTool" + Description="Building Output Directories" + CommandLine="if not exist Debug\Resources mkdir Debug\Resources +if not exist Debug\Resources\ExplorerPlugin.dll.Resources mkdir Debug\Resources\ExplorerPlugin.dll.Resources +if not exist Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj mkdir Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj"/> + Name="VCPreLinkEventTool" + Description="Building Output Directories" + CommandLine="if not exist Release\Root mkdir Release\Root +if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files" +if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour" +if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources" +if not exist "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources" +if not exist "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj" mkdir "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj""/> + Name="VCPreLinkEventTool" + Description="Building Output Directories" + CommandLine="if not exist Debug\Resources mkdir Debug\Resources +if not exist Debug\Resources\ExplorerPlugin.dll.Resources mkdir Debug\Resources\ExplorerPlugin.dll.Resources"/> + Name="VCPreLinkEventTool" + Description="Building Output Directories" + CommandLine="if not exist Release\Root mkdir Release\Root +if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files" +if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour" +if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources" +if not exist "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources""/> 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 diff --git a/Clients/ExplorerPlugin/resource_dll.h b/Clients/ExplorerPlugin/resource_dll.h index 628228d..6374ce2 100755 --- a/Clients/ExplorerPlugin/resource_dll.h +++ b/Clients/ExplorerPlugin/resource_dll.h @@ -4,7 +4,6 @@ // #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 IDS_FIREWALL 111 diff --git a/Clients/ExplorerPlugin/resource_loc_res.h b/Clients/ExplorerPlugin/resource_loc_res.h index baf2213..ea18e83 100755 --- a/Clients/ExplorerPlugin/resource_loc_res.h +++ b/Clients/ExplorerPlugin/resource_loc_res.h @@ -4,7 +4,6 @@ // #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 IDS_FIREWALL 111 diff --git a/Clients/ExplorerPlugin/resource_res.h b/Clients/ExplorerPlugin/resource_res.h index b0217b3..4f66a0c 100755 --- a/Clients/ExplorerPlugin/resource_res.h +++ b/Clients/ExplorerPlugin/resource_res.h @@ -4,7 +4,6 @@ // #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 IDS_FIREWALL 111 diff --git a/Clients/Java/nmakefile b/Clients/Java/nmakefile index 4c655d8..6fa95cb 100644 --- a/Clients/Java/nmakefile +++ b/Clients/Java/nmakefile @@ -100,7 +100,7 @@ $(BUILDDIR)\BrowserApp.jar: $(BROWSERAPPOBJ) $(BROWSERAPPMAN) JAVASRC = . .SUFFIXES : .java {$(JAVASRC)}.java{$(BAOBJ)}.class: - $(JAVAC) -d $(BAOBJ) -classpath $(BAOBJ) $< + $(JAVAC) -d $(BAOBJ) -classpath $(BAOBJ);$(DNS_SD) $< {$(JAVASRC)}.java{$(SCOBJ)}.class: - $(JAVAC) -d $(SCOBJ) -classpath $(SCOBJ) $< + $(JAVAC) -d $(SCOBJ) -classpath $(SCOBJ);$(DNS_SD) $< diff --git a/Clients/PrinterSetupWizard/FourthPage.cpp b/Clients/PrinterSetupWizard/FourthPage.cpp index 8c330df..a2a7a50 100644 --- a/Clients/PrinterSetupWizard/FourthPage.cpp +++ b/Clients/PrinterSetupWizard/FourthPage.cpp @@ -23,6 +23,9 @@ Change History (most recent first): $Log: FourthPage.cpp,v $ +Revision 1.6 2005/02/08 21:45:06 shersche + Default to Generic PostScript or PCL if unable to match driver + Revision 1.5 2005/01/06 08:17:08 shersche Display the selected protocol ("Raw", "LPR", "IPP") rather than the port name @@ -126,7 +129,7 @@ CFourthPage::OnSetActive() m_printerNameCtrl.SetWindowText( printer->actualName ); m_printerManufacturerCtrl.SetWindowText ( printer->manufacturer ); - m_printerModelCtrl.SetWindowText ( printer->model ); + m_printerModelCtrl.SetWindowText ( printer->displayModelName ); Service * service = printer->services.front(); require_quiet( service, exit ); diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizard.rc b/Clients/PrinterSetupWizard/PrinterSetupWizard.rc index 4899ef7..71c00d0 100644 --- a/Clients/PrinterSetupWizard/PrinterSetupWizard.rc +++ b/Clients/PrinterSetupWizard/PrinterSetupWizard.rc @@ -103,11 +103,11 @@ BEGIN BLOCK "040904e4" BEGIN VALUE "CompanyName", "Apple Computer, Inc." - VALUE "FileDescription", "Rendezvous Printer Wizard" + VALUE "FileDescription", "Bonjour Printer Wizard" VALUE "FileVersion", MASTER_PROD_VERS_STR - VALUE "InternalName", "RendezvousPrinterWizard.exe" + VALUE "InternalName", "PrinterWizard.exe" VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT - VALUE "OriginalFilename", "RendezvousPrinterWizard.exe" + VALUE "OriginalFilename", "PrinterWizard.exe" VALUE "ProductName", MASTER_PROD_NAME VALUE "ProductVersion", MASTER_PROD_VERS_STR END @@ -133,8 +133,8 @@ IDR_MANIFEST RT_MANIFEST "res\\PrinterSetupWizard.manifes STRINGTABLE BEGIN - IDS_REINSTALL "Rendezvous Printer Wizard cannot run because some of its required files are missing. Please reinstall Rendezvous Printer Wizard." - IDS_REINSTALL_CAPTION "Rendezvous Printer Wizard" + IDS_REINSTALL "Bonjour Printer Wizard cannot run because some of its required files are missing. Please reinstall Bonjour Printer Wizard." + IDS_REINSTALL_CAPTION "Bonjour Printer Wizard" END #endif // English (U.S.) resources diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizard.vcproj b/Clients/PrinterSetupWizard/PrinterSetupWizard.vcproj index c26dc3e..4bff36a 100644 --- a/Clients/PrinterSetupWizard/PrinterSetupWizard.vcproj +++ b/Clients/PrinterSetupWizard/PrinterSetupWizard.vcproj @@ -39,7 +39,7 @@ Update name + +Revision 1.6 2005/02/10 22:35:10 cheshire + Update name + Revision 1.5 2005/01/25 18:30:02 shersche Fix call to PathForResource() by passing in NULL as first parameter. @@ -117,7 +123,7 @@ BOOL CPrinterSetupWizardApp::InitInstance() // Load Resources - res = PathForResource( NULL, L"RendezvousPrinterWizard.dll", resource, MAX_PATH ); + res = PathForResource( NULL, L"PrinterWizard.dll", resource, MAX_PATH ); err = translate_errno( res != 0, kUnknownErr, kUnknownErr ); require_noerr( err, exit ); @@ -125,15 +131,15 @@ BOOL CPrinterSetupWizardApp::InitInstance() translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr ); require_noerr( err, exit ); - res = PathForResource( NULL, L"RendezvousPrinterWizardLocalized.dll", resource, MAX_PATH ); + res = PathForResource( NULL, L"PrinterWizardLocalized.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 ); + require_noerr( err, exit ); + + AfxSetResourceHandle( g_localizedResources ); // InitCommonControls() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc b/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc index 521b2ef..7a2842f 100755 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc @@ -103,7 +103,7 @@ END IDD_SECOND_PAGE DIALOGEX 0, 0, 290, 154 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Rendezvous Printer Wizard" +CAPTION "Bonjour Printer Wizard" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN LTEXT "Shared printers:",IDC_STATIC,3,0,171,8 @@ -120,13 +120,13 @@ END IDD_FIRST_PAGE DIALOGEX 0, 0, 290, 199 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Rendezvous Printer Wizard" +CAPTION "Bonjour Printer Wizard" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "Welcome to the Rendezvous Printer Setup Wizard", + LTEXT "Welcome to the Bonjour Printer Setup Wizard", IDC_GREETING,114,7,171,46 LTEXT "Click next to continue.",IDC_STATIC,115,188,143,8 - LTEXT "This wizard helps you connect to a shared printer using Rendezvous. Make sure your printer is turned on and connected to your network.", + LTEXT "This wizard helps you connect to a shared printer using Bonjour. Make sure your printer is turned on and connected to your network.", IDC_STATIC,146,60,139,62 ICON "",IDC_INFO,118,60,20,20,SS_REALSIZEIMAGE END @@ -134,7 +134,7 @@ END IDD_THIRD_PAGE DIALOGEX 0, 0, 290, 154 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rendezvous Printer Wizard" +CAPTION "Bonjour Printer Wizard" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL "",IDC_PRINTER_MODEL,"SysListView32",LVS_REPORT | @@ -145,22 +145,22 @@ BEGIN LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,2,58,105,76 ICON 1017,1,0,0,20,27 LTEXT "",IDC_PRINTER_NAME,40,5,173,8 - LTEXT "The Rendezvous Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer.", - IDC_PRINTER_SELECTION_TEXT,40,23,243,26 + LTEXT "The Bonjour Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer.", + IDC_PRINTER_SELECTION_TEXT,40,18,243,33 CONTROL "Use this printer as the default printer", IDC_DEFAULT_PRINTER,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,3,142,224,10 + WS_TABSTOP,3,142,140,10 PUSHBUTTON "Have Disk...",IDC_HAVE_DISK,238,140,50,14 END IDD_FOURTH_PAGE DIALOGEX 0, 0, 290, 199 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Rendezvous Printer Wizard" +CAPTION "Bonjour Printer Wizard" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - LTEXT "Completing the Rendezvous Printer Wizard",IDC_GOODBYE, + LTEXT "Completing the Bonjour Printer Wizard",IDC_GOODBYE, 116,7,171,27 - LTEXT "You have successfully completed the Rendezvous Printer Wizard. The printer has the following settings:", + LTEXT "You have successfully completed the Bonjour Printer Wizard. The printer has the following settings:", IDC_STATIC,116,42,158,31 LTEXT "Name:",IDC_STATIC,116,78,22,8 LTEXT "Manufacturer:",IDC_STATIC,116,91,47,8 @@ -213,11 +213,11 @@ BEGIN BLOCK "040904e4" BEGIN VALUE "CompanyName", "Apple Computer, Inc." - VALUE "FileDescription", "Rendezvous Printer Wizard Resource Module" + VALUE "FileDescription", "Bonjour Resource Module" VALUE "FileVersion", MASTER_PROD_VERS_STR - VALUE "InternalName", "RendezvousPrinterWizardLocalized.dll" + VALUE "InternalName", "PrinterWizardLocalized.dll" VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT - VALUE "OriginalFilename", "RendezvousPrinterWizardLocalized.dll" + VALUE "OriginalFilename", "PrinterWizardLocalized.dll" VALUE "ProductName", MASTER_PROD_NAME VALUE "ProductVersion", MASTER_PROD_VERS_STR END @@ -237,15 +237,15 @@ END STRINGTABLE BEGIN IDS_ABOUTBOX "&About Printer Setup Wizard..." - IDS_GOODBYE "Completing the Rendezvous Printer Setup Wizard." - IDS_GREETING "Welcome to the Rendezvous Printer Setup Wizard" - IDS_BROWSE_TITLE "Browse for Rendezvous Printers" + IDS_GOODBYE "Completing the Bonjour Printer Setup Wizard." + IDS_GREETING "Welcome to the Bonjour Printer Setup Wizard" + IDS_BROWSE_TITLE "Browse for Bonjour Printers" IDS_BROWSE_SUBTITLE "Select the printer you want to use from the list below." - IDS_CAPTION "Rendezvous Printer Wizard" - IDS_GOODBYE_GOOD1 "You have successfully completed the Rendezvous Printer Wizard. The printer has the following settings:" + IDS_CAPTION "Bonjour Printer Wizard" + IDS_GOODBYE_GOOD1 "You have successfully completed the Bonjour Printer Wizard. The printer has the following settings:" IDS_SEARCHING "Searching for printers..." IDS_GOODBYTE_GOOD2 "To close this wizard, click Finish." - IDS_INSTALL_TITLE "Install Rendezvous Printer" + IDS_INSTALL_TITLE "Install Bonjour Printer" IDS_INSTALL_SUBTITLE "The manufacturer and model determine which printer software to use." END @@ -259,16 +259,18 @@ BEGIN "You do not have sufficient access to your computer to connect to the selected printer." IDS_MANUFACTURER_HEADING "Manufacturer" IDS_MODEL_HEADING "Model" - IDS_NO_RENDEZVOUS_PRINTERS "No Rendezvous Printers are available" - IDS_NO_MDNSRESPONDER_SERVICE_TEXT "Rendezvous Service is not available." + IDS_NO_PRINTERS "No Bonjour Printers are available" + IDS_NO_MDNSRESPONDER_SERVICE_TEXT "Bonjour Service is not available." IDS_NO_MDNSRESPONDER_SERVICE_CAPTION "Error" - IDS_PRINTER_MATCH_GOOD "The Rendezvous Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer." - 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. " + IDS_PRINTER_MATCH_GOOD "The Bonjour Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer." + IDS_PRINTER_MATCH_BAD "The Bonjour 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. " + IDS_PRINTER_MATCH_MAYBE "The Bonjour Printer Wizard has selected a generic printer driver for this printer. If your printer came with an installation disk, click 'Have Disk' now to load the manufacturer's drivers." IDS_YES "Yes" IDS_NO "No" IDS_LARGE_FONT "MS Sans Serif" - IDS_FIREWALL "Please check firewall setting to ensure the Rendezvous Printer Wizard operates correctly." + IDS_FIREWALL "Please check firewall setting to ensure the Bonjour Printer Wizard operates correctly." IDS_ERROR_CAPTION "Error" + IDS_PRINTER_UNAVAILABLE "The Bonjour printer you have selected is no longer available. Please make sure the printer is powered-on and plugged-in." END STRINGTABLE diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj b/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj index e7d0271..c97e842 100755 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj @@ -12,7 +12,7 @@ + Name="VCPreLinkEventTool" + Description="Building Output Directories" + CommandLine="if not exist Debug\Resources mkdir Debug\Resources +if not exist Debug\Resources\PrinterWizard.exe.Resources mkdir Debug\Resources\PrinterWizard.exe.Resources +if not exist Debug\Resources\PrinterWizard.exe.Resources\en.lproj mkdir Debug\Resources\PrinterWizard.exe.Resources\en.lproj +"/> + Name="VCPreLinkEventTool" + Description="Building Output Directories" + CommandLine="if not exist Release\Root mkdir Release\Root +if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files" +if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour" +if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources" +if not exist "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources" +if not exist "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj" mkdir "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj""/> + Name="VCPreLinkEventTool" + Description="Building Output Directories" + CommandLine="if not exist Debug\Resources mkdir Debug\Resources +if not exist Debug\Resources\PrinterWizard.exe.Resources mkdir Debug\Resources\PrinterWizard.exe.Resources"/> + Name="VCPreLinkEventTool" + Description="Building Output Directories" + CommandLine="if not exist Release\Root mkdir Release\Root +if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files" +if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour" +if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources" +if not exist "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources""/> Default pdl key to "application/postscript" + +Revision 1.28 2005/02/14 20:37:53 shersche + Populate comment field with the model name that users see in the wizard UI. + +Revision 1.27 2005/02/09 05:04:03 shersche + Use TXTRecordGetValuePtr() API in ParseTextRecord + +Revision 1.26 2005/02/08 21:45:06 shersche + Default to Generic PostScript or PCL if unable to match driver + +Revision 1.25 2005/02/08 18:54:17 shersche + Default queue name is "lp" when rp key is not specified. + +Revision 1.24 2005/02/01 02:15:55 shersche + Use TXTRecord parsing APIs in ParseTextRecord + +Revision 1.23 2005/01/31 23:54:30 shersche + Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object. + Revision 1.22 2005/01/25 18:49:43 shersche Get icon resources from resource DLL @@ -127,7 +148,8 @@ First checked in // Private Messages -#define WM_PROCESS_EVENT ( WM_USER + 0x100 ) +#define WM_SOCKET_EVENT ( WM_USER + 0x100 ) +#define WM_PROCESS_EVENT ( WM_USER + 0x101 ) // CPrinterSetupWizardSheet @@ -138,7 +160,10 @@ CPrinterSetupWizardSheet::CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParen :CPropertySheet(nIDCaption, pParentWnd, iSelectPage), m_selectedPrinter(NULL), m_driverThreadExitCode( 0 ), - m_driverThreadFinished( false ) + m_driverThreadFinished( false ), + m_pdlBrowser( NULL ), + m_ippBrowser( NULL ), + m_lprBrowser( NULL ) { m_arrow = LoadCursor(0, IDC_ARROW); m_wait = LoadCursor(0, IDC_APPSTARTING); @@ -146,15 +171,21 @@ CPrinterSetupWizardSheet::CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParen m_self = this; Init(); + + LoadPrinterNames(); } CPrinterSetupWizardSheet::~CPrinterSetupWizardSheet() { - if ( m_selectedPrinter != NULL ) + Printer * printer; + + while ( m_printers.size() > 0 ) { - delete m_selectedPrinter; - m_selectedPrinter = NULL; + printer = m_printers.front(); + m_printers.pop_front(); + + delete printer; } m_self = NULL; @@ -176,6 +207,60 @@ CPrinterSetupWizardSheet::SetSelectedPrinter(Printer * printer) } +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; +} + + + // ------------------------------------------------------ // InstallPrinter // @@ -358,8 +443,8 @@ CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * s pInfo.pServerName = NULL; pInfo.pShareName = NULL; pInfo.pPortName = printer->portName.GetBuffer(); - pInfo.pDriverName = printer->model.GetBuffer(); - pInfo.pComment = printer->model.GetBuffer(); + pInfo.pDriverName = printer->modelName.GetBuffer(); + pInfo.pComment = printer->displayModelName.GetBuffer(); pInfo.pLocation = service->location.GetBuffer(); pInfo.pDevMode = NULL; pInfo.pDevMode = NULL; @@ -415,9 +500,10 @@ CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service pInfo.pPrinterName = printer->actualName.GetBuffer(); pInfo.pPortName = printer->portName.GetBuffer(); - pInfo.pDriverName = printer->model.GetBuffer(); + pInfo.pDriverName = printer->modelName.GetBuffer(); pInfo.pPrintProcessor = L"winprint"; pInfo.pLocation = service->location.GetBuffer(); + pInfo.pComment = printer->displayModelName.GetBuffer(); pInfo.Attributes = PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL; hPrinter = AddPrinter(NULL, 2, (LPBYTE)&pInfo); @@ -436,6 +522,7 @@ exit: BEGIN_MESSAGE_MAP(CPrinterSetupWizardSheet, CPropertySheet) +ON_MESSAGE( WM_SOCKET_EVENT, OnSocketEvent ) ON_MESSAGE( WM_PROCESS_EVENT, OnProcessEvent ) ON_WM_SETCURSOR() ON_WM_TIMER() @@ -468,8 +555,39 @@ BOOL CPrinterSetupWizardSheet::OnCommand(WPARAM wParam, LPARAM lParam) // BOOL CPrinterSetupWizardSheet::OnInitDialog() { + OSStatus err; + CPropertySheet::OnInitDialog(); + err = StartBrowse(); + require_noerr( err, exit ); + +exit: + + if ( err ) + { + StopBrowse(); + + 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 TRUE; } @@ -532,6 +650,8 @@ CPrinterSetupWizardSheet::OnOK() MessageBox(message, caption, MB_OK|MB_ICONEXCLAMATION); } + + StopBrowse(); } @@ -556,6 +676,39 @@ void CPrinterSetupWizardSheet::Init(void) } +LONG +CPrinterSetupWizardSheet::OnSocketEvent(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) { @@ -594,7 +747,7 @@ CPrinterSetupWizardSheet::InstallDriverThread( LPVOID inParam ) si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); - command.Format(L"rundll32.exe printui.dll,PrintUIEntry /ia /m \"%s\" /f \"%s\"", (LPCTSTR) printer->model, (LPCTSTR) printer->infFileName ); + command.Format(L"rundll32.exe printui.dll,PrintUIEntry /ia /m \"%s\" /f \"%s\"", (LPCTSTR) printer->modelName, (LPCTSTR) printer->infFileName ); ok = CreateProcess(NULL, command.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); err = translate_errno( ok, errno_compat(), kUnknownErr ); @@ -633,3 +786,933 @@ exit: 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; + bool moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing); + CPropertyPage * active; + Printer * printer = NULL; + Service * service = NULL; + OSStatus err = kNoErr; + + require_noerr( inErrorCode, exit ); + + self = reinterpret_cast ( inContext ); + require_quiet( self, exit ); + + active = self->GetActivePage(); + require_quiet( active, exit ); + + // Have we seen this printer before? + + printer = self->Lookup( inName ); + + if ( printer ) + { + service = printer->LookupService( inType ); + } + + if ( inFlags & kDNSServiceFlagsAdd ) + { + if (printer == NULL) + { + // If not, then create a new one + + printer = self->OnAddPrinter( inInterfaceIndex, inName, inType, inDomain, moreComing ); + require_action( printer, exit, err = kUnknownErr ); + } + + if ( !service ) + { + err = self->OnAddService( printer, inInterfaceIndex, inName, inType, inDomain ); + require_noerr( err, exit ); + } + else + { + service->refs++; + } + } + else if ( printer ) + { + check( service ); + + err = self->OnRemoveService( service ); + require_noerr( err, exit ); + + if ( printer->services.size() == 0 ) + { + err = self->OnRemovePrinter( printer, moreComing ); + require_noerr( err, exit ); + } + } + +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); + + CPrinterSetupWizardSheet * self; + Service * service; + Queue * q; + uint32_t qpriority = kDefaultPriority; + CString qname; + int idx; + OSStatus err; + + require_noerr( inErrorCode, exit ); + + service = reinterpret_cast( 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 ); + + // + // 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, 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 ); + + + 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 +CPrinterSetupWizardSheet::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; + CPrinterSetupWizardSheet * self; + OSStatus err = kNoErr; + + require_noerr( inErrorCode, exit ); + + service = reinterpret_cast( 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, q->name, q->priority ); + require_noerr( err, exit ); + + // + // 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; +} + + +Printer* +CPrinterSetupWizardSheet::OnAddPrinter( + uint32_t inInterfaceIndex, + const char * inName, + const char * inType, + const char * inDomain, + bool moreComing) +{ + Printer * printer = NULL; + DWORD printerNameCount; + OSStatus err; + + DEBUG_UNUSED( inInterfaceIndex ); + DEBUG_UNUSED( inType ); + DEBUG_UNUSED( inDomain ); + + 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 (;;) + { + CPrinterSetupWizardSheet::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++; + } + + m_printers.push_back( printer ); + + if ( GetActivePage() == &m_pgSecond ) + { + m_pgSecond.OnAddPrinter( printer, moreComing ); + } + +exit: + + return printer; +} + + +OSStatus +CPrinterSetupWizardSheet::OnAddService( + Printer * printer, + uint32_t inInterfaceIndex, + const char * inName, + const char * inType, + const char * inDomain) +{ + Service * service = NULL; + OSStatus err = kNoErr; + + DEBUG_UNUSED( inName ); + DEBUG_UNUSED( inDomain ); + + 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 ( printer == m_selectedPrinter ) + { + StartResolve( service ); + } + +exit: + + return err; +} + + +OSStatus +CPrinterSetupWizardSheet::OnRemovePrinter( Printer * printer, bool moreComing ) +{ + CPropertyPage * active = GetActivePage(); + OSStatus err = kNoErr; + + if ( active == &m_pgSecond ) + { + m_pgSecond.OnRemovePrinter( printer, moreComing ); + } + + m_printers.remove( printer ); + + if ( m_selectedPrinter == printer ) + { + m_selectedPrinter = NULL; + + if ( ( active == &m_pgThird ) || ( active == &m_pgFourth ) ) + { + CString caption; + CString message; + + caption.LoadString( IDS_ERROR_CAPTION ); + message.LoadString( IDS_PRINTER_UNAVAILABLE ); + + MessageBox(message, caption, MB_OK|MB_ICONEXCLAMATION); + + SetActivePage( &m_pgSecond ); + } + } + + delete printer; + + return err; +} + + +OSStatus +CPrinterSetupWizardSheet::OnRemoveService( Service * service ) +{ + OSStatus err = kNoErr; + + if ( service && ( --service->refs == 0 ) ) + { + if ( service->serviceRef != NULL ) + { + err = StopResolve( service ); + require_noerr( err, exit ); + } + + service->printer->services.remove( service ); + + delete service; + } + +exit: + + return err; +} + + +void +CPrinterSetupWizardSheet::OnResolveService( Service * service ) +{ + // Make sure that the active page is page 2 + + check( GetActivePage() == &m_pgSecond ); + + 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 ); + + // Now we can hit next + + SetWizardButtons( PSWIZB_BACK|PSWIZB_NEXT ); + + // Reset the cursor + + m_active = m_arrow; + + // And tell page 2 about it + + m_pgSecond.OnResolveService( service ); + } +} + + +OSStatus +CPrinterSetupWizardSheet::StartBrowse() +{ + OSStatus err; + + // + // setup the DNS-SD browsing + // + 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 err; +} + + +OSStatus +CPrinterSetupWizardSheet::StopBrowse() +{ + OSStatus err; + + err = StopOperation( m_pdlBrowser ); + require_noerr( err, exit ); + + 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 err; +} + + +OSStatus +CPrinterSetupWizardSheet::StartResolve( Printer * printer ) +{ + OSStatus err = kNoErr; + Services::iterator it; + + check( printer ); + + for ( it = printer->services.begin(); it != printer->services.end(); it++ ) + { + if ( (*it)->serviceRef == NULL ) + { + err = StartResolve( *it ); + require_noerr( err, exit ); + } + } + + m_selectedPrinter = printer; + +exit: + + return err; +} + + +OSStatus +CPrinterSetupWizardSheet::StartResolve( Service * service ) +{ + OSStatus err = kNoErr; + + check( service->serviceRef == NULL ); + + // + // clean out any queues that were collected during a previous + // resolve + // + + service->EmptyQueues(); + + // + // now start the new resolve + // + + 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 ); + + // + // If we're not currently resolving, then disable the next button + // and set the cursor to hourglass + // + + if ( !service->printer->resolving ) + { + SetWizardButtons( PSWIZB_BACK ); + + m_active = m_wait; + SetCursor(m_active); + } + + service->printer->resolving++; + +exit: + + return err; +} + + +OSStatus +CPrinterSetupWizardSheet::StopResolve(Printer * printer) +{ + OSStatus err = kNoErr; + + check( printer ); + + Services::iterator it; + + for ( it = printer->services.begin(); it != printer->services.end(); it++ ) + { + if ( (*it)->serviceRef ) + { + err = StopResolve( *it ); + require_noerr( err, exit ); + } + } + +exit: + + return err; +} + + +OSStatus +CPrinterSetupWizardSheet::StopResolve( Service * service ) +{ + OSStatus err; + + check( service->serviceRef ); + + err = StopOperation( service->serviceRef ); + require_noerr( err, exit ); + + service->printer->resolving--; + +exit: + + return err; +} + + +OSStatus +CPrinterSetupWizardSheet::StartOperation( DNSServiceRef ref ) +{ + OSStatus err; + + err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(ref), m_hWnd, WM_SOCKET_EVENT, FD_READ|FD_CLOSE); + require_noerr( err, exit ); + + m_serviceRefList.push_back( ref ); + +exit: + + return err; +} + + +OSStatus +CPrinterSetupWizardSheet::StopOperation( DNSServiceRef & ref ) +{ + OSStatus err = kNoErr; + + if ( ref ) + { + m_serviceRefList.remove( ref ); + + if ( IsWindow( m_hWnd ) ) + { + err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD( ref ), m_hWnd, 0, 0 ); + require_noerr( err, exit ); + } + + DNSServiceRefDeallocate( ref ); + ref = NULL; + } + +exit: + + return err; +} + + +OSStatus +CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, CString & qname, uint32_t & qpriority ) +{ + // Use TXTRecord APIs declared in dns_sd.h + + bool qtotalDefined = false; + const void * val; + char buf[256]; + uint8_t len; + OSStatus err = kNoErr; + + // Default to queue "lp" + + qname = L"lp"; + + // Default pdl key to be "application/postscript" + + service->pdl = L"application/postscript"; + + if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "rp", &len ) ) != NULL ) + { + // Stringize val ( doesn't have trailing '\0' yet ) + + memcpy( buf, val, len ); + buf[len] = '\0'; + + err = UTF8StringToStringObject( buf, qname ); + require_noerr( err, exit ); + } + + if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "pdl", &len ) ) != NULL ) + { + // Stringize val ( doesn't have trailing '\0' yet ) + + memcpy( buf, val, len ); + buf[len] = '\0'; + + err = UTF8StringToStringObject( buf, service->pdl ); + require_noerr( err, exit ); + } + + if ( ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_mfg", &len ) ) != NULL ) || + ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_manufacturer", &len ) ) != NULL ) ) + { + // Stringize val ( doesn't have trailing '\0' yet ) + + memcpy( buf, val, len ); + buf[len] = '\0'; + + err = UTF8StringToStringObject( buf, service->usb_MFG ); + require_noerr( err, exit ); + } + + if ( ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_mdl", &len ) ) != NULL ) || + ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_model", &len ) ) != NULL ) ) + { + // Stringize val ( doesn't have trailing '\0' yet ) + + memcpy( buf, val, len ); + buf[len] = '\0'; + + err = UTF8StringToStringObject( buf, service->usb_MDL ); + require_noerr( err, exit ); + } + + if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "ty", &len ) ) != NULL ) + { + // Stringize val ( doesn't have trailing '\0' yet ) + + memcpy( buf, val, len ); + buf[len] = '\0'; + + err = UTF8StringToStringObject( buf, service->description ); + require_noerr( err, exit ); + } + + if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "product", &len ) ) != NULL ) + { + // Stringize val ( doesn't have trailing '\0' yet ) + + memcpy( buf, val, len ); + buf[len] = '\0'; + + err = UTF8StringToStringObject( buf, service->product ); + require_noerr( err, exit ); + } + + if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "note", &len ) ) != NULL ) + { + // Stringize val ( doesn't have trailing '\0' yet ) + + memcpy( buf, val, len ); + buf[len] = '\0'; + + err = UTF8StringToStringObject( buf, service->location ); + require_noerr( err, exit ); + } + + if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "qtotal", &len ) ) != NULL ) + { + // Stringize val ( doesn't have trailing '\0' yet ) + + memcpy( buf, val, len ); + buf[len] = '\0'; + + service->qtotal = (unsigned short) atoi( buf ); + qtotalDefined = true; + } + + if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "priority", &len ) ) != NULL ) + { + // Stringize val ( doesn't have trailing '\0' yet ) + + memcpy( buf, val, len ); + buf[len] = '\0'; + + qpriority = atoi( buf ); + } + +exit: + + // The following code is to fix a problem with older HP + // printers that don't include "qtotal" in their text + // record. We'll check to see if the qname is "TEXT" + // and if so, we're going to modify it to be "lp" so + // that we don't use the wrong queue + + if ( !err && !qtotalDefined && ( qname == L"TEXT" ) ) + { + qname = "lp"; + } + + return err; +} + + +Printer* +CPrinterSetupWizardSheet::Lookup(const char * inName) +{ + check( inName ); + + Printer * printer = NULL; + Printers::iterator it; + + for ( it = m_printers.begin(); it != m_printers.end(); it++ ) + { + if ( (*it)->name == inName ) + { + printer = *it; + break; + } + } + + return printer; +} + + +bool +CPrinterSetupWizardSheet::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 +CPrinterSetupWizardSheet::OrderQueueFunc( const Queue * q1, const Queue * q2 ) +{ + return ( q1->priority <= q2->priority ) ? true : false; +} + + + diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h index be4bd6a..cf7f096 100644 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h @@ -23,6 +23,12 @@ Change History (most recent first): $Log: PrinterSetupWizardSheet.h,v $ +Revision 1.8 2005/02/08 18:53:33 shersche +Remove qtotalDefined parameter from ParseTextRecord() + +Revision 1.7 2005/01/31 23:54:29 shersche + Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object. + Revision 1.6 2005/01/03 19:05:01 shersche Store pointer to instance of wizard sheet so that print driver install thread sends a window message to the correct window @@ -97,6 +103,9 @@ public: // virtual LONG OnProcessEvent(WPARAM inWParam, LPARAM inLParam); + + virtual LONG + OnSocketEvent(WPARAM inWParam, LPARAM inLParam); virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); @@ -113,6 +122,14 @@ public: afx_msg void OnOK(); + OSStatus + StartResolve( Printer * printer ); + + OSStatus + StopResolve( Printer * printer ); + + Printers m_printers; + HCURSOR m_active; HCURSOR m_arrow; HCURSOR m_wait; @@ -132,6 +149,106 @@ protected: private: + 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); + + Printer* + OnAddPrinter( + uint32_t inInterfaceIndex, + const char * inName, + const char * inType, + const char * inDomain, + bool moreComing); + + OSStatus + OnRemovePrinter( + Printer * printer, + bool moreComing); + + OSStatus + OnAddService( + Printer * printer, + uint32_t inInterfaceIndex, + const char * inName, + const char * inType, + const char * inDomain); + + OSStatus + OnRemoveService( + Service * service); + + void + OnResolveService( + Service * service ); + + static bool + OrderServiceFunc( const Service * a, const Service * b ); + + static bool + OrderQueueFunc( const Queue * q1, const Queue * q2 ); + + OSStatus + StartOperation( DNSServiceRef ref ); + + OSStatus + StopOperation( DNSServiceRef & ref ); + + OSStatus + StartBrowse(); + + OSStatus + StopBrowse(); + + OSStatus + StartResolve( Service * service ); + + OSStatus + StopResolve( Service * service ); + + OSStatus + ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, CString & qname, uint32_t & qpriority ); + + OSStatus + LoadPrinterNames(); + + Printer* + Lookup( const char * name ); + OSStatus InstallPrinter(Printer * printer); @@ -144,10 +261,18 @@ private: static unsigned WINAPI InstallDriverThread( LPVOID inParam ); + typedef std::map PrinterNameMap; + typedef std::list ServiceRefList; static CPrinterSetupWizardSheet * m_self; + PrinterNameMap m_printerNames; Printer * m_selectedPrinter; bool m_driverThreadFinished; DWORD m_driverThreadExitCode; + ServiceRefList m_serviceRefList; + DNSServiceRef m_pdlBrowser; + DNSServiceRef m_lprBrowser; + DNSServiceRef m_ippBrowser; + DNSServiceRef m_resolver; }; diff --git a/Clients/PrinterSetupWizard/SecondPage.cpp b/Clients/PrinterSetupWizard/SecondPage.cpp index 9e3720a..63665ee 100644 --- a/Clients/PrinterSetupWizard/SecondPage.cpp +++ b/Clients/PrinterSetupWizard/SecondPage.cpp @@ -23,6 +23,15 @@ Change History (most recent first): $Log: SecondPage.cpp,v $ +Revision 1.13 2005/02/15 07:50:10 shersche + Update name + +Revision 1.12 2005/02/10 22:35:11 cheshire + Update name + +Revision 1.11 2005/01/31 23:54:30 shersche + Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object. + Revision 1.10 2005/01/20 19:54:38 shersche Fix parse error when text record is NULL @@ -74,17 +83,11 @@ First checked in // 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), - m_pdlBrowser( NULL ), - m_lprBrowser( NULL ), - m_ippBrowser( NULL ), - m_selected( NULL ) + : CPropertyPage(CSecondPage::IDD) { m_psp.dwFlags &= ~(PSP_HASHELP); m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE; @@ -92,71 +95,14 @@ CSecondPage::CSecondPage() m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_BROWSE_TITLE); m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_BROWSE_SUBTITLE); - m_resolver = NULL; 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; } @@ -170,9 +116,9 @@ CSecondPage::InitBrowseList() require_quiet( psheet, exit ); // - // load the no rendezvous printers message until something shows up in the browse list + // load the no printers message until something shows up in the browse list // - text.LoadString(IDS_NO_RENDEZVOUS_PRINTERS); + text.LoadString(IDS_NO_PRINTERS); LoadTextAndDisableWindow( text ); @@ -192,267 +138,20 @@ exit: } -OSStatus -CSecondPage::StartOperation( DNSServiceRef ref ) -{ - 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; -} - - -OSStatus -CSecondPage::StopOperation( DNSServiceRef & ref ) -{ - OSStatus err = kNoErr; - - if ( ref ) - { - m_serviceRefList.remove( ref ); - - if ( IsWindow( m_hWnd ) ) - { - err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD( ref ), m_hWnd, 0, 0 ); - require_noerr( err, exit ); - } - - DNSServiceRefDeallocate( ref ); - ref = NULL; - } - -exit: - - return err; -} - - -Printer* -CSecondPage::Lookup(const char * inName) -{ - check( IsWindow( m_hWnd ) ); - check( inName ); - - HTREEITEM item = m_browseList.GetChildItem( TVI_ROOT ); - while ( item ) - { - Printer * printer; - DWORD_PTR data; - - data = m_browseList.GetItemData( item ); - printer = reinterpret_cast(data); - - if ( printer && ( printer->name == inName ) ) - { - return printer; - } - - item = m_browseList.GetNextItem( item, TVGN_NEXT ); - } - - return NULL; -} - - -OSStatus -CSecondPage::StartBrowse() -{ - OSStatus err; - - // - // setup the DNS-SD browsing - // - 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 err; -} - - -OSStatus -CSecondPage::StopBrowse() -{ - OSStatus err; - - err = StopOperation( m_pdlBrowser ); - require_noerr( err, exit ); - - 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 err; -} - - -OSStatus -CSecondPage::StartResolve( Printer * printer ) -{ - CPrinterSetupWizardSheet * psheet; - OSStatus err = kNoErr; - Services::iterator it; - - psheet = reinterpret_cast(GetParent()); - require_quiet( psheet, exit ); - - check( printer ); - - 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 ) -{ - CPrinterSetupWizardSheet * psheet; - OSStatus err = kNoErr; - - psheet = reinterpret_cast(GetParent()); - require_quiet( psheet, exit ); - - check( service->serviceRef == NULL ); - - // - // clean out any queues that were collected during a previous - // resolve - // - - service->EmptyQueues(); - - // - // now start the new resolve - // - - 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 ); - - // - // If we're not currently resolving, then disable the next button - // and set the cursor to hourglass - // - - if ( !service->printer->resolving ) - { - psheet->SetWizardButtons( PSWIZB_BACK ); - - psheet->m_active = psheet->m_wait; - SetCursor(psheet->m_active); - } - - service->printer->resolving++; - -exit: - - return err; -} - - -OSStatus -CSecondPage::StopResolve(Printer * printer) -{ - OSStatus err = kNoErr; - - check( printer ); - - Services::iterator it; - - for ( it = printer->services.begin(); it != printer->services.end(); it++ ) - { - if ( (*it)->serviceRef ) - { - err = StopResolve( *it ); - require_noerr( err, exit ); - } - } - -exit: - - return err; -} - - -OSStatus -CSecondPage::StopResolve( Service * service ) +void CSecondPage::DoDataExchange(CDataExchange* pDX) { - OSStatus err; - - check( service->serviceRef ); - - err = StopOperation( service->serviceRef ); - require_noerr( err, exit ); + CPropertyPage::DoDataExchange(pDX); + DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList); + DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation); - service->printer->resolving--; + DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel); -exit: + DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField); - return err; -} + DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel); + DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField); -void CSecondPage::DoDataExchange(CDataExchange* pDX) -{ - CPropertyPage::DoDataExchange(pDX); - DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList); - DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation); - DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel); - DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField); - DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel); - DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField); } @@ -481,343 +180,45 @@ CSecondPage::OnSetActive() { CPrinterSetupWizardSheet * psheet; Printer * printer; + Printers::iterator it; OSStatus err = kNoErr; psheet = reinterpret_cast(GetParent()); require_action( psheet, exit, err = kUnknownErr ); - if ( ( printer = psheet->GetSelectedPrinter() ) != NULL ) - { - psheet->SetSelectedPrinter( NULL ); - delete printer; - } - - // // initialize the browse list...this will remove everything currently - // in it, and add the no rendezvous printers item - // - InitBrowseList(); - - // - // start browing - // - err = StartBrowse(); - require_noerr( err, exit ); - -exit: - - if ( err != kNoErr ) - { - if ( err == kDNSServiceErr_Firewall ) - { - CString text, caption; + // in it, and add the no printers item - 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(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 ( 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( 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 ); + InitBrowseList(); - // - // remove the trailing dot on hostname - // - idx = service->hostname.ReverseFind('.'); + // And populate the list with any printers that we currently know about - if ((idx > 1) && ((service->hostname.GetLength() - 1) == idx)) + for ( it = psheet->m_printers.begin(); it != psheet->m_printers.end(); it++ ) { - service->hostname.Delete(idx, 1); + OnAddPrinter( *it, false ); } - // - // 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 ); + printer = psheet->GetSelectedPrinter(); - if ( qtotalDefined ) - { - q->name = qname; - } - - q->priority = qpriority; - - service->queues.push_back( q ); - - // - // we've completely resolved this service - // - - self->OnResolveService( service ); - } - else + if ( printer != NULL ) { - // - // 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 ); + m_browseList.Select( printer->item, TVGN_FIRSTVISIBLE ); } exit: - return; + return CPropertyPage::OnSetActive(); } -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) +BOOL +CSecondPage::OnKillActive() { - 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( 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; + return CPropertyPage::OnKillActive(); } 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() @@ -826,17 +227,10 @@ 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, + bool moreComing ) { - Printer * printer; - Service * service; CPrinterSetupWizardSheet * psheet; - DWORD printerNameCount; - bool newPrinter = false; OSStatus err = kNoErr; check( IsWindow( m_hWnd ) ); @@ -846,131 +240,31 @@ CSecondPage::OnAddPrinter( psheet = reinterpret_cast(GetParent()); require_quiet( psheet, exit ); - printer = Lookup( inName ); + printer->item = m_browseList.InsertItem(printer->displayName); - if (printer == NULL) - { - try - { - printer = new Printer; - } - catch (...) - { - printer = NULL; - } - - require_action( printer, exit, err = E_OUTOFMEMORY ); + m_browseList.SetItemData( printer->item, (DWORD_PTR) printer ); - printer->window = this; - printer->name = inName; + m_browseList.SortChildren(TVI_ROOT); - 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 ) + if ( printer->name == m_selectedName ) { - service->refs++; + m_browseList.SelectItem( printer->item ); } - 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 ) + // + // 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) { - 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); - } + m_browseList.DeleteItem(m_emptyListItem); + m_emptyListItem = NULL; + m_browseList.EnableWindow(TRUE); } exit: @@ -987,80 +281,44 @@ exit: OSStatus CSecondPage::OnRemovePrinter( - const char * inName, - const char * inType, - const char * inDomain, - bool moreComing) + Printer * printer, + bool moreComing) { - DEBUG_UNUSED( inDomain ); - DEBUG_UNUSED( inType ); - - Printer * printer; - OSStatus err = kNoErr; + CPrinterSetupWizardSheet * psheet; + OSStatus err = kNoErr; check( IsWindow( m_hWnd ) ); + check( printer ); - m_browseList.SetRedraw(FALSE); + psheet = reinterpret_cast(GetParent()); + require_quiet( psheet, exit ); - printer = Lookup( inName ); + m_browseList.SetRedraw(FALSE); - if ( 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) { - 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; - } + // + // if we're not the only thing in the list, then + // simply remove it from the list + // + m_browseList.DeleteItem( printer->item ); + } + else + { + // + // if we're the only thing in the list, then redisplay + // it with the no printers message + // + InitBrowseList(); } exit: - if (!moreComing) + if ( !moreComing ) { m_browseList.SetRedraw(TRUE); m_browseList.Invalidate(); @@ -1078,40 +336,25 @@ CSecondPage::OnResolveService( Service * service ) 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 set it to selected + // - // - // and update the printer information box - // - SetPrinterInformationState( TRUE ); + m_selectedName = service->printer->name; - m_descriptionField.SetWindowText( service->description ); - m_locationField.SetWindowText( service->location ); + // + // and update the printer information box + // + SetPrinterInformationState( TRUE ); - psheet->SetWizardButtons( PSWIZB_BACK|PSWIZB_NEXT ); + m_descriptionField.SetWindowText( service->description ); + m_locationField.SetWindowText( service->location ); - // - // reset the cursor - // + // + // reset the cursor + // - psheet->m_active = psheet->m_arrow; - SetCursor(psheet->m_active); - } + SetCursor(psheet->m_active); exit: @@ -1119,39 +362,6 @@ exit: } -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(pNMHDR); @@ -1173,7 +383,7 @@ void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult) // this call will trigger a resolve. When the resolve is complete, // our OnResolve will be called. // - err = StartResolve( printer ); + err = psheet->StartResolve( printer ); require_noerr( err, exit ); // @@ -1200,53 +410,6 @@ exit: } -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 ) { @@ -1276,96 +439,17 @@ CSecondPage::LoadTextAndDisableWindow( CString & text ) void CSecondPage::SetPrinterInformationState( BOOL state ) { - m_printerInformation.EnableWindow( state ); - m_descriptionLabel.EnableWindow( state ); - m_descriptionField.EnableWindow( state ); - m_locationLabel.EnableWindow( state ); - m_locationField.EnableWindow( state ); -} - - -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]; + m_printerInformation.EnableWindow( state ); - unsigned char num = *inTXT; - check( (int) num < inTXTSize ); + m_descriptionLabel.EnableWindow( state ); - 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); - } - } - } + m_descriptionField.EnableWindow( state ); - inTXTSize -= (num + 1); - inTXT += (num + 1); - } + m_locationLabel.EnableWindow( state ); -exit: + m_locationField.EnableWindow( state ); - if ( rpOnly ) - { - qtotalDefined = true; - } - - return err; } + diff --git a/Clients/PrinterSetupWizard/SecondPage.h b/Clients/PrinterSetupWizard/SecondPage.h index 9d9c4fb..aa08260 100644 --- a/Clients/PrinterSetupWizard/SecondPage.h +++ b/Clients/PrinterSetupWizard/SecondPage.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: SecondPage.h,v $ +Revision 1.7 2005/01/31 23:54:30 shersche + Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object. + Revision 1.6 2005/01/04 21:09:14 shersche Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once. @@ -73,44 +76,6 @@ public: // Dialog Data enum { IDD = IDD_SECOND_PAGE }; - 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: void InitBrowseList(); @@ -126,68 +91,25 @@ public: HTREEITEM m_emptyListItem; bool m_selectOkay; CTreeCtrl m_browseList; - DNSServiceRef m_resolver; bool m_initialized; bool m_waiting; - - 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 ); + afx_msg void OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult); OSStatus OnAddPrinter( - uint32_t inInterfaceIndex, - const char * inName, - const char * inType, - const char * inDomain, + Printer * printer, bool moreComing); OSStatus OnRemovePrinter( - const char * inName, - const char * inType, - const char * inDomain, + Printer * printer, bool moreComing); void OnResolveService( Service * service ); - static bool - OrderServiceFunc( const Service * a, const Service * b ); - - static bool - OrderQueueFunc( const Queue * q1, const Queue * q2 ); +private: void LoadTextAndDisableWindow( CString & text ); @@ -195,22 +117,6 @@ private: void SetPrinterInformationState( BOOL state ); - OSStatus - ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, bool & qtotalDefined, CString & qname, uint32_t & qpriority ); - - typedef std::map PrinterNameMap; - typedef std::list ServiceRefList; - typedef std::list 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; private: diff --git a/Clients/PrinterSetupWizard/ThirdPage.cpp b/Clients/PrinterSetupWizard/ThirdPage.cpp index 76978cd..acd8d3c 100644 --- a/Clients/PrinterSetupWizard/ThirdPage.cpp +++ b/Clients/PrinterSetupWizard/ThirdPage.cpp @@ -23,6 +23,24 @@ Change History (most recent first): $Log: ThirdPage.cpp,v $ +Revision 1.20 2005/03/05 02:27:45 shersche + Generic drivers don't do color + +Revision 1.19 2005/02/23 02:08:51 shersche + If we can't match the manufacturer, and select a generic printer, then show all the manufacturers in the manufacturer pane, not just "Generic". + +Revision 1.18 2005/02/15 07:02:51 shersche + Display different UI text when generic printer drivers are selected + +Revision 1.17 2005/02/08 21:45:06 shersche + Default to Generic PostScript or PCL if unable to match driver + +Revision 1.16 2005/02/08 18:56:03 shersche +Fix generated IPP url so that it doesn't add "/printers" string + +Revision 1.15 2005/02/01 01:44:07 shersche +Load ntprint.inf at startup. This will cause the wizard to take a second or two longer to come up, but will eliminate the pause when auto-selecting the print drivers. + Revision 1.14 2005/01/25 08:55:54 shersche Load icons at run-time from resource DLL Bug #: 3911084 @@ -102,8 +120,17 @@ First checked in // // These are pre-defined names for Generic manufacturer and model // -#define kGenericManufacturer L"Generic" -#define kGenericModel L"Generic / Text Only" +#define kGenericManufacturer L"Generic" +#define kGenericText L"Generic / Text Only" +#define kGenericPostscript L"Generic / Postscript" +#define kGenericPCL L"Generic / PCL" +#define kPDLPostscriptKey L"application/postscript" +#define kPDLPCLKey L"application/vnd.hp-pcl" +#define kGenericPSColorDriver L"HP Color LaserJet 4550 PS" +#define kGenericPSDriver L"HP LaserJet 4050 Series PS" +#define kGenericPCLColorDriver L"HP Color LaserJet 4550 PCL" +#define kGenericPCLDriver L"HP LaserJet 4050 Series PCL" + // // states for parsing ntprint.inf @@ -125,11 +152,45 @@ CThirdPage::CThirdPage() m_initialized(false), m_printerImage( NULL ) { + static const int bufferSize = 32768; + TCHAR windowsDirectory[bufferSize]; + CString header; + CString ntPrint; + OSStatus err; + BOOL ok; + m_psp.dwFlags &= ~(PSP_HASHELP); m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE; m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_INSTALL_TITLE); m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_INSTALL_SUBTITLE); + + // + // load printers from ntprint.inf + // + ok = GetWindowsDirectory( windowsDirectory, bufferSize ); + err = translate_errno( ok, errno_compat(), kUnknownErr ); + require_noerr( err, exit ); + + ntPrint.Format(L"%s\\%s", windowsDirectory, kNTPrintFile); + err = LoadPrintDriverDefsFromFile( m_manufacturers, ntPrint, false ); + require_noerr(err, exit); + + // + // load printer drivers that have been installed on this machine + // + err = LoadPrintDriverDefs( m_manufacturers ); + require_noerr(err, exit); + + // + // and lastly load our own special generic printer defs + // + err = LoadGenericPrintDriverDefs( m_manufacturers ); + require_noerr( err, exit ); + +exit: + + return; } @@ -170,7 +231,7 @@ CThirdPage::~CThirdPage() // // ---------------------------------------------------- void -CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model) +CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturers & manufacturers, Manufacturer * manufacturer, Model * model) { LVFINDINFO info; int nIndex; @@ -179,9 +240,6 @@ CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * man check( manufacturer != NULL ); check( model != NULL ); - Manufacturers manufacturers; - manufacturers[manufacturer->name] = manufacturer; - PopulateUI( manufacturers ); // @@ -202,7 +260,7 @@ CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * man // select the model // info.flags = LVFI_STRING; - info.psz = model->name; + info.psz = model->displayName; nIndex = m_modelListCtrl.FindItem(&info); @@ -229,7 +287,8 @@ void CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufacturer * manufacturer, Model * model ) { printer->manufacturer = manufacturer->name; - printer->model = model->name; + printer->displayModelName = model->displayName; + printer->modelName = model->name; printer->driverInstalled = model->driverInstalled; printer->infFileName = model->infFileName; @@ -261,7 +320,7 @@ CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufactu if ( q->name.GetLength() > 0 ) { - printer->portName.Format(L"http://%s:%d/printers/%s", static_cast(service->hostname), service->portNumber, static_cast(q->name) ); + printer->portName.Format(L"http://%s:%d/%s", static_cast(service->hostname), service->portNumber, static_cast(q->name) ); } else { @@ -583,6 +642,7 @@ CThirdPage::LoadPrintDriverDefsFromFile(Manufacturers & manufacturers, const CSt require_action( model, exit, err = kNoMemoryErr ); model->infFileName = filename; + model->displayName = name; model->name = name; model->driverInstalled = false; @@ -722,6 +782,7 @@ CThirdPage::LoadPrintDriverDefs( Manufacturers & manufacturers ) require_action( model, exit, err = kNoMemoryErr ); + model->displayName = info[i].pName; model->name = info[i].pName; model->driverInstalled = true; @@ -741,6 +802,137 @@ exit: } +// ------------------------------------------------------- +// LoadGenericPrintDriverDefs +// +// This function is responsible for loading polymorphic +// generic print drivers defs. The UI will read +// something like "Generic / Postscript" and we can map +// that to any print driver we want. +// ------------------------------------------------------- +OSStatus +CThirdPage::LoadGenericPrintDriverDefs( Manufacturers & manufacturers ) +{ + Manufacturer * manufacturer; + Model * model; + Manufacturers::iterator iter; + CString psDriverName; + CString pclDriverName; + OSStatus err = 0; + + // Generic drivers don't do color + + // First try and find our generic driver names + + iter = manufacturers.find(L"HP"); + require_action( iter != manufacturers.end(), exit, err = kUnknownErr ); + manufacturer = iter->second; + + // Look for Postscript + + model = manufacturer->find( kGenericPSColorDriver ); + + if ( !model ) + { + model = manufacturer->find( kGenericPSDriver ); + } + + if ( model ) + { + psDriverName = model->name; + + } + + // Look for PCL + + model = manufacturer->find( kGenericPCLColorDriver ); + + if ( !model ) + { + model = manufacturer->find( kGenericPCLDriver ); + } + + if ( model ) + { + pclDriverName = model->name; + } + + // If we found either a generic PS driver, or a generic PCL driver, + // then add them to the list + + if ( psDriverName.GetLength() || pclDriverName.GetLength() ) + { + // Try and find generic manufacturer if there is one + + iter = manufacturers.find(L"Generic"); + + if (iter != manufacturers.end()) + { + manufacturer = iter->second; + } + else + { + try + { + manufacturer = new Manufacturer; + } + catch (...) + { + manufacturer = NULL; + } + + require_action( manufacturer, exit, err = kNoMemoryErr ); + + manufacturer->name = "Generic"; + manufacturers[manufacturer->name] = manufacturer; + } + + if ( psDriverName.GetLength() > 0 ) + { + try + { + m_genericPostscript = new Model; + } + catch (...) + { + m_genericPostscript = NULL; + } + + require_action( m_genericPostscript, exit, err = kNoMemoryErr ); + + m_genericPostscript->displayName = kGenericPostscript; + m_genericPostscript->name = psDriverName; + m_genericPostscript->driverInstalled = false; + + manufacturer->models.push_back( m_genericPostscript ); + } + + if ( pclDriverName.GetLength() > 0 ) + { + try + { + m_genericPCL = new Model; + } + catch (...) + { + m_genericPCL = NULL; + } + + require_action( m_genericPCL, exit, err = kNoMemoryErr ); + + m_genericPCL->displayName = kGenericPCL; + m_genericPCL->name = pclDriverName; + m_genericPCL->driverInstalled = false; + + manufacturer->models.push_back( m_genericPCL ); + } + } + +exit: + + return err; +} + // ------------------------------------------------------ // ConvertToManufacturerName // @@ -839,11 +1031,13 @@ CThirdPage::NormalizeManufacturerName( const CString & name ) OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service) { CString normalizedProductName; - Manufacturer * manufacturer = NULL; - Model * model = NULL; - bool found = false; + Manufacturer * manufacturer = NULL; + Manufacturer * genericManufacturer = NULL; + Model * model = NULL; + Model * genericModel = NULL; + bool found = false; CString text; - OSStatus err = kNoErr; + OSStatus err = kNoErr; // // first look to see if we have a usb_MFG descriptor @@ -871,7 +1065,7 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print model = MatchModel ( manufacturer, ConvertToModelName ( service->usb_MDL ) ); } - if ( model == NULL ) + if ( ( model == NULL ) && ( service->product.GetLength() > 0 ) ) { service->product.Remove('('); service->product.Remove(')'); @@ -881,7 +1075,10 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print if ( model != NULL ) { - SelectMatch(printer, service, manufacturer, model); + Manufacturers manufacturers; + + manufacturers[manufacturer->name] = manufacturer; + SelectMatch(printer, service, manufacturers, manufacturer, model); found = true; } } @@ -894,6 +1091,27 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print { text.LoadString(IDS_PRINTER_MATCH_GOOD); } + else if ( MatchGeneric( printer, service, &genericManufacturer, &genericModel ) ) + { + Manufacturers * pManufacturers; + Manufacturers manufacturers; + + text.LoadString(IDS_PRINTER_MATCH_MAYBE); + + if ( manufacturer ) + { + manufacturers[genericManufacturer->name] = genericManufacturer; + manufacturers[manufacturer->name] = manufacturer; + + pManufacturers = &manufacturers; + } + else + { + pManufacturers = &m_manufacturers; + } + + SelectMatch( printer, service, *pManufacturers, genericManufacturer, genericModel ); + } else { text.LoadString(IDS_PRINTER_MATCH_BAD); @@ -1021,6 +1239,45 @@ CThirdPage::MatchModel(Manufacturer * manufacturer, const CString & name) } +// ------------------------------------------------------- +// MatchGeneric +// +// This function will attempt to find a generic printer +// driver for a printer that we weren't able to match +// specifically +// +BOOL +CThirdPage::MatchGeneric( Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model ) +{ + CString pdl; + BOOL ok = FALSE; + + DEBUG_UNUSED( printer ); + + Manufacturers::iterator iter = m_manufacturers.find( kGenericManufacturer ); + require_action_quiet( iter != m_manufacturers.end(), exit, ok = FALSE ); + + *manufacturer = iter->second; + + pdl = service->pdl; + pdl.MakeLower(); + + if ( pdl.Find( kPDLPCLKey ) != -1 ) + { + *model = m_genericPCL; + ok = TRUE; + } + else if ( pdl.Find( kPDLPostscriptKey ) != -1 ) + { + *model = m_genericPostscript; + ok = TRUE; + } + +exit: + + return ok; +} + // ----------------------------------------------------------- // OnInitPage @@ -1031,15 +1288,14 @@ CThirdPage::MatchModel(Manufacturer * manufacturer, const CString & name) OSStatus CThirdPage::OnInitPage() { - static const int bufferSize = 32768; - TCHAR windowsDirectory[bufferSize]; - CString header; - CString ntPrint; - OSStatus err; - BOOL ok; + CString header; + CString ntPrint; + OSStatus err = kNoErr; + + // Load printer icon + + - // Load printer icon - check( m_printerImage == NULL ); m_printerImage = (CStatic*) GetDlgItem( IDR_MANIFEST ); @@ -1074,25 +1330,6 @@ OSStatus CThirdPage::OnInitPage() m_modelListCtrl.InsertColumn(0, header, LVCFMT_LEFT, 247); m_modelSelected = NULL; - // - // load printers from ntprint.inf - // - ok = GetWindowsDirectory( windowsDirectory, bufferSize ); - err = translate_errno( ok, errno_compat(), kUnknownErr ); - require_noerr( err, exit ); - - ntPrint.Format(L"%s\\%s", windowsDirectory, kNTPrintFile); - err = LoadPrintDriverDefsFromFile( m_manufacturers, ntPrint, false ); - require_noerr(err, exit); - - // - // load printer drivers that have been installed on this machine - // - err = LoadPrintDriverDefs( m_manufacturers ); - require_noerr(err, exit); - -exit: - return (err); } @@ -1104,7 +1341,8 @@ void CThirdPage::DoDataExchange(CDataExchange* pDX) 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); + } @@ -1230,7 +1468,7 @@ void CThirdPage::OnLvnItemchangedManufacturer(NMHDR *pNMHDR, LRESULT *pResult) { Model * model = *iter; - int nItem = m_modelListCtrl.InsertItem(0, model->name); + int nItem = m_modelListCtrl.InsertItem( 0, model->displayName ); m_modelListCtrl.SetItemData(nItem, (DWORD_PTR) model); } diff --git a/Clients/PrinterSetupWizard/ThirdPage.h b/Clients/PrinterSetupWizard/ThirdPage.h index b775fb8..a5a9bb6 100644 --- a/Clients/PrinterSetupWizard/ThirdPage.h +++ b/Clients/PrinterSetupWizard/ThirdPage.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: ThirdPage.h,v $ +Revision 1.4 2005/02/08 21:45:06 shersche + Default to Generic PostScript or PCL if unable to match driver + Revision 1.3 2005/01/25 08:57:28 shersche Add m_printerControl member for dynamic loading of icons from resource DLLs Bug #: 3911084 @@ -85,6 +88,13 @@ private: // OSStatus LoadPrintDriverDefs(Manufacturers & manufacturers); + // + // LoadGenericPrintDriversDefs + // + // Loads generic postscript and pcl print driver defs + // + OSStatus LoadGenericPrintDriverDefs( Manufacturers & manufacturers ); + // // PopulateUI // @@ -115,7 +125,8 @@ private: Manufacturer * MatchManufacturer( Manufacturers & manufacturer, const CString & name ); Model * MatchModel( Manufacturer * manufacturer, const CString & name ); - void SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model); + BOOL MatchGeneric( Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model ); + void SelectMatch(Printer * printer, Service * service, Manufacturers & manufacturers, Manufacturer * manufacturer, Model * model); void CopyPrinterSettings(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model); Manufacturers m_manufacturers; @@ -126,6 +137,9 @@ private: CListCtrl m_modelListCtrl; Model * m_modelSelected; + Model * m_genericPostscript; + Model * m_genericPCL; + bool m_initialized; public: diff --git a/Clients/PrinterSetupWizard/UtilTypes.h b/Clients/PrinterSetupWizard/UtilTypes.h index 11042dd..5e2fe19 100644 --- a/Clients/PrinterSetupWizard/UtilTypes.h +++ b/Clients/PrinterSetupWizard/UtilTypes.h @@ -23,6 +23,15 @@ Change History (most recent first): $Log: UtilTypes.h,v $ +Revision 1.11 2005/03/05 02:27:46 shersche + Generic drivers don't do color + +Revision 1.10 2005/02/08 21:45:06 shersche + Default to Generic PostScript or PCL if unable to match driver + +Revision 1.9 2005/02/01 01:16:12 shersche +Change window owner from CSecondPage to CPrinterSetupWizardSheet + Revision 1.8 2005/01/06 08:18:26 shersche Add protocol field to service, add EmptyQueues() function to service @@ -62,7 +71,7 @@ First checked in #include #include -class CSecondPage; +class CPrinterSetupWizardSheet; #define kDefaultPriority 50 #define kDefaultQTotal 1 @@ -76,6 +85,7 @@ namespace PrinterSetupWizard struct Model; typedef std::list Queues; + typedef std::list Printers; typedef std::list Services; typedef std::list Models; @@ -91,7 +101,7 @@ namespace PrinterSetupWizard const std::string & type ); - CSecondPage * window; + CPrinterSetupWizardSheet * window; HTREEITEM item; // @@ -120,7 +130,8 @@ namespace PrinterSetupWizard bool driverInstalled; CString infFileName; CString manufacturer; - CString model; + CString displayModelName; + CString modelName; CString portName; bool deflt; @@ -152,6 +163,7 @@ namespace PrinterSetupWizard DNSServiceRef serviceRef; CString hostname; unsigned short portNumber; + CString pdl; CString usb_MFG; CString usb_MDL; CString description; @@ -190,6 +202,9 @@ namespace PrinterSetupWizard CString name; CString tag; Models models; + + Model* + find( const CString & name ); }; @@ -197,6 +212,7 @@ namespace PrinterSetupWizard { bool driverInstalled; CString infFileName; + CString displayName; CString name; }; @@ -275,6 +291,24 @@ namespace PrinterSetupWizard Queue::~Queue() { } + + inline Model* + Manufacturer::find( const CString & name ) + { + Models::iterator it; + + for ( it = models.begin(); it != models.end(); it++ ) + { + Model * model = *it; + + if ( model->name = name ) + { + return model; + } + } + + return NULL; + } } diff --git a/Clients/PrinterSetupWizard/resource_exe.h b/Clients/PrinterSetupWizard/resource_exe.h index c0f5429..46cd451 100755 --- a/Clients/PrinterSetupWizard/resource_exe.h +++ b/Clients/PrinterSetupWizard/resource_exe.h @@ -25,7 +25,7 @@ #define IDS_INSTALL_ERROR_MESSAGE 115 #define IDS_MANUFACTURER_HEADING 116 #define IDS_MODEL_HEADING 117 -#define IDS_NO_RENDEZVOUS_PRINTERS 118 +#define IDS_NO_PRINTERS 118 #define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119 #define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120 #define IDS_PRINTER_MATCH_GOOD 121 diff --git a/Clients/PrinterSetupWizard/resource_loc_res.h b/Clients/PrinterSetupWizard/resource_loc_res.h index 7f77da3..b5a3bf9 100755 --- a/Clients/PrinterSetupWizard/resource_loc_res.h +++ b/Clients/PrinterSetupWizard/resource_loc_res.h @@ -25,11 +25,12 @@ #define IDS_INSTALL_ERROR_MESSAGE 115 #define IDS_MANUFACTURER_HEADING 116 #define IDS_MODEL_HEADING 117 -#define IDS_NO_RENDEZVOUS_PRINTERS 118 +#define IDS_NO_PRINTERS 118 #define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119 #define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120 #define IDS_PRINTER_MATCH_GOOD 121 #define IDS_PRINTER_MATCH_BAD 122 +#define IDS_PRINTER_MATCH_MAYBE 146 #define IDS_YES 123 #define IDS_NO 124 #define IDS_LARGE_FONT 125 @@ -49,6 +50,7 @@ #define IDS_REINSTALL 142 #define IDS_REINSTALL_CAPTION 143 #define IDC_INFO 144 +#define IDS_PRINTER_UNAVAILABLE 145 #define IDC_BUTTON1 1000 #define IDC_LIST1 1000 #define IDC_BROWSE_LIST 1000 diff --git a/Clients/PrinterSetupWizard/resource_res.h b/Clients/PrinterSetupWizard/resource_res.h index c0f5429..46cd451 100755 --- a/Clients/PrinterSetupWizard/resource_res.h +++ b/Clients/PrinterSetupWizard/resource_res.h @@ -25,7 +25,7 @@ #define IDS_INSTALL_ERROR_MESSAGE 115 #define IDS_MANUFACTURER_HEADING 116 #define IDS_MODEL_HEADING 117 -#define IDS_NO_RENDEZVOUS_PRINTERS 118 +#define IDS_NO_PRINTERS 118 #define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119 #define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120 #define IDS_PRINTER_MATCH_GOOD 121 diff --git a/Clients/dns-sd.c b/Clients/dns-sd.c index 5c6adac..699a932 100644 --- a/Clients/dns-sd.c +++ b/Clients/dns-sd.c @@ -90,7 +90,7 @@ typedef int pid_t; typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16; static int operation; -static uint32_t interface = kDNSServiceInterfaceIndexAny; +static uint32_t opinterface = kDNSServiceInterfaceIndexAny; static DNSServiceRef client = NULL; static DNSServiceRef client2 = NULL; static int num_printed; @@ -269,6 +269,8 @@ static void DNSSD_API enum_reply(DNSServiceRef client, DNSServiceFlags flags, ui GetNextLabel(label[labels-1-depth], text); printf("> %s\n", text); } + + fflush( stdout ); } static void DNSSD_API browse_reply(DNSServiceRef client, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, @@ -281,6 +283,7 @@ static void DNSSD_API browse_reply(DNSServiceRef client, DNSServiceFlags flags, if (num_printed++ == 0) printf("Timestamp A/R Flags if %-24s %-24s %s\n", "Domain", "Service Type", "Instance Name"); printtimestamp(); printf("%s%6X%3d %-24s %-24s %s\n", op, flags, ifIndex, replyDomain, replyType, replyName); + fflush( stdout ); } static void DNSSD_API resolve_reply(DNSServiceRef client, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, @@ -328,6 +331,7 @@ static void DNSSD_API resolve_reply(DNSServiceRef client, DNSServiceFlags flags, printf(" TXT %s", txtInfo); } printf("\n"); + fflush( stdout ); } static void myTimerCallBack(void) @@ -399,6 +403,7 @@ static void DNSSD_API reg_reply(DNSServiceRef client, DNSServiceFlags flags, DNS } if (operation == 'A' || operation == 'U' || operation == 'N') timeOut = 5; + fflush( stdout ); } static void DNSSD_API qr_reply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, @@ -428,6 +433,7 @@ static void DNSSD_API qr_reply(DNSServiceRef sdRef, DNSServiceFlags flags, uint3 if (num_printed++ == 0) printf("Timestamp A/R Flags if %-30s%4s%4s Rdata\n", "Name", "T", "C"); printtimestamp(); printf("%s%6X%3d %-30s%4d%4d %s\n", op, flags, ifIndex, fullname, rrtype, rrclass, rdb); + fflush( stdout ); } //************************************************************************************************************* @@ -517,6 +523,7 @@ static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordR case kDNSServiceErr_NameConflict: printf("Name in use, please choose another\n"); exit(-1); default: printf("Error %d\n", errorCode); return; } + fflush( stdout ); } static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef *sdRef, const char *host, const char *ip) @@ -533,8 +540,8 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef, { uint16_t PortAsNumber = atoi(port); Opaque16 registerPort = { { PortAsNumber >> 8, PortAsNumber & 0xFF } }; - char txt[2048] = ""; - char *ptr = txt; + unsigned char txt[2048] = ""; + unsigned char *ptr = txt; int i; if (nam[0] == '.' && nam[1] == 0) nam = ""; // We allow '.' on the command line as a synonym for empty string @@ -542,16 +549,16 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef, for (i = 0; i < argc; i++) { - char *len = ptr++; + unsigned char *len = ptr++; *len = strlen(argv[i]); - strcpy(ptr, argv[i]); + strcpy((char*)ptr, argv[i]); ptr += *len; } 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, interface, nam, typ, dom, host, registerPort.NotAnInteger, ptr-txt, txt, reg_reply, NULL)); + return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, ptr-txt, txt, reg_reply, NULL)); } int main(int argc, char **argv) @@ -573,7 +580,7 @@ int main(int argc, char **argv) { argc--; argv++; - interface = kDNSServiceInterfaceIndexLocalOnly; + opinterface = kDNSServiceInterfaceIndexLocalOnly; printf("Using LocalOnly\n"); } @@ -584,13 +591,13 @@ int main(int argc, char **argv) switch (operation) { case 'E': printf("Looking for recommended registration domains:\n"); - err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsRegistrationDomains, interface, enum_reply, NULL); + err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsRegistrationDomains, opinterface, enum_reply, NULL); break; case 'F': printf("Looking for recommended browsing domains:\n"); - err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsBrowseDomains, interface, enum_reply, NULL); + err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsBrowseDomains, opinterface, 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, "bonjour.nicta.com.au.", NULL); //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "ibm.com.", NULL); //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "dns-sd.ibm.com.", NULL); break; @@ -599,14 +606,14 @@ int main(int argc, char **argv) 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, interface, argv[optind+0], dom, browse_reply, NULL); + err = DNSServiceBrowse(&client, 0, opinterface, 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, interface, argv[optind+0], argv[optind+1], dom, resolve_reply, NULL); + err = DNSServiceResolve(&client, 0, opinterface, argv[optind+0], argv[optind+1], dom, resolve_reply, NULL); break; case 'R': if (argc < optind+4) goto Fail; @@ -626,7 +633,7 @@ int main(int argc, char **argv) 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, interface, argv[optind+0], rrtype, rrclass, qr_reply, NULL); + err = DNSServiceQueryRecord(&client, flags, opinterface, argv[optind+0], rrtype, rrclass, qr_reply, NULL); break; } @@ -636,7 +643,7 @@ int main(int argc, char **argv) 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, interface, "Test", "_testupdate._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL); + err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testupdate._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL); break; } @@ -647,7 +654,7 @@ int main(int argc, char **argv) for (i=0; i> 5); printf("Registering Service Test._testlargetxt._tcp.local.\n"); - err = DNSServiceRegister(&client, 0, interface, "Test", "_testlargetxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT), TXT, reg_reply, NULL); + err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testlargetxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT), TXT, reg_reply, NULL); break; } @@ -657,7 +664,7 @@ int main(int argc, char **argv) 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, interface, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL); + err = DNSServiceRegister(&client, 0, opinterface, "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; } @@ -667,7 +674,7 @@ int main(int argc, char **argv) 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, interface, "Test", "_testtxt._tcp.", "", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL); + err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testtxt._tcp.", "", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL); if (!err) err = DNSServiceUpdateRecord(client, NULL, 0, sizeof(TXT)-1, TXT, 0); break; } diff --git a/Makefile b/Makefile index 436297d..0497542 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ include /Developer/Makefiles/pb_makefiles/platform.make -MVERS = "mDNSResponder-98" +MVERS = "mDNSResponder-107" install: cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) diff --git a/README.txt b/README.txt index 5f17866..86b041e 100644 --- a/README.txt +++ b/README.txt @@ -1,11 +1,11 @@ What is mDNSResponder? ---------------------- -The mDNSResponder project is a component of Rendezvous, +The mDNSResponder project is a component of Bonjour, Apple's ease-of-use IP networking initiative: - + -Apple's Rendezvous software derives from the ongoing standardization +Apple's Bonjour software derives from the ongoing standardization work of the IETF Zero Configuration Networking Working Group: @@ -57,8 +57,8 @@ local significance (e.g. "yourcomputer.local."). About the mDNSResponder Code ---------------------------- -Because Apple benefits more from widespread adoption of Rendezvous than -it would benefit from keeping Rendezvous proprietary, Apple is making +Because Apple benefits more from widespread adoption of Bonjour than +it would benefit from keeping Bonjour proprietary, Apple is making this code open so that other developers can use it too. Because Apple recognises that networks are hetrogenous environments diff --git a/mDNSCore/DNSCommon.c b/mDNSCore/DNSCommon.c index 4116c1c..a2039b9 100644 --- a/mDNSCore/DNSCommon.c +++ b/mDNSCore/DNSCommon.c @@ -23,6 +23,18 @@ Change History (most recent first): $Log: DNSCommon.c,v $ +Revision 1.87 2005/02/25 04:21:00 cheshire + mDNS -F returns the same domain multiple times with different casing + +Revision 1.86 2005/02/18 00:43:12 cheshire + mDNSResponder should auto-truncate service names that are too long + +Revision 1.85 2005/02/10 22:35:17 cheshire + Update name + +Revision 1.84 2005/02/03 00:44:38 cheshire + DNSServiceUpdateRecord returns kDNSServiceErr_Invalid when rdlen=0, rdata=NULL + Revision 1.83 2005/01/27 22:57:55 cheshire Fix compile errors on gcc4 @@ -55,7 +67,7 @@ Revision 1.74 2004/12/09 22:49:15 ksekar Wide-Area Goodbyes broken Revision 1.73 2004/12/07 22:49:06 cheshire - BIND doesn't like zero-length rdata + BIND doesn't allow zero-length TXT records Revision 1.72 2004/12/06 21:15:20 ksekar mDNSResponder crashed in CheckServiceRegistrations @@ -156,7 +168,7 @@ Fix param order error moving putPrereqNameNotInUse from uDNS.c using ustrcpy macro to DNSCommon.c using mDNSPlatformStrCopy(). Revision 1.42 2004/08/10 23:19:14 ksekar -: DNS Extension daemon for Wide Area Rendezvous +: DNS Extension daemon for Wide Area Service Discovery Moved routines/constants to allow extern access for garbage collection daemon Revision 1.41 2004/08/10 01:10:01 cheshire @@ -410,6 +422,9 @@ mDNSexport char *DNSTypeName(mDNSu16 rrtype) } } +// Note slight bug: this code uses the rdlength from the ResourceRecord object, to display +// the rdata from the RDataBody object. Sometimes this could be the wrong length -- but as +// long as this routine is only used for debugging messages, it probably isn't a big problem. mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *rr, RDataBody *rd, char *buffer) { char *ptr = buffer; @@ -817,7 +832,7 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, for (i=0; i < (int)sizeof(SubTypeLabel); i++) *dst++ = SubTypeLabel[i]; type = (domainname *)s1; - // Special support for queries done by older versions of "Rendezvous Browser" + // Special support for queries done by some third-party network monitoring software // For these queries, we retract the "._sub" we just added between the subtype and the main type if (SameDomainName((domainname*)s0, (domainname*)"\x09_services\x07_dns-sd\x04_udp") || SameDomainName((domainname*)s0, (domainname*)"\x09_services\x05_mdns\x04_udp")) @@ -910,6 +925,45 @@ mDNSexport mDNSBool DeconstructServiceName(const domainname *const fqdn, return(mDNStrue); } +// Notes on UTF-8: +// 0xxxxxxx represents a 7-bit ASCII value from 0x00 to 0x7F +// 10xxxxxx is a continuation byte of a multi-byte character +// 110xxxxx is the first byte of a 2-byte character (11 effective bits; values 0x 80 - 0x 800-1) +// 1110xxxx is the first byte of a 3-byte character (16 effective bits; values 0x 800 - 0x 10000-1) +// 11110xxx is the first byte of a 4-byte character (21 effective bits; values 0x 10000 - 0x 200000-1) +// 111110xx is the first byte of a 5-byte character (26 effective bits; values 0x 200000 - 0x 4000000-1) +// 1111110x is the first byte of a 6-byte character (31 effective bits; values 0x4000000 - 0x80000000-1) +// +// UTF-16 surrogate pairs are used in UTF-16 to encode values larger than 0xFFFF. +// Although UTF-16 surrogate pairs are not supposed to appear in legal UTF-8, we want to be defensive +// about that too. (See , "What are surrogates?") +// The first of pair is a UTF-16 value in the range 0xD800-0xDBFF (11101101 1010xxxx 10xxxxxx in UTF-8), +// and the second is a UTF-16 value in the range 0xDC00-0xDFFF (11101101 1011xxxx 10xxxxxx in UTF-8). + +mDNSexport mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max) + { + if (length > max) + { + mDNSu8 c1 = string[max]; // First byte after cut point + mDNSu8 c2 = (max+1 < length) ? string[max+1] : 0xB0; // Second byte after cut point + length = max; // Trim length down + while (length > 0) + { + // Check if the byte right after the chop point is a UTF-8 continuation byte, + // or if the character right after the chop point is the second of a UTF-16 surrogate pair. + // If so, then we continue to chop more bytes until we get to a legal chop point. + mDNSBool continuation = ((c1 & 0xC0) == 0x80); + mDNSBool secondsurrogate = (c1 == 0xED && (c2 & 0xF0) == 0xB0); + if (!continuation && !secondsurrogate) break; + c2 = c1; + c1 = string[--length]; + } + // Having truncated characters off the end of our string, also cut off any residual white space + while (length > 0 && string[length-1] <= ' ') length--; + } + return(length); + } + // Returns true if a rich text label ends in " (nnn)", or if an RFC 1034 // name ends in "-nnn", where n is some decimal number. mDNSexport mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText) @@ -974,13 +1028,7 @@ mDNSexport void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichT while (val >= divisor * 10) { divisor *= 10; chars++; } - if (name->c[0] > (mDNSu8)(MAX_DOMAIN_LABEL - chars)) - { - name->c[0] = (mDNSu8)(MAX_DOMAIN_LABEL - chars); - // If the following character is a UTF-8 continuation character, - // we just chopped a multi-byte UTF-8 character in the middle, so strip back to a safe truncation point - while (name->c[0] > 0 && (name->c[name->c[0]+1] & 0xC0) == 0x80) name->c[0]--; - } + name->c[0] = TruncateUTF8ToLength(name->c+1, name->c[0], MAX_DOMAIN_LABEL - chars); if (RichText) { name->c[++name->c[0]] = ' '; name->c[++name->c[0]] = '('; } else { name->c[++name->c[0]] = '-'; } @@ -1037,10 +1085,9 @@ mDNSexport mDNSu32 RDataHashValue(mDNSu16 const rdlength, const RDataBody *const mDNSexport mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2) { - if (r1->rrtype != r2->rrtype) return(mDNSfalse); - if (r1->rdlength != r2->rdlength) return(mDNSfalse); - if (r1->rdatahash != r2->rdatahash) return(mDNSfalse); - if (r1->rdnamehash != r2->rdnamehash) return(mDNSfalse); + if (r1->rrtype != r2->rrtype) return(mDNSfalse); + if (r1->rdlength != r2->rdlength) return(mDNSfalse); + if (r1->rdatahash != r2->rdatahash) return(mDNSfalse); switch(r1->rrtype) { case kDNSType_CNAME:// Same as PTR @@ -1102,10 +1149,6 @@ mDNSexport mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate mDNSexport mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd) { mDNSu16 len; - // Some (or perhaps all) versions of BIND named (name daemon) don't allow updates - // with zero-length rdata, so for consistency we don't allow them for mDNS either. - // Otherwise we risk having applications that work with mDNS but not with uDNS. - if (!rdlength) return(mDNSfalse); switch(rrtype) { @@ -1121,12 +1164,14 @@ mDNSexport mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, case kDNSType_MR: // Same as PTR //case kDNSType_NULL not checked (no specified format, so always valid) //case kDNSType_WKS not checked - case kDNSType_PTR: len = DomainNameLength(&rd->u.name); + case kDNSType_PTR: if (!rdlength) return(mDNSfalse); + len = DomainNameLength(&rd->u.name); return(len <= MAX_DOMAIN_NAME && rdlength == len); case kDNSType_HINFO:// Same as TXT (roughly) case kDNSType_MINFO:// Same as TXT (roughly) - case kDNSType_TXT: { + case kDNSType_TXT: if (!rdlength) return(mDNSfalse); // TXT record has to be at least one byte (RFC 1035) + { const mDNSu8 *ptr = rd->u.txt.c; const mDNSu8 *end = rd->u.txt.c + rdlength; while (ptr < end) ptr += 1 + ptr[0]; @@ -1135,10 +1180,12 @@ mDNSexport mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, case kDNSType_AAAA: return(rdlength == sizeof(mDNSv6Addr)); - case kDNSType_MX: len = DomainNameLength(&rd->u.mx.exchange); + case kDNSType_MX: if (!rdlength) return(mDNSfalse); + len = DomainNameLength(&rd->u.mx.exchange); return(len <= MAX_DOMAIN_NAME && rdlength == 2+len); - case kDNSType_SRV: len = DomainNameLength(&rd->u.srv.target); + case kDNSType_SRV: if (!rdlength) return(mDNSfalse); + len = DomainNameLength(&rd->u.srv.target); return(len <= MAX_DOMAIN_NAME && rdlength == 6+len); default: return(mDNStrue); // Allow all other types without checking @@ -1628,8 +1675,7 @@ mDNSexport void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 r target = GetRRDomainNameTarget(rr); rr->rdlength = GetRDLength(rr, mDNSfalse); rr->rdestimate = GetRDLength(rr, mDNStrue); - rr->rdatahash = RDataHashValue(rr->rdlength, &rr->rdata->u); - rr->rdnamehash = target ? DomainNameHashValue(target) : 0; + rr->rdatahash = target ? DomainNameHashValue(target) : RDataHashValue(rr->rdlength, &rr->rdata->u); } mDNSexport const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end) diff --git a/mDNSCore/DNSCommon.h b/mDNSCore/DNSCommon.h index 6a6ae70..1b11e11 100644 --- a/mDNSCore/DNSCommon.h +++ b/mDNSCore/DNSCommon.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: DNSCommon.h,v $ +Revision 1.31 2005/02/18 00:43:11 cheshire + mDNSResponder should auto-truncate service names that are too long + Revision 1.30 2005/01/19 03:12:44 cheshire Move LocalRecordReady() macro from mDNS.c to DNSCommon.h @@ -74,7 +77,7 @@ Revision 1.16 2004/08/13 23:46:58 cheshire "asyncronous" -> "asynchronous" Revision 1.15 2004/08/10 23:19:14 ksekar -: DNS Extension daemon for Wide Area Rendezvous +: DNS Extension daemon for Wide Area Service Discovery Moved routines/constants to allow extern access for garbage collection daemon Revision 1.14 2004/05/28 23:42:36 ksekar @@ -213,6 +216,7 @@ extern mDNSu32 mDNSRandom(mDNSu32 max); extern mDNSu16 CompressedDomainNameLength(const domainname *const name, const domainname *parent); +extern mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max); extern mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText); extern mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText); extern void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichText); diff --git a/mDNSCore/mDNS.c b/mDNSCore/mDNS.c index f517066..d89a42b 100755 --- a/mDNSCore/mDNS.c +++ b/mDNSCore/mDNS.c @@ -45,6 +45,24 @@ Change History (most recent first): $Log: mDNS.c,v $ +Revision 1.522 2005/03/04 21:48:12 cheshire + Fractional time rounded down instead of up on platforms with coarse clock granularity + +Revision 1.521 2005/02/25 04:21:00 cheshire + mDNS -F returns the same domain multiple times with different casing + +Revision 1.520 2005/02/16 01:14:11 cheshire +Convert RR Cache LogOperation() calls to debugf() + +Revision 1.519 2005/02/15 01:57:20 cheshire +When setting "q->LastQTxTime = m->timenow", must also clear q->RecentAnswerPkts to zero + +Revision 1.518 2005/02/10 22:35:17 cheshire + Update name + +Revision 1.517 2005/02/03 00:21:21 cheshire +Update comments about BIND named and zero-length TXT records + Revision 1.516 2005/01/28 06:06:32 cheshire Update comment @@ -159,7 +177,7 @@ Revision 1.483 2004/12/07 23:00:14 ksekar Call RecordProbeFailure even if there is no record callback Revision 1.482 2004/12/07 22:49:06 cheshire - BIND doesn't like zero-length rdata + BIND doesn't allow zero-length TXT records Revision 1.481 2004/12/07 21:26:04 ksekar DNSServiceRegisterRecord() can crash on deregistration @@ -168,7 +186,7 @@ Revision 1.480 2004/12/07 20:42:33 cheshire Add explicit context parameter to mDNS_RemoveRecordFromService() Revision 1.479 2004/12/07 17:50:49 ksekar - BIND doesn't like zero-length rdata + BIND doesn't allow zero-length TXT records Revision 1.478 2004/12/06 21:15:22 ksekar mDNSResponder crashed in CheckServiceRegistrations @@ -466,7 +484,7 @@ Revision 1.390 2004/08/11 02:17:01 cheshire Registering service with port number 0 should create a "No Such Service" record Revision 1.389 2004/08/10 23:19:14 ksekar -: DNS Extension daemon for Wide Area Rendezvous +: DNS Extension daemon for Wide Area Service Discovery Moved routines/constants to allow extern access for garbage collection daemon Revision 1.388 2004/07/30 17:40:06 ksekar @@ -2531,8 +2549,9 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) 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 - // existing mDNS clients to create empty TXT records, so we silently change those to a TXT record containing a single empty string. + // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct, + // since RFC 1035 specifies a TXT record as "One or more s", not "Zero or more s". + // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here. if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; } // Don't do this until *after* we've set rr->resrec.rdlength @@ -2540,8 +2559,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) { LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); } rr->resrec.namehash = DomainNameHashValue(rr->resrec.name); - rr->resrec.rdatahash = RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u); - rr->resrec.rdnamehash = target ? DomainNameHashValue(target) : 0; + rr->resrec.rdatahash = target ? DomainNameHashValue(target) : RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u); if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly) { @@ -2571,7 +2589,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) if (r) { - debugf("Adding %p %##s (%s) to duplicate list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + debugf("Adding to duplicate list %p %s", rr, ARDisplayString(m,rr)); *d = rr; // If the previous copy of this record is already verified unique, // then indicate that we should move this record promptly to kDNSRecordTypeUnique state. @@ -2582,7 +2600,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) } else { - debugf("Adding %p %##s (%s) to active record list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + debugf("Adding to active record list %p %s", rr, ARDisplayString(m,rr)); if (!m->NewLocalRecords) m->NewLocalRecords = rr; *p = rr; } @@ -2808,7 +2826,7 @@ mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseR for (rr2=m->ResourceRecords; rr2; rr2=rr2->next) // Scan list of resource records 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 + rr->resrec.rdatahash == rr2->resrec.namehash && // ... whose name is the name of the SRV target SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name)) AddRecordToResponseList(nrpp, rr2, rr); } @@ -2999,7 +3017,7 @@ mDNSlocal void SendResponses(mDNS *const m) if (RRTypeIsAddressType(r2->resrec.rrtype) && // For all address records (A/AAAA) ... 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 + rr->resrec.rdatahash == r2->resrec.namehash && // ... whose name is the name of the SRV target 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 @@ -3401,7 +3419,7 @@ mDNSlocal void ReconfirmAntecedents(mDNS *const m, DNSQuestion *q) CacheRecord *rr; domainname *target; FORALL_CACHERECORDS(slot, cg, rr) - if ((target = GetRRDomainNameTarget(&rr->resrec)) && rr->resrec.rdnamehash == q->qnamehash && SameDomainName(target, &q->qname)) + if ((target = GetRRDomainNameTarget(&rr->resrec)) && rr->resrec.rdatahash == q->qnamehash && SameDomainName(target, &q->qname)) mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForNoAnswer); } @@ -3750,7 +3768,7 @@ mDNSlocal void SendQueries(mDNS *const m) m->omsg.h.numAuthorities, m->omsg.h.numAuthorities == 1 ? "" : "s", intf->InterfaceID); if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, &AllDNSLinkGroup_v4, MulticastDNSPort, -1, mDNSNULL); if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, &AllDNSLinkGroup_v6, MulticastDNSPort, -1, mDNSNULL); - if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + mDNSPlatformOneSecond/10); + if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10); if (++pktcount >= 1000) { LogMsg("SendQueries exceeded loop limit %d: giving up", pktcount); break; } // There might be more records left in the known answer list, or more questions to send @@ -3816,6 +3834,7 @@ mDNSlocal void AnswerQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, C { q->LastQTime = m->timenow; q->LastQTxTime = m->timenow; + q->RecentAnswerPkts = 0; q->ThisQInterval = MaxQuestionInterval; q->RequestUnicast = mDNSfalse; } @@ -4252,7 +4271,7 @@ mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const Pre m->rrcache_free = e->next; if (++m->rrcache_totalused >= m->rrcache_report) { - LogOperation("RR Cache now using %ld objects", m->rrcache_totalused); + debugf("RR Cache now using %ld objects", m->rrcache_totalused); if (m->rrcache_report < 100) m->rrcache_report += 10; else m->rrcache_report += 100; } @@ -5063,7 +5082,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con // on platforms where the native clock rate is less than fifty ticks per second, // we still guarantee that the final calculated delay is at least one platform tick. // We want to make sure we don't ever allow the delay to be zero ticks, - // because if that happens we'll fail the Rendezvous Conformance Test. + // because if that happens we'll fail the Bonjour Conformance Test. // Our final computed delay is 20-120ms for normal delayed replies, // or 400-500ms in the case of multi-packet known-answer lists. m->SuppressSending = m->timenow + (delayresponse + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*5) + 49) / 50; @@ -5283,8 +5302,8 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // else, the packet RR has different type or different rdata -- check to see if this is a conflict else if (m->rec.r.resrec.rroriginalttl > 0 && PacketRRConflict(m, rr, &m->rec.r)) { - debugf("mDNSCoreReceiveResponse: Our Record: %08lX %08lX %s", rr-> resrec.rdatahash, rr-> resrec.rdnamehash, ARDisplayString(m, rr)); - debugf("mDNSCoreReceiveResponse: Pkt Record: %08lX %08lX %s", m->rec.r.resrec.rdatahash, m->rec.r.resrec.rdnamehash, CRDisplayString(m, &m->rec.r)); + debugf("mDNSCoreReceiveResponse: Our Record: %08lX %s", rr-> resrec.rdatahash, ARDisplayString(m, rr)); + debugf("mDNSCoreReceiveResponse: Pkt Record: %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r)); // If this record is marked DependentOn another record for conflict detection purposes, // then *that* record has to be bumped back to probing state to resolve the conflict @@ -5366,13 +5385,25 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, } } - if (m->rec.r.resrec.rroriginalttl > 0) + if (!mDNSPlatformMemSame(m->rec.r.resrec.rdata->u.data, rr->resrec.rdata->u.data, m->rec.r.resrec.rdlength)) + { + // If the rdata of the packet record differs in name capitalization from the record in our cache + // then mDNSPlatformMemSame will detect this. In this case, throw the old record away, so that clients get + // a 'remove' event for the record with the old capitalization, and then an 'add' event for the new one. + rr->resrec.rroriginalttl = 0; + rr->UnansweredQueries = MaxUnansweredQueries; + SetNextCacheCheckTime(m, rr); + // DO NOT break out here -- we want to continue as if we never found it + } + else if (m->rec.r.resrec.rroriginalttl > 0) { rr->resrec.rroriginalttl = m->rec.r.resrec.rroriginalttl; rr->UnansweredQueries = 0; rr->MPUnansweredQ = 0; rr->MPUnansweredKA = 0; rr->MPExpectingKA = mDNSfalse; + SetNextCacheCheckTime(m, rr); + break; } else { @@ -5383,9 +5414,9 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // lifetime (800ms and 900ms from now) which is a pointless waste of network bandwidth. rr->resrec.rroriginalttl = 1; rr->UnansweredQueries = MaxUnansweredQueries; + SetNextCacheCheckTime(m, rr); + break; } - SetNextCacheCheckTime(m, rr); - break; } } @@ -6717,7 +6748,9 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, { mStatus status; mDNS_Lock(m); - // Some (or perhaps all) versions of BIND named (name daemon) don't allow updates with zero-length rdata. + // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct, + // since RFC 1035 specifies a TXT record as "One or more s", not "Zero or more s". + // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here. // (We have to duplicate this check here because uDNS_RegisterService() bypasses the usual mDNS_Register_internal() bottleneck) if (!sr->RR_TXT.resrec.rdlength) { sr->RR_TXT.resrec.rdlength = 1; sr->RR_TXT.resrec.rdata->u.txt.c[0] = 0; } status = uDNS_RegisterService(m, sr); @@ -6757,7 +6790,9 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, 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. + // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct, + // since RFC 1035 specifies a TXT record as "One or more s", not "Zero or more s". + // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here. // (We have to duplicate this check here because uDNS_AddRecordToService() bypasses the usual mDNS_Register_internal() bottleneck) if (extra->r.resrec.rrtype == kDNSType_TXT && extra->r.resrec.rdlength == 0) { extra->r.resrec.rdlength = 1; extra->r.resrec.rdata->u.txt.c[0] = 0; } @@ -6958,7 +6993,7 @@ mDNSlocal void mDNS_GrowCache_internal(mDNS *const m, CacheEntity *storage, mDNS if (storage && numrecords) { mDNSu32 i; - LogOperation("Adding cache storage for %d more records (%d bytes)", numrecords, numrecords*sizeof(CacheEntity)); + debugf("Adding cache storage for %d more records (%d bytes)", numrecords, numrecords*sizeof(CacheEntity)); for (i=0; irrcache_free; m->rrcache_free = storage; diff --git a/mDNSCore/mDNSEmbeddedAPI.h b/mDNSCore/mDNSEmbeddedAPI.h index 6397c1f..852322f 100755 --- a/mDNSCore/mDNSEmbeddedAPI.h +++ b/mDNSCore/mDNSEmbeddedAPI.h @@ -60,6 +60,24 @@ Change History (most recent first): $Log: mDNSEmbeddedAPI.h,v $ +Revision 1.281 2005/02/25 17:47:44 ksekar + SendServiceRegistration fails on wake from sleep + +Revision 1.280 2005/02/25 04:21:00 cheshire + mDNS -F returns the same domain multiple times with different casing + +Revision 1.279 2005/02/17 01:56:14 cheshire +Increase ifname field to 64 bytes + +Revision 1.278 2005/02/09 23:38:51 ksekar + Reregister hostname when DNS server changes but IP address does not + +Revision 1.277 2005/02/09 23:31:12 ksekar + NAT-PMP response callback should return a boolean indicating if the packet matched the request + +Revision 1.276 2005/02/01 19:33:29 ksekar + Keychain format too restrictive + Revision 1.275 2005/01/27 22:57:55 cheshire Fix compile errors on gcc4 @@ -144,10 +162,10 @@ Revision 1.249 2004/12/03 05:18:33 ksekar mDNSResponder needs to return more specific TSIG errors Revision 1.248 2004/12/02 20:03:48 ksekar - Rendezvous still publishes wide-area domains even after switching to a local subnet + Still publishes wide-area domains even after switching to a local subnet Revision 1.247 2004/12/01 20:57:19 ksekar - Wide Area Rendezvous must be split-DNS aware + Wide Area Service Discovery must be split-DNS aware Revision 1.246 2004/11/29 23:26:32 cheshire Added NonZeroTime() function, which usually returns the value given, with the exception @@ -172,7 +190,7 @@ Revision 1.241 2004/11/22 17:16:19 ksekar Unicast services don't disappear when you disable all networking Revision 1.240 2004/11/19 02:32:43 ksekar -Wide-Area Rendezvous Security: Add LLQ-ID to events +Wide-Area Security: Add LLQ-ID to events Revision 1.239 2004/11/15 20:09:23 ksekar Wide Area support for Add/Remove record @@ -360,7 +378,7 @@ Revision 1.184 2004/08/11 17:09:31 cheshire Add comment clarifying the applicability of these APIs Revision 1.183 2004/08/10 23:19:14 ksekar -: DNS Extension daemon for Wide Area Rendezvous +: DNS Extension daemon for Wide Area Service Discovery Moved routines/constants to allow extern access for garbage collection daemon Revision 1.182 2004/07/30 17:40:06 ksekar @@ -1155,8 +1173,8 @@ enum mStatus_BadTime = -65559, mStatus_BadSig = -65560, // while we define this per RFC 2845, BIND 9 returns Refused for bad/missing signatures mStatus_BadKey = -65561, - - // -65562 to -65786 currently unused; available for allocation + mStatus_TransientErr = -65562, // transient failures, e.g. sending packets shortly after a network transition or wake from sleep + // -65563 to -65786 currently unused; available for allocation // tcp connection status mStatus_ConnPending = -65787, @@ -1362,7 +1380,7 @@ typedef packedstruct #define StandardAuthRDSize 264 #define MaximumRDSize 8192 -// InlineCacheRDSize is 64 +// InlineCacheRDSize is 68 // Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object // Records received from the network with rdata larger than this have additional storage allocated for the rdata // A quick unscientific sample from a busy network at Apple with lots of machines revealed this: @@ -1374,7 +1392,7 @@ typedef packedstruct // 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 InlineCacheRDSize 68 #define InlineCacheGroupNameSize 144 @@ -1428,9 +1446,13 @@ typedef struct mDNSu32 rroriginalttl; // In seconds mDNSu16 rdlength; // Size of the raw rdata, in bytes mDNSu16 rdestimate; // Upper bound on size of rdata after name compression - mDNSu32 namehash; // Name-based (i.e. case insensitive) hash of name - 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.) + mDNSu32 namehash; // Name-based (i.e. case-insensitive) hash of name + mDNSu32 rdatahash; // For rdata containing domain name (e.g. PTR, SRV, CNAME etc.), case-insensitive name hash + // else, for all other rdata, 32-bit hash of the raw rdata + // Note: This requirement is important. Various routines like AddAdditionalsToResponseList(), + // ReconfirmAntecedents(), etc., use rdatahash as a pre-flight check to see + // whether it's worth doing a full SameDomainName() call. If the rdatahash + // is not a correct case-insensitive name hash, they'll get false negatives. RData *rdata; // Pointer to storage for this rdata } ResourceRecord; @@ -1610,6 +1632,7 @@ typedef struct DNSServer struct DNSServer *next; mDNSAddr addr; domainname domain; // name->server matching for "split dns" + int flag; // temporary marker for list intersection } DNSServer; typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo; @@ -1641,7 +1664,7 @@ struct NetworkInterfaceInfo_struct mDNSInterfaceID InterfaceID; // Identifies physical interface; MUST NOT be 0, -1, or -2 mDNSAddr ip; // The IPv4 or IPv6 address to advertise mDNSAddr mask; - char ifname[16]; + char ifname[64]; // Windows uses a GUID string for the interface name, which doesn't fit in 16 bytes mDNSBool Advertise; // False if you are only searching on this interface mDNSBool McastTxRx; // Send/Receive multicast on this { InterfaceID, address family } ? }; @@ -1938,7 +1961,7 @@ typedef packedstruct } NATPortMapReply; // Pass NULL for pkt on error (including timeout) -typedef void (*NATResponseHndlr)(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len); +typedef mDNSBool (*NATResponseHndlr)(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len); struct NATTraversalInfo_struct { @@ -2474,13 +2497,12 @@ typedef struct uDNS_AuthInfo // // mDNS_SetSecretForZone tells the core to authenticate (via TSIG with an HMAC_MD5 hash of the shared secret) // when dynamically updating a given zone (and its subdomains). The key used in authentication must be in -// domain name format. The shared secret must be a base64 encoded string with the base64 parameter set to -// true, or binary data with the base64 parameter set to false. The length is the size of the secret in -// bytes. (A minimum size of 16 bytes (128 bits) is recommended for an MD5 hash as per RFC 2485). +// domain name format. The shared secret must be a null-terminated base64 encoded string. A minimum size of +// 16 bytes (128 bits) is recommended for an MD5 hash as per RFC 2485. // 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 char *sharedSecret, mDNSu32 ssLen, mDNSBool base64); +extern mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const char *sharedSecret); // Hostname/Unicast Interface Configuration diff --git a/mDNSCore/uDNS.c b/mDNSCore/uDNS.c index c4eda13..e9d0991 100755 --- a/mDNSCore/uDNS.c +++ b/mDNSCore/uDNS.c @@ -23,6 +23,72 @@ Change History (most recent first): $Log: uDNS.c,v $ +Revision 1.203 2005/03/04 03:00:03 ksekar + Retransmissions happen too early, causing registrations to conflict with themselves + +Revision 1.202 2005/03/01 19:29:17 ksekar +changed LogMsgs to debugfs + +Revision 1.201 2005/02/26 03:04:13 cheshire + Should not indicate successful dynamic update if no network connection +Don't try to do updates to root name server. This ensures status dot turns red if user +enters a bad host name such as just "fred" instead of a properly fully-qualified name. + +Revision 1.200 2005/02/25 17:47:45 ksekar + SendServiceRegistration fails on wake from sleep + +Revision 1.199 2005/02/25 04:21:00 cheshire + mDNS -F returns the same domain multiple times with different casing + +Revision 1.198 2005/02/25 02:35:22 cheshire + Should not indicate successful dynamic update if no network connection +If we get NXDomain error looking for the _dns-update._udp record, +update status from 1 (in progress) to mStatus_NoSuchNameErr (failed) + +Revision 1.197 2005/02/24 21:56:59 ksekar +Change LogMsgs to debugfs + +Revision 1.196 2005/02/24 21:52:28 ksekar + Remove "deferred deregistration" logic for hostnames + +Revision 1.195 2005/02/22 17:53:08 ksekar +Changed successful NAT Traversals from LogMsg to LogOperation + +Revision 1.194 2005/02/15 18:38:03 ksekar + change expected/redundant log messages to debugfs. + +Revision 1.193 2005/02/15 01:17:48 ksekar +Fixed build failure. + +Revision 1.192 2005/02/14 23:01:28 ksekar +Refinement to previous checkin - don't log bad LLQ opcode if we had to send the request more than once. + +Revision 1.191 2005/02/14 18:26:51 ksekar + mDNSResponder complains about bad LLQ Opcode 2 + +Revision 1.190 2005/02/11 19:44:06 shersche +Remove extra semicolon at end of line + +Revision 1.189 2005/02/10 21:07:02 ksekar +Don't goto error in ReceiveNATAddrResponse if we receive a malformatted response + +Revision 1.188 2005/02/10 02:02:44 ksekar +Remove double semi-colon + +Revision 1.187 2005/02/09 23:28:01 ksekar + NAT-PMP response callback should return a +boolean indicating if the packet matched the request + +Revision 1.186 2005/02/04 21:56:29 ksekar + Simultaneous port map requests sometimes fail +- Refinement to previous checkin. + +Revision 1.185 2005/02/03 23:48:22 ksekar + Simultaneous port map requests sometimes fail + +Revision 1.184 2005/02/01 19:33:29 ksekar + Keychain format too restrictive + Revision 1.183 2005/01/27 22:57:55 cheshire Fix compile errors on gcc4 @@ -175,13 +241,13 @@ Revision 1.135 2004/12/03 05:18:33 ksekar mDNSResponder needs to return more specific TSIG errors Revision 1.134 2004/12/02 20:03:49 ksekar - Rendezvous still publishes wide-area domains even after switching to a local subnet + Still publishes wide-area domains even after switching to a local subnet Revision 1.133 2004/12/02 18:37:52 ksekar Registering with port number zero should not create a port mapping Revision 1.132 2004/12/01 20:57:19 ksekar - Wide Area Rendezvous must be split-DNS aware + Wide Area Service Discovery must be split-DNS aware Revision 1.131 2004/12/01 19:59:27 cheshire Crash in mDNSPlatformTCPConnect @@ -220,7 +286,7 @@ Revision 1.121 2004/11/19 04:24:08 ksekar Security: Enforce a "window" on one-shot wide-area queries Revision 1.120 2004/11/19 02:32:43 ksekar - Wide-Area Rendezvous Security: Add LLQ-ID to events + Wide-Area Security: Add LLQ-ID to events Revision 1.119 2004/11/18 23:21:24 ksekar LLQ Security: Need to verify src port/address for LLQ handshake @@ -413,7 +479,7 @@ Revision 1.63 2004/08/12 00:32:36 ksekar : LLQ Refreshes never terminate if unanswered Revision 1.62 2004/08/10 23:19:14 ksekar -: DNS Extension daemon for Wide Area Rendezvous +: DNS Extension daemon for Wide Area Service Discovery Moved routines/constants to allow extern access for garbage collection daemon Revision 1.61 2004/07/30 17:40:06 ksekar @@ -808,12 +874,12 @@ mDNSlocal void SwapRData(mDNS *m, AuthRecord *rr, mDNSBool DeallocOld) // set retry timestamp for record with exponential backoff // (for service record sets, use RR_SRV as representative for time checks -mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr) +mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mStatus SendErr) { 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; } + if (SendErr == mStatus_TransientErr || rr->ThisAPInterval < INIT_UCAST_POLL_INTERVAL) rr->ThisAPInterval = INIT_UCAST_POLL_INTERVAL; + else if (rr->ThisAPInterval*2 <= MAX_UCAST_POLL_INTERVAL) rr->ThisAPInterval *= 2; + else if (rr->ThisAPInterval != MAX_UCAST_POLL_INTERVAL) rr->ThisAPInterval = MAX_UCAST_POLL_INTERVAL; } @@ -871,14 +937,14 @@ mDNSexport void mDNS_DeleteDNSServers(mDNS *const m) #pragma mark - authorization management #endif -mDNSlocal uDNS_AuthInfo *GetAuthInfoForZone(const uDNS_GlobalInfo *u, const domainname *zone) +mDNSlocal uDNS_AuthInfo *GetAuthInfoForName(const uDNS_GlobalInfo *u, const domainname *name) { uDNS_AuthInfo *ptr; - while (zone->c[0]) + while (name->c[0]) { for (ptr = u->AuthInfoList; ptr; ptr = ptr->next) - if (SameDomainName(&ptr->zone, zone)) return(ptr); - zone = (const domainname *)(zone->c + 1 + zone->c[0]); + if (SameDomainName(&ptr->zone, name)) return(ptr); + name = (const domainname *)(name->c + 1 + name->c[0]); } return mDNSNULL; } @@ -900,7 +966,7 @@ mDNSlocal void DeleteAuthInfoForZone(uDNS_GlobalInfo *u, const domainname *zone) } } -mDNSexport mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const char *sharedSecret, mDNSu32 ssLen, mDNSBool base64) +mDNSexport mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const char *sharedSecret) { uDNS_AuthInfo *info; mDNSu8 keybuf[1024]; @@ -910,28 +976,24 @@ mDNSexport mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const mDNS_Lock(m); - if (GetAuthInfoForZone(u, zone)) DeleteAuthInfoForZone(u, zone); + if (GetAuthInfoForName(u, zone)) DeleteAuthInfoForZone(u, zone); if (!key) goto exit; - info = (uDNS_AuthInfo*)umalloc(sizeof(uDNS_AuthInfo) + ssLen); + info = (uDNS_AuthInfo*)umalloc(sizeof(*info)); if (!info) { LogMsg("ERROR: umalloc"); status = mStatus_NoMemoryErr; goto exit; } - ubzero(info, sizeof(uDNS_AuthInfo)); + ubzero(info, sizeof(*info)); AssignDomainName(&info->zone, zone); AssignDomainName(&info->keyname, key); - if (base64) + keylen = DNSDigest_Base64ToBin(sharedSecret, keybuf, 1024); + if (keylen < 0) { - 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); + LogMsg("ERROR: mDNS_SetSecretForZone - could not convert shared secret %s from base64", sharedSecret); + ufree(info); + status = mStatus_UnknownErr; + goto exit; } - else DNSDigest_ConstructHMACKey(info, (mDNSu8*)sharedSecret, ssLen); + DNSDigest_ConstructHMACKey(info, keybuf, (mDNSu32)keylen); // link into list info->next = m->uDNS_info.AuthInfoList; @@ -1027,7 +1089,7 @@ mDNSlocal void SendNATMsg(NATTraversalInfo *info, mDNS *m) 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); @@ -1042,7 +1104,7 @@ mDNSlocal void SendNATMsg(NATTraversalInfo *info, mDNS *m) info->retry = mDNSPlatformTimeNow(m) + info->RetryInterval; } -mDNSlocal void ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len) +mDNSlocal mDNSBool ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len) { mStatus err = mStatus_NoError; AuthRecord *rr = mDNSNULL; @@ -1052,16 +1114,14 @@ mDNSlocal void ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, if (n->state != NATState_Request) { LogMsg("ReceiveNATAddrResponse: bad state %d", n->state); - err = mStatus_UnknownErr; - goto end; + return mDNSfalse; } rr = n->reg.RecordRegistration; if (!rr) { LogMsg("ReceiveNATAddrResponse: registration cancelled"); - err = mStatus_UnknownErr; - goto end; + return mDNSfalse; } addr.type = mDNSAddrType_IPv4; @@ -1084,20 +1144,17 @@ mDNSlocal void ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, if (len < sizeof(*response)) { LogMsg("ReceiveNATAddrResponse: response too short (%d bytes)", len); - err = mStatus_NATTraversal; - goto end; + return mDNSfalse; } if (response->vers != NATMAP_VERS) { LogMsg("ReceiveNATAddrResponse: received version %d (expect version %d)", pkt[0], NATMAP_VERS); - err = mStatus_NATTraversal; - goto end; + return mDNSfalse; } if (response->opcode != (NATOp_AddrRequest | NATMAP_RESPONSE_MASK)) { LogMsg("ReceiveNATAddrResponse: bad response code %d", response->opcode); - err = mStatus_NATTraversal; - goto end; + return mDNSfalse; } if (response->err.NotAnInteger) { LogMsg("ReceiveAddrResponse: received error %d", mDNSVal16(response->err)); err = mStatus_NATTraversal; goto end; } @@ -1124,11 +1181,12 @@ mDNSlocal void ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, rr->RecordCallback(m, rr, mStatus_NATTraversal); // note - unsafe to touch rr after callback } - return; + return mDNStrue; } - 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 LogOperation("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); + return mDNStrue; } @@ -1197,34 +1255,19 @@ mDNSlocal void LLQNatMapComplete(mDNS *m) } } -mDNSlocal void ReceivePortMapReply(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len) +mDNSlocal mDNSBool ReceivePortMapReply(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len) { - ServiceRecordSet *srs; - mDNSIPPort priv; + ServiceRecordSet *srs = n->reg.ServiceRegistration; + mDNSIPPort priv = srs ? srs->RR_SRV.resrec.rdata->u.srv.port : m->UnicastPort4; mDNSu32 lease; - mDNSBool deletion; + mDNSBool deletion = !n->request.PortReq.lease.NotAnInteger; NATPortMapReply *reply = (NATPortMapReply *)pkt; - + mDNSu8 *service = srs ? srs->RR_SRV.resrec.name->c : (mDNSu8 *)"\016LLQ event port"; + if (n->state != NATState_Request && n->state != NATState_Refresh) - { LogMsg("ReceivePortMapReply: bad state %d", n->state); return; } - - 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 - // it to determine the public port to delete in the SRV record. - - srs = n->reg.ServiceRegistration; - if (!srs && n != m->uDNS_info.LLQNatInfo) - { - debugf("ReceivePortMapReply: registration cancelled"); - FreeNATInfo(m, n); - return; - } - - priv = srs ? srs->RR_SRV.resrec.rdata->u.srv.port : m->UnicastPort4; - - if (!pkt) // timeout + { LogMsg("ReceivePortMapReply (%##s): bad state %d", service, n->state); return mDNSfalse; } + + if (!pkt && !deletion) // timeout { #ifdef _LEGACY_NAT_TRAVERSAL_ mDNSIPPort pub; @@ -1259,38 +1302,47 @@ mDNSlocal void ReceivePortMapReply(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mD #endif // _LEGACY_NAT_TRAVERSAL_ } - 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; } + if (len < sizeof(*reply)) { LogMsg("ReceivePortMapReply: response too short (%d bytes)", len); return mDNSfalse; } + if (reply->vers != NATMAP_VERS) { LogMsg("ReceivePortMapReply: received version %d (expect version %d)", pkt[0], NATMAP_VERS); return mDNSfalse; } + if (reply->opcode != (n->op | NATMAP_RESPONSE_MASK)) { LogMsg("ReceivePortMapReply: bad response code %d", pkt[1]); return mDNSfalse; } + if (reply->err.NotAnInteger) { LogMsg("ReceivePortMapReply: received error %d", mDNSVal16(reply->err)); return mDNSfalse; } + if (priv.NotAnInteger != reply->priv.NotAnInteger) return mDNSfalse; // packet does not match this request + if (!srs && n != m->uDNS_info.LLQNatInfo) + { + LogMsg("ReceivePortMapReply: registration cancelled"); //!!!KRS change to debugf before checkin + FreeNATInfo(m, n); + return mDNStrue; + } + + if (deletion) { n->state = NATState_Deleted; return mDNStrue; } + lease = (mDNSu32)mDNSVal32(reply->lease); if (lease > 0x70000000UL / mDNSPlatformOneSecond) lease = 0x70000000UL / mDNSPlatformOneSecond; - if (n->state == NATState_Refresh && reply->pub.NotAnInteger != n->PublicPort.NotAnInteger) + 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 = reply->pub; + // this should never happen + n->PublicPort = reply->pub; n->retry = mDNSPlatformTimeNow(m) + ((mDNSs32)lease * mDNSPlatformOneSecond / 2); // retry half way to expiration - - if (n->state == NATState_Refresh) { n->state = NATState_Established; return; } + + if (n->state == NATState_Refresh) { n->state = NATState_Established; return mDNStrue; } n->state = NATState_Established; end: if (n->state != NATState_Established && n->state != NATState_Legacy) { - LogMsg("NAT Port Mapping: timeout"); + LogMsg("NAT Port Mapping (%##s): timeout", service); + if (pkt) LogMsg("!!! timeout with non-null packet"); n->state = NATState_Error; if (srs) srs->uDNS_info.state = regState_NATError; else LLQNatMapComplete(m); - return; // note - unsafe to touch srs here + return mDNStrue; // 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; } + LogOperation("Mapped private port %d to public port %d", mDNSVal16(priv), mDNSVal16(n->PublicPort)); + if (!srs) { LLQNatMapComplete(m); return mDNStrue; } 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 @@ -1298,6 +1350,7 @@ mDNSlocal void ReceivePortMapReply(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mD srs->uDNS_info.state = regState_FetchingZoneData; startGetZoneData(srs->RR_SRV.resrec.name, m, mDNStrue, mDNSfalse, serviceRegistrationCallback, srs); } + return mDNStrue; } mDNSlocal void FormatPortMaprequest(NATTraversalInfo *info, mDNSIPPort port) @@ -1645,34 +1698,17 @@ mDNSlocal void GetStaticHostname(mDNS *m) mDNSlocal void UpdateHostnameRegistrations(mDNS *m) { uDNS_GlobalInfo *u = &m->uDNS_info; - AuthRecord *new; uDNS_HostnameInfo *i; for (i = u->Hostnames; i; i = i->next) { - // only allocate new record if existing record is actually registered (i.e. it wasn't pending the hostname or IP being set) - if (i->ar->uDNS_info.state == regState_Unregistered) new = i->ar; - else - { - new = umalloc(sizeof(AuthRecord)); - if (!new) { LogMsg("ERROR: UpdateHostnameRegistration - malloc"); return; } - mDNS_SetupResourceRecord(new, mDNSNULL, 0, kDNSType_A, kWideAreaTTL, kDNSRecordTypeKnownUnique, HostnameCallback, i); - } - - // setup new record - AssignDomainName(new->resrec.name, i->ar->resrec.name); - new->resrec.rdata->u.ipv4 = u->PrimaryIP.ip.v4; + // unlink and clear uDNS state (old registrations just get overwritten) + if (i->ar->uDNS_info.state != regState_Unregistered) unlinkAR(&u->RecordRegistrations, i->ar); + ubzero(&i->ar->uDNS_info, sizeof(i->ar->uDNS_info)); - if (i->ar->uDNS_info.state != regState_Unregistered) - { - // delete old record - i->ar->RecordContext = mDNSNULL; // clear backpointer to HostnameInfo - uDNS_DeregisterRecord(m, i->ar); - i->ar = new; - } - - // advertise new - AdvertiseHostname(m, i); + // set rdata and register + i->ar->resrec.rdata->u.ipv4 = u->PrimaryIP.ip.v4; + AdvertiseHostname(m, i); } } @@ -2062,7 +2098,7 @@ mDNSlocal mStatus checkUpdateResult(domainname *displayname, mDNSu8 rcode, mDNS if (!rcode) return mStatus_NoError; else if (rcode == kDNSFlag1_RC_YXDomain) { - LogMsg("name in use: %##s", displayname->c); + debugf("name in use: %##s", displayname->c); return mStatus_NameConflict; } else if (rcode == kDNSFlag1_RC_Refused) @@ -2411,7 +2447,7 @@ mDNSlocal void SetUpdateExpiration(mDNS *m, DNSMessage *msg, const mDNSu8 *end, mDNSexport void uDNS_ReceiveNATMap(mDNS *m, mDNSu8 *pkt, mDNSu16 len) { uDNS_GlobalInfo *u = &m->uDNS_info; - NATTraversalInfo *ptr, *cur; + NATTraversalInfo *ptr = u->NATTraversals; NATOp_t op; // check length, version, opcode @@ -2420,16 +2456,12 @@ mDNSexport void uDNS_ReceiveNATMap(mDNS *m, mDNSu8 *pkt, mDNSu16 len) op = pkt[1]; if (!(op & NATMAP_RESPONSE_MASK)) { LogMsg("Received NAT Traversal message that is not a response (opcode %d)", op); return; } - ptr = u->NATTraversals; while (ptr) { - cur = ptr; + if ((ptr->state == NATState_Request || ptr->state == NATState_Refresh) && (ptr->op | NATMAP_RESPONSE_MASK) == op) + if (ptr->ReceiveResponse(ptr, m, pkt, len)) break; // note callback may invalidate ptr if it return value is non-zero ptr = ptr->next; - 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 - } + } } mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, @@ -2466,7 +2498,7 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS if (qptr->uDNS_info.id.NotAnInteger == msg->h.id.NotAnInteger) { if (timenow - (qptr->LastQTime + RESPONSE_WINDOW) > 0) - { LogMsg("uDNS_ReceiveMsg - response received after maximum allowed window. Discarding"); return; } + { debugf("uDNS_ReceiveMsg - response received after maximum allowed window. Discarding"); return; } if (msg->h.flags.b[0] & kDNSFlag0_TC) { hndlTruncatedAnswer(qptr, srcaddr, m); return; } else @@ -2668,7 +2700,7 @@ mDNSlocal void sendLLQRefresh(mDNS *m, DNSQuestion *q, mDNSu32 lease) if (!end) { LogMsg("ERROR: sendLLQRefresh - putLLQ"); return; } err = mDNSSendDNSMessage(m, &msg, end, mDNSInterface_Any, &info->servAddr, info->servPort, -1, mDNSNULL); - if (err) LogMsg("ERROR: sendLLQRefresh - mDNSSendDNSMessage returned %ld", err); + if (err) debugf("ERROR: sendLLQRefresh - mDNSSendDNSMessage returned %ld", err); if (info->state == LLQ_Established) info->ntries = 1; else info->ntries++; @@ -2687,10 +2719,10 @@ mDNSlocal mDNSBool recvLLQEvent(mDNS *m, DNSQuestion *q, DNSMessage *msg, const (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 object does not contain LLQ metadata"); return mDNSfalse; } - if (!sameID(opt.id, q->uDNS_info.llq->id)) { return mDNSfalse; } + if (!getLLQAtIndex(m, msg, end, &opt, 0)) { debugf("Pkt does not contain LLQ Opt"); 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; } + if (opt.llqOp != kLLQOp_Event) { if (!q->uDNS_info.llq->ntries) LogMsg("recvLLQEvent - Bad LLQ Opcode %d", opt.llqOp); return mDNSfalse; } // invoke response handler m->uDNS_info.CurrentQuery = q; @@ -2702,7 +2734,7 @@ mDNSlocal mDNSBool recvLLQEvent(mDNS *m, DNSQuestion *q, DNSMessage *msg, const 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); - if (err) LogMsg("ERROR: recvLLQEvent - mDNSSendDNSMessage returned %ld", err); + if (err) debugf("ERROR: recvLLQEvent - mDNSSendDNSMessage returned %ld", err); return mDNStrue; } @@ -2747,7 +2779,6 @@ mDNSlocal void sendChallengeResponse(mDNS *m, DNSQuestion *q, LLQOptData *llq) return; } - if (!llq) { llq = &llqBuf; @@ -2766,7 +2797,7 @@ mDNSlocal void sendChallengeResponse(mDNS *m, DNSQuestion *q, LLQOptData *llq) if (!responsePtr) { LogMsg("ERROR: sendChallengeResponse - putLLQ"); goto error; } err = mDNSSendDNSMessage(m, &response, responsePtr, mDNSInterface_Any, &info->servAddr, info->servPort, -1, mDNSNULL); - if (err) LogMsg("ERROR: sendChallengeResponse - mDNSSendDNSMessage returned %ld", err); + if (err) debugf("ERROR: sendChallengeResponse - mDNSSendDNSMessage returned %ld", err); // on error, we procede as normal and retry after the appropriate interval return; @@ -2810,7 +2841,7 @@ mDNSlocal void hndlRequestChallenge(mDNS *m, DNSMessage *pktMsg, const mDNSu8 *e } if (info->origLease != llq->lease) - LogMsg("hndlRequestChallenge: requested lease %lu, granted lease %lu", info->origLease, llq->lease); + debugf("hndlRequestChallenge: requested lease %lu, granted lease %lu", info->origLease, llq->lease); // cache expiration in case we go to sleep before finishing setup info->origLease = llq->lease; @@ -2912,7 +2943,7 @@ mDNSlocal void startLLQHandshake(mDNS *m, LLQ_Info *info, mDNSBool defer) if (!defer) // if we are to defer, we simply set the retry timers so the request goes out in the future { err = mDNSSendDNSMessage(m, &msg, end, mDNSInterface_Any, &info->servAddr, info->servPort, -1, mDNSNULL); - if (err) LogMsg("ERROR: startLLQHandshake - mDNSSendDNSMessage returned %ld", err); + if (err) debugf("ERROR: startLLQHandshake - mDNSSendDNSMessage returned %ld", err); // on error, we procede as normal and retry after the appropriate interval } @@ -3184,9 +3215,9 @@ mDNSlocal mStatus startQuery(mDNS *const m, DNSQuestion *const question, mDNSBoo { err = mDNSSendDNSMessage(m, &msg, endPtr, mDNSInterface_Any, &server, UnicastDNSPort, -1, mDNSNULL); if (err) { debugf("ERROR: startQuery - %ld (keeping question in list for retransmission", err); } + if (err == mStatus_TransientErr) err = mStatus_NoError; // don't return transient errors to caller } - - return mStatus_NoError; // don't return transient errors to caller + return err; } mDNSexport mStatus uDNS_StartQuery(mDNS *const m, DNSQuestion *const question) @@ -3513,7 +3544,7 @@ mDNSlocal smAction confirmNS(DNSMessage *msg, const mDNSu8 *end, ntaContext *con 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); + debugf("ERROR: could not confirm existence of record %##s NS %##s", context->zone.c, context->ns.c); return smError; } else { LogMsg("ERROR: confirmNS - bad state %d", context->state); return smError; } @@ -3687,7 +3718,7 @@ mDNSlocal void conQueryCallback(int sd, void *context, mDNSBool ConnectionEstabl if (err) { LogMsg("ERROR: conQueryCallback: constructQueryMsg - %ld", err); goto error; } err = mDNSSendDNSMessage(m, msg, end, mDNSInterface_Any, &zeroAddr, zeroIPPort, sd, mDNSNULL); question->LastQTime = mDNSPlatformTimeNow(m); - if (err) { LogMsg("ERROR: conQueryCallback: mDNSSendDNSMessage_tcp - %ld", err); goto error; } + if (err) { debugf("ERROR: conQueryCallback: mDNSSendDNSMessage_tcp - %ld", err); goto error; } } else { @@ -3801,11 +3832,11 @@ mDNSlocal void sendRecordRegistration(mDNS *const m, AuthRecord *rr) if (rr->uDNS_info.lease) { 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); + err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, ®Info->ns, regInfo->port, -1, GetAuthInfoForName(u, rr->resrec.name)); + if (err) debugf("ERROR: sendRecordRegistration - mDNSSendDNSMessage - %ld", err); + + SetRecordRetry(m, rr, err); if (regInfo->state != regState_Refresh && regInfo->state != regState_DeregDeferred) regInfo->state = regState_Pending; return; @@ -3863,6 +3894,17 @@ mDNSlocal void RecordRegistrationCallback(mStatus err, mDNS *const m, void *auth goto error; } + // Don't try to do updates to the root name server. + // We might be tempted also to block updates to any single-label name server (e.g. com, edu, net, etc.) but some + // organizations use their own private pseudo-TLD, like ".home", etc, and we don't want to block that. + if (zoneData->zoneName.c[0] == 0) + { + LogMsg("ERROR: Only name server claiming responsibility for \"%##s\" is \"%##s\"!", + newRR->resrec.name->c, zoneData->zoneName.c); + err = mStatus_NoSuchNameErr; + goto error; + } + // cache zone data AssignDomainName(&newRR->uDNS_info.zone, &zoneData->zoneName); newRR->uDNS_info.ns.type = mDNSAddrType_IPv4; @@ -3980,13 +4022,13 @@ mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs) if (srs->uDNS_info.lease) { ptr = putUpdateLease(&msg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) goto error; } - 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; } + err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rInfo->ns, rInfo->port, -1, GetAuthInfoForName(u, srs->RR_SRV.resrec.name)); + if (err) debugf("ERROR: SendServiceRegistration - mDNSSendDNSMessage - %ld", err); if (rInfo->state != regState_Refresh && rInfo->state != regState_DeregDeferred && srs->uDNS_info.state != regState_UpdatePending) rInfo->state = regState_Pending; - SetRecordRetry(m, &srs->RR_SRV); + SetRecordRetry(m, &srs->RR_SRV, err); rInfo->id.NotAnInteger = id.NotAnInteger; if (mapped) srv->resrec.rdata->u.srv.port = privport; return; @@ -4095,8 +4137,7 @@ mDNSlocal mStatus SetupRecordRegistration(mDNS *m, AuthRecord *rr) } 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; + rr->resrec.rdatahash = target ? DomainNameHashValue(target) : RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u); rr->uDNS_info.state = regState_FetchingZoneData; rr->next = m->uDNS_info.RecordRegistrations; @@ -4127,10 +4168,10 @@ mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr) if (!ptr) goto error; 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); + err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rr->uDNS_info.ns, rr->uDNS_info.port, -1, GetAuthInfoForName(u, rr->resrec.name)); + if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %ld", err); - SetRecordRetry(m, rr); + SetRecordRetry(m, rr, err); rr->uDNS_info.state = regState_DeregPending; return; @@ -4230,7 +4271,7 @@ mDNSexport mStatus uDNS_RegisterService(mDNS *const m, ServiceRecordSet *srs) if (!GetServiceTarget(&m->uDNS_info, &srs->RR_SRV, &target)) { // defer registration until we've got a target - LogMsg("uDNS_RegisterService - no target for %##s", srs->RR_SRV.resrec.name->c); + debugf("uDNS_RegisterService - no target for %##s", srs->RR_SRV.resrec.name->c); info->state = regState_NoTarget; return mStatus_NoError; } @@ -4263,10 +4304,10 @@ mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs) 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; } + err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &info->ns, info->port, -1, GetAuthInfoForName(u, srs->RR_SRV.resrec.name)); + if (err && err != mStatus_TransientErr) { debugf("ERROR: SendServiceDeregistration - mDNSSendDNSMessage - %ld", err); goto error; } - SetRecordRetry(m, &srs->RR_SRV); + SetRecordRetry(m, &srs->RR_SRV, err); info->id.NotAnInteger = id.NotAnInteger; info->state = regState_DeregPending; @@ -4380,11 +4421,10 @@ mDNSlocal void SendRecordUpdate(mDNS *m, AuthRecord *rr, uDNS_RegInfo *info) { 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)); + err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &info->ns, info->port, -1, GetAuthInfoForName(u, rr->resrec.name)); if (err) debugf("ERROR: sendRecordRegistration - mDNSSendDNSMessage - %ld", err); - //!!! Update this when we implement retransmission for services - SetRecordRetry(m, rr); + SetRecordRetry(m, rr, err); rr->uDNS_info.state = regState_UpdatePending; if (&rr->uDNS_info != info) info->state = regState_UpdatePending; // set parent SRS @@ -4591,9 +4631,9 @@ mDNSlocal mDNSs32 CheckQueries(mDNS *m, mDNSs32 timenow) else { err = mDNSSendDNSMessage(m, &msg, end, mDNSInterface_Any, &server, UnicastDNSPort, -1, mDNSNULL); - if (err) { debugf("ERROR: uDNS_idle - mDNSSendDNSMessage - %ld", err); } // surpress syslog messages if we have no network q->LastQTime = timenow; - if (q->ThisQInterval < MAX_UCAST_POLL_INTERVAL) q->ThisQInterval = q->ThisQInterval * 2; + if (err) debugf("ERROR: uDNS_idle - mDNSSendDNSMessage - %ld", err); // surpress syslog messages if we have no network + else if (q->ThisQInterval < MAX_UCAST_POLL_INTERVAL) q->ThisQInterval = q->ThisQInterval * 2; // don't increase interval if send failed } } } @@ -4806,9 +4846,8 @@ mDNSexport void mDNS_UpdateLLQs(mDNS *m) mDNS_Lock(m); if (u->LLQNatInfo) { - NATTraversalInfo *nat = u->LLQNatInfo; - u->LLQNatInfo = mDNSNULL; - DeleteNATPortMapping(m, nat, mDNSNULL); + DeleteNATPortMapping(m, u->LLQNatInfo, mDNSNULL); + FreeNATInfo(m, u->LLQNatInfo); // routine clears u->LLQNatInfo ptr } SuspendLLQs(m, mDNStrue); RestartQueries(m); @@ -4842,7 +4881,7 @@ mDNSlocal void SleepRecordRegistrations(mDNS *m) ptr = putDeletionRecord(&msg, ptr, &rr->resrec); if (!ptr) { LogMsg("Error: SleepRecordRegistrations - could not put deletion record"); return; } - mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rr->uDNS_info.ns, rr->uDNS_info.port, -1, GetAuthInfoForZone(&m->uDNS_info, &rr->uDNS_info.zone)); + mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rr->uDNS_info.ns, rr->uDNS_info.port, -1, GetAuthInfoForName(&m->uDNS_info, rr->resrec.name)); rr->uDNS_info.state = regState_Refresh; rr->LastAPTime = timenow; rr->ThisAPInterval = 300 * mDNSPlatformOneSecond; diff --git a/mDNSCore/uDNS.h b/mDNSCore/uDNS.h index 7ae7f3c..85b68d5 100755 --- a/mDNSCore/uDNS.h +++ b/mDNSCore/uDNS.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: uDNS.h,v $ +Revision 1.30 2005/03/04 03:00:03 ksekar + Retransmissions happen too early, causing registrations to conflict with themselves + Revision 1.29 2005/01/11 22:50:53 ksekar Fixed constant naming (was using kLLQ_DefLease for update leases) @@ -128,12 +131,12 @@ Revision 1.1 2003/12/13 03:05:27 ksekar extern "C" { #endif -#define RESTART_GOODBYE_DELAY (2 * mDNSPlatformOneSecond) // delay after restarting LLQ before nuking previous known answers (avoids flutter if we restart before we have networking up) -#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 RESTART_GOODBYE_DELAY (6 * mDNSPlatformOneSecond) // delay after restarting LLQ before nuking previous known answers (avoids flutter if we restart before we have networking up) +#define MIN_UCAST_PERIODIC_EXEC (5 * mDNSPlatformOneSecond) +#define INIT_UCAST_POLL_INTERVAL (3 * 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 (60 * 60 * mDNSPlatformOneSecond) -#define RESPONSE_WINDOW (60 * mDNSPlatformOneSecond) // require server responses within one minute of request +#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 diff --git a/mDNSMacOS9/mDNSLibraryResources.r b/mDNSMacOS9/mDNSLibraryResources.r index d69b739..a518d9d 100644 --- a/mDNSMacOS9/mDNSLibraryResources.r +++ b/mDNSMacOS9/mDNSLibraryResources.r @@ -23,6 +23,24 @@ Change History (most recent first): $Log: mDNSLibraryResources.r,v $ +Revision 1.31 2005/03/15 02:14:14 cheshire +mDNSResponder-107 + +Revision 1.30 2005/03/10 01:32:37 cheshire +mDNSResponder-105 + +Revision 1.29 2005/02/26 05:20:13 cheshire +mDNSResponder-102 + +Revision 1.28 2005/02/19 00:42:58 cheshire +mDNSResponder-101 + +Revision 1.27 2005/02/10 21:56:38 cheshire +mDNSResponder-100 + +Revision 1.26 2005/02/04 03:25:10 cheshire +mDNSResponder-99 + Revision 1.25 2005/01/28 00:04:16 cheshire mDNSResponder-98 @@ -116,16 +134,16 @@ like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code resource 'vers' (1, purgeable) { - 0x01, 0x00, alpha, 98, verUS, - "1.0a98", - "Multicast DNS & DNS Service Discovery 1.0a98" + 0x01, 0x00, alpha, 107, verUS, + "1.0a107", + "Multicast DNS & DNS Service Discovery 1.0a107" }; resource 'vers' (2, purgeable) { - 0x01, 0x00, alpha, 98, verUS, - "1.0a98", - "developer.apple.com/darwin/projects/rendezvous/" + 0x01, 0x00, alpha, 107, verUS, + "1.0a107", + "developer.apple.com/darwin/projects/bonjour/" }; /* We need to load OT, so make sure the system heap has enough space for it */ diff --git a/mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff b/mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff new file mode 100644 index 0000000000000000000000000000000000000000..b78b0c2a631a0fd47323d347943cf1f44180a630 GIT binary patch literal 728 zcmebEWzb?^U=nIzP;kr;V9;i5KCsXr!^KRLug&>Upu`eAU4iZ+4-->lO8?bNus^@a zQe=`_?W9xum$v^|^H+D8_cEcMQ?4cJOx}O~^Uf=u%IfD`Q2!$SrZR`KFYMEt`Yu(O$@V{e!^7dY_mg)QJ-=D0$tM+Ej|2x9puF2f~d-Ht# z?y6Y1`JT70y#Bgd#SCi-v|3oe|W$9gYj+70~17qUhm^wBhK!);f~GAJ?BmA z`3?qZuX{H4qUV2+xff$X#au7uBuXCrxF%KF&G1a7^zn&T3ZBgq;{2~LPe`U!$>WmF zMAZ|Ya;B<#8uiRnKQ(E}f@kxLPX5=KXLM()p7*6U2Mteu);VhIW9)O%`0V763(w{S zcmB7S7d+>wmEYwxA8pTle)HAd--PF<{e>x_4A173c>Z^pR}w4g7I-CB(evV$wW{7h zCTBIhFHgB@@azijTBl7{vZwk6T@@A1S}c(HH#Yp5Xm4udwW(`!Bd>OFFfi~jGB7YR zFfcGOhyw{mC|eB3W&*QWfa&D`BQsQ-6)4UIWitWUf($@;pk4+B4n|R^I8cO93?|N) z!YB@7GjTFXF#t^fsb@ODC=F*{V3dLC1V!kV1Is- zrN|_=+DWJQFKz#`=CAHF?`1+ir(8?cnY{n}=bcwRmDSI?p#DYtPbu4f?@RHoex>To z_6fhd%9Lwr*vjzb*Ro1iZ7tduy&*_5WXj&M!||J=a>aIi-F7}^Q^cBWr)#fW&D(u< z-PGvbW8drdB*Seki;D5*dz(kQ$@kw^SnuXjPhS80WmVOj`|i|c=b!wY#W8>KiBAp}dc>Yhxv=s-*OUu;ba|Wu&RFsvF66Nl zbl#}rD0o!R#N*ji!OZ_+Qw3{cCENmgGNq3dp2?MU+xVtX_JrVq@^=zt9=YNfGd0kqwQTNoRH(T|+jd^zJpP4Lj;Mvq*&;KS zXnFSYny1!&#%EqypPzi?!?O##Yne7($ezmUbWub&Yq3D)Us?A{BE71fm!_=M^}N`@ z!N9=B$iTqN0E}z~aUj76Ws3pXOkg$(0|V0xMrNouD^Q#b%4Pzx1sQmdRmmgM<37C+E`Zw_N1tJo7Hwy#CCxNgtTl*qEj*B$@yA*cV^F?OeO} z%97od`{VM4FKuoNX?*bgcZP~k{r2tezw`5VAIQwR|GRc98ucpszw14{zO(#YT=evHPtWg+%&TT#J;S4Vxuw)e$obIiqW@R+A7p6%{YQ^` z|N7s**ckg?*zlYBo__IC!EcqoHU{1%7NMRKf;MG#j|_VLtziFSrOD;~`_QvqgH3Fk z59t)iFexO=ViWJ?5abC_aFaasf9}Q|dS%BN7~6D?1=d709_^T-z_cJ?5u1oY;x0D% zlb>>?t1KvTV&zbpWW~njks+Yhc>0A%Orv*)$eM0VjTD7f4H+`G*^YWlVq)N9WME)s z07e~y0FYorVl#o+EDQ`xX^hNJaaN!jHYl43$QEP($^-Q>FmN!6LdAh1jAAfxCI&`v y7@KheqZ9+s1dw{BJVt3ayNpo=suw83sDWgD5JDWN4`>S%a{XywU{DuefYJcVmc^O? literal 0 HcmV?d00001 diff --git a/mDNSMacOSX/PreferencePane/Artwork/inprogress.tiff b/mDNSMacOSX/PreferencePane/Artwork/inprogress.tiff new file mode 100644 index 0000000000000000000000000000000000000000..340bb33527d25e9b3a15d24444953b8776be3df3 GIT binary patch literal 644 zcmebEWzb?^VBFWhpb%i8BF4+!;*=P$BgIUXzr!Ud&|(1tlO<;Z_tFbL7{jVW8e}eU ziWJ#O^g0|cj0oVECc~f*&gvli_u4|^{r9`CxV)+~n`8g1II`v#8`Crf2ImVW7!K^! zZHRw=_29vO|MOO_de7FHw>x5OsMb}ksYY|%+fO}kNRHUSu%SS)rPTCf+q&bnq1W5I zc76Nte^0F5b?Ld=?lUucEiCB}&^2;nu#$b5Q2h7ZQUUw>*@A0cX3ni!yLsoH*LU4# zo_t#PQ$j-TqHbf0$WjI7rFSMVq)l_wUJ&$qU;X+YGCG&eS8l)a=G$)B8g&ToJYd?o z0=u=RpWW$VY<~1i!LLeSD+5E+6`_764+ekv)X5u4JGplLveJ6~lVkPVN1IFT^fQI1 zvu|A!B*UbTaf(H}J8vdW=mZAFwxa0^Zr&=I(dcDZvf z#-)(x#3sEU@y}|_Q$|(n>Iwl#nraIYQlc80KC2vS^zjhc(XFYGBJsQ-L*_BdQIAPX z3=DjX3=GT+zzAdz01}KyY$h<9g@J)7hmjd7&I(k+24w>^GYT>Q<$-z`7&sV3q2fRh zMlqN;69c0-jLo=}QHlX*0!Tem38OTeUBf5?)eDqi)Ic&n2q6yC2ebtWx&AaTFsKVK GKxqJn$;+|; literal 0 HcmV?d00001 diff --git a/mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff b/mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff new file mode 100644 index 0000000000000000000000000000000000000000..70d3dd9cd744b63efb28f10148a882fcacb96339 GIT binary patch literal 698 zcmebEWzb?^VEod+px_uGz{JVibnwB287WG#-0g=J1>9%}Qx|M%?Vq^)=Qmr~{^R|d zI3<7i{GTkpRH)KtU8wF1ZvsJ5BMtk4L*|yqr+s*uqmvY6qV~@Se+a0^E zeD>OJAM18s&adEp`k%LPZ@9sZ9yN1*pM#G--Z(Q&UU^FW%Hqg5wC4}4J~rSoaB z#nQ{qw7;9DZTpp zQhM93Hf!g(S7l|kdTqORZo2jT*WCZ=)yr>R&$js;cfI}W-5;ejb^qDJPk($>`ja^P`yAIMhztMgAn3CeL!2F Pkn2wa1B1E%1C#~;v3dv> literal 0 HcmV?d00001 diff --git a/mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff b/mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff new file mode 100644 index 0000000000000000000000000000000000000000..dacc97c3e995cc829637225feae7247ec5433fe9 GIT binary patch literal 694 zcmebEWzb?^VEoX)px_uGz{JVibnwB287WG#-0g=J1>9%}Qx|M%?Vq^)=Qmr~{^R|d zI3<7i{GTkpRH)KtU8wF1ZvsJ5BMtk4L*|yqr+s*uqmvY6qV~@Se+a0^E zeD>OJAM18s&adEp`k%LPZ@9sZ9yN1*pM#G--Z(Q&UU^FW z!S`JHW|u!l>z=*2VSjhG?X=5jZ*RRb`}vpCxOS=P{*yL#;==9+?+csH>TTZm|LpTO zRkFPIo#Qv&{Z@8&@Acy1`)|w3W$mU^1m?sKj8Q4S-B(oAAxem03UI-gA;00*_|fzXmdCV%+cjNY_RKDg$w&1hYFWK z9(SQ56Kz6;T_^fPi?|8K#7Z7Bta?^)oc&Kh#qq#1<#NX-{%Mu>n8eeq;3*{2t9sJN z>RF{1`=14sUO_#}wN6divsK%B(wW^lK0yAmQIG*B57f)Rz`-aA z6$gqiiowJgOBluB?B|S93_ue=>Y0`?O2gUf7-gV(fijF5NahD2#DV&Nwm>1*p9Tg7 JbpZw_4FG|-{1X5G literal 0 HcmV?d00001 diff --git a/mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff b/mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff new file mode 100644 index 0000000000000000000000000000000000000000..de3f877911039bd5f5e95f4acbcbd6b5218514ed GIT binary patch literal 656 zcmebEWzb?^U_8~ppx_uGz{JVibnwB287WG#-0g=J1>9%}Qx|M%?Vq^)=Qmr~{^R|d zI3<7i{GTkpRH)KtU8wF1ZvsJ5BMtk4L*|yqr+s*uqmvY6qV~@Se+a0^E zeD>OJAM18s&adEp`k%LPZ@9sZ9yN1*pM#G--Z(Q&UU^FW z!S`JHW|u!l>z*yWVgHRQcG~gut+#T&y#JK;-OIavQbmlMTz}(Uwe&C6b!oTf?tFf2 z^_+X{;f2>d8$tb2Uy)YFVp!>eH01TBn8HY}Z*=%(c@{*I0R}(V1eOi>7Bj=bSY^8(g$w zuHWP}Z>`S@pZRKge)6fN1q&1y_!t=&m>GbP$sh(K7?IdaU^WW_15*VfGgO=vsD=&7 zW&*MW8G!OYy$lQ-jG|C+pa`QFOq{WVQ5?=b#3;o8Gy$ZZsew@%&hB88f$9ayFlr!~ XAA}GG>I2#WgAX)-9dussm|^J}y5{>wg3TwYb0&9Q%099eUWjcFPKgM*_4!vPh` zhWHo95)b}6Sh9Nl+v|s&w#Tl%mQ@=5*J-KG^1z3mHZVwt*)r&GaUPWZD{$6e|K+vK zSAFND>`%}yzrFX_^V02i5)v{)^d>T~wt6$LJDNuE)z1iTV*h!u%d~!8q!shEe(U-5 z(>Le;*_Nz2rLpO4z?upM1zG(DS>+wS|6DrGX@Bm_g(WxVA9dKWV+CLEpQ{Jz-!t(4 zJ@$%C;O6OsM1_Yo3_De|t6 zhQz)$53{m?0LlaPGB9v3ibBPKB8*}%aV7>vaTuHNDx(ww&;*cr orYVflaP}NV8K_>M45J2;`9TPApgy22P{{SCfq_9?fB{Ma0N0M#1poj5 literal 0 HcmV?d00001 diff --git a/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c b/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c new file mode 100644 index 0000000..b0464a8 --- /dev/null +++ b/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c @@ -0,0 +1,193 @@ +/* + File: ConfigurationAuthority.c + + Abstract: Interface to system security framework that manages access + to protected resources like system configuration preferences. + + Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under Apple's + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Change History (most recent first): + +$Log: ConfigurationAuthority.c,v $ +Revision 1.1 2005/02/05 02:28:22 cheshire +Add Preference Pane to facilitate testing of DDNS & wide-area features + +*/ + +#include "ConfigurationAuthority.h" +#include "ConfigurationRights.h" + +#include + + +static AuthorizationRef gAuthRef = 0; + +static AuthorizationItem gAuthorizations[] = { { UPDATE_SC_RIGHT, 0, NULL, 0 }, + { EDIT_SYS_KEYCHAIN_RIGHT, 0, NULL, 0 }}; +static AuthorizationRights gAuthSet = { sizeof gAuthorizations / sizeof gAuthorizations[0], gAuthorizations }; + +static CFDictionaryRef CreateRightsDict( CFStringRef prompt) +/* Create a CFDictionary decribing an auth right. See /etc/authorization for examples. */ +/* Specifies that the right requires admin authentication, which persists for 5 minutes. */ +{ + CFMutableDictionaryRef dict = NULL, tmpDict; + CFMutableArrayRef mechanisms; + CFNumberRef timeout; + int val; + + tmpDict = CFDictionaryCreateMutable( (CFAllocatorRef) NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + require( tmpDict != NULL, MakeDictFailed); + + CFDictionaryAddValue(tmpDict, CFSTR("class"), CFSTR("user")); + CFDictionaryAddValue(tmpDict, CFSTR("comment"), prompt); + CFDictionaryAddValue(tmpDict, CFSTR("group"), CFSTR("admin")); + + mechanisms = CFArrayCreateMutable((CFAllocatorRef) NULL, 1, &kCFTypeArrayCallBacks); + require( mechanisms != NULL, MakeArrayFailed); + CFArrayAppendValue( mechanisms, CFSTR("builtin:authenticate")); + CFDictionaryAddValue( tmpDict, CFSTR("mechanisms"), mechanisms); + + val = 300; // seconds + timeout = CFNumberCreate((CFAllocatorRef) NULL, kCFNumberIntType, &val); + require( timeout != NULL, MakeIntFailed); + CFDictionaryAddValue( tmpDict, CFSTR("timeout"), timeout); + CFDictionaryAddValue( tmpDict, CFSTR("shared"), kCFBooleanTrue); + + dict = tmpDict; + tmpDict = NULL; + + CFRelease( timeout); +MakeIntFailed: + CFRelease( mechanisms); +MakeArrayFailed: + if ( tmpDict) + CFRelease( tmpDict); +MakeDictFailed: + return dict; +} + +OSStatus InitConfigAuthority(void) +/* Initialize the authorization record-keeping */ +{ + OSStatus err; + CFDictionaryRef dict; + CFStringRef rightInfo; + + err = AuthorizationCreate((AuthorizationRights*) NULL, (AuthorizationEnvironment*) NULL, + (AuthorizationFlags) 0, &gAuthRef); + require_noerr( err, NewAuthFailed); + + err = AuthorizationRightGet( UPDATE_SC_RIGHT, (CFDictionaryRef*) NULL); + if( err == errAuthorizationDenied) + { + rightInfo = CFCopyLocalizedString(CFSTR("Authentication required to set Dynamic DNS preferences."), + CFSTR("Describes operation that requires user authorization")); + require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;); + dict = CreateRightsDict(rightInfo); + require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;); + + err = AuthorizationRightSet(gAuthRef, UPDATE_SC_RIGHT, dict, (CFStringRef) NULL, + (CFBundleRef) NULL, (CFStringRef) NULL); + CFRelease(rightInfo); + CFRelease(dict); + } + require_noerr( err, AuthSetFailed); + + err = AuthorizationRightGet( EDIT_SYS_KEYCHAIN_RIGHT, (CFDictionaryRef*) NULL); + if( err == errAuthorizationDenied) + { + rightInfo = CFCopyLocalizedString( CFSTR("Authentication required to edit System Keychain."), + CFSTR("Describes operation that requires user authorization")); + require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;); + dict = CreateRightsDict( rightInfo); + require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;); + + err = AuthorizationRightSet(gAuthRef, EDIT_SYS_KEYCHAIN_RIGHT, dict, (CFStringRef) NULL, + (CFBundleRef) NULL, (CFStringRef) NULL); + CFRelease( rightInfo); + CFRelease( dict); + } + require_noerr( err, AuthSetFailed); + + (void) AttemptAcquireAuthority( false); + +AuthSetFailed: +GetStrFailed: +NewAuthFailed: + return err; +} + +OSStatus AttemptAcquireAuthority( Boolean allowUI) +/* Try to get permission for privileged ops, either implicitly or by asking the user for */ +/* authority to perform operations (if necessary) */ +{ + AuthorizationFlags allowFlag = allowUI ? kAuthorizationFlagInteractionAllowed : 0; + OSStatus err; + + err = AuthorizationCopyRights( gAuthRef, &gAuthSet, (AuthorizationEnvironment*) NULL, + kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize | + allowFlag, + (AuthorizationRights**) NULL); + return err; +} + +OSStatus ReleaseAuthority(void) +/* Discard authority to perform operations */ +{ + (void) AuthorizationFree( gAuthRef, kAuthorizationFlagDestroyRights); + gAuthRef = 0; + return AuthorizationCreate( (AuthorizationRights*) NULL, (AuthorizationEnvironment*) NULL, + (AuthorizationFlags) 0, &gAuthRef); +} + +Boolean CurrentlyAuthorized(void) +{ + OSStatus err; + + err = AuthorizationCopyRights(gAuthRef, &gAuthSet, (AuthorizationEnvironment*) NULL, + (AuthorizationFlags) 0, (AuthorizationRights**) NULL); + + return err == noErr; +} + + +OSStatus ExternalizeAuthority(AuthorizationExternalForm *pAuth) +/* Package up current authorizations for transfer to another process */ +{ + return AuthorizationMakeExternalForm(gAuthRef, pAuth); +} diff --git a/mDNSMacOSX/PreferencePane/ConfigurationAuthority.h b/mDNSMacOSX/PreferencePane/ConfigurationAuthority.h new file mode 100644 index 0000000..5a1a720 --- /dev/null +++ b/mDNSMacOSX/PreferencePane/ConfigurationAuthority.h @@ -0,0 +1,59 @@ +/* + File: ConfigurationAuthority.h + + Abstract: Interface to system security framework that manages access + to protected resources like system configuration preferences. + + Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under Apple's + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Change History (most recent first): + +$Log: ConfigurationAuthority.h,v $ +Revision 1.1 2005/02/05 02:32:30 cheshire +Add Preference Pane to facilitate testing of DDNS & wide-area features + +*/ + +#include +#include + +OSStatus InitConfigAuthority(void); +Boolean CurrentlyAuthorized(void); +OSStatus AttemptAcquireAuthority(Boolean allowUI); +OSStatus ReleaseAuthority(void); +OSStatus ExternalizeAuthority(AuthorizationExternalForm *pAuth); diff --git a/mDNSMacOSX/PreferencePane/ConfigurationRights.h b/mDNSMacOSX/PreferencePane/ConfigurationRights.h new file mode 100644 index 0000000..85f441e --- /dev/null +++ b/mDNSMacOSX/PreferencePane/ConfigurationRights.h @@ -0,0 +1,55 @@ +/* + File: ConfigurationRights.h + + Abstract: Defines the rights we need, namely, (i) the right to write to + the system configuration settings for Dynamic DNS and Wide-Area DNS-SD, + and (ii) the right to write to the system keychain to store Dynamic DNS + shared secrets used to perform authorized updates to DDNS servers. + Right now these are both actually the same right: "system.preferences" + + Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under Apple's + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Change History (most recent first): +$Log: ConfigurationRights.h,v $ +Revision 1.1 2005/02/05 01:59:19 cheshire +Add Preference Pane to facilitate testing of DDNS & wide-area features + +*/ + +#define UPDATE_SC_RIGHT "system.preferences" +#define EDIT_SYS_KEYCHAIN_RIGHT "system.preferences" diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h new file mode 100644 index 0000000..21f98f5 --- /dev/null +++ b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h @@ -0,0 +1,189 @@ +/* + File: DNSServiceDiscoveryPref.h + + Abstract: System Preference Pane for Dynamic DNS and Wide-Area DNS Service Discovery + + Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under Apple's + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Change History (most recent first): +$Log: DNSServiceDiscoveryPref.h,v $ +Revision 1.5 2005/02/26 00:44:24 cheshire +Restore default reg domain if user deletes text and clicks "apply" + +Revision 1.4 2005/02/25 02:29:28 cheshire +Show yellow dot for "update in progress" + +Revision 1.3 2005/02/10 22:35:19 cheshire + Update name + +Revision 1.2 2005/02/08 01:32:05 cheshire +Add trimCharactersFromDomain routine to strip leading and trailing +white space and punctuation from user-entered fields. + +Revision 1.1 2005/02/05 01:59:19 cheshire +Add Preference Pane to facilitate testing of DDNS & wide-area features + +*/ + +#import +#import +#import +#import +#import +#import + +typedef struct MyDNSServiceState { + DNSServiceRef service; + CFRunLoopSourceRef source; + CFSocketRef socket; +} MyDNSServiceState; + + +@interface DNSServiceDiscoveryPref : NSPreferencePane +{ + IBOutlet NSTextField *hostName; + IBOutlet NSTextField *sharedSecretName; + IBOutlet NSSecureTextField *sharedSecretValue; + IBOutlet NSComboBox *browseDomainsComboBox; + IBOutlet NSComboBox *regDomainsComboBox; + IBOutlet NSButton *wideAreaCheckBox; + IBOutlet NSButton *hostNameSharedSecretButton; + IBOutlet NSButton *registrationSharedSecretButton; + IBOutlet NSButton *applyButton; + IBOutlet NSButton *revertButton; + IBOutlet NSWindow *sharedSecretWindow; + IBOutlet NSWindow *addBrowseDomainWindow; + IBOutlet NSButton *addBrowseDomainButton; + IBOutlet NSButton *removeBrowseDomainButton; + IBOutlet NSButton *browseOKButton; + IBOutlet NSButton *browseCancelButton; + IBOutlet NSButton *secretOKButton; + IBOutlet NSButton *secretCancelButton; + IBOutlet NSImageView *statusImageView; + IBOutlet NSTabView *tabView; + IBOutlet NSTableView *browseDomainList; + IBOutlet SFAuthorizationView *comboAuthButton; + + NSWindow *mainWindow; + NSString *currentHostName; + NSString *currentRegDomain; + NSArray *currentBrowseDomainsArray; + NSMutableArray *browseDomainsArray; + NSMutableArray *defaultBrowseDomainsArray; + NSString *defaultRegDomain; + + NSString *hostNameSharedSecretName; + NSString *hostNameSharedSecretValue; + NSString *regSharedSecretName; + NSString *regSharedSecretValue; + BOOL currentWideAreaState; + BOOL prefsNeedUpdating; + BOOL toolInstalled; + BOOL browseDomainListEnabled; + BOOL justStartedEditing; + NSImage *successImage; + NSImage *inprogressImage; + NSImage *failureImage; + + MyDNSServiceState regQuery; + MyDNSServiceState browseQuery; + NSMutableArray *browseDataSource; + NSMutableArray *registrationDataSource; +} + +- (IBAction)applyClicked:(id)sender; +- (IBAction)enableBrowseDomainClicked:(id)sender; +- (IBAction)addBrowseDomainClicked:(id)sender; +- (IBAction)removeBrowseDomainClicked:(id)sender; +- (IBAction)revertClicked:(id)sender; +- (IBAction)changeButtonPressed:(id)sender; +- (IBAction)closeMyCustomSheet:(id)sender; +- (IBAction)comboAction:(id)sender; +- (IBAction)wideAreaCheckBoxChanged:(id)sender; + + +- (NSMutableArray *)browseDataSource; +- (NSMutableArray *)registrationDataSource; +- (NSComboBox *)browseDomainsComboBox; +- (NSComboBox *)regDomainsComboBox; +- (NSString *)currentRegDomain; +- (NSMutableArray *)defaultBrowseDomainsArray; +- (NSArray *)currentBrowseDomainsArray; +- (NSString *)currentHostName; +- (NSString *)defaultRegDomain; +- (void)setDefaultRegDomain:(NSString *)domain; + + + +- (void)enableApplyButton; +- (void)disableApplyButton; +- (void)applyCurrentState; +- (void)setBrowseDomainsComboBox; +- (void)setupInitialValues; +- (void)startDomainBrowsing; +- (void)toggleWideAreaBonjour:(BOOL)state; +- (void)updateApplyButtonState; +- (void)enableControls; +- (void)disableControls; +- (void)validateTextFields; +- (void)readPreferences; +- (void)savePreferences; +- (void)restorePreferences; +- (void)watchForPreferenceChanges; +- (void)updateStatusImageView; + + +- (NSString *)sharedSecretKeyName:(NSString * )domain; +- (NSString *)domainForHostName:(NSString *)hostNameString; +- (int)statusForHostName:(NSString * )domain; +- (NSData *)dataForDomainArray:(NSArray *)domainArray; +- (NSData *)dataForDomain:(NSString *)domainName isEnabled:(BOOL)enabled; +- (NSData *)dataForSharedSecret:(NSString *)secret domain:(NSString *)domainName key:(NSString *)keyName; +- (BOOL)domainAlreadyInList:(NSString *)domainString; +- (NSString *)trimCharactersFromDomain:(NSString *)domain; + + +// Delegate methods +- (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view; +- (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view; +- (void)mainViewDidLoad; +- (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox; +- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)index; +- (void)controlTextDidChange:(NSNotification *) notification; + +@end diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns new file mode 100644 index 0000000000000000000000000000000000000000..028a3a2d883e2a9be53e1bdd6b96c0cc57520edb GIT binary patch literal 38889 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 Update name + +Revision 1.2 2005/02/08 01:32:05 cheshire +Add trimCharactersFromDomain routine to strip leading and trailing +white space and punctuation from user-entered fields. + +Revision 1.1 2005/02/05 01:59:19 cheshire +Add Preference Pane to facilitate testing of DDNS & wide-area features + +*/ + +#import "DNSServiceDiscoveryPref.h" +#import "ConfigurationAuthority.h" +#import "PrivilegedOperations.h" +#import + +@implementation DNSServiceDiscoveryPref + +static CFComparisonResult +MyArrayCompareFunction(id val1, id val2, void *context) +{ + return CFStringCompare((CFStringRef)val1, (CFStringRef)val2, kCFCompareCaseInsensitive); +} + + +static CFComparisonResult +MyDomainArrayCompareFunction(id val1, id val2, void *context) +{ + NSString *domain1 = [val1 objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; + NSString *domain2 = [val2 objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; + return CFStringCompare((CFStringRef)domain1, (CFStringRef)domain2, kCFCompareCaseInsensitive); +} + + +static const char * +GetNextLabel(const char *cstr, char label[64]) +{ + char *ptr = label; + while (*cstr && *cstr != '.') // While we have characters in the label... + { + char c = *cstr++; + if (c == '\\') + { + c = *cstr++; + if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1])) + { + int v0 = cstr[-1] - '0'; // then interpret as three-digit decimal + int v1 = cstr[ 0] - '0'; + int v2 = cstr[ 1] - '0'; + int val = v0 * 100 + v1 * 10 + v2; + if (val <= 255) { c = (char)val; cstr += 2; } // If valid three-digit decimal value, use it + } + } + *ptr++ = c; + if (ptr >= label+64) return(NULL); + } + if (*cstr) cstr++; // Skip over the trailing dot (if present) + *ptr++ = 0; + return(cstr); +} + + +static void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context) +{ + DNSServiceDiscoveryPref * me = (DNSServiceDiscoveryPref *)context; + assert(me != NULL); + + [me setupInitialValues]; +} + + +static void ServiceDomainEnumReply( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *replyDomain, void *context, DNSServiceFlags enumType) +{ + if (strcmp(replyDomain, "local.") == 0) return; // local domain is not interesting + + DNSServiceDiscoveryPref * me = (DNSServiceDiscoveryPref *)context; + BOOL moreComing = (BOOL)(flags & kDNSServiceFlagsMoreComing); + NSMutableArray * domainArray; + NSMutableArray * defaultBrowseDomainsArray = nil; + NSComboBox * domainComboBox; + NSString * domainString; + NSString * currentDomain = nil; + char decodedDomainString[kDNSServiceMaxDomainName] = "\0"; + char nextLabel[256] = "\0"; + char * buffer = (char *)replyDomain; + + while (*buffer) { + buffer = (char *)GetNextLabel(buffer, nextLabel); + strcat(decodedDomainString, nextLabel); + strcat(decodedDomainString, "."); + } + + // Remove trailing dot from domain name. + decodedDomainString[strlen(decodedDomainString)-1] = '\0'; + + domainString = [[[NSString alloc] initWithUTF8String:(const char *)decodedDomainString] autorelease]; + + if (enumType & kDNSServiceFlagsRegistrationDomains) { + domainArray = [me registrationDataSource]; + domainComboBox = [me regDomainsComboBox]; + currentDomain = [me currentRegDomain]; + } else { + domainArray = [me browseDataSource]; + domainComboBox = [me browseDomainsComboBox]; + defaultBrowseDomainsArray = [me defaultBrowseDomainsArray]; + } + + if (flags & kDNSServiceFlagsAdd) { + [domainArray removeObject:domainString]; // How can I check if an object is in the array? + [domainArray addObject:domainString]; + if ((flags & kDNSServiceFlagsDefault) && (enumType & kDNSServiceFlagsRegistrationDomains)) { + [me setDefaultRegDomain:domainString]; + if ([[domainComboBox stringValue] length] == 0) [domainComboBox setStringValue:domainString]; + } else if ((flags & kDNSServiceFlagsDefault) && !(enumType & kDNSServiceFlagsRegistrationDomains)) { + [defaultBrowseDomainsArray removeObject:domainString]; + [defaultBrowseDomainsArray addObject:domainString]; + } + } + + if (moreComing == NO) { + [domainArray sortUsingFunction:MyArrayCompareFunction context:nil]; + [domainComboBox reloadData]; + } +} + + +void +browseDomainReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *replyDomain, void *context) +{ + ServiceDomainEnumReply(sdRef, flags, interfaceIndex, errorCode, replyDomain, context, kDNSServiceFlagsBrowseDomains); +} + + +void +registrationDomainReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *replyDomain, void *context) +{ + ServiceDomainEnumReply(sdRef, flags, interfaceIndex, errorCode, replyDomain, context, kDNSServiceFlagsRegistrationDomains); +} + + + +static void +MyDNSServiceCleanUp(MyDNSServiceState * query) +{ + /* Remove the CFRunLoopSource from the current run loop. */ + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), query->source, kCFRunLoopCommonModes); + CFRelease(query->source); + + /* Invalidate the CFSocket. */ + CFSocketInvalidate(query->socket); + CFRelease(query->socket); + + /* Workaround that gives time to CFSocket's select thread so it can remove the socket from its FD set + before we close the socket by calling DNSServiceRefDeallocate. */ + usleep(1000); + + /* Terminate the connection with the mDNSResponder daemon, which cancels the query. */ + DNSServiceRefDeallocate(query->service); +} + + + +static void +MySocketReadCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void * data, void * info) +{ + #pragma unused(s) + #pragma unused(type) + #pragma unused(address) + #pragma unused(data) + + DNSServiceErrorType err; + + MyDNSServiceState * query = (MyDNSServiceState *)info; // context passed in to CFSocketCreateWithNative(). + assert(query != NULL); + + /* Read a reply from the mDNSResponder. */ + err= DNSServiceProcessResult(query->service); + if (err != kDNSServiceErr_NoError) { + fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); + + /* Terminate the query operation and release the CFRunLoopSource and CFSocket. */ + MyDNSServiceCleanUp(query); + } +} + + + +void +MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query) +{ + CFSocketNativeHandle sock; + CFOptionFlags sockFlags; + CFSocketContext context = { 0, query, NULL, NULL, NULL }; // Use MyDNSServiceState as context data. + + /* Access the underlying Unix domain socket to communicate with the mDNSResponder daemon. */ + sock = DNSServiceRefSockFD(query->service); + assert(sock != -1); + + /* Create a CFSocket using the Unix domain socket. */ + query->socket = CFSocketCreateWithNative(NULL, sock, kCFSocketReadCallBack, MySocketReadCallback, &context); + assert(query->socket != NULL); + + /* Prevent CFSocketInvalidate from closing DNSServiceRef's socket. */ + sockFlags = CFSocketGetSocketFlags(query->socket); + CFSocketSetSocketFlags(query->socket, sockFlags & (~kCFSocketCloseOnInvalidate)); + + /* Create a CFRunLoopSource from the CFSocket. */ + query->source = CFSocketCreateRunLoopSource(NULL, query->socket, 0); + assert(query->source != NULL); + + /* Add the CFRunLoopSource to the current run loop. */ + CFRunLoopAddSource(CFRunLoopGetCurrent(), query->source, kCFRunLoopCommonModes); +} + + + +-(void)updateStatusImageView +{ + int value = [self statusForHostName:currentHostName]; + if (value == 0) [statusImageView setImage:successImage]; + else if (value > 0) [statusImageView setImage:inprogressImage]; + else [statusImageView setImage:failureImage]; +} + + +- (void)watchForPreferenceChanges +{ + SCDynamicStoreContext context = { 0, self, NULL, NULL, NULL }; + SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("watchForPreferenceChanges"), NetworkChanged, &context); + CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFRunLoopSourceRef rls; + + assert(store != NULL); + assert(keys != NULL); + + CFArrayAppendValue(keys, SC_DYNDNS_STATE_KEY); + CFArrayAppendValue(keys, SC_DYNDNS_SETUP_KEY); + + (void)SCDynamicStoreSetNotificationKeys(store, keys, NULL); + + rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); + assert(rls != NULL); + + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopCommonModes); + + CFRelease(keys); + CFRelease(store); +} + + +-(int)statusForHostName:(NSString * )domain +{ + SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("statusForHostName"), NULL, NULL); + NSString *lowercaseDomain = [domain lowercaseString]; + int status = 1; + + assert(store != NULL); + + NSDictionary *dynamicDNS = (NSDictionary *)SCDynamicStoreCopyValue(store, SC_DYNDNS_STATE_KEY); + if (dynamicDNS) { + NSDictionary *hostNames = [dynamicDNS objectForKey:(NSString *)SC_DYNDNS_HOSTNAMES_KEY]; + NSDictionary *infoDict = [hostNames objectForKey:lowercaseDomain]; + if (infoDict) status = [[infoDict objectForKey:(NSString*)SC_DYNDNS_STATUS_KEY] intValue]; + CFRelease(dynamicDNS); + } + CFRelease(store); + + return status; +} + + +- (void)startDomainBrowsing +{ + DNSServiceFlags flags; + OSStatus err = noErr; + + flags = kDNSServiceFlagsRegistrationDomains; + err = DNSServiceEnumerateDomains(®Query.service, flags, 0, registrationDomainReply, (void *)self); + if (err == kDNSServiceErr_NoError) MyDNSServiceAddServiceToRunLoop(®Query); + + flags = kDNSServiceFlagsBrowseDomains; + err = DNSServiceEnumerateDomains(&browseQuery.service, flags, 0, browseDomainReply, (void *)self); + if (err == kDNSServiceErr_NoError) MyDNSServiceAddServiceToRunLoop(&browseQuery); +} + + +-(void)readPreferences +{ + NSDictionary *origDict; + NSArray *regDomainArray; + NSArray *hostArray; + + if (currentRegDomain) [currentRegDomain release]; + if (currentBrowseDomainsArray) [currentBrowseDomainsArray release]; + if (currentHostName) [currentHostName release]; + + SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("com.apple.preference.bonjour"), NULL, NULL); + origDict = (NSDictionary *)SCDynamicStoreCopyValue(store, SC_DYNDNS_SETUP_KEY); + + regDomainArray = [origDict objectForKey:(NSString *)SC_DYNDNS_REGDOMAINS_KEY]; + if (regDomainArray && [regDomainArray count] > 0) { + currentRegDomain = [[[regDomainArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY] copy]; + currentWideAreaState = [[[regDomainArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY] intValue]; + } else { + currentRegDomain = [[NSString alloc] initWithString:@""]; + currentWideAreaState = NO; + } + + currentBrowseDomainsArray = [[origDict objectForKey:(NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY] retain]; + + hostArray = [origDict objectForKey:(NSString *)SC_DYNDNS_HOSTNAMES_KEY]; + if (hostArray && [hostArray count] > 0) { + currentHostName = [[[hostArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY] copy]; + } else { + currentHostName = [[NSString alloc] initWithString:@""]; + } + + [origDict release]; + CFRelease(store); +} + + +- (void)tableViewSelectionDidChange:(NSNotification *)notification; +{ + [removeBrowseDomainButton setEnabled:[[notification object] numberOfSelectedRows]]; +} + + +- (void)setBrowseDomainsComboBox; +{ + NSString * domain = nil; + + if ([defaultBrowseDomainsArray count] > 0) { + NSEnumerator * arrayEnumerator = [defaultBrowseDomainsArray objectEnumerator]; + while (domain = [arrayEnumerator nextObject]) { + if ([self domainAlreadyInList:domain] == NO) break; + } + } + if (domain) [browseDomainsComboBox setStringValue:domain]; + else [browseDomainsComboBox setStringValue:@""]; +} + + +- (IBAction)addBrowseDomainClicked:(id)sender; +{ + [self setBrowseDomainsComboBox]; + + [NSApp beginSheet:addBrowseDomainWindow modalForWindow:mainWindow modalDelegate:self + didEndSelector:@selector(addBrowseDomainSheetDidEnd:returnCode:contextInfo:) contextInfo:sender]; + + [browseDomainList deselectAll:sender]; + [self updateApplyButtonState]; +} + + +- (IBAction)removeBrowseDomainClicked:(id)sender; +{ + int selectedBrowseDomain = [browseDomainList selectedRow]; + [browseDomainsArray removeObjectAtIndex:selectedBrowseDomain]; + [browseDomainList reloadData]; + [self updateApplyButtonState]; +} + + +- (IBAction)enableBrowseDomainClicked:(id)sender; +{ + NSTableView *tableView = sender; + NSMutableDictionary *browseDomainDict; + int value; + + browseDomainDict = [[browseDomainsArray objectAtIndex:[tableView clickedRow]] mutableCopy]; + value = [[browseDomainDict objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY] intValue]; + [browseDomainDict setObject:[[[NSNumber alloc] initWithInt:(!value)] autorelease] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY]; + [browseDomainsArray replaceObjectAtIndex:[tableView clickedRow] withObject:browseDomainDict]; + [tableView reloadData]; + [self updateApplyButtonState]; +} + + + +- (int)numberOfRowsInTableView:(NSTableView *)tableView; +{ + int numberOfRows = 0; + + if (browseDomainsArray) { + numberOfRows = [browseDomainsArray count]; + } + return numberOfRows; +} + + +- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem; +{ + [browseDomainList deselectAll:self]; + [mainWindow makeFirstResponder:nil]; +} + + +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row; +{ + NSDictionary *browseDomainDict; + id value = nil; + + if (browseDomainsArray) { + browseDomainDict = [browseDomainsArray objectAtIndex:row]; + if (browseDomainDict) { + if ([[tableColumn identifier] isEqualTo:(NSString *)SC_DYNDNS_ENABLED_KEY]) { + value = [browseDomainDict objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY]; + } else if ([[tableColumn identifier] isEqualTo:(NSString *)SC_DYNDNS_DOMAIN_KEY]) { + value = [browseDomainDict objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; + } + } + } + return value; +} + + +- (void)setupInitialValues +{ + [self readPreferences]; + + if (currentHostName) { + [hostName setStringValue:currentHostName]; + [self updateStatusImageView]; + } + + if (browseDomainsArray) { + [browseDomainsArray release]; + browseDomainsArray = nil; + } + + if (currentBrowseDomainsArray) { + browseDomainsArray = [currentBrowseDomainsArray mutableCopy]; + if (browseDomainsArray) { + [browseDomainsArray sortUsingFunction:MyDomainArrayCompareFunction context:nil]; + if ([browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO) { + OSStatus err = WriteBrowseDomain((CFDataRef)[self dataForDomainArray:browseDomainsArray]); + if (err != noErr) NSLog(@"WriteBrowseDomain returned %d\n", err); + [currentBrowseDomainsArray release]; + currentBrowseDomainsArray = [browseDomainsArray copy]; + } + } + } else { + browseDomainsArray = nil; + } + [browseDomainList reloadData]; + + if (currentRegDomain && ([currentRegDomain length] > 0)) { + [regDomainsComboBox setStringValue:currentRegDomain]; + [registrationDataSource removeObject:currentRegDomain]; + [registrationDataSource addObject:currentRegDomain]; + [registrationDataSource sortUsingFunction:MyArrayCompareFunction context:nil]; + [regDomainsComboBox reloadData]; + } + + if (currentWideAreaState) { + [self toggleWideAreaBonjour:YES]; + } else { + [self toggleWideAreaBonjour:NO]; + } + + if (hostNameSharedSecretValue) { + [hostNameSharedSecretValue release]; + hostNameSharedSecretValue = nil; + } + + if (regSharedSecretValue) { + [regSharedSecretValue release]; + regSharedSecretValue = nil; + } + + [self updateApplyButtonState]; + [mainWindow makeFirstResponder:nil]; + [browseDomainList deselectAll:self]; + [removeBrowseDomainButton setEnabled:NO]; +} + + + +- (void)awakeFromNib +{ + OSStatus err; + + prefsNeedUpdating = NO; + toolInstalled = NO; + browseDomainListEnabled = NO; + defaultRegDomain = nil; + currentRegDomain = nil; + currentBrowseDomainsArray = nil; + currentHostName = nil; + hostNameSharedSecretValue = nil; + regSharedSecretValue = nil; + browseDomainsArray = nil; + justStartedEditing = YES; + currentWideAreaState = NO; + NSString *successPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"success" ofType:@"tiff"]; + NSString *inprogressPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"inprogress" ofType:@"tiff"]; + NSString *failurePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"failure" ofType:@"tiff"]; + + registrationDataSource = [[NSMutableArray alloc] init]; + browseDataSource = [[NSMutableArray alloc] init]; + defaultBrowseDomainsArray = [[NSMutableArray alloc] init]; + successImage = [[NSImage alloc] initWithContentsOfFile:successPath]; + inprogressImage = [[NSImage alloc] initWithContentsOfFile:inprogressPath]; + failureImage = [[NSImage alloc] initWithContentsOfFile:failurePath]; + + [tabView selectFirstTabViewItem:self]; + [self setupInitialValues]; + [self startDomainBrowsing]; + [self watchForPreferenceChanges]; + + [tabView setDelegate:self]; + + InitConfigAuthority(); + err = EnsureToolInstalled(); + if (err == noErr) toolInstalled = YES; + else fprintf(stderr, "EnsureToolInstalled returned %ld\n", err); + +} + + +- (IBAction)closeMyCustomSheet:(id)sender +{ + BOOL result = [sender isEqualTo:browseOKButton] || [sender isEqualTo:secretOKButton]; + + if (result) [NSApp endSheet:[sender window] returnCode:NSOKButton]; + else [NSApp endSheet:[sender window] returnCode:NSCancelButton]; +} + + +- (void)sharedSecretSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + NSButton * button = (NSButton *)contextInfo; + [sheet orderOut:self]; + [self enableControls]; + + if (returnCode == NSOKButton) { + if ([button isEqualTo:hostNameSharedSecretButton]) { + hostNameSharedSecretName = [[NSString alloc] initWithString:[sharedSecretName stringValue]]; + hostNameSharedSecretValue = [[NSString alloc] initWithString:[sharedSecretValue stringValue]]; + } else { + regSharedSecretName = [[NSString alloc] initWithString:[sharedSecretName stringValue]]; + regSharedSecretValue = [[NSString alloc] initWithString:[sharedSecretValue stringValue]]; + } + [self updateApplyButtonState]; + } + [sharedSecretValue setStringValue:@""]; +} + + +- (BOOL)domainAlreadyInList:(NSString *)domainString +{ + if (browseDomainsArray) { + NSDictionary *domainDict; + NSString *domainName; + NSEnumerator *arrayEnumerator = [browseDomainsArray objectEnumerator]; + while (domainDict = [arrayEnumerator nextObject]) { + domainName = [domainDict objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; + if ([domainString caseInsensitiveCompare:domainName] == NSOrderedSame) return YES; + } + } + return NO; +} + + +- (NSString *)trimCharactersFromDomain:(NSString *)domain +{ + NSMutableCharacterSet * trimSet = [[[NSCharacterSet whitespaceCharacterSet] mutableCopy] autorelease]; + [trimSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]]; + return [domain stringByTrimmingCharactersInSet:trimSet]; +} + + +- (void)addBrowseDomainSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + [sheet orderOut:self]; + [self enableControls]; + + if (returnCode == NSOKButton) { + NSString * newBrowseDomainString = [self trimCharactersFromDomain:[browseDomainsComboBox stringValue]]; + NSMutableDictionary *newBrowseDomainDict; + + if (browseDomainsArray == nil) browseDomainsArray = [[NSMutableArray alloc] initWithCapacity:0]; + if ([self domainAlreadyInList:newBrowseDomainString] == NO) { + newBrowseDomainDict = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease]; + + [newBrowseDomainDict setObject:newBrowseDomainString forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; + [newBrowseDomainDict setObject:[[[NSNumber alloc] initWithBool:YES] autorelease] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY]; + + [browseDomainsArray addObject:newBrowseDomainDict]; + [browseDomainsArray sortUsingFunction:MyDomainArrayCompareFunction context:nil]; + [browseDomainList reloadData]; + [self updateApplyButtonState]; + } + } +} + + +-(void)validateTextFields +{ + [hostName validateEditing]; + [browseDomainsComboBox validateEditing]; + [regDomainsComboBox validateEditing]; +} + + +- (IBAction)changeButtonPressed:(id)sender +{ + NSString * keyName; + + [self disableControls]; + [self validateTextFields]; + [mainWindow makeFirstResponder:nil]; + [browseDomainList deselectAll:sender]; + + if ([sender isEqualTo:hostNameSharedSecretButton]) { + if (hostNameSharedSecretValue) { + [sharedSecretValue setStringValue:hostNameSharedSecretValue]; + } else if (keyName = [self sharedSecretKeyName:[hostName stringValue]]) { + [sharedSecretName setStringValue:keyName]; + [sharedSecretValue setStringValue:@"****************"]; + } else { + [sharedSecretName setStringValue:[hostName stringValue]]; + [sharedSecretValue setStringValue:@""]; + } + + } else { + if (regSharedSecretValue) { + [sharedSecretValue setStringValue:regSharedSecretValue]; + } else if (keyName = [self sharedSecretKeyName:[regDomainsComboBox stringValue]]) { + [sharedSecretName setStringValue:keyName]; + [sharedSecretValue setStringValue:@"****************"]; + } else { + [sharedSecretName setStringValue:[regDomainsComboBox stringValue]]; + [sharedSecretValue setStringValue:@""]; + } + } + + [sharedSecretWindow resignFirstResponder]; + + if ([[sharedSecretName stringValue] length] > 0) [sharedSecretWindow makeFirstResponder:sharedSecretValue]; + else [sharedSecretWindow makeFirstResponder:sharedSecretName]; + + [NSApp beginSheet:sharedSecretWindow modalForWindow:mainWindow modalDelegate:self + didEndSelector:@selector(sharedSecretSheetDidEnd:returnCode:contextInfo:) contextInfo:sender]; +} + + +- (IBAction)wideAreaCheckBoxChanged:(id)sender +{ + [self toggleWideAreaBonjour:[sender state]]; + [self updateApplyButtonState]; + [mainWindow makeFirstResponder:nil]; +} + + +- (void)updateApplyButtonState +{ + NSString *hostNameString = [hostName stringValue]; + NSString *regDomainString = [regDomainsComboBox stringValue]; + + NSComparisonResult hostNameResult = [hostNameString compare:currentHostName]; + NSComparisonResult regDomainResult = [regDomainString compare:currentRegDomain]; + + if ((currentHostName && (hostNameResult != NSOrderedSame)) || + (currentRegDomain && (regDomainResult != NSOrderedSame) && ([wideAreaCheckBox state])) || + (currentHostName == nil && ([hostNameString length]) > 0) || + (currentRegDomain == nil && ([regDomainString length]) > 0) || + (currentWideAreaState != [wideAreaCheckBox state]) || + (hostNameSharedSecretValue != nil) || + (regSharedSecretValue != nil) || + (browseDomainsArray && [browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO)) + { + [self enableApplyButton]; + } else { + [self disableApplyButton]; + } +} + + + +- (void)controlTextDidChange:(NSNotification *)notification; +{ + [self updateApplyButtonState]; +} + + + +- (IBAction)comboAction:(id)sender; +{ + [self updateApplyButtonState]; +} + + +- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)index +{ + NSString *domain = nil; + if ([aComboBox isEqualTo:browseDomainsComboBox]) domain = [browseDataSource objectAtIndex:index]; + else if ([aComboBox isEqualTo:regDomainsComboBox]) domain = [registrationDataSource objectAtIndex:index]; + return domain; +} + + + +- (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox +{ + int count = 0; + if ([aComboBox isEqualTo:browseDomainsComboBox]) count = [browseDataSource count]; + else if ([aComboBox isEqualTo:regDomainsComboBox]) count = [registrationDataSource count]; + return count; +} + + +- (NSMutableArray *)browseDataSource +{ + return browseDataSource; +} + + +- (NSMutableArray *)registrationDataSource +{ + return registrationDataSource; +} + + +- (NSComboBox *)browseDomainsComboBox +{ + return browseDomainsComboBox; +} + + +- (NSComboBox *)regDomainsComboBox +{ + return regDomainsComboBox; +} + + +- (NSString *)currentRegDomain +{ + return currentRegDomain; +} + + +- (NSMutableArray *)defaultBrowseDomainsArray +{ + return defaultBrowseDomainsArray; +} + + +- (NSArray *)currentBrowseDomainsArray +{ + return currentBrowseDomainsArray; +} + + +- (NSString *)currentHostName +{ + return currentHostName; +} + + +- (NSString *)defaultRegDomain +{ + return defaultRegDomain; +} + + +- (void)setDefaultRegDomain:(NSString *)domain +{ + [defaultRegDomain release]; + defaultRegDomain = domain; + [defaultRegDomain retain]; +} + + +- (void)didSelect +{ + [super didSelect]; + mainWindow = [[self mainView] window]; +} + + +- (void)mainViewDidLoad +{ + [comboAuthButton setString:"system.preferences"]; + [comboAuthButton setDelegate:self]; + [comboAuthButton updateStatus:nil]; + [comboAuthButton setAutoupdate:YES]; +} + + + +- (IBAction)applyClicked:(id)sender +{ + [self applyCurrentState]; +} + + +- (void)applyCurrentState +{ + [self validateTextFields]; + + if (toolInstalled == YES) { + [self savePreferences]; + [self disableApplyButton]; + [mainWindow makeFirstResponder:nil]; + } +} + + +- (void)enableApplyButton +{ + [applyButton setEnabled:YES]; + [revertButton setEnabled:YES]; + prefsNeedUpdating = YES; +} + + +- (void)disableApplyButton +{ + [applyButton setEnabled:NO]; + [revertButton setEnabled:NO]; + prefsNeedUpdating = NO; +} + + +- (void)toggleWideAreaBonjour:(BOOL)state +{ + [wideAreaCheckBox setState:state]; + [regDomainsComboBox setEnabled:state]; + [registrationSharedSecretButton setEnabled:state]; +} + + +- (IBAction)revertClicked:(id)sender; +{ + [self restorePreferences]; + [browseDomainList deselectAll:sender]; + [mainWindow makeFirstResponder:nil]; +} + + +- (void)restorePreferences +{ + [self setupInitialValues]; +} + + +- (void)savePanelWillClose:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + DNSServiceDiscoveryPref * me = (DNSServiceDiscoveryPref *)contextInfo; + + if (returnCode == NSAlertDefaultReturn) { + [me applyCurrentState]; + } else if (returnCode == NSAlertAlternateReturn ) { + [me restorePreferences]; + } + + [me enableControls]; + [me replyToShouldUnselect:(returnCode != NSAlertOtherReturn)]; +} + + +-(SecKeychainItemRef)copyKeychainItemforDomain:(NSString *)domain +{ + const char * serviceName = [domain UTF8String]; + UInt32 type = 'ddns'; + UInt32 typeLength = sizeof(type); + + SecKeychainAttribute attrs[] = { { kSecServiceItemAttr, strlen(serviceName), (char *)serviceName }, + { kSecTypeItemAttr, typeLength, (UInt32 *)&type } }; + + SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; + SecKeychainSearchRef searchRef; + SecKeychainItemRef itemRef = NULL; + OSStatus err; + + err = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributes, &searchRef); + if (err == noErr) { + err = SecKeychainSearchCopyNext(searchRef, &itemRef); + if (err != noErr) itemRef = NULL; + } + return itemRef; +} + + +-(NSString *)sharedSecretKeyName:(NSString * )domain +{ + SecKeychainItemRef itemRef = NULL; + NSString *keyName = nil; + OSStatus err; + + err = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); + assert(err == noErr); + + itemRef = [self copyKeychainItemforDomain:[domain lowercaseString]]; + if (itemRef) { + UInt32 tags[1]; + SecKeychainAttributeInfo attrInfo; + SecKeychainAttributeList *attrList = NULL; + SecKeychainAttribute attribute; + int i; + + tags[0] = kSecAccountItemAttr; + attrInfo.count = 1; + attrInfo.tag = tags; + attrInfo.format = NULL; + + err = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, &attrList, NULL, NULL); + if (err == noErr) { + for (i = 0; i < attrList->count; i++) { + attribute = attrList->attr[i]; + if (attribute.tag == kSecAccountItemAttr) { + keyName = [[NSString alloc] initWithBytes:attribute.data length:attribute.length encoding:NSUTF8StringEncoding]; + break; + } + } + if (attrList) (void)SecKeychainItemFreeAttributesAndData(attrList, NULL); + } + CFRelease(itemRef); + } + return keyName; +} + + +-(NSString *)domainForHostName:(NSString *)hostNameString +{ + NSString * domainName = nil; + char text[64]; + char * ptr = NULL; + + ptr = (char *)[hostNameString UTF8String]; + if (ptr) { + ptr = (char *)GetNextLabel(ptr, text); + domainName = [[NSString alloc] initWithUTF8String:(const char *)ptr]; + } + return ([domainName autorelease]); +} + + +- (NSData *)dataForDomain:(NSString *)domainName isEnabled:(BOOL)enabled +{ + NSMutableArray *domainsArray; + NSMutableDictionary *domainDict = nil; + + if (domainName && [domainName length] > 0) { + domainDict= [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease]; + [domainDict setObject:domainName forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; + [domainDict setObject:[[[NSNumber alloc] initWithBool:enabled] autorelease] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY]; + } + domainsArray = [[[NSMutableArray alloc] initWithCapacity:1] autorelease]; + if (domainDict) [domainsArray addObject:domainDict]; + return [NSArchiver archivedDataWithRootObject:domainsArray]; +} + + +- (NSData *)dataForDomainArray:(NSArray *)domainArray +{ + return [NSArchiver archivedDataWithRootObject:domainArray]; +} + + +- (NSData *)dataForSharedSecret:(NSString *)secret domain:(NSString *)domainName key:(NSString *)keyName +{ + NSMutableDictionary *sharedSecretDict = [[[NSMutableDictionary alloc] initWithCapacity:3] autorelease]; + [sharedSecretDict setObject:secret forKey:(NSString *)SC_DYNDNS_SECRET_KEY]; + [sharedSecretDict setObject:[domainName lowercaseString] forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; + [sharedSecretDict setObject:keyName forKey:(NSString *)SC_DYNDNS_KEYNAME_KEY]; + return [NSArchiver archivedDataWithRootObject:sharedSecretDict]; +} + + +-(void)savePreferences +{ + NSString *hostNameString = [hostName stringValue]; + NSString *browseDomainString = [browseDomainsComboBox stringValue]; + NSString *regDomainString = [regDomainsComboBox stringValue]; + NSString *tempHostNameSharedSecretName = hostNameSharedSecretName; + NSString *tempRegSharedSecretName = regSharedSecretName; + NSData *browseDomainData = nil; + BOOL regSecretWasSet = NO; + BOOL hostSecretWasSet = NO; + OSStatus err = noErr; + + hostNameString = [self trimCharactersFromDomain:hostNameString]; + browseDomainString = [self trimCharactersFromDomain:browseDomainString]; + regDomainString = [self trimCharactersFromDomain:regDomainString]; + tempHostNameSharedSecretName = [self trimCharactersFromDomain:tempHostNameSharedSecretName]; + tempRegSharedSecretName = [self trimCharactersFromDomain:tempRegSharedSecretName]; + + [hostName setStringValue:hostNameString]; + [regDomainsComboBox setStringValue:regDomainString]; + + // Convert Shared Secret account names to lowercase. + tempHostNameSharedSecretName = [tempHostNameSharedSecretName lowercaseString]; + tempRegSharedSecretName = [tempRegSharedSecretName lowercaseString]; + + // Save hostname shared secret. + if ([hostNameSharedSecretName length] > 0 && ([hostNameSharedSecretValue length] > 0)) { + SetKeyForDomain((CFDataRef)[self dataForSharedSecret:hostNameSharedSecretValue domain:hostNameString key:tempHostNameSharedSecretName]); + [hostNameSharedSecretValue release]; + hostNameSharedSecretValue = nil; + hostSecretWasSet = YES; + } + + // Save registration domain shared secret. + if (([regSharedSecretName length] > 0) && ([regSharedSecretValue length] > 0)) { + SetKeyForDomain((CFDataRef)[self dataForSharedSecret:regSharedSecretValue domain:regDomainString key:tempRegSharedSecretName]); + [regSharedSecretValue release]; + regSharedSecretValue = nil; + regSecretWasSet = YES; + } + + // Save hostname. + if ((currentHostName == NULL) || [currentHostName compare:hostNameString] != NSOrderedSame) { + err = WriteHostname((CFDataRef)[self dataForDomain:hostNameString isEnabled:YES]); + if (err != noErr) NSLog(@"WriteHostname returned %d\n", err); + currentHostName = [hostNameString copy]; + } else if (hostSecretWasSet) { + WriteHostname((CFDataRef)[self dataForDomain:@"" isEnabled:NO]); + usleep(200000); // Temporary hack + if ([currentHostName length] > 0) WriteHostname((CFDataRef)[self dataForDomain:(NSString *)currentHostName isEnabled:YES]); + } + + // Save browse domain. + if (browseDomainsArray && [browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO) { + browseDomainData = [self dataForDomainArray:browseDomainsArray]; + err = WriteBrowseDomain((CFDataRef)browseDomainData); + if (err != noErr) NSLog(@"WriteBrowseDomain returned %d\n", err); + currentBrowseDomainsArray = [browseDomainsArray copy]; + } + + // Save registration domain. + if ((currentRegDomain == NULL) || ([currentRegDomain compare:regDomainString] != NSOrderedSame) || (currentWideAreaState != [wideAreaCheckBox state])) { + + err = WriteRegistrationDomain((CFDataRef)[self dataForDomain:regDomainString isEnabled:[wideAreaCheckBox state]]); + if (err != noErr) NSLog(@"WriteRegistrationDomain returned %d\n", err); + + if (currentRegDomain) CFRelease(currentRegDomain); + currentRegDomain = [regDomainString copy]; + + if ([currentRegDomain length] > 0) { + currentWideAreaState = [wideAreaCheckBox state]; + [registrationDataSource removeObject:regDomainString]; + [registrationDataSource addObject:currentRegDomain]; + [registrationDataSource sortUsingFunction:MyArrayCompareFunction context:nil]; + [regDomainsComboBox reloadData]; + } else { + currentWideAreaState = NO; + [self toggleWideAreaBonjour:NO]; + if (defaultRegDomain != nil) [regDomainsComboBox setStringValue:defaultRegDomain]; + } + } else if (regSecretWasSet) { + WriteRegistrationDomain((CFDataRef)[self dataForDomain:@"" isEnabled:NO]); + usleep(200000); // Temporary hack + if ([currentRegDomain length] > 0) WriteRegistrationDomain((CFDataRef)[self dataForDomain:currentRegDomain isEnabled:currentWideAreaState]); + } +} + + +- (NSPreferencePaneUnselectReply)shouldUnselect +{ +#if 1 + if (prefsNeedUpdating == YES) { + + [self disableControls]; + + NSBeginAlertSheet( + @"Apply Configuration Changes?", + @"Apply", + @"Don't Apply", + @"Cancel", + mainWindow, + self, + @selector( savePanelWillClose:returnCode:contextInfo: ), + NULL, + (void *) self, // sender, + @"" ); + return NSUnselectLater; + } +#endif + + return NSUnselectNow; +} + + +-(void)disableControls +{ + [hostName setEnabled:NO]; + [hostNameSharedSecretButton setEnabled:NO]; + [browseDomainsComboBox setEnabled:NO]; + [applyButton setEnabled:NO]; + [revertButton setEnabled:NO]; + [wideAreaCheckBox setEnabled:NO]; + [regDomainsComboBox setEnabled:NO]; + [registrationSharedSecretButton setEnabled:NO]; + [statusImageView setEnabled:NO]; + + browseDomainListEnabled = NO; + [browseDomainList deselectAll:self]; + [browseDomainList setEnabled:NO]; + + [addBrowseDomainButton setEnabled:NO]; + [removeBrowseDomainButton setEnabled:NO]; +} + + +- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row; +{ + return browseDomainListEnabled; +} + + +-(void)enableControls +{ + [hostName setEnabled:YES]; + [hostNameSharedSecretButton setEnabled:YES]; + [browseDomainsComboBox setEnabled:YES]; + [wideAreaCheckBox setEnabled:YES]; + [registrationSharedSecretButton setEnabled:YES]; + [self toggleWideAreaBonjour:[wideAreaCheckBox state]]; + [statusImageView setEnabled:YES]; + [addBrowseDomainButton setEnabled:YES]; + + [browseDomainList setEnabled:YES]; + [browseDomainList deselectAll:self]; + browseDomainListEnabled = YES; + + [removeBrowseDomainButton setEnabled:[browseDomainList numberOfSelectedRows]]; + [applyButton setEnabled:prefsNeedUpdating]; + [revertButton setEnabled:prefsNeedUpdating]; +} + + +- (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view +{ + [self enableControls]; +} + + +- (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view +{ + [self disableControls]; +} + + +@end \ No newline at end of file diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff new file mode 100644 index 0000000000000000000000000000000000000000..985ae197b065eec4b20bd10cd963749f05e48bb0 GIT binary patch literal 17394 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 literal 0 HcmV?d00001 diff --git a/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib new file mode 100644 index 0000000..58c1f3e --- /dev/null +++ b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib @@ -0,0 +1,59 @@ +{ + IBClasses = ( + { + ACTIONS = { + addBrowseDomainClicked = id; + applyClicked = id; + changeButtonPressed = id; + closeMyCustomSheet = id; + comboAction = id; + enableBrowseDomainClicked = id; + removeBrowseDomainClicked = id; + revertClicked = id; + wideAreaCheckBoxChanged = id; + }; + CLASS = DNSServiceDiscoveryPref; + LANGUAGE = ObjC; + OUTLETS = { + addBrowseDomainButton = NSButton; + addBrowseDomainWindow = NSWindow; + applyButton = NSButton; + browseCancelButton = NSButton; + browseDomainList = NSTableView; + browseDomainsComboBox = NSComboBox; + browseOKButton = NSButton; + comboAuthButton = SFAuthorizationView; + hostName = NSTextField; + hostNameSharedSecretButton = NSButton; + regDomainsComboBox = NSComboBox; + registrationSharedSecretButton = NSButton; + removeBrowseDomainButton = NSButton; + revertButton = NSButton; + secretCancelButton = NSButton; + secretOKButton = NSButton; + sharedSecretName = NSTextField; + sharedSecretValue = NSSecureTextField; + sharedSecretWindow = NSWindow; + statusImageView = NSImageView; + tabView = NSTabView; + wideAreaCheckBox = NSButton; + }; + SUPERCLASS = NSPreferencePane; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + CLASS = NSPreferencePane; + LANGUAGE = ObjC; + OUTLETS = { + "_firstKeyView" = id; + "_initialKeyView" = id; + "_lastKeyView" = id; + "_window" = id; + }; + SUPERCLASS = NSObject; + }, + {CLASS = NSSegmentedControl; LANGUAGE = ObjC; SUPERCLASS = NSControl; }, + {CLASS = SFAuthorizationView; LANGUAGE = ObjC; SUPERCLASS = NSView; } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib new file mode 100644 index 0000000..3759d87 --- /dev/null +++ b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib @@ -0,0 +1,18 @@ + + + + + IBDocumentLocation + 32 63 547 281 0 0 1024 746 + IBFramework Version + 364.0 + IBOpenObjects + + 12 + 255 + 333 + + IBSystem Version + 7U13 + + diff --git a/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..d024da1bdedbb92d7a5eb555d2a430fbb2e6b9c9 GIT binary patch literal 17441 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 Xa4FOjl!tGg<_SaA%+$rK%HL{Uq8nKl literal 0 HcmV?d00001 diff --git a/mDNSMacOSX/PreferencePane/PrivilegedOperations.c b/mDNSMacOSX/PreferencePane/PrivilegedOperations.c new file mode 100644 index 0000000..242d426 --- /dev/null +++ b/mDNSMacOSX/PreferencePane/PrivilegedOperations.c @@ -0,0 +1,227 @@ +/* + File: PrivilegedOperations.c + + Abstract: Interface to "ddnswriteconfig" setuid root tool. + + Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under Apple's + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Change History (most recent first): +$Log: PrivilegedOperations.c,v $ +Revision 1.2 2005/02/10 22:35:20 cheshire + Update name + +Revision 1.1 2005/02/05 01:59:19 cheshire +Add Preference Pane to facilitate testing of DDNS & wide-area features + +*/ + +#include "PrivilegedOperations.h" +#include "ConfigurationAuthority.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Boolean gToolApproved = false; + +pid_t execTool(const char *args[]) +// fork/exec and return new pid +{ + pid_t child; + + child = vfork(); + if (child == 0) + { + execv(args[0], (char *const *)args); +printf("exec of %s failed; errno = %d\n", args[0], errno); + _exit(-1); // exec failed + } + else + return child; +} + +OSStatus EnsureToolInstalled(void) +// Make sure that the tool is installed in the right place, with the right privs, and the right version. +{ + CFURLRef bundleURL; + pid_t toolPID; + int status; + OSStatus err = noErr; + const char *args[] = { kToolPath, "0", "V", NULL }; + char toolPath[PATH_MAX] = {}; + + if (gToolApproved) + return noErr; + + // Check version of installed tool + toolPID = execTool(args); + if (toolPID > 0) + { + waitpid(toolPID, &status, 0); + if (WIFEXITED(status) && WEXITSTATUS(status) == PRIV_OP_TOOL_VERS) + return noErr; + } + + // Locate our in-bundle copy of privop tool + bundleURL = CFBundleCopyBundleURL(CFBundleGetBundleWithIdentifier(CFSTR("com.apple.preference.bonjour")) ); + if (bundleURL != NULL) + { + CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolPath, sizeof toolPath); + strcat(toolPath, "/Contents/Resources/" kToolName); + } + else + return coreFoundationUnknownErr; + + // Obtain authorization and run in-bundle copy as root to install it + { + AuthorizationItem aewpRight = { kAuthorizationRightExecute, strlen(toolPath), toolPath, 0 }; + AuthorizationItemSet rights = { 1, &aewpRight }; + AuthorizationRef authRef; + + err = AuthorizationCreate(&rights, (AuthorizationEnvironment*) NULL, + kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights | + kAuthorizationFlagPreAuthorize, &authRef); + if (err == noErr) + { + args[2] = "I"; + err = AuthorizationExecuteWithPrivileges(authRef, toolPath, 0, (char * const *)&args[1], (FILE**) NULL); + if (err == noErr) + gToolApproved = true; + (void) AuthorizationFree(authRef, kAuthorizationFlagDestroyRights); + } + } + + return err; +} + + +static OSStatus ExecWithCmdAndParam(const char *subCmd, CFDataRef paramData) +// Execute our privop tool with the supplied subCmd and parameter +{ + OSStatus err = noErr; + int commFD, dataLen; + u_int32_t len; + pid_t child; + char fileNum[16]; + UInt8 *buff; + const char *args[] = { kToolPath, NULL, "A", NULL, NULL }; + AuthorizationExternalForm authExt; + + err = ExternalizeAuthority(&authExt); + require_noerr(err, AuthFailed); + + dataLen = CFDataGetLength(paramData); + buff = (UInt8*) malloc(dataLen * sizeof(UInt8)); + require_action(buff != NULL, AllocBuffFailed, err=memFullErr;); + { + CFRange all = { 0, dataLen }; + CFDataGetBytes(paramData, all, buff); + } + + commFD = fileno(tmpfile()); + sprintf(fileNum, "%d", commFD); + args[1] = fileNum; + args[3] = subCmd; + + // write authority to pipe + len = 0; // tag, unused + write(commFD, &len, sizeof len); + len = sizeof authExt; // len + write(commFD, &len, sizeof len); + write(commFD, &authExt, len); + + // write parameter to pipe + len = 0; // tag, unused + write(commFD, &len, sizeof len); + len = dataLen; // len + write(commFD, &len, sizeof len); + write(commFD, buff, len); + + child = execTool(args); + if (child > 0) { + int status; + waitpid(child, &status, 0); + if (WIFEXITED(status)) + err = WEXITSTATUS(status); + //fprintf(stderr, "child exited; status = %d (%ld)\n", status, err); + } + + close(commFD); + + free(buff); +AllocBuffFailed: +AuthFailed: + return err; +} + +OSStatus +WriteBrowseDomain(CFDataRef domainArrayData) +{ + if (!CurrentlyAuthorized()) + return authFailErr; + return ExecWithCmdAndParam("Wb", domainArrayData); +} + +OSStatus +WriteRegistrationDomain(CFDataRef domainArrayData) +{ + if (!CurrentlyAuthorized()) + return authFailErr; + return ExecWithCmdAndParam("Wd", domainArrayData); +} + +OSStatus +WriteHostname(CFDataRef domainArrayData) +{ + if (!CurrentlyAuthorized()) + return authFailErr; + return ExecWithCmdAndParam("Wh", domainArrayData); +} + +OSStatus +SetKeyForDomain(CFDataRef secretData) +{ + if (!CurrentlyAuthorized()) + return authFailErr; + return ExecWithCmdAndParam("Wk", secretData); +} diff --git a/mDNSMacOSX/PreferencePane/PrivilegedOperations.h b/mDNSMacOSX/PreferencePane/PrivilegedOperations.h new file mode 100644 index 0000000..706be05 --- /dev/null +++ b/mDNSMacOSX/PreferencePane/PrivilegedOperations.h @@ -0,0 +1,84 @@ +/* + File: PrivilegedOperations.h + + Abstract: Interface to "ddnswriteconfig" setuid root tool. + + Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under Apple's + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Change History (most recent first): +$Log: PrivilegedOperations.h,v $ +Revision 1.3 2005/02/16 00:17:35 cheshire +Don't create empty arrays -- CFArrayGetValueAtIndex(array,0) returns an essentially random (non-null) +result for empty arrays, which can lead to code crashing if it's not sufficiently defensive. + +Revision 1.2 2005/02/10 22:35:20 cheshire + Update name + +Revision 1.1 2005/02/05 01:59:19 cheshire +Add Preference Pane to facilitate testing of DDNS & wide-area features + +*/ + +#include +#include + +#define PRIV_OP_TOOL_VERS 2 + +#define kToolHome "/Library/Application Support/" +#define kToolDir "Bonjour" +#define kToolName "ddnswriteconfig" +#define kToolPath kToolHome kToolDir "/" kToolName + +#define SC_DYNDNS_SETUP_KEY CFSTR("Setup:/Network/DynamicDNS") +#define SC_DYNDNS_STATE_KEY CFSTR("State:/Network/DynamicDNS") +#define SC_DYNDNS_REGDOMAINS_KEY CFSTR("RegistrationDomains") +#define SC_DYNDNS_BROWSEDOMAINS_KEY CFSTR("BrowseDomains") +#define SC_DYNDNS_HOSTNAMES_KEY CFSTR("HostNames") +#define SC_DYNDNS_DOMAIN_KEY CFSTR("Domain") +#define SC_DYNDNS_KEYNAME_KEY CFSTR("KeyName") +#define SC_DYNDNS_SECRET_KEY CFSTR("Secret") +#define SC_DYNDNS_ENABLED_KEY CFSTR("Enabled") +#define SC_DYNDNS_STATUS_KEY CFSTR("Status") +#define DYNDNS_KEYCHAIN_DESCRIPTION "Dynamic DNS Key" + + +OSStatus EnsureToolInstalled(void); +OSStatus WriteRegistrationDomain(CFDataRef domainArrayData); +OSStatus WriteBrowseDomain(CFDataRef domainArrayData); +OSStatus WriteHostname(CFDataRef domainArrayData); +OSStatus SetKeyForDomain(CFDataRef secretData); diff --git a/mDNSMacOSX/PreferencePane/ddnswriteconfig.m b/mDNSMacOSX/PreferencePane/ddnswriteconfig.m new file mode 100644 index 0000000..f9383c6 --- /dev/null +++ b/mDNSMacOSX/PreferencePane/ddnswriteconfig.m @@ -0,0 +1,494 @@ +/* + File: ddnswriteconfig.m + + Abstract: Setuid root tool invoked by Preference Pane to perform + privileged accesses to system configuration preferences and the system keychain. + Invoked by PrivilegedOperations.c. + + Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under Apple's + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Change History (most recent first): +$Log: ddnswriteconfig.m,v $ +Revision 1.3 2005/02/16 00:17:35 cheshire +Don't create empty arrays -- CFArrayGetValueAtIndex(array,0) returns an essentially random (non-null) +result for empty arrays, which can lead to code crashing if it's not sufficiently defensive. + +Revision 1.2 2005/02/10 22:35:20 cheshire + Update name + +Revision 1.1 2005/02/05 01:59:19 cheshire +Add Preference Pane to facilitate testing of DDNS & wide-area features + +*/ + + +#import "PrivilegedOperations.h" +#import "ConfigurationRights.h" + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + + +static AuthorizationRef gAuthRef = 0; + +int +CopySUIDTool(const char *srcPath, const char *dstPath) +// Copy a tool from srcPath to dstPath and set its 'x' and SUID bits. Return 0 on success. +{ + int srcFD, dstFD, err = 0; + off_t len, written; + void *pSrc; + + srcFD = open( srcPath, O_RDONLY, (mode_t) 0); + require_action( srcFD > 0, OpenSrcFailed, err=errno;); + + len = lseek( srcFD, 0, SEEK_END); + require_action( len > 0, GetSrcLenFailed, err=errno;); + pSrc = mmap( NULL, len, PROT_READ, MAP_FILE, srcFD, 0); + require_action( pSrc != (void*)-1, MMapFailed, err=errno;); + + dstFD = open( dstPath, O_RDWR | O_CREAT | O_TRUNC, (mode_t) 0); + require_action( dstFD > 0, OpenDstFailed, err=errno;); + + written = write( dstFD, pSrc, len); + require_action( written == len, WriteFailed, err=errno;); + + err = fchmod( dstFD, S_IRUSR | S_IXUSR | S_ISUID | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + +WriteFailed: + close( dstFD); +OpenDstFailed: + munmap( pSrc, len); +MMapFailed: +GetSrcLenFailed: + close( srcFD); +OpenSrcFailed: + return err; +} + + +int +InstallRootTool( const char *srcPath) +{ + if (geteuid() != 0) + return -1; // failure; not running as root + + (void) mkdir(kToolHome kToolDir, S_IRUSR | S_IXUSR | S_IWUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + + return CopySUIDTool( srcPath, kToolPath); +} + + +OSStatus +WriteArrayToDynDNS(CFStringRef arrayKey, CFArrayRef domainArray) +{ + SCPreferencesRef store; + OSStatus err = noErr; + CFDictionaryRef origDict; + CFMutableDictionaryRef dict = NULL; + Boolean result; + CFStringRef scKey = CFSTR("/System/Network/DynamicDNS"); + + + // Add domain to the array member ("arrayKey") of the DynamicDNS dictionary + // Will replace duplicate, at head of list + // At this point, we only support a single-item list + store = SCPreferencesCreate(NULL, CFSTR("com.apple.preference.bonjour"), NULL); + require_action(store != NULL, SysConfigErr, err=paramErr;); + require_action(true == SCPreferencesLock( store, true), LockFailed, err=coreFoundationUnknownErr;); + + origDict = SCPreferencesPathGetValue(store, scKey); + if (origDict) { + dict = CFDictionaryCreateMutableCopy(NULL, 0, origDict); + } + + if (!dict) { + dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + require_action( dict != NULL, NoDict, err=memFullErr;); + + if (CFArrayGetCount(domainArray) > 0) { + CFDictionarySetValue(dict, arrayKey, domainArray); + } else { + CFDictionaryRemoveValue(dict, arrayKey); + } + + result = SCPreferencesPathSetValue(store, scKey, dict); + require_action(result, SCError, err=kernelPrivilegeErr;); + + result = SCPreferencesCommitChanges(store); + require_action(result, SCError, err=kernelPrivilegeErr;); + result = SCPreferencesApplyChanges(store); + require_action(result, SCError, err=kernelPrivilegeErr;); + +SCError: + CFRelease(dict); +NoDict: + SCPreferencesUnlock(store); +LockFailed: + CFRelease(store); +SysConfigErr: + return err; +} + + +static int +readTaggedBlock(int fd, u_int32_t *pTag, u_int32_t *pLen, char **ppBuff) +// Read tag, block len and block data from stream and return. Dealloc *ppBuff via free(). +{ + ssize_t num; + u_int32_t tag, len; + int result = 0; + + num = read(fd, &tag, sizeof tag); + require_action(num == sizeof tag, GetTagFailed, result = -1;); + num = read(fd, &len, sizeof len); + require_action(num == sizeof len, GetLenFailed, result = -1;); + + *ppBuff = (char*) malloc( len); + require_action(*ppBuff != NULL, AllocFailed, result = -1;); + + num = read(fd, *ppBuff, len); + if (num == len) { + *pTag = tag; + *pLen = len; + } else { + free(*ppBuff); + result = -1; + } + +AllocFailed: +GetLenFailed: +GetTagFailed: + return result; +} + + + +int +SetAuthInfo( int fd) +{ + int result = 0; + u_int32_t tag, len; + char *p; + + result = readTaggedBlock( fd, &tag, &len, &p); + require( result == 0, ReadParamsFailed); + + if (gAuthRef != 0) { + (void) AuthorizationFree(gAuthRef, kAuthorizationFlagDestroyRights); + gAuthRef = 0; + } + + result = AuthorizationCreateFromExternalForm((AuthorizationExternalForm*) p, &gAuthRef); + + free( p); +ReadParamsFailed: + return result; +} + + +int +HandleWriteDomain(int fd, int domainType) +{ + CFArrayRef domainArray; + CFDataRef domainData; + int result = 0; + u_int32_t tag, len; + char *p; + + AuthorizationItem scAuth = { UPDATE_SC_RIGHT, 0, NULL, 0 }; + AuthorizationRights authSet = { 1, &scAuth }; + + if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags)0, NULL))) + return result; + + result = readTaggedBlock(fd, &tag, &len, &p); + require(result == 0, ReadParamsFailed); + + domainData = CFDataCreate(NULL, (UInt8 *)p, len); + domainArray = (CFArrayRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)domainData]; + + if (domainType) { + result = WriteArrayToDynDNS(SC_DYNDNS_REGDOMAINS_KEY, domainArray); + } else { + result = WriteArrayToDynDNS(SC_DYNDNS_BROWSEDOMAINS_KEY, domainArray); + } + +ReadParamsFailed: + return result; +} + + +int +HandleWriteHostname(int fd) +{ + CFArrayRef domainArray; + CFDataRef domainData; + int result = 0; + u_int32_t tag, len; + char *p; + + AuthorizationItem scAuth = { UPDATE_SC_RIGHT, 0, NULL, 0 }; + AuthorizationRights authSet = { 1, &scAuth }; + + if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags) 0, NULL))) + return result; + + result = readTaggedBlock(fd, &tag, &len, &p); + require(result == 0, ReadParamsFailed); + + domainData = CFDataCreate(NULL, (const UInt8 *)p, len); + domainArray = (CFArrayRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)domainData]; + result = WriteArrayToDynDNS(SC_DYNDNS_HOSTNAMES_KEY, domainArray); + +ReadParamsFailed: + return result; +} + + +SecAccessRef +MyMakeUidAccess(uid_t uid) +{ + // make the "uid/gid" ACL subject + // this is a CSSM_LIST_ELEMENT chain + CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = { + CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version + CSSM_ACL_MATCH_UID, // set mask: match uids (only) + uid, // uid to match + 0 // gid (not matched here) + }; + CSSM_LIST_ELEMENT subject2 = { NULL, 0 }; + subject2.Element.Word.Data = (UInt8 *)&selector; + subject2.Element.Word.Length = sizeof(selector); + CSSM_LIST_ELEMENT subject1 = { &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID }; + + + // rights granted (replace with individual list if desired) + CSSM_ACL_AUTHORIZATION_TAG rights[] = { + CSSM_ACL_AUTHORIZATION_ANY // everything + }; + // owner component (right to change ACL) + CSSM_ACL_OWNER_PROTOTYPE owner = { + // TypedSubject + { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, + // Delegate + false + }; + // ACL entries (any number, just one here) + CSSM_ACL_ENTRY_INFO acls[] = { + { + // prototype + { + // TypedSubject + { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, + false, // Delegate + // rights for this entry + { sizeof(rights) / sizeof(rights[0]), rights }, + // rest is defaulted + } + } + }; + + SecAccessRef access = NULL; + (void) SecAccessCreateFromOwnerAndACL(&owner, sizeof(acls) / sizeof(acls[0]), acls, &access); + return access; +} + + +OSStatus +MyAddDynamicDNSPassword(SecKeychainRef keychain, SecAccessRef access, UInt32 serviceNameLength, const char *serviceName, + UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData) +{ + char * description = DYNDNS_KEYCHAIN_DESCRIPTION; + UInt32 descriptionLength = strlen(DYNDNS_KEYCHAIN_DESCRIPTION); + UInt32 type = 'ddns'; + UInt32 creator = 'ddns'; + UInt32 typeLength = sizeof(type); + UInt32 creatorLength = sizeof(creator); + OSStatus err; + + // set up attribute vector (each attribute consists of {tag, length, pointer}) + SecKeychainAttribute attrs[] = { { kSecLabelItemAttr, serviceNameLength, (char *)serviceName }, + { kSecAccountItemAttr, accountNameLength, (char *)accountName }, + { kSecServiceItemAttr, serviceNameLength, (char *)serviceName }, + { kSecDescriptionItemAttr, descriptionLength, (char *)description }, + { kSecTypeItemAttr, typeLength, (UInt32 *)&type }, + { kSecCreatorItemAttr, creatorLength, (UInt32 *)&creator } }; + SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; + + err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, passwordLength, passwordData, keychain, access, NULL); + return err; +} + + +int +SetKeychainEntry(int fd) +// Create a new entry in system keychain, or replace existing +{ + CFDataRef secretData; + CFDictionaryRef secretDictionary; + CFStringRef keyNameString; + CFStringRef domainString; + CFStringRef secretString; + SecKeychainItemRef item = NULL; + int result = 0; + u_int32_t tag, len; + char *p; + char keyname[1005]; + char domain[1005]; + char secret[1005]; + + AuthorizationItem kcAuth = { EDIT_SYS_KEYCHAIN_RIGHT, 0, NULL, 0 }; + AuthorizationRights authSet = { 1, &kcAuth }; + + if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags)0, NULL))) + return result; + + result = readTaggedBlock(fd, &tag, &len, &p); + require_noerr(result, ReadParamsFailed); + + secretData = CFDataCreate(NULL, (UInt8 *)p, len); + secretDictionary = (CFDictionaryRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)secretData]; + + keyNameString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_KEYNAME_KEY); + assert(keyNameString != NULL); + + domainString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_DOMAIN_KEY); + assert(domainString != NULL); + + secretString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_SECRET_KEY); + assert(secretString != NULL); + + CFStringGetCString(keyNameString, keyname, 1005, kCFStringEncodingUTF8); + CFStringGetCString(domainString, domain, 1005, kCFStringEncodingUTF8); + CFStringGetCString(secretString, secret, 1005, kCFStringEncodingUTF8); + + result = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); + if (result == noErr) { + result = SecKeychainFindGenericPassword(NULL, strlen(domain), domain, 0, NULL, 0, NULL, &item); + if (result == noErr) { + result = SecKeychainItemDelete(item); + if (result != noErr) fprintf(stderr, "SecKeychainItemDelete returned %d\n", result); + } + + result = MyAddDynamicDNSPassword(NULL, MyMakeUidAccess(0), strlen(domain), domain, strlen(keyname)+1, keyname, strlen(secret)+1, secret); + if (result != noErr) fprintf(stderr, "MyAddDynamicDNSPassword returned %d\n", result); + if (item) CFRelease(item); + } + +ReadParamsFailed: + return result; +} + + +int main( int argc, char **argv) +/* argv[0] is the exec path; argv[1] is a fd for input data; argv[2]... are operation codes. + The tool supports the following operations: + V -- exit with status PRIV_OP_TOOL_VERS + I -- install self as suid-root tool into system (must be run as root) + A -- read AuthInfo from input pipe + Wd -- write registration domain to dynamic store + Wb -- write browse domain to dynamic store + Wh -- write hostname to dynamic store + Wk -- write keychain entry for given account name +*/ +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + int commFD = -1, iArg, savedUID, result = 0; + + if ( argc == 3 && 0 == strcmp( argv[2], "I")) { + return InstallRootTool( argv[0]); + } + + savedUID = geteuid(); +#if 1 + if ( 0 != seteuid( 0)) + return -1; +#else + sleep( 10); +#endif + + if ( argc == 3 && 0 == strcmp( argv[2], "V")) + return PRIV_OP_TOOL_VERS; + + if ( argc >= 1) + { + commFD = strtol( argv[1], NULL, 0); + lseek( commFD, 0, SEEK_SET); + } + for ( iArg = 2; iArg < argc && result == 0; iArg++) + { + if ( 0 == strcmp( "A", argv[ iArg])) // get auth info + { + result = SetAuthInfo( commFD); + } + else if ( 0 == strcmp( "Wd", argv[ iArg])) // Write registration domain + { + result = HandleWriteDomain( commFD, 1); + } + else if ( 0 == strcmp( "Wb", argv[ iArg])) // Write browse domain + { + result = HandleWriteDomain( commFD, 0); + } + else if ( 0 == strcmp( "Wh", argv[ iArg])) // Write hostname + { + result = HandleWriteHostname( commFD); + } + else if ( 0 == strcmp( "Wk", argv[ iArg])) // Write keychain entry + { + result = SetKeychainEntry( commFD); + } + } + [pool release]; + return result; +} diff --git a/mDNSMacOSX/daemon.c b/mDNSMacOSX/daemon.c index d977a4a..97ef560 100644 --- a/mDNSMacOSX/daemon.c +++ b/mDNSMacOSX/daemon.c @@ -36,6 +36,43 @@ Change History (most recent first): $Log: daemon.c,v $ +Revision 1.255 2005/03/09 00:48:43 cheshire + QU packets getting sent too early on wake from sleep +Move "m->p->NetworkChanged = 0;" line from caller to callee + +Revision 1.254 2005/03/03 04:34:19 cheshire + Bonjour name conflict dialog appears during MacBuddy + +Revision 1.253 2005/03/03 03:55:09 cheshire + Name collision notifications should be localized + +Revision 1.252 2005/02/23 02:29:17 cheshire + "Local Hostname is already in use..." dialogue shows for only 60 seconds before being removed +Minor refinements, better variable names, improved comments + +Revision 1.251 2005/02/21 21:31:24 ksekar + changed LogMsg to debugf + +Revision 1.250 2005/02/19 01:25:04 cheshire + "Local Hostname is already in use..." dialogue shows for only 60 seconds before being removed +Further refinements + +Revision 1.249 2005/02/19 00:28:45 cheshire + "Local Hostname is already in use..." dialogue shows for only 60 seconds before being removed + +Revision 1.248 2005/02/19 00:18:34 cheshire +Confusing variable name -- alertMessage should be called alertHeader + +Revision 1.247 2005/02/15 02:13:49 cheshire +If we did registerBootstrapService() when starting, then we must do +destroyBootstrapService() before exiting, or Mach init will keep restarting us. + +Revision 1.246 2005/02/03 00:44:37 cheshire + DNSServiceUpdateRecord returns kDNSServiceErr_Invalid when rdlen=0, rdata=NULL + +Revision 1.245 2005/02/01 19:56:47 ksekar +Moved LogMsg from daemon.c to uds_daemon.c, cleaned up wording + Revision 1.244 2005/01/28 00:34:49 cheshire Turn off "Starting time value" log message @@ -609,6 +646,8 @@ static mach_port_t server_priv_port = MACH_PORT_NULL; static int restarting_via_mach_init = 0; static int started_via_launchdaemon = 0; +static int OSXVers; + //************************************************************************************************************* // Active client list structures @@ -707,7 +746,7 @@ static DNSServiceRegistration *DNSServiceRegistrationList = NULL; char _malloc_options[] = "AXZ"; -static void validatelists(mDNS *const m) +mDNSlocal void validatelists(mDNS *const m) { DNSServiceDomainEnumeration *e; DNSServiceBrowser *b; @@ -1513,7 +1552,6 @@ mDNSexport void DefaultRegDomainChanged(const domainname *d, mDNSBool add) { DNSServiceRegistration *reg; - LogMsg("%s default registration domain %##s", add ? "Adding" : "Removing", d->c); for (reg = DNSServiceRegistrationList; reg; reg = reg->next) { if (reg->DefaultDomain) @@ -1538,7 +1576,7 @@ mDNSexport void DefaultRegDomainChanged(const domainname *d, mDNSBool add) prev = si; si = si->next; } - if (!si) LogMsg("Requested removal of default domain %##s not in client %5d's list", d, reg->ClientMachPort); + if (!si) debugf("Requested removal of default domain %##s not in client %5d's list", d, reg->ClientMachPort); // normal if registration failed } } } @@ -1670,21 +1708,73 @@ fail: return(err); } +mDNSlocal CFUserNotificationRef gNotification = NULL; +mDNSlocal CFRunLoopSourceRef gNotificationRLS = NULL; +mDNSlocal domainlabel gNotificationPrefHostLabel; // The prefs as they were the last time we saw them +mDNSlocal domainlabel gNotificationPrefNiceLabel; +mDNSlocal domainlabel gNotificationUserHostLabel; // The prefs as they were the last time the user changed them +mDNSlocal domainlabel gNotificationUserNiceLabel; + +mDNSlocal void NotificationCallBackDismissed(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) + { + (void)responseFlags; // Unused + if (userNotification != gNotification) LogMsg("NotificationCallBackDismissed: Wrong CFUserNotificationRef"); + if (gNotificationRLS) + { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), gNotificationRLS, kCFRunLoopDefaultMode); + CFRelease(gNotificationRLS); + gNotificationRLS = NULL; + CFRelease(gNotification); + gNotification = NULL; + } + // By dismissing the alert, the user has conceptually acknowleged the rename. + // (e.g. the machine's name is now officially "computer-2.local", not "computer.local".) + // If we get *another* conflict, the new alert should refer to the 'old'. + // name as now being "computer-2.local", not "computer.local" + gNotificationUserHostLabel = gNotificationPrefHostLabel; + gNotificationUserNiceLabel = gNotificationPrefNiceLabel; + } + +mDNSlocal void ShowNameConflictNotification(CFStringRef header, CFStringRef subtext) + { + CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!dictionary) return; + CFDictionarySetValue(dictionary, kCFUserNotificationAlertHeaderKey, header); + CFDictionarySetValue(dictionary, kCFUserNotificationAlertMessageKey, subtext); + + CFURLRef urlRef = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/CoreServices/mDNSResponder.bundle"), kCFURLPOSIXPathStyle, true); + if (urlRef) { CFDictionarySetValue(dictionary, kCFUserNotificationLocalizationURLKey, urlRef); CFRelease(urlRef); } + + if (gNotification) // If notification already on-screen, update it in place + CFUserNotificationUpdate(gNotification, 0, kCFUserNotificationCautionAlertLevel, dictionary); + else // else, we need to create it + { + SInt32 error; + gNotification = CFUserNotificationCreate(NULL, 0, kCFUserNotificationCautionAlertLevel, &error, dictionary); + if (!gNotification) { LogMsg("ShowNameConflictNotification: CFUserNotificationRef"); return; } + gNotificationRLS = CFUserNotificationCreateRunLoopSource(NULL, gNotification, NotificationCallBackDismissed, 0); + if (!gNotificationRLS) { LogMsg("ShowNameConflictNotification: RLS"); CFRelease(gNotification); gNotification = NULL; return; } + CFRunLoopAddSource(CFRunLoopGetCurrent(), gNotificationRLS, kCFRunLoopDefaultMode); + } + + CFRelease(dictionary); + } + // This updates either the text of the field currently labelled "Local Hostname", // or the text of the field currently labelled "Computer Name" // in the Sharing Prefs Control Panel -mDNSlocal void RecordUpdatedName(const mDNS *const m, domainlabel *n1, domainlabel *n2, char *msg, char *suffix, CFStringRef subtext) +mDNSlocal void RecordUpdatedName(const mDNS *const m, const domainlabel *const olddl, const domainlabel *const newdl, + const char *const msg, const char *const suffix, const CFStringRef subtext) { char oldname[MAX_DOMAIN_LABEL+1]; char newname[MAX_DOMAIN_LABEL+1]; - ConvertDomainLabelToCString_unescaped(n1, oldname); - ConvertDomainLabelToCString_unescaped(n2, newname); - const CFStringRef cfoldname = CFStringCreateWithCString(NULL, oldname, kCFStringEncodingUTF8); - const CFStringRef cfnewname = CFStringCreateWithCString(NULL, newname, kCFStringEncodingUTF8); - const CFStringRef f1 = CFStringCreateWithCString(NULL, "“%@%s”", kCFStringEncodingUTF8); - const CFStringRef f2 = CFStringCreateWithCString(NULL, "“%@%s”", kCFStringEncodingUTF8); + ConvertDomainLabelToCString_unescaped(olddl, oldname); + ConvertDomainLabelToCString_unescaped(newdl, newname); + const CFStringRef cfoldname = CFStringCreateWithCString(NULL, oldname, kCFStringEncodingUTF8); + const CFStringRef cfnewname = CFStringCreateWithCString(NULL, newname, kCFStringEncodingUTF8); + const CFStringRef f1 = CFStringCreateWithCString(NULL, " “%@%s” ", kCFStringEncodingUTF8); + const CFStringRef f2 = CFStringCreateWithCString(NULL, " “%@%s” ", kCFStringEncodingUTF8); const SCPreferencesRef session = SCPreferencesCreate(NULL, CFSTR("mDNSResponder"), NULL); - *n1 = *n2; if (!cfoldname || !cfnewname || !f1 || !f2 || !session || !SCPreferencesLock(session, 0)) // If we can't get the lock don't wait LogMsg("RecordUpdatedName: ERROR: Couldn't create SCPreferences session"); else @@ -1692,30 +1782,41 @@ mDNSlocal void RecordUpdatedName(const mDNS *const m, domainlabel *n1, domainlab const CFStringRef s0 = CFStringCreateWithCString(NULL, msg, kCFStringEncodingUTF8); const CFStringRef s1 = CFStringCreateWithFormat(NULL, NULL, f1, cfoldname, suffix); const CFStringRef s2 = CFStringCreateWithFormat(NULL, NULL, f2, cfnewname, suffix); -// const CFMutableArrayRef alertMessage = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - const CFMutableStringRef alertMessage = CFStringCreateMutable(NULL, 0); + // On Tiger and later, if we pass an array instead of a string, CFUserNotification will translate each + // element of the array individually for us, and then concatenate the results to make the final message. + // This lets us have the relevant bits localized, but not the literal names, which should not be translated. + // On Panther this does not work, so we just build the string directly, and it will not be translated. + const CFMutableStringRef alertHeader = + (OSXVers < 8) ? CFStringCreateMutable(NULL, 0) : (CFMutableStringRef)CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); Boolean result; - if (n2 == &m->hostlabel) result = SCPreferencesSetLocalHostName(session, cfnewname); - else result = SCPreferencesSetComputerName(session, cfnewname, kCFStringEncodingUTF8); - if (!result || !SCPreferencesCommitChanges(session) || !SCPreferencesApplyChanges(session) || !s0 || !s1 || !s2 || !alertMessage) + if (newdl == &gNotificationPrefHostLabel) result = SCPreferencesSetLocalHostName(session, cfnewname); + else result = SCPreferencesSetComputerName(session, cfnewname, kCFStringEncodingUTF8); + if (!result || !SCPreferencesCommitChanges(session) || !SCPreferencesApplyChanges(session) || !s0 || !s1 || !s2 || !alertHeader) LogMsg("RecordUpdatedName: ERROR: Couldn't update SCPreferences"); else if (m->p->NotifyUser) { -// CFArrayAppendValue(alertMessage, s0); - CFStringAppend(alertMessage, s0); - CFStringAppend(alertMessage, s1); - CFStringAppend(alertMessage, CFSTR(" is already in use on this network. The name has been changed to ")); - CFStringAppend(alertMessage, s2); - CFStringAppend(alertMessage, CFSTR(" automatically.")); - CFUserNotificationDisplayNotice(60.0, // Auto-dismiss after 60 seconds - kCFUserNotificationCautionAlertLevel, - NULL, NULL, NULL, // iconURL, soundURL, localizationURL - (CFStringRef)alertMessage, subtext, NULL); // alertHeader, alertMessage, defaultButtonTitle + uid_t uid; + gid_t gid; + CFStringRef userName = SCDynamicStoreCopyConsoleUser(NULL, &uid, &gid); + if (userName) + { + CFRelease(userName); + typedef void CFStringAppendFN(CFMutableStringRef theString, CFStringRef appendedString); + CFStringAppendFN *const append = (OSXVers < 8) ? &CFStringAppend : (CFStringAppendFN*)&CFArrayAppendValue; + append(alertHeader, s0); + append(alertHeader, s1); + append(alertHeader, CFSTR("is already in use on this network.")); + append(alertHeader, CFSTR(" ")); + append(alertHeader, CFSTR("The name has been changed to")); + append(alertHeader, s2); + append(alertHeader, CFSTR("automatically.")); + ShowNameConflictNotification(alertHeader, subtext); + } } - if (s0) CFRelease(s0); - if (s1) CFRelease(s1); - if (s2) CFRelease(s2); - if (alertMessage) CFRelease(alertMessage); + if (s0) CFRelease(s0); + if (s1) CFRelease(s1); + if (s2) CFRelease(s2); + if (alertHeader) CFRelease(alertHeader); SCPreferencesUnlock(session); } if (cfoldname) CFRelease(cfoldname); @@ -1730,11 +1831,24 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result) (void)m; // Unused if (result == mStatus_NoError) { - // Allow three seconds in case we get a Computer Name update too -- don't want to alert the user twice - RecordUpdatedNiceLabel(m, mDNSPlatformOneSecond*3); + // One second pause in case we get a Computer Name update too -- don't want to alert the user twice + RecordUpdatedNiceLabel(m, mDNSPlatformOneSecond); } else if (result == mStatus_ConfigChanged) { + // If the user-specified hostlabel from System Configuration has changed since the last time + // we saw it, and *we* didn't change it, then that implies that the user has changed it, + // so we auto-dismiss the name conflict alert. + if (!SameDomainLabel(m->p->userhostlabel.c, gNotificationPrefHostLabel.c) || + !SameDomainLabel(m->p->usernicelabel.c, gNotificationPrefNiceLabel.c)) + { + gNotificationUserHostLabel = gNotificationPrefHostLabel = m->p->userhostlabel; + gNotificationUserNiceLabel = gNotificationPrefNiceLabel = m->p->usernicelabel; + // If we're showing a name conflict notification, and the user has manually edited + // the name to remedy the conflict, we should now remove the notification window. + if (gNotificationRLS) CFUserNotificationCancel(gNotification); + } + DNSServiceRegistration *r; for (r = DNSServiceRegistrationList; r; r=r->next) if (r->autoname) @@ -1847,6 +1961,11 @@ mDNSlocal mStatus UpdateRecord(ServiceRecordSet *srs, mach_port_t client, AuthRe // Fill in new length, and data newrdata->MaxRDLength = size; memcpy(&newrdata->u, data, data_len); + + // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct, + // since RFC 1035 specifies a TXT record as "One or more s", not "Zero or more s". + // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here. + if (rr->resrec.rrtype == kDNSType_TXT && data_len == 0) { data_len = 1; newrdata->u.txt.c[0] = 0; } // Do the operation LogOperation("%5d: DNSServiceRegistrationUpdateRecord(%##s, new length %d)", @@ -2223,6 +2342,9 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void } } +// On 10.2 the MachServerName is DNSServiceDiscoveryServer +// On 10.3 and later, the MachServerName is com.apple.mDNSResponder + mDNSlocal kern_return_t mDNSDaemonInitialize(void) { mStatus err; @@ -2230,7 +2352,7 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void) CFMachPortRef s_port = CFMachPortCreate(NULL, DNSserverCallback, NULL, NULL); CFMachPortRef i_port = CFMachPortCreate(NULL, SignalCallback, NULL, NULL); mach_port_t m_port = CFMachPortGetPort(s_port); - char *MachServerName = mDNSMacOSXSystemBuildNumber(NULL) < 7 ? "DNSServiceDiscoveryServer" : "com.apple.mDNSResponder"; + char *MachServerName = OSXVers < 7 ? "DNSServiceDiscoveryServer" : "com.apple.mDNSResponder"; kern_return_t status = bootstrap_register(bootstrap_port, MachServerName, m_port); CFRunLoopSourceRef d_rls = CFMachPortCreateRunLoopSource(NULL, d_port, 0); CFRunLoopSourceRef s_rls = CFMachPortCreateRunLoopSource(NULL, s_port, 0); @@ -2252,6 +2374,9 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void) if (err) { LogMsg("Daemon start: mDNS_Init failed %ld", err); return(err); } + gNotificationUserHostLabel = gNotificationPrefHostLabel = PlatformStorage.userhostlabel; + gNotificationUserNiceLabel = gNotificationPrefNiceLabel = PlatformStorage.usernicelabel; + client_death_port = CFMachPortGetPort(d_port); signal_port = CFMachPortGetPort(i_port); @@ -2275,7 +2400,7 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m) // 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); } + if (m->p->NetworkChanged && now - m->p->NetworkChanged >= 0) mDNSMacOSXNetworkChanged(m); // 2. Call mDNS_Execute() to let mDNSCore do what it needs to do mDNSs32 nextevent = mDNS_Execute(m); @@ -2346,15 +2471,20 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m) if (!SameDomainLabel(m->p->usernicelabel.c, m->nicelabel.c)) { LogMsg("Updating Computer Name from \"%#s\" to \"%#s\"", m->p->usernicelabel.c, m->nicelabel.c); - RecordUpdatedName(m, &m->p->usernicelabel, &m->nicelabel, "The name of your computer ", "", - CFSTR("To change the name of your computer, open System Preferences and click Sharing. Then type the name in the Computer Name field.")); - m->p->NotifyUser = 0; // Clear m->p->NotifyUser here -- even if the hostlabel has changed too, we don't want to bug the user with *two* alerts + gNotificationPrefNiceLabel = m->p->usernicelabel = m->nicelabel; + RecordUpdatedName(m, &gNotificationUserNiceLabel, &gNotificationPrefNiceLabel, "The name of your computer", "", + CFSTR("To change the name of your computer, open System Preferences and click Sharing. " + "Then type the name in the Computer Name field.")); + // Clear m->p->NotifyUser here -- even if the hostlabel has changed too, we don't want to bug the user with *two* alerts + m->p->NotifyUser = 0; } if (!SameDomainLabel(m->p->userhostlabel.c, m->hostlabel.c)) { LogMsg("Updating Local Hostname from \"%#s.local\" to \"%#s.local\"", m->p->userhostlabel.c, m->hostlabel.c); - RecordUpdatedName(m, &m->p->userhostlabel, &m->hostlabel, "This computer's local hostname ", ".local", - CFSTR("To change the local hostname, open System Preferences and click Sharing. Then click Edit and type the name in the Local Hostname field.")); + gNotificationPrefHostLabel = m->p->userhostlabel = m->hostlabel; + RecordUpdatedName(m, &gNotificationUserHostLabel, &gNotificationPrefHostLabel, "This computer’s local hostname", ".local", + CFSTR("To change the local hostname, open System Preferences and click Sharing. " + "Then click Edit and type the name in the Local Hostname field.")); } m->p->NotifyUser = 0; } @@ -2436,10 +2566,11 @@ mDNSexport int main(int argc, char **argv) // 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); } + if (status) { LogMsg("Daemon start: udsserver_init failed"); goto exit; } // First do the all the initialization we need root privilege for, before we change to user "nobody" LogMsgIdent(mDNSResponderVersionString, "starting"); + OSXVers = mDNSMacOSXSystemBuildNumber(NULL); status = mDNSDaemonInitialize(); #if CAN_UPDATE_DYNAMIC_STORE_WITHOUT_BEING_ROOT @@ -2502,9 +2633,10 @@ mDNSexport int main(int argc, char **argv) mDNS_Close(&mDNSStorage); } - if (!mDNS_DebugMode && !started_via_launchdaemon) destroyBootstrapService(); - LogMsgIdent(mDNSResponderVersionString, "exiting"); + +exit: + if (!mDNS_DebugMode && !started_via_launchdaemon) destroyBootstrapService(); return(status); } @@ -2524,7 +2656,7 @@ typedef struct CFSocketEventSource CFSocketEventSource; static GenLinkedList gEventSources; // linked list of CFSocketEventSource's -static void cf_callback(CFSocketRef s, CFSocketCallBackType t, CFDataRef dr, const void *c, void *i) +mDNSlocal void cf_callback(CFSocketRef s, CFSocketCallBackType t, CFDataRef dr, const void *c, void *i) // Called by CFSocket when data appears on socket { (void)s; // Unused diff --git a/mDNSMacOSX/mDNSMacOSX.c b/mDNSMacOSX/mDNSMacOSX.c index 8a74c6f..8d553ca 100644 --- a/mDNSMacOSX/mDNSMacOSX.c +++ b/mDNSMacOSX/mDNSMacOSX.c @@ -24,6 +24,52 @@ Change History (most recent first): $Log: mDNSMacOSX.c,v $ +Revision 1.308 2005/03/09 00:48:44 cheshire + QU packets getting sent too early on wake from sleep +Move "m->p->NetworkChanged = 0;" line from caller to callee + +Revision 1.307 2005/03/03 03:12:02 cheshire +Add comment about mDNSMacOSXSystemBuildNumber() + +Revision 1.306 2005/03/02 22:18:00 cheshire + mDNSResponder requires AppleInternal packages to build on Tiger + +Revision 1.305 2005/02/26 05:08:28 cheshire + mDNSResponder requires AppleInternal packages to build on Tiger +Added dnsinfo.h to project directory + +Revision 1.304 2005/02/25 23:51:22 cheshire + SendServiceRegistration fails on wake from sleep +Return mStatus_UnknownErr instead of -1 + +Revision 1.303 2005/02/25 17:47:45 ksekar + SendServiceRegistration fails on wake from sleep + +Revision 1.302 2005/02/25 02:34:14 cheshire + Should not indicate successful dynamic update if no network connection +Show status as 1 (in progress) while we're trying + +Revision 1.301 2005/02/24 21:55:57 ksekar + Should not indicate successful dynamic update if no network connection + +Revision 1.300 2005/02/15 20:03:13 ksekar + Crash when SCPreferences contains empty array + +Revision 1.299 2005/02/15 02:46:53 cheshire + Don't log ENETUNREACH errors for unicast destinations + +Revision 1.298 2005/02/10 00:41:59 cheshire +Fix compiler warning + +Revision 1.297 2005/02/09 23:38:51 ksekar + Reregister hostname when DNS server changes but IP address does not + +Revision 1.296 2005/02/01 21:06:52 ksekar +Avoid spurious log message + +Revision 1.295 2005/02/01 19:33:30 ksekar + Keychain format too restrictive + Revision 1.294 2005/01/27 21:30:23 cheshire "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 @@ -173,7 +219,7 @@ Add "#ifdef MAC_OS_X_VERSION_10_4" around split-DNS code that can't be compiled (When compiled on 10.3, code will not include split-DNS support.) Revision 1.248 2004/12/01 20:57:20 ksekar - Wide Area Rendezvous must be split-DNS aware + Wide Area Service Discovery must be split-DNS aware Revision 1.247 2004/12/01 03:26:58 cheshire Remove unused variables @@ -213,7 +259,7 @@ Let interface name/index mapping capability live directly in JNISupport.c, instead of having to call through to the daemon via IPC to get this information. Revision 1.235 2004/11/17 01:45:35 cheshire - Rendezvous buddy list frequently becomes empty if you let the machine sleep + mDNS buddy list frequently becomes empty if you let the machine sleep Refresh our interface list on receiving kIOMessageSystemHasPoweredOn, in case we get no System Configuration Framework "network changed" event. @@ -925,10 +971,7 @@ Minor code tidying #include -#include -#ifdef MAC_OS_X_VERSION_10_4 -#include -#endif +#include "dnsinfo.h" // Code contributed by Dave Heller: // Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will @@ -1217,16 +1260,17 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms if (err < 0) { // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations - if (!mDNSAddressIsAllDNSLinkGroup(dst) && (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH)) return(err); + if (!mDNSAddressIsAllDNSLinkGroup(dst)) + if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr); // Don't report EHOSTUNREACH in the first three minutes after boot // This is because mDNSResponder intentionally starts up early in the boot process (See ) // 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); + if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr); // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change - if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(err); + if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(mStatus_TransientErr); 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); + return(mStatus_UnknownErr); } return(mStatus_NoError); @@ -1663,7 +1707,7 @@ mDNSlocal void GetUserSpecifiedDDNSConfig(domainname *const fqdn, domainname *co if (dict) { CFArrayRef fqdnArray = CFDictionaryGetValue(dict, CFSTR("HostNames")); - if (fqdnArray) + if (fqdnArray && CFArrayGetCount(fqdnArray) > 0) { 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)) @@ -1680,7 +1724,7 @@ mDNSlocal void GetUserSpecifiedDDNSConfig(domainname *const fqdn, domainname *co } CFArrayRef regArray = CFDictionaryGetValue(dict, CFSTR("RegistrationDomains")); - if (regArray) + if (regArray && CFArrayGetCount(regArray) > 0) { CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0); if (regDict && DDNSSettingEnabled(regDict)) @@ -1696,7 +1740,7 @@ mDNSlocal void GetUserSpecifiedDDNSConfig(domainname *const fqdn, domainname *co } } CFArrayRef browseArray = CFDictionaryGetValue(dict, CFSTR("BrowseDomains")); - if (browseArray) + if (browseArray && CFArrayGetCount(browseArray) > 0) { CFRetain(browseArray); *browseDomains = browseArray; @@ -2342,9 +2386,9 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc) mDNSlocal mStatus GetDNSConfig(void **result) { -#ifndef MAC_OS_X_VERSION_10_4 +#if MDNS_NO_DNSINFO static int MessageShown = 0; - if (!MessageShown) { MessageShown = 1; LogMsg("Note: Compiled without Apple-specific split DNS support"); } + if (!MessageShown) { MessageShown = 1; LogMsg("Note: Compiled without Apple-specific Split-DNS support"); } *result = NULL; return mStatus_UnsupportedErr; #else @@ -2366,20 +2410,25 @@ mDNSlocal mStatus GetDNSConfig(void **result) return mStatus_UnknownErr; } return mStatus_NoError; -#endif // MAC_OS_X_VERSION_10_4 +#endif // MDNS_NO_DNSINFO } -mDNSlocal mStatus RegisterSplitDNS(mDNS *m) +mDNSlocal mStatus RegisterSplitDNS(mDNS *m, int *nAdditions, int *nDeletions) { (void)m; // unused on 10.3 systems void *v; + *nAdditions = *nDeletions = 0; mStatus err = GetDNSConfig(&v); + +#if !MDNS_NO_DNSINFO if (!err && v) { -#ifdef MAC_OS_X_VERSION_10_4 int i; + DNSServer *p; dns_config_t *config = v; // use void * to allow compilation on 10.3 systems - mDNS_DeleteDNSServers(m); + mDNS_Lock(m); + p = m->uDNS_info.Servers; + while (p) { p->flag = -1; p = p->next; } // mark all for deletion LogOperation("RegisterSplitDNS: Registering %d resolvers", config->n_resolver); for (i = 0; i < config->n_resolver; i++) @@ -2415,15 +2464,47 @@ mDNSlocal mStatus RegisterSplitDNS(mDNS *m) 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); + p = m->uDNS_info.Servers; + while (p) + { + if (mDNSSameAddress(&p->addr, &saddr) && SameDomainName(&p->domain, &d)) { p->flag = 0; break; } + else p = p->next; + } + if (!p) + { + p = mallocL("DNSServer", sizeof(*p)); + if (!p) { LogMsg("Error: malloc"); mDNS_Unlock(m); return mStatus_UnknownErr; } + p->addr = saddr; + AssignDomainName(&p->domain, &d); + p->flag = 0; + p->next = m->uDNS_info.Servers; + m->uDNS_info.Servers = p; + (*nAdditions)++; + } break; // !!!KRS if we ever support round-robin servers, don't break here } } } + + // remove all servers marked for deletion + DNSServer **s = &m->uDNS_info.Servers; + while (*s) + { + if ((*s)->flag < 0) + { + p = *s; + *s = (*s)->next; + freeL("DNSServer", p); + (*nDeletions)--; + } + else s = &(*s)->next; + } + mDNS_Unlock(m); dns_configuration_free(config); -#endif } - return err; +#endif + + return err; } mDNSlocal mStatus RegisterNameServers(mDNS *const m, CFDictionaryRef dict) @@ -2561,9 +2642,10 @@ mDNSlocal mStatus GetSearchDomains(void) { void *v; mStatus err = GetDNSConfig(&v); + +#if !MDNS_NO_DNSINFO if (!err && v) { -#ifdef MAC_OS_X_VERSION_10_4 int i; dns_config_t *config = v; if (!config->n_resolver) return err; @@ -2572,8 +2654,9 @@ mDNSlocal mStatus GetSearchDomains(void) for (i = 0; i < resolv->n_search; i++) MarkSearchListElem(resolv->search[i]); if (resolv->domain) MarkSearchListElem(resolv->domain); dns_configuration_free(config); -#endif } +#endif + return err; } @@ -2725,14 +2808,20 @@ mDNSlocal void SCPrefsDynDNSCallback(mDNS *const m, AuthRecord *const rr, mStatu mDNSlocal void SetSecretForDomain(mDNS *m, const domainname *domain) { OSStatus err = 0; - SecKeychainRef SysKeychain = NULL; - SecKeychainItemRef KeychainItem; char dstring[MAX_ESCAPED_DOMAIN_NAME]; mDNSu32 secretlen; void *secret = NULL; domainname *d, canon; int i, dlen; - + mDNSu32 type = 'ddns'; + mDNSu32 typelen = sizeof(type); + char *failedfn = "(none)"; + SecKeychainAttributeList *attrList = NULL; + SecKeychainItemRef itemRef = NULL; + + err = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); + if (err) { failedfn = "SecKeychainSetPreferenceDomain"; goto cleanup; } + // canonicalize name by converting to lower case (keychain and some name servers are case sensitive) ConvertDomainNameToCString(domain, dstring); dlen = strlen(dstring); @@ -2740,30 +2829,63 @@ mDNSlocal void SetSecretForDomain(mDNS *m, const domainname *domain) MakeDomainNameFromDNSNameString(&canon, dstring); d = &canon; - err = SecKeychainOpen(SYS_KEYCHAIN_PATH, &SysKeychain); - if (err) { LogMsg("SetSecretForDomain: couldn't open system keychain (error %d)", err); return; } - // find longest-match key ("account") name, excluding last label (e.g. excluding ".com") + // find longest-match key, excluding last label (e.g. excluding ".com") while (d->c[0] && *(d->c + d->c[0] + 1)) { if (!ConvertDomainNameToCString(d, dstring)) { LogMsg("SetSecretForDomain: bad domain %##s", d->c); return; } dlen = strlen(dstring); if (dstring[dlen-1] == '.') { dstring[dlen-1] = '\0'; dlen--; } // chop trailing dot - err = SecKeychainFindGenericPassword(SysKeychain, strlen(DYNDNS_KEYCHAIN_SERVICE), DYNDNS_KEYCHAIN_SERVICE, dlen, dstring, &secretlen, &secret, &KeychainItem); + SecKeychainAttribute attrs[] = { { kSecServiceItemAttr, strlen(dstring), dstring }, + { kSecTypeItemAttr, typelen, (UInt32 *)&type } }; + SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; + SecKeychainSearchRef searchRef; + + err = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributes, &searchRef); + if (err) { failedfn = "SecKeychainSearchCreateFromAttributes"; goto cleanup; } + + err = SecKeychainSearchCopyNext(searchRef, &itemRef); if (!err) { - debugf("Setting shared secret for zone %s with key %##s", dstring, d->c); - mDNS_SetSecretForZone(m, d, d, secret, secretlen, mDNStrue); - free(secret); - return; - } - if (err == errSecItemNotFound) d = (domainname *)(d->c + d->c[0] + 1); - else - { - if (err == errSecNoSuchKeychain) debugf("SetSecretForDomain: keychain not found"); - else LogMsg("SetSecretForDomain: SecKeychainFindGenericPassword returned error %d", err); - return; + mDNSu32 tags[1]; + SecKeychainAttributeInfo attrInfo; + mDNSu32 i; + char keybuf[MAX_ESCAPED_DOMAIN_NAME+1]; + domainname keyname; + + tags[0] = kSecAccountItemAttr; + attrInfo.count = 1; + attrInfo.tag = tags; + attrInfo.format = NULL; + + err = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, &attrList, &secretlen, &secret); + if (err || !attrList) { failedfn = "SecKeychainItemCopyAttributesAndData"; goto cleanup; } + if (!secretlen || !secret) { LogMsg("SetSecretForDomain - bad shared secret"); return; } + if (((char *)secret)[secretlen-1]) { LogMsg("SetSecretForDomain - Shared secret not NULL-terminated"); goto cleanup; } + + for (i = 0; i < attrList->count; i++) + { + SecKeychainAttribute attr = attrList->attr[i]; + if (attr.tag == kSecAccountItemAttr) + { + if (!attr.length || attr.length > MAX_ESCAPED_DOMAIN_NAME) { LogMsg("SetSecretForDomain - Bad key length %d", attr.length); goto cleanup; } + strncpy(keybuf, attr.data, attr.length); + if (!MakeDomainNameFromDNSNameString(&keyname, keybuf)) { LogMsg("SetSecretForDomain - bad key %s", keybuf); goto cleanup; } + debugf("Setting shared secret for zone %s with key %##s", dstring, keyname.c); + mDNS_SetSecretForZone(m, d, &keyname, secret); + break; + } + } + if (i == attrList->count) LogMsg("SetSecretForDomain - no key name set"); + goto cleanup; } + else if (err == errSecItemNotFound) d = (domainname *)(d->c + d->c[0] + 1); + else { failedfn = "SecKeychainSearchCopyNext"; goto cleanup; } } + + cleanup: + if (err && err != errSecItemNotFound) LogMsg("Error: SetSecretForDomain - %s failed with error code %d", failedfn, err); + if (attrList) SecKeychainItemFreeAttributesAndData(attrList, secret); + if (itemRef) CFRelease(itemRef); } mDNSlocal void SetSCPrefsBrowseDomainsFromCFArray(mDNS *m, CFArrayRef browseDomains, mDNSBool add) @@ -2802,6 +2924,7 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m) CFStringRef key; domainname RegDomain, fqdn; CFArrayRef NewBrowseDomains = NULL; + int nAdditions = 0, nDeletions = 0; // get fqdn, zone from SCPrefs GetUserSpecifiedDDNSConfig(&fqdn, &RegDomain, &NewBrowseDomains); @@ -2843,8 +2966,8 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m) if (DynDNSHostname.c[0]) { SetSecretForDomain(m, &fqdn); // no-op if "zone" secret, above, is to be used for hostname + SetDDNSNameStatus(&DynDNSHostname, 1); // Set status to 1 to indicate "in progress" mDNS_AddDynDNSHostName(m, &DynDNSHostname, SCPrefsDynDNSCallback, NULL); - SetDDNSNameStatus(&DynDNSHostname, 1); } } @@ -2858,7 +2981,7 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m) CFRelease(key); // handle any changes to search domains and DNS server addresses - if (RegisterSplitDNS(m) != mStatus_NoError) + if (RegisterSplitDNS(m, &nAdditions, &nDeletions) != mStatus_NoError) if (dict) RegisterNameServers(m, dict); // fall back to non-split DNS aware configuration on failure RegisterSearchDomains(m, dict); // note that we register name servers *before* search domains if (dict) CFRelease(dict); @@ -2869,8 +2992,12 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m) dict = SCDynamicStoreCopyValue(store, key); CFRelease(key); CFRelease(store); - if (!dict) - { mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL); return; } // lost v4 + if (!dict) // lost v4 + { + mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL); + if (DynDNSHostname.c[0]) SetDDNSNameStatus(&DynDNSHostname, 1); // Set status to 1 to indicate temporary failure + return; + } // handle router changes mDNSAddr r; @@ -2896,6 +3023,8 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m) } // handle primary interface changes + // if we gained or lost DNS servers (e.g. logged into VPN) "toggle" primary address so it gets re-registered even if it is unchanged + if (nAdditions || nDeletions) mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL); CFStringRef primary = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface); if (primary) { @@ -2938,6 +3067,7 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m) mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m) { LogOperation("*** Network Configuration Change ***"); + m->p->NetworkChanged = 0; // If we received a network change event and deferred processing, we're now dealing with it mDNSs32 utc = mDNSPlatformUTC(); MarkAllInterfacesInactive(m, utc); UpdateInterfaceList(m, utc); @@ -3047,26 +3177,26 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag (void)service; // Parameter not used switch(messageType) { - case kIOMessageCanSystemPowerOff: debugf("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240 - 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); mDNSMacOSXNetworkChanged(m); break; // E0000280 - case kIOMessageSystemWillNotSleep: debugf("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290 - case kIOMessageSystemHasPoweredOn: debugf("PowerChanged kIOMessageSystemHasPoweredOn"); + case kIOMessageCanSystemPowerOff: debugf ("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240 + case kIOMessageSystemWillPowerOff: LogOperation("PowerChanged kIOMessageSystemWillPowerOff"); + mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000250 + case kIOMessageSystemWillNotPowerOff: debugf ("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260 + case kIOMessageCanSystemSleep: debugf ("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270 + case kIOMessageSystemWillSleep: LogOperation("PowerChanged kIOMessageSystemWillSleep"); + mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000280 + case kIOMessageSystemWillNotSleep: debugf ("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290 + case kIOMessageSystemHasPoweredOn: LogOperation("PowerChanged kIOMessageSystemHasPoweredOn"); // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now if (m->SleepState) mDNSCoreMachineSleep(m, false); // Just to be safe, also make sure our interface list is fully up to date, in case we // haven't yet received the System Configuration Framework "network changed" event that // we expect to receive some time shortly after the kIOMessageSystemWillPowerOn message - mDNSMacOSXNetworkChanged(m); break; // E0000300 - case kIOMessageSystemWillRestart: debugf("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310 - case kIOMessageSystemWillPowerOn: debugf("PowerChanged kIOMessageSystemWillPowerOn"); + mDNSMacOSXNetworkChanged(m); break; // E0000300 + case kIOMessageSystemWillRestart: debugf ("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310 + case kIOMessageSystemWillPowerOn: LogOperation("PowerChanged kIOMessageSystemWillPowerOn"); // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake - mDNSMacOSXNetworkChanged(m); mDNSCoreMachineSleep(m, false); break; // E0000320 - default: debugf("PowerChanged unknown message %X", messageType); break; + mDNSMacOSXNetworkChanged(m); mDNSCoreMachineSleep(m, false); break; // E0000320 + default: LogOperation("PowerChanged unknown message %X", messageType); break; } IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument); } @@ -3089,6 +3219,9 @@ CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey; CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey; CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey; +// Major version 6 is 10.2.x (Jaguar) +// Major version 7 is 10.3.x (Panther) +// Major version 8 is 10.4.x (Tiger) mDNSexport int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring) { int major = 0, minor = 0; @@ -3429,7 +3562,7 @@ mDNSexport mDNSs32 mDNSPlatformRawTime(void) LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time); // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug() last_mach_absolute_time = this_mach_absolute_time; - // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xxx) or later + // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xyyy) or later if (mDNSMacOSXSystemBuildNumber(NULL) >= 8) NotifyOfElusiveBug("mach_absolute_time went backwards!", 3438376, ""); } diff --git a/mDNSMacOSX/mDNSMacOSX.h b/mDNSMacOSX/mDNSMacOSX.h index 0222d04..645e8ee 100644 --- a/mDNSMacOSX/mDNSMacOSX.h +++ b/mDNSMacOSX/mDNSMacOSX.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: mDNSMacOSX.h,v $ +Revision 1.50 2005/02/19 00:04:18 cheshire +Add comments + Revision 1.49 2004/12/17 23:37:47 cheshire Guard against repeating wireless dissociation/re-association (and other repetitive configuration changes) @@ -241,8 +244,8 @@ struct mDNS_PlatformSupport_struct { NetworkInterfaceInfoOSX *InterfaceList; CFSocketSet unicastsockets; - domainlabel userhostlabel; - domainlabel usernicelabel; + domainlabel userhostlabel; // The hostlabel as it was set in System Preferences the last time we looked + domainlabel usernicelabel; // The nicelabel as it was set in System Preferences the last time we looked mDNSs32 NotifyUser; mDNSs32 NetworkChanged; SCDynamicStoreRef Store; diff --git a/mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings b/mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings new file mode 100644 index 0000000..bba4c2c --- /dev/null +++ b/mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings @@ -0,0 +1,10 @@ +"The name of your computer" = "The name of your computer"; +"This computer’s local hostname" = "This computer’s local hostname"; +"is already in use on this network." = "is already in use on this network."; + +"The name has been changed to" = "The name has been changed to"; +"automatically." = "automatically."; + +"To change the name of your computer, open System Preferences and click Sharing. Then type the name in the Computer Name field." = "To change the name of your computer, open System Preferences and click Sharing. Then type the name in the Computer Name field."; + +"To change the local hostname, open System Preferences and click Sharing. Then click Edit and type the name in the Local Hostname field." = "To change the local hostname, open System Preferences and click Sharing. Then click Edit and type the name in the Local Hostname field."; diff --git a/mDNSMacOSX/mDNSResponder-bundle/Resources/French.lproj/Localizable.strings b/mDNSMacOSX/mDNSResponder-bundle/Resources/French.lproj/Localizable.strings new file mode 100644 index 0000000..be7a444 --- /dev/null +++ b/mDNSMacOSX/mDNSResponder-bundle/Resources/French.lproj/Localizable.strings @@ -0,0 +1,10 @@ +"The name of your computer" = "Le nom de l’ordinateur"; +"This computer’s local hostname" = "Le nom d’hôte local de cet ordinateur"; +"is already in use on this network." = "est déjà utilié sur ce réseau."; + +"The name has been changed to" = "Le non a été changé par"; +"automatically." = "automatiquement."; + +"To change the name of your computer, open System Preferences and click Sharing. Then type the name in the Computer Name field." = "Pour changer le nom de votre ordinateur, ouvrez Préférences Systèmes et cliquer Partage. Ensuite entrez le nom dans le champ Nom de l’ordinateur."; + +"To change the local hostname, open System Preferences and click Sharing. Then click Edit and type the name in the Local Hostname field." = "Pour changer le nom d’hôte local, ouvrez Préférences Systèmes et cliquer Partage. Ensuite cliquer Modifier et entrez le nom dans le champ Nom local de l’ordinateur."; diff --git a/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj b/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj index 41f07c3..3fe2b31 100644 --- a/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj +++ b/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj @@ -23,7 +23,7 @@ FRAMEWORK_SEARCH_PATHS = ""; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_VERSION = 3.3; - HEADER_SEARCH_PATHS = "\"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\""; + HEADER_SEARCH_PATHS = "../mDNSShared \"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\" \"$(OBJROOT)\""; LIBRARY_SEARCH_PATHS = ""; MACOSX_DEPLOYMENT_TARGET = 10.2; OPTIMIZATION_CFLAGS = "-O0"; @@ -178,6 +178,7 @@ FF16238F07023BD2001AB7D7, FFD41DDB0664169900F0C438, FFD41DDC0664169B00F0C438, + FF2A870707B4481500B14068, ); isa = PBXAggregateTarget; name = "Build All"; @@ -252,6 +253,8 @@ DB2CC4530662DD6800335AB3, DB2CC4660662DF5C00335AB3, FF25792906C9A70800376F7B, + FFFB0DA907B43C9100B88D48, + FF2609E107B440DD00CE10E5, ); }; 08FB7794FE84155DC02AAC07 = { @@ -260,6 +263,7 @@ 6575FC1F022EB78C00000109, 6575FBFE022EAFA800000109, DB2CC4420662DCE500335AB3, + FFFB0DA407B43BED00B88D48, 08FB779DFE84155DC02AAC07, 19C28FBDFE9D53C911CA2CBB, ); @@ -301,10 +305,13 @@ 08FB779DFE84155DC02AAC07 = { children = ( 7F869685066EE02400D2A2DC, + FFFB0DB407B43D2700B88D48, 09AB6884FE841BABC02AAC07, 65713D46025A293200000109, 00CA213D02786FC30CCA2C71, DB2CC4680662DFF500335AB3, + FF2609FA07B4433800CE10E5, + FF260A1F07B4436900CE10E5, ); isa = PBXGroup; name = "External Frameworks and Libraries"; @@ -324,7 +331,7 @@ FRAMEWORK_SEARCH_PATHS = ""; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_VERSION = 3.3; - HEADER_SEARCH_PATHS = "\"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\""; + HEADER_SEARCH_PATHS = "../mDNSShared \"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\" \"$(OBJROOT)\""; INSTALL_PATH = /usr/sbin; LIBRARY_SEARCH_PATHS = ""; MACOSX_DEPLOYMENT_TARGET = 10.2; @@ -434,6 +441,8 @@ FFD41DDA0664157900F0C438, FF25794406C9A70800376F7B, FF1C919B07021C84001048AB, + FFFB0DAA07B43C9100B88D48, + FF2609E207B440DD00CE10E5, ); isa = PBXGroup; name = Products; @@ -944,7 +953,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; GCC_VERSION = 3.3; - INSTALL_PATH = /System/Library/Java/Extensions; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Java/Extensions"; JAVA_ARCHIVE_CLASSES = YES; JAVA_ARCHIVE_COMPRESSION = YES; JAVA_ARCHIVE_TYPE = JAR; @@ -952,6 +961,7 @@ JAVA_COMPILER_TARGET_VM_VERSION = 1.2; JAVA_SOURCE_SUBDIR = .; LIBRARY_STYLE = STATIC; + MACOSX_DEPLOYMENT_TARGET = 10.2; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ""; OTHER_LIBTOOL_FLAGS = ""; @@ -1101,6 +1111,7 @@ HEADER_SEARCH_PATHS = "../mDNSShared \"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/A/Headers\" \"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/1.3.1/Headers\" \"$(OBJROOT)/mDNSResponder.build/dns_sd.jar.build\""; INSTALL_PATH = /usr/lib/java; LIBRARY_STYLE = DYNAMIC; + MACOSX_DEPLOYMENT_TARGET = 10.2; OTHER_CFLAGS = ""; OTHER_LIBTOOL_FLAGS = ""; OTHER_REZFLAGS = ""; @@ -1275,6 +1286,18 @@ //FF2 //FF3 //FF4 + FF08480607CEB8E800AE6769 = { + isa = PBXFileReference; + name = inprogress.tiff; + path = PreferencePane/Artwork/inprogress.tiff; + refType = 2; + }; + FF08480707CEB8E800AE6769 = { + fileRef = FF08480607CEB8E800AE6769; + isa = PBXBuildFile; + settings = { + }; + }; FF0E0B5D065ADC7600FE4D9C = { fileEncoding = 4; isa = PBXFileReference; @@ -1585,6 +1608,385 @@ isa = PBXTargetDependency; target = FF25792906C9A70800376F7B; }; + FF2609DC07B440DD00CE10E5 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FF2609DD07B440DD00CE10E5 = { + buildActionMask = 2147483647; + files = ( + FF260A2B07B4464B00CE10E5, + FF260A2C07B4464B00CE10E5, + FF260A2D07B4464B00CE10E5, + FF260A2E07B4464B00CE10E5, + FF260A2F07B4464B00CE10E5, + FF260A3007B4464B00CE10E5, + FF260A3107B4464B00CE10E5, + FF260A3407B4466900CE10E5, + FF260A3507B4466900CE10E5, + FF260A4A07B4475600CE10E5, + FF260A4D07B4477F00CE10E5, + FF2A870607B447EF00B14068, + FF08480707CEB8E800AE6769, + ); + isa = PBXResourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FF2609DE07B440DD00CE10E5 = { + buildActionMask = 2147483647; + files = ( + FF2609E407B441D400CE10E5, + FF2609E507B441D700CE10E5, + FF2609E607B441DB00CE10E5, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FF2609DF07B440DD00CE10E5 = { + buildActionMask = 2147483647; + files = ( + FF2609F607B442BA00CE10E5, + FF2609F707B442C000CE10E5, + FF2609FB07B4433800CE10E5, + FF260A2007B4436900CE10E5, + FF260A2107B443B500CE10E5, + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FF2609E007B440DD00CE10E5 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FF2609E107B440DD00CE10E5 = { + buildPhases = ( + FF2609DC07B440DD00CE10E5, + FF2609DD07B440DD00CE10E5, + FF2609DE07B440DD00CE10E5, + FF2609DF07B440DD00CE10E5, + FF2609E007B440DD00CE10E5, + ); + buildSettings = { + EXPORTED_SYMBOLS_FILE = ""; + GCC_VERSION = 3.3; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/PreferencePanes"; + MACOSX_DEPLOYMENT_TARGET = 10.2; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = "-twolevel_namespace"; + OTHER_REZFLAGS = ""; + PREBINDING = NO; + PRODUCT_NAME = Bonjour; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + WRAPPER_EXTENSION = prefPane; + }; + dependencies = ( + FF2609E307B440EC00CE10E5, + ); + isa = PBXBundleTarget; + name = PreferencePane; + productInstallPath = "$(SYSTEM_LIBRARY_DIR)/PreferencePanes"; + productName = PreferencePane; + productReference = FF2609E207B440DD00CE10E5; + productSettingsXML = " + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + Bonjour + CFBundleGetInfoString + + CFBundleIconFile + DNSServiceDiscoveryPref + CFBundleIdentifier + com.apple.preference.bonjour + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + + CFBundlePackageType + BNDL + CFBundleShortVersionString + + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + DNSServiceDiscoveryPref + NSPrefPaneIconFile + DNSServiceDiscoveryPref.tiff + NSPrefPaneIconLabel + Bonjour + NSPrincipalClass + DNSServiceDiscoveryPref + + +"; + }; + FF2609E207B440DD00CE10E5 = { + isa = PBXBundleReference; + path = Bonjour.prefPane; + refType = 3; + }; + FF2609E307B440EC00CE10E5 = { + isa = PBXTargetDependency; + target = FFFB0DA907B43C9100B88D48; + }; + FF2609E407B441D400CE10E5 = { + fileRef = FFFB0DAC07B43CBA00B88D48; + isa = PBXBuildFile; + settings = { + }; + }; + FF2609E507B441D700CE10E5 = { + fileRef = FFFB0DAD07B43CBA00B88D48; + isa = PBXBuildFile; + settings = { + }; + }; + FF2609E607B441DB00CE10E5 = { + fileRef = FFFB0DAE07B43CBA00B88D48; + isa = PBXBuildFile; + settings = { + }; + }; + FF2609F607B442BA00CE10E5 = { + fileRef = 65713D46025A293200000109; + isa = PBXBuildFile; + settings = { + }; + }; + FF2609F707B442C000CE10E5 = { + fileRef = 7F869685066EE02400D2A2DC; + isa = PBXBuildFile; + settings = { + }; + }; + FF2609FA07B4433800CE10E5 = { + isa = PBXFrameworkReference; + name = Cocoa.framework; + path = /System/Library/Frameworks/Cocoa.framework; + refType = 0; + }; + FF2609FB07B4433800CE10E5 = { + fileRef = FF2609FA07B4433800CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A1F07B4436900CE10E5 = { + isa = PBXFrameworkReference; + name = PreferencePanes.framework; + path = /System/Library/Frameworks/PreferencePanes.framework; + refType = 0; + }; + FF260A2007B4436900CE10E5 = { + fileRef = FF260A1F07B4436900CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A2107B443B500CE10E5 = { + fileRef = 09AB6884FE841BABC02AAC07; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A2207B443C500CE10E5 = { + fileRef = 09AB6884FE841BABC02AAC07; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A2307B4463400CE10E5 = { + children = ( + FF260A2407B4464B00CE10E5, + FF260A2507B4464B00CE10E5, + FF260A2607B4464B00CE10E5, + FF260A2707B4464B00CE10E5, + FF260A2907B4464B00CE10E5, + FF260A2807B4464B00CE10E5, + FF08480607CEB8E800AE6769, + FF260A2A07B4464B00CE10E5, + FF260A3207B4466900CE10E5, + FF260A3307B4466900CE10E5, + FF260A4807B4475600CE10E5, + FF260A4B07B4477F00CE10E5, + ); + isa = PBXGroup; + name = Resources; + refType = 4; + }; + FF260A2407B4464B00CE10E5 = { + isa = PBXFileReference; + name = remove_idle.tiff; + path = PreferencePane/Artwork/remove_idle.tiff; + refType = 2; + }; + FF260A2507B4464B00CE10E5 = { + isa = PBXFileReference; + name = add_pressed.tiff; + path = PreferencePane/Artwork/add_pressed.tiff; + refType = 2; + }; + FF260A2607B4464B00CE10E5 = { + isa = PBXFileReference; + name = remove_disabled.tiff; + path = PreferencePane/Artwork/remove_disabled.tiff; + refType = 2; + }; + FF260A2707B4464B00CE10E5 = { + isa = PBXFileReference; + name = add_idle.tiff; + path = PreferencePane/Artwork/add_idle.tiff; + refType = 2; + }; + FF260A2807B4464B00CE10E5 = { + isa = PBXFileReference; + name = success.tiff; + path = PreferencePane/Artwork/success.tiff; + refType = 2; + }; + FF260A2907B4464B00CE10E5 = { + isa = PBXFileReference; + name = remove_pressed.tiff; + path = PreferencePane/Artwork/remove_pressed.tiff; + refType = 2; + }; + FF260A2A07B4464B00CE10E5 = { + isa = PBXFileReference; + name = failure.tiff; + path = PreferencePane/Artwork/failure.tiff; + refType = 2; + }; + FF260A2B07B4464B00CE10E5 = { + fileRef = FF260A2407B4464B00CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A2C07B4464B00CE10E5 = { + fileRef = FF260A2507B4464B00CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A2D07B4464B00CE10E5 = { + fileRef = FF260A2607B4464B00CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A2E07B4464B00CE10E5 = { + fileRef = FF260A2707B4464B00CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A2F07B4464B00CE10E5 = { + fileRef = FF260A2807B4464B00CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A3007B4464B00CE10E5 = { + fileRef = FF260A2907B4464B00CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A3107B4464B00CE10E5 = { + fileRef = FF260A2A07B4464B00CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A3207B4466900CE10E5 = { + isa = PBXFileReference; + name = DNSServiceDiscoveryPref.icns; + path = PreferencePane/DNSServiceDiscoveryPref.icns; + refType = 2; + }; + FF260A3307B4466900CE10E5 = { + isa = PBXFileReference; + name = DNSServiceDiscoveryPref.tiff; + path = PreferencePane/DNSServiceDiscoveryPref.tiff; + refType = 2; + }; + FF260A3407B4466900CE10E5 = { + fileRef = FF260A3207B4466900CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A3507B4466900CE10E5 = { + fileRef = FF260A3307B4466900CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A4807B4475600CE10E5 = { + children = ( + FF260A4907B4475600CE10E5, + ); + isa = PBXVariantGroup; + name = DNSServiceDiscoveryPref.nib; + path = PreferencePane; + refType = 2; + }; + FF260A4907B4475600CE10E5 = { + isa = PBXFileReference; + name = English; + path = PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib; + refType = 2; + }; + FF260A4A07B4475600CE10E5 = { + fileRef = FF260A4807B4475600CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF260A4B07B4477F00CE10E5 = { + children = ( + FF260A4C07B4477F00CE10E5, + ); + isa = PBXVariantGroup; + name = InfoPlist.strings; + path = PreferencePane; + refType = 2; + }; + FF260A4C07B4477F00CE10E5 = { + fileEncoding = 4; + isa = PBXFileReference; + name = English; + path = PreferencePane/English.lproj/InfoPlist.strings; + refType = 2; + }; + FF260A4D07B4477F00CE10E5 = { + fileRef = FF260A4B07B4477F00CE10E5; + isa = PBXBuildFile; + settings = { + }; + }; + FF2A870607B447EF00B14068 = { + fileRef = FFFB0DAA07B43C9100B88D48; + isa = PBXBuildFile; + settings = { + }; + }; + FF2A870707B4481500B14068 = { + isa = PBXTargetDependency; + target = FF2609E107B440DD00CE10E5; + }; FF37BE9207614059003C0420 = { buildActionMask = 2147483647; files = ( @@ -1596,7 +1998,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -e /usr/local/lib/libdnsinfo.a ]\nthen\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi"; + shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/dnsinfo.h\"\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/dnsinfo.h\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi"; }; FF485D5105632E0000130380 = { fileEncoding = 4; @@ -1615,8 +2017,8 @@ 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"; + shellPath = /bin/tcsh; + shellScript = "# Install plist to tell launchd to start mDNSResponder\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons\ncp ${SRCROOT}/LaunchDaemonInfo.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\n\n# Install mDNSResponder.bundle containing language localizations\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices\ncp -R ${SRCROOT}/mDNSResponder-bundle ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle\n\n# Remove unwanted CVS directories\nfind ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -depth -name CVS -exec rm -rf {} \\;\n\n# Expand UTF-8 files to UTF-16 (not necessary, but required by B&I policy)\nforeach file (`find ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -name Localizable.strings`)\niconv -f utf-8 -t utf-16 ${file} > ${file}.new\nmv -f ${file}.new ${file}\nend\n\n# Remove French localization (not wanted for Apple B&I builds)\nrm -rf ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle/Resources/French.lproj\n"; }; FF5A0AE705632EA600743C27 = { buildActionMask = 8; @@ -1684,6 +2086,27 @@ isa = PBXTargetDependency; target = DB2CC4530662DD6800335AB3; }; + FFE6935007C2CA7F00283007 = { + fileEncoding = 4; + isa = PBXFileReference; + name = ConfigurationAuthority.h; + path = PreferencePane/ConfigurationAuthority.h; + refType = 2; + }; + FFE6935207C2CAA400283007 = { + fileEncoding = 4; + isa = PBXFileReference; + name = DNSServiceDiscoveryPref.h; + path = PreferencePane/DNSServiceDiscoveryPref.h; + refType = 2; + }; + FFE6935407C2CABD00283007 = { + fileEncoding = 4; + isa = PBXFileReference; + name = PrivilegedOperations.h; + path = PreferencePane/PrivilegedOperations.h; + refType = 2; + }; FFF4F63A06CFE4DD00459EFD = { fileEncoding = 4; isa = PBXFileReference; @@ -1724,7 +2147,139 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -e /usr/local/lib/libdnsinfo.a ]\nthen\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi"; + shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/dnsinfo.h\"\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/dnsinfo.h\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi"; + }; + FFFB0DA407B43BED00B88D48 = { + children = ( + FFE6935007C2CA7F00283007, + FFFB0DAE07B43CBA00B88D48, + FFE6935207C2CAA400283007, + FFFB0DAC07B43CBA00B88D48, + FFE6935407C2CABD00283007, + FFFB0DAD07B43CBA00B88D48, + FFFB0DAF07B43CBA00B88D48, + FF260A2307B4463400CE10E5, + ); + isa = PBXGroup; + path = PreferencePane; + refType = 2; + }; + FFFB0DA507B43C9100B88D48 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FFFB0DA607B43C9100B88D48 = { + buildActionMask = 2147483647; + files = ( + FFFB0DB307B43CBA00B88D48, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FFFB0DA707B43C9100B88D48 = { + buildActionMask = 2147483647; + files = ( + FFFB0DB507B43D2700B88D48, + FFFB0DB907B43D5F00B88D48, + FFFB0DBD07B43D7400B88D48, + FF260A2207B443C500CE10E5, + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FFFB0DA807B43C9100B88D48 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FFFB0DA907B43C9100B88D48 = { + buildPhases = ( + FFFB0DA507B43C9100B88D48, + FFFB0DA607B43C9100B88D48, + FFFB0DA707B43C9100B88D48, + FFFB0DA807B43C9100B88D48, + ); + buildSettings = { + MACOSX_DEPLOYMENT_TARGET = 10.2; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = ddnswriteconfig; + REZ_EXECUTABLE = YES; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + dependencies = ( + ); + isa = PBXToolTarget; + name = ddnswriteconfig; + productInstallPath = /usr/local/bin; + productName = ddnswriteconfig; + productReference = FFFB0DAA07B43C9100B88D48; + }; + FFFB0DAA07B43C9100B88D48 = { + isa = PBXExecutableFileReference; + path = ddnswriteconfig; + refType = 3; + }; + FFFB0DAC07B43CBA00B88D48 = { + fileEncoding = 4; + isa = PBXFileReference; + path = DNSServiceDiscoveryPref.m; + refType = 4; + }; + FFFB0DAD07B43CBA00B88D48 = { + fileEncoding = 4; + isa = PBXFileReference; + path = PrivilegedOperations.c; + refType = 4; + }; + FFFB0DAE07B43CBA00B88D48 = { + fileEncoding = 4; + isa = PBXFileReference; + path = ConfigurationAuthority.c; + refType = 4; + }; + FFFB0DAF07B43CBA00B88D48 = { + fileEncoding = 4; + isa = PBXFileReference; + path = ddnswriteconfig.m; + refType = 4; + }; + FFFB0DB307B43CBA00B88D48 = { + fileRef = FFFB0DAF07B43CBA00B88D48; + isa = PBXBuildFile; + settings = { + }; + }; + FFFB0DB407B43D2700B88D48 = { + isa = PBXFrameworkReference; + name = Foundation.framework; + path = /System/Library/Frameworks/Foundation.framework; + refType = 0; + }; + FFFB0DB507B43D2700B88D48 = { + fileRef = FFFB0DB407B43D2700B88D48; + isa = PBXBuildFile; + settings = { + }; + }; + FFFB0DB907B43D5F00B88D48 = { + fileRef = 7F869685066EE02400D2A2DC; + isa = PBXBuildFile; + settings = { + }; + }; + FFFB0DBD07B43D7400B88D48 = { + fileRef = 65713D46025A293200000109; + isa = PBXBuildFile; + settings = { + }; }; }; rootObject = 08FB7793FE84155DC02AAC07; diff --git a/mDNSPosix/Client.c b/mDNSPosix/Client.c index 7b0d48e..6aafe37 100755 --- a/mDNSPosix/Client.c +++ b/mDNSPosix/Client.c @@ -24,6 +24,9 @@ Change History (most recent first): $Log: Client.c,v $ +Revision 1.16 2005/02/04 01:00:53 cheshire +Add '-d' command-line option to specify domain to browse + Revision 1.15 2004/12/16 20:17:11 cheshire Cache memory management improvements @@ -158,21 +161,24 @@ static mDNSBool CheckThatServiceTypeIsUsable(const char *serviceType, mDNSBool p return result; } -static const char kDefaultServiceType[] = "_afpovertcp._tcp."; +static const char kDefaultServiceType[] = "_afpovertcp._tcp"; +static const char kDefaultDomain[] = "local."; static void PrintUsage() { fprintf(stderr, - "Usage: %s [-v level] [-t type]\n", + "Usage: %s [-v level] [-t type] [-d domain]\n", gProgramName); fprintf(stderr, " -v verbose mode, level is a number from 0 to 2\n"); fprintf(stderr, " 0 = no debugging info (default)\n"); fprintf(stderr, " 1 = standard debugging info\n"); fprintf(stderr, " 2 = intense debugging info\n"); fprintf(stderr, " -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType); + fprintf(stderr, " -d uses 'domain' as the domain to browse (default is '%s')\n", kDefaultDomain); } static const char *gServiceType = kDefaultServiceType; +static const char *gServiceDomain = kDefaultDomain; static void ParseArguments(int argc, char **argv) // Parses our command line arguments into the global variables @@ -192,7 +198,7 @@ static void ParseArguments(int argc, char **argv) // Parse command line options using getopt. do { - ch = getopt(argc, argv, "v:t:"); + ch = getopt(argc, argv, "v:t:d:"); if (ch != -1) { switch (ch) { case 'v': @@ -210,6 +216,9 @@ static void ParseArguments(int argc, char **argv) exit(1); } break; + case 'd': + gServiceDomain = optarg; + break; case '?': default: PrintUsage(); @@ -250,7 +259,7 @@ int main(int argc, char **argv) // Construct and start the query. MakeDomainNameFromDNSNameString(&type, gServiceType); - MakeDomainNameFromDNSNameString(&domain, "local."); + MakeDomainNameFromDNSNameString(&domain, gServiceDomain); status = mDNS_StartBrowse(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, mDNSfalse, BrowseCallback, NULL); diff --git a/mDNSPosix/Makefile b/mDNSPosix/Makefile index b9ed8ec..638b56d 100755 --- a/mDNSPosix/Makefile +++ b/mDNSPosix/Makefile @@ -24,6 +24,9 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # $Log: Makefile,v $ +# Revision 1.56 2005/02/02 02:25:21 cheshire +# /var/run/mDNSResponder should be /var/run/mdnsd on Linux +# # Revision 1.55 2005/01/27 22:55:00 cheshire # Add "make os=tiger" target which uses gcc4 and "-Wdeclaration-after-statement" # @@ -216,7 +219,7 @@ LD = ld -shared CP = cp RM = rm LN = ln -s -f -CFLAGS_COMMON = -I. -I$(COREDIR) -I$(SHAREDDIR) -W -Wall -DPID_FILE=\"/var/run/mdnsd.pid\" +CFLAGS_COMMON = -I. -I$(COREDIR) -I$(SHAREDDIR) -W -Wall -DPID_FILE=\"/var/run/mdnsd.pid\" -DMDNS_UDS_SERVERPATH=\"/var/run/mdnsd\" LIBFLAGS = DNSEXT_FLAGS = -D_REENTRANT -g -Wall -lpthread LDSUFFIX = so diff --git a/mDNSPosix/PosixDaemon.c b/mDNSPosix/PosixDaemon.c index 3ebc304..6b991ec 100644 --- a/mDNSPosix/PosixDaemon.c +++ b/mDNSPosix/PosixDaemon.c @@ -28,6 +28,12 @@ Change History (most recent first): $Log: PosixDaemon.c,v $ +Revision 1.27 2005/02/04 00:39:59 cheshire +Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it + +Revision 1.26 2005/02/02 02:21:30 cheshire +Update references to "mDNSResponder" to say "mdnsd" instead + Revision 1.25 2005/01/27 20:01:50 cheshire udsSupportRemoveFDFromEventLoop() needs to close the file descriptor as well @@ -41,7 +47,7 @@ Revision 1.22 2004/12/10 13:12:08 cheshire Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c Revision 1.21 2004/12/01 20:57:20 ksekar - Wide Area Rendezvous must be split-DNS aware + Wide Area Service Discovery must be split-DNS aware Revision 1.20 2004/12/01 04:28:43 cheshire Darwin patches for Solaris and Suse @@ -118,8 +124,6 @@ Add support for mDNSResponder on Linux. #include #include #include -#include -#include #include "mDNSEmbeddedAPI.h" #include "mDNSDebug.h" @@ -127,8 +131,6 @@ Add support for mDNSResponder on Linux. #include "uds_daemon.h" #include "PlatformCommon.h" -#define uDNS_SERVERS_FILE "/etc/resolv.conf" - #define CONFIG_FILE "/etc/mdnsd.conf" static domainname DynDNSZone; // Default wide-area zone for service registration static domainname DynDNSHostname; @@ -138,32 +140,6 @@ static CacheEntity gRRCache[RR_CACHE_SIZE]; extern const char mDNSResponderVersionString[]; -static int ParseDNSServers(mDNS *m, const char *filePath) - { - char line[256]; - char nameserver[16]; - char keyword[10]; - int numOfServers = 0; - FILE *fp = fopen(filePath, "r"); - if (fp == NULL) return -1; - while (fgets(line,sizeof(line),fp)) - { - struct in_addr ina; - line[255]='\0'; // just to be safe - if (sscanf(line,"%10s %15s", keyword, nameserver) != 2) continue; // it will skip whitespaces - if (strncmp(keyword,"nameserver",10)) continue; - if (inet_aton(nameserver, (struct in_addr *)&ina) != 0) - { - mDNSAddr DNSAddr; - DNSAddr.type = mDNSAddrType_IPv4; - DNSAddr.ip.v4.NotAnInteger = ina.s_addr; - mDNS_AddDNSServer(m, &DNSAddr, NULL); - numOfServers++; - } - } - return (numOfServers > 0) ? 0 : -1; - } - static void Reconfigure(mDNS *m) { mDNSAddr DynDNSIP; @@ -183,7 +159,7 @@ static void ParseCmdLinArgs(int argc, char **argv) if (argc > 1) { if (0 == strcmp(argv[1], "-debug")) mDNS_DebugMode = mDNStrue; - else printf("Usage: mDNSResponder [-debug]\n"); + else printf("Usage: %s [-debug]\n", argv[0]); } if (!mDNS_DebugMode) @@ -191,7 +167,7 @@ static void ParseCmdLinArgs(int argc, char **argv) int result = daemon(0, 0); if (result != 0) { LogMsg("Could not run as daemon - exiting"); exit(result); } #if __APPLE__ - LogMsg("The POSIX mDNSResponder should only be used on OS X for testing - exiting"); + LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting"); exit(-1); #endif } @@ -258,6 +234,8 @@ int main(int argc, char **argv) ParseCmdLinArgs(argc, argv); + LogMsgIdent(mDNSResponderVersionString, "starting"); + err = mDNS_Init(&mDNSRecord, &platformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); @@ -279,6 +257,8 @@ int main(int argc, char **argv) if (mStatus_NoError == err) err = MainLoop(&mDNSRecord); + LogMsgIdent(mDNSResponderVersionString, "stopping"); + mDNS_Close(&mDNSRecord); if (udsserver_exit() < 0) diff --git a/mDNSPosix/ReadMe.txt b/mDNSPosix/ReadMe.txt index d128c8d..80f8fa3 100755 --- a/mDNSPosix/ReadMe.txt +++ b/mDNSPosix/ReadMe.txt @@ -15,9 +15,9 @@ technologies, see the zeroconf web site. -Apple uses the brand name "Rendezvous" to describe our implementation of +Apple uses the trade mark "Bonjour" to describe our implementation of zeroconf technologies. This sample is designed to show how easy it is -to make a device "Rendezvous compatible". +to make a device "Bonjour compatible". The code in this sample was compiled and tested on Mac OS X (10.1.x, 10.2, 10.3), Solaris (SunOS 5.8), Linux (Redhat 2.4.9-21, Fedora Core 1), diff --git a/mDNSPosix/Responder.c b/mDNSPosix/Responder.c index b54d3a8..7765669 100755 --- a/mDNSPosix/Responder.c +++ b/mDNSPosix/Responder.c @@ -24,6 +24,9 @@ Change History (most recent first): $Log: Responder.c,v $ +Revision 1.29 2005/03/04 21:35:33 cheshire + Services.txt file not parsed properly when it contains more than one service + Revision 1.28 2005/01/11 01:55:26 ksekar Fix compile errors in Posix debug build @@ -211,42 +214,26 @@ static void HandleSigQuit(int sigraised) #pragma mark ***** Parameter Checking #endif -static mDNSBool CheckThatRichTextHostNameIsUsable(const char *richTextHostName, mDNSBool printExplanation) - // Checks that richTextHostName is a reasonable host name +static mDNSBool CheckThatRichTextNameIsUsable(const char *richTextName, mDNSBool printExplanation) + // Checks that richTextName is reasonable // label and, if it isn't and printExplanation is true, prints // an explanation of why not. { - mDNSBool result; - domainlabel richLabel; - domainlabel poorLabel; - - result = mDNStrue; - if (result && strlen(richTextHostName) > 63) { + mDNSBool result = mDNStrue; + if (result && strlen(richTextName) > 63) { if (printExplanation) { fprintf(stderr, - "%s: Host name is too long (must be 63 characters or less)\n", + "%s: Service name is too long (must be 63 characters or less)\n", gProgramName); } result = mDNSfalse; } - if (result && richTextHostName[0] == 0) { + if (result && richTextName[0] == 0) { if (printExplanation) { - fprintf(stderr, "%s: Host name can't be empty\n", gProgramName); + fprintf(stderr, "%s: Service name can't be empty\n", gProgramName); } result = mDNSfalse; } - if (result) { - MakeDomainLabelFromLiteralString(&richLabel, richTextHostName); - ConvertUTF8PstringToRFC1034HostLabel(richLabel.c, &poorLabel); - if (poorLabel.c[0] == 0) { - if (printExplanation) { - fprintf(stderr, - "%s: Host name doesn't produce a usable RFC-1034 name\n", - gProgramName); - } - result = mDNSfalse; - } - } return result; } @@ -318,7 +305,7 @@ static void PrintUsage() fprintf(stderr, " 2 = intense debugging info\n"); fprintf(stderr, " can be cycled kill -USR1\n"); fprintf(stderr, " -r also bind to port 53 (port 5353 is always bound)\n"); - fprintf(stderr, " -n uses 'name' as the host name (default is none)\n"); + fprintf(stderr, " -n uses 'name' as the service name (required)\n"); fprintf(stderr, " -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType); fprintf(stderr, " -d uses 'domain' as the service domain (default is '%s')\n", kDefaultServiceDomain); fprintf(stderr, " -p uses 'port' as the port number (default is '%d')\n", kDefaultPortNumber); @@ -333,7 +320,7 @@ static void PrintUsage() } static mDNSBool gAvoidPort53 = mDNStrue; -static const char *gRichTextHostName = ""; +static const char *gServiceName = ""; static const char *gServiceType = kDefaultServiceType; static const char *gServiceDomain = kDefaultServiceDomain; static mDNSu8 gServiceText[sizeof(RDataBody)]; @@ -377,8 +364,8 @@ static void ParseArguments(int argc, char **argv) gAvoidPort53 = mDNSfalse; break; case 'n': - gRichTextHostName = optarg; - if ( ! CheckThatRichTextHostNameIsUsable(gRichTextHostName, mDNStrue) ) { + gServiceName = optarg; + if ( ! CheckThatRichTextNameIsUsable(gServiceName, mDNStrue) ) { exit(1); } break; @@ -435,9 +422,9 @@ static void ParseArguments(int argc, char **argv) // Check for inconsistency between the arguments. - if ( (gRichTextHostName[0] == 0) && (gServiceFile[0] == 0) ) { + if ( (gServiceName[0] == 0) && (gServiceFile[0] == 0) ) { PrintUsage(); - fprintf(stderr, "%s: You must specify a service to register (-n) or a service file (-f).\n", gProgramName); + fprintf(stderr, "%s: You must specify a service name to register (-n) or a service file (-f).\n", gProgramName); exit(1); } } @@ -515,7 +502,7 @@ static void RegistrationCallback(mDNS *const m, ServiceRecordSet *const thisRegi static int gServiceID = 0; -static mStatus RegisterOneService(const char * richTextHostName, +static mStatus RegisterOneService(const char * richTextName, const char * serviceType, const char * serviceDomain, const mDNSu8 text[], @@ -534,7 +521,7 @@ static mStatus RegisterOneService(const char * richTextHostName, status = mStatus_NoMemoryErr; } if (status == mStatus_NoError) { - MakeDomainLabelFromLiteralString(&name, richTextHostName); + MakeDomainLabelFromLiteralString(&name, richTextName); MakeDomainNameFromDNSNameString(&type, serviceType); MakeDomainNameFromDNSNameString(&domain, serviceDomain); status = mDNS_RegisterService(&mDNSStorage, &thisServ->coreServ, @@ -557,7 +544,7 @@ static mStatus RegisterOneService(const char * richTextHostName, "%s: Registered service %d, name '%s', type '%s', port %ld\n", gProgramName, thisServ->serviceID, - richTextHostName, + richTextName, serviceType, portNumber); } @@ -575,7 +562,7 @@ static mDNSBool ReadALine(char *buf, size_t bufSize, FILE *fp) mDNSBool good, skip; do { good = (fgets(buf, bufSize, fp) != NULL); - skip = (good && (buf[0] == '#' || buf[0] == '\r' || buf[0] == '\n')); + skip = (good && (buf[0] == '#')); } while (good && skip); if (good) { @@ -598,6 +585,7 @@ static mStatus RegisterServicesInFile(const char *filePath) if (status == mStatus_NoError) { mDNSBool good = mDNStrue; do { + int ch; char name[256]; char type[256]; const char *dom = kDefaultServiceDomain; @@ -605,6 +593,10 @@ static mStatus RegisterServicesInFile(const char *filePath) mDNSu8 text[sizeof(RDataBody)]; mDNSu16 textLen = 0; char port[256]; + + // Skip over any blank lines. + do ch = fgetc(fp); while ( ch == '\n' || ch == '\r' ); + if (ch != EOF) good = (ungetc(ch, fp) == ch); // Read three lines, check them for validity, and register the service. good = ReadALine(name, sizeof(name), fp); @@ -623,28 +615,32 @@ static mStatus RegisterServicesInFile(const char *filePath) good = ReadALine(port, sizeof(port), fp); } if (good) { - good = CheckThatRichTextHostNameIsUsable(name, mDNSfalse) + good = CheckThatRichTextNameIsUsable(name, mDNSfalse) && CheckThatServiceTypeIsUsable(type, mDNSfalse) && CheckThatPortNumberIsUsable(atol(port), mDNSfalse); } if (good) { while (1) { + int len; if (!ReadALine(rawText, sizeof(rawText), fp)) break; - text[textLen] = strlen(rawText); - if (text[textLen] == 0) break; - memcpy(text + textLen + 1, rawText, text[textLen]); - textLen += 1 + text[textLen]; + len = strlen(rawText); + if (len <= 255) + { + text[textLen] = len; + if (text[textLen] == 0) break; + memcpy(text + textLen + 1, rawText, text[textLen]); + textLen += 1 + text[textLen]; + } + else + fprintf(stderr, "%s: TXT attribute too long for name = %s, type = %s, port = %s\n", + gProgramName, name, type, port); } } if (good) { status = RegisterOneService(name, type, dom, text, textLen, atol(port)); if (status != mStatus_NoError) { - fprintf(stderr, - "%s: Failed to register service, name = %s, type = %s, port = %s\n", - gProgramName, - name, - type, - port); + fprintf(stderr, "%s: Failed to register service, name = %s, type = %s, port = %s\n", + gProgramName, name, type, port); status = mStatus_NoError; // keep reading } } @@ -668,8 +664,8 @@ static mStatus RegisterOurServices(void) mStatus status; status = mStatus_NoError; - if (gRichTextHostName[0] != 0) { - status = RegisterOneService(gRichTextHostName, + if (gServiceName[0] != 0) { + status = RegisterOneService(gServiceName, gServiceType, gServiceDomain, gServiceText, gServiceTextLen, diff --git a/mDNSPosix/dnsextd.c b/mDNSPosix/dnsextd.c index c9d0c73..687507e 100644 --- a/mDNSPosix/dnsextd.c +++ b/mDNSPosix/dnsextd.c @@ -24,6 +24,15 @@ Change History (most recent first): $Log: dnsextd.c,v $ +Revision 1.33 2005/03/11 19:09:02 ksekar +Fixed ZERO_LLQID macro + +Revision 1.32 2005/03/10 22:54:33 ksekar + dnsextd leaks memory/ports + +Revision 1.31 2005/02/24 02:37:57 ksekar + dnsextd memory management improvements + Revision 1.30 2005/01/27 22:57:56 cheshire Fix compile errors on gcc4 @@ -71,7 +80,7 @@ Revision 1.16 2004/11/25 02:02:28 ksekar Fixed verbose log message argument Revision 1.15 2004/11/19 02:35:02 ksekar - Wide Area Rendezvous Security: Add LLQ-ID to events + Wide Area Security: Add LLQ-ID to events Revision 1.14 2004/11/17 06:17:58 cheshire Update comments to show correct SRV names: _dns-update._udp.. and _dns-llq._udp.. @@ -180,7 +189,7 @@ Revision 1.1 2004/08/11 00:43:26 ksekar #endif #define SAME_INADDR(x,y) (*((mDNSu32 *)&x) == *((mDNSu32 *)&y)) -#define ZERO_LLQID(x) (!memcmp(x, "\x0\x0\x0\x0", 8)) +#define ZERO_LLQID(x) (!memcmp(x, "\x0\x0\x0\x0\x0\x0\x0\x0", 8)) // // Data Structures @@ -213,6 +222,16 @@ typedef enum Established = 2 } LLQState; +typedef struct AnswerListElem + { + struct AnswerListElem *next; + domainname name; + mDNSu16 type; + CacheRecord *KnownAnswers; // All valid answers delivered to client + CacheRecord *EventList; // New answers (adds/removes) to be sent to client + int refcount; + } AnswerListElem; + // llq table entry typedef struct LLQEntry { @@ -224,7 +243,7 @@ typedef struct LLQEntry LLQState state; mDNSu32 lease; // original lease, in seconds mDNSs32 expire; // expiration, absolute, in seconds since epoch - CacheRecord *KnownAnswers;// !!!KRS this should be shared amongst identical questions + AnswerListElem *AnswerList; } LLQEntry; // daemon-wide information @@ -248,6 +267,7 @@ typedef struct // LLQ table variables LLQEntry *LLQTable[LLQ_TABLESIZE]; // !!!KRS change this and RRTable to use a common data structure + AnswerListElem *AnswerTable[LLQ_TABLESIZE]; int LLQEventListenSock; // Unix domain socket pair - polling thread writes to ServPollSock, which wakes int LLQServPollSock; // the main thread listening on EventListenSock, indicating that the zone has changed } DaemonInfo; @@ -576,6 +596,7 @@ mDNSlocal void RehashTable(DaemonInfo *d) RRTableElem *ptr, *tmp, **new; int i, bucket, newnbuckets = d->nbuckets * 2; + VLog("Rehashing lease table (new size %d buckets)", newnbuckets); new = malloc(sizeof(RRTableElem *) * newnbuckets); if (!new) { LogErr("RehashTable", "malloc"); return; } bzero(new, newnbuckets * sizeof(RRTableElem *)); @@ -593,6 +614,8 @@ mDNSlocal void RehashTable(DaemonInfo *d) } } d->nbuckets = newnbuckets; + free(d->table); + d->table = new; } // print entire contents of hashtable, invoked via SIGINFO @@ -995,9 +1018,10 @@ mDNSlocal void DeleteExpiredRecords(DaemonInfo *d) // Add, delete, or refresh records in table based on contents of a successfully completed dynamic update mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease) { - RRTableElem *prev, *rptr, *new = NULL; - int i, bucket; + RRTableElem **rptr, *tmp; + int i, allocsize, bucket; LargeCacheRecord lcr; + ResourceRecord *rr = &lcr.r.resrec; const mDNSu8 *ptr, *end; struct timeval time; DNSQuestion zone; @@ -1014,68 +1038,77 @@ mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease) for (i = 0; i < pkt->msg.h.mDNS_numUpdates; i++) { + mDNSBool DeleteAllRRSets = mDNSfalse, DeleteOneRRSet = mDNSfalse, DeleteOneRR = mDNSfalse; + ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); if (!ptr) { Log("UpdateLeaseTable: GetLargeResourceRecord returned NULL"); goto cleanup; } - //!!!KRS we should include rdata in hash here - bucket = lcr.r.resrec.namehash % d->nbuckets; - - // look for RR in table - prev = NULL; - rptr = d->table[bucket]; - while (rptr) + bucket = rr->namehash % d->nbuckets; + rptr = &d->table[bucket]; + + // handle deletions + if (rr->rrtype == kDNSQType_ANY && !rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength) + DeleteAllRRSets = mDNStrue; // delete all rrsets for a name + else if (!rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength) + DeleteOneRRSet = mDNStrue; + else if (!rr->rroriginalttl && rr->rrclass == kDNSClass_NONE) + DeleteOneRR = mDNStrue; + + if (DeleteAllRRSets || DeleteOneRRSet || DeleteOneRR) { - if (SameResourceRecord(&rptr->rr.resrec, &lcr.r.resrec)) break; - prev = rptr; - rptr = rptr->next; + while (*rptr) + { + if (SameDomainName((*rptr)->rr.resrec.name, rr->name) && + (DeleteAllRRSets || + (DeleteOneRRSet && (*rptr)->rr.resrec.rrtype == rr->rrtype) || + (DeleteOneRR && SameResourceRecord(&(*rptr)->rr.resrec, rr)))) + { + tmp = *rptr; + VLog("Received deletion update for %s", GetRRDisplayString_rdb(&tmp->rr.resrec, &tmp->rr.resrec.rdata->u, buf)); + *rptr = (*rptr)->next; + free(tmp); + d->nelems--; + } + else rptr = &(*rptr)->next; + } } - - if (rptr) + else if (lease > 0) { - // Record is already in table - if (!lcr.r.resrec.rroriginalttl && lcr.r.resrec.rrclass == kDNSClass_NONE) + // see if add or refresh + while (*rptr && !SameResourceRecord(&(*rptr)->rr.resrec, rr)) rptr = &(*rptr)->next; + if (*rptr) { - // deletion record - VLog("Received deletion update for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); - if (prev) prev->next = rptr->next; - else d->table[bucket] = rptr->next; - free(rptr); - d->nelems--; + // refresh + if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } + (*rptr)->expire = time.tv_sec + (unsigned)lease; + VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); } else { - // refresh - if (lease < 0) + // New record - add to table + if (d->nelems > d->nbuckets) { - Log("Update for record %s already in lease table with no refresh lease specified", - GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); - } - else - { - if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } - rptr->expire = time.tv_sec + (unsigned)lease; - VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); + RehashTable(d); + bucket = rr->namehash % d->nbuckets; + rptr = &d->table[bucket]; } + if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } + allocsize = sizeof(RRTableElem); + if (rr->rdlength > InlineCacheRDSize) allocsize += (rr->rdlength - InlineCacheRDSize); + tmp = malloc(allocsize); + if (!tmp) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; } + memcpy(&tmp->rr, &lcr.r, sizeof(CacheRecord) + rr->rdlength - InlineCacheRDSize); + tmp->rr.resrec.rdata = (RData *)&tmp->rr.rdatastorage; + AssignDomainName(&tmp->name, rr->name); + tmp->rr.resrec.name = &tmp->name; + tmp->expire = time.tv_sec + (unsigned)lease; + tmp->cli.sin_addr = pkt->src.sin_addr; + AssignDomainName(&tmp->zone, &zone.qname); + tmp->next = d->table[bucket]; + d->table[bucket] = tmp; + d->nelems++; + VLog("Adding update for %s to lease table", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); } } - else if (lease > 0) - { - // New record - add to table - if (d->nelems > d->nbuckets) RehashTable(d); - if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } - new = malloc(sizeof(RRTableElem) + lcr.r.resrec.rdlength - InlineCacheRDSize); - 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; - AssignDomainName(&new->zone, &zone.qname); - new->next = d->table[bucket]; - d->table[bucket] = new; - d->nelems++; - VLog("Adding update for %s to lease table", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); - } } cleanup: @@ -1172,41 +1205,39 @@ mDNSlocal mDNSu32 LLQLease(LLQEntry *e) else return e->expire - t.tv_sec; } -mDNSlocal void FreeKnownAnswers(LLQEntry *e) - { - CacheRecord *tmp; - - while(e->KnownAnswers) - { - tmp = e->KnownAnswers; - e->KnownAnswers = e->KnownAnswers->next; - free(tmp); - } - } - mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e) { - int bucket = bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE; - LLQEntry *prev = NULL, *ptr = d->LLQTable[bucket]; + int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE; + LLQEntry **ptr = &d->LLQTable[bucket]; + AnswerListElem *a = e->AnswerList; char addr[32]; inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); VLog("Deleting LLQ table entry for %##s client %s", e->qname.c, addr); - FreeKnownAnswers(e); - while(ptr) + // free shared answer structure if ref count drops to zero + if (a && !(--a->refcount)) { - if (ptr == e) + CacheRecord *cr = a->KnownAnswers, *tmp; + AnswerListElem **tbl = &d->AnswerTable[bucket]; + + while (cr) { - if (prev) prev->next = ptr->next; - else d->LLQTable[bucket] = ptr->next; - free(e); - return; + tmp = cr; + cr = cr->next; + free(tmp); } - prev = ptr; - ptr = ptr->next; + + while (*tbl && *tbl != a) tbl = &(*tbl)->next; + if (*tbl) { *tbl = (*tbl)->next; free(a); } + else Log("Error: DeleteLLQ - AnswerList not found in table"); } - Log("Error: DeleteLLQ - LLQ not in table"); + + // remove LLQ from table, free memory + while(*ptr && *ptr != e) ptr = &(*ptr)->next; + if (!*ptr) { Log("Error: DeleteLLQ - LLQ not in table"); return; } + *ptr = (*ptr)->next; + free(e); } mDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst) @@ -1227,7 +1258,7 @@ mDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst) // if non-negative, sd is a TCP socket connected to the nameserver // otherwise, this routine creates and closes its own socket -mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd) +mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e, int sd) { PktMsg q; int i; @@ -1240,13 +1271,13 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd) mDNSu8 rcode; mDNSBool CloseSDOnExit = sd < 0; - VLog("Querying server for %##s type %d", e->qname.c, e->qtype); + VLog("Querying server for %##s type %d", e->name.c, e->type); flags.b[0] |= kDNSFlag0_RD; // recursion desired id.NotAnInteger = 0; InitializeDNSMessage(&q.msg.h, id, flags); - end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); + end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->name, e->type, kDNSClass_IN); if (!end) { Log("Error: AnswerQuestion - putQuestion returned NULL"); goto end; } q.len = (int)(end - (mDNSu8 *)&q.msg); @@ -1258,7 +1289,7 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd) if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery)) { Log("AnswerQuestion: %##s type %d - Invalid response flags from server"); goto end; } rcode = (mDNSu8)(reply->msg.h.flags.b[1] & kDNSFlag1_RC); - if (rcode && rcode != kDNSFlag1_RC_NXDomain) { Log("AnswerQuestion: %##s type %d - non-zero rcode %d from server", e->qname.c, e->qtype, rcode); goto end; } + if (rcode && rcode != kDNSFlag1_RC_NXDomain) { Log("AnswerQuestion: %##s type %d - non-zero rcode %d from server", e->name.c, e->type, rcode); goto end; } end = (mDNSu8 *)&reply->msg + reply->len; ansptr = LocateAnswers(&reply->msg, end); @@ -1266,18 +1297,16 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd) for (i = 0; i < reply->msg.h.numAnswers; i++) { - //rr = malloc(sizeof(*rr)); - //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->type || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->name)) { Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d. Discarding", - lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->qname.c, e->qtype); + lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->name.c, e->type); } else { - CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->qname); + CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->name); if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; } cr->next = AnswerList; AnswerList = cr; @@ -1287,94 +1316,102 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd) end: if (sd > -1 && CloseSDOnExit) close(sd); if (reply) free(reply); - e->state = Established; return AnswerList; } -mDNSlocal void UpdateAnswerList(DaemonInfo *d, LLQEntry *e, CacheRecord *answers) +// Routine sets EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list +mDNSlocal void UpdateAnswerList(DaemonInfo *d, AnswerListElem *a, int sd) { - CacheRecord *prev = NULL, *na, *ka; // "new answer", "known answer" - PktMsg response; - mDNSu8 *end = (mDNSu8 *)&response.msg.data; - mDNSOpaque16 msgID; - char rrbuf[80], addrbuf[32]; - AuthRecord opt; + CacheRecord *cr, *NewAnswers, **na, **ka; // "new answer", "known answer" + + // get up to date answers + NewAnswers = AnswerQuestion(d, a, sd); // first pass - mark all answers for deletion - for (ka = e->KnownAnswers; ka; ka = ka->next) - ka->resrec.rroriginalttl = -1; // -1 means delete + for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) + (*ka)->resrec.rroriginalttl = (unsigned)-1; // -1 means delete // second pass - mark answers pre-existent - for (ka = e->KnownAnswers; ka; ka = ka->next) + for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) { - for (na = answers; na; na = na->next) + for (na = &NewAnswers; *na; na = &(*na)->next) { - if (SameResourceRecord(&ka->resrec, &na->resrec)) - { ka->resrec.rroriginalttl = 0; break; } // 0 means no change + if (SameResourceRecord(&(*ka)->resrec, &(*na)->resrec)) + { (*ka)->resrec.rroriginalttl = 0; break; } // 0 means no change } } - // third pass - add new records - for (na = answers; na; na = na->next) + // third pass - add new records to Event list + na = &NewAnswers; + while (*na) { - for (ka = e->KnownAnswers; ka; ka = ka->next) - if (SameResourceRecord(&ka->resrec, &na->resrec)) break; - if (!ka) + for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) + if (SameResourceRecord(&(*ka)->resrec, &(*na)->resrec)) break; + if (!*ka) { - // answer is not in KA list - CacheRecord *cr = CopyCacheRecord(na, &e->qname); - if (!cr) { Log("Error: UpdateAnswerList - CopyCacheRecord returned NULL"); return; } + // answer is not in list - splice from NewAnswers list, add to Event list + cr = *na; + *na = (*na)->next; // splice from list + cr->next = a->EventList; // add spliced record to event list + a->EventList = cr; cr->resrec.rroriginalttl = 1; // 1 means add - cr->next = e->KnownAnswers; - e->KnownAnswers = cr; } + else na = &(*na)->next; } - - // now send the update - msgID.NotAnInteger = random(); - InitializeDNSMessage(&response.msg.h, msgID, ResponseFlags); - end = putQuestion(&response.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); - if (!end) { Log("Error: UpdateAnswerList - putQuestion returned NULL"); return; } - - if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32); - // put adds/removes in packet - for (ka = e->KnownAnswers; ka; ka = ka->next) + + // move all the removes from the answer list to the event list + ka = &a->KnownAnswers; + while (*ka) { - if (ka->resrec.rroriginalttl) + if ((*ka)->resrec.rroriginalttl == (unsigned)-1) { - if (verbose) GetRRDisplayString_rdb(&ka->resrec, &ka->resrec.rdata->u, rrbuf); - VLog("%s (%s): %s", addrbuf, (mDNSs32)ka->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf); - end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &ka->resrec, ka->resrec.rroriginalttl); - if (!end) { Log("Error: UpdateAnswerList - UpdateAnswerList returned NULL"); return; } + cr = *ka; + *ka = (*ka)->next; + cr->next = a->EventList; + a->EventList = cr; } + else ka = &(*ka)->next; } + + // lastly, free the remaining records (known answers) in NewAnswers list + while (NewAnswers) + { + cr = NewAnswers; + NewAnswers = NewAnswers->next; + free(cr); + } + } - // delete removes from list - ka = e->KnownAnswers; - while (ka) +mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e) + { + PktMsg response; + CacheRecord *cr; + mDNSu8 *end = (mDNSu8 *)&response.msg.data; + mDNSOpaque16 msgID; + char rrbuf[80], addrbuf[32]; + AuthRecord opt; + + msgID.NotAnInteger = random(); + if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32); + InitializeDNSMessage(&response.msg.h, msgID, ResponseFlags); + end = putQuestion(&response.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); + if (!end) { Log("Error: SendEvents - putQuestion returned NULL"); return; } + + // put adds/removes in packet + for (cr = e->AnswerList->EventList; cr; cr = cr->next) { - if ((mDNSs32)ka->resrec.rroriginalttl < 0) - { - CacheRecord *fptr = ka; - if (prev) prev->next = ka->next; - else e->KnownAnswers = ka->next; - ka = ka->next; - free(fptr); - } - else - { - prev = ka; - ka = ka->next; - } + if (verbose) GetRRDisplayString_rdb(&cr->resrec, &cr->resrec.rdata->u, rrbuf); + VLog("%s (%s): %s", addrbuf, (mDNSs32)cr->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf); + end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &cr->resrec, cr->resrec.rroriginalttl); + if (!end) { Log("Error: SendEvents - UpdateAnswerList returned NULL"); return; } } FormatLLQOpt(&opt, kLLQOp_Event, e->id, LLQLease(e)); end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAdditionals, &opt.resrec, 0); - if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } + if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo"); return; } response.len = (int)(end - (mDNSu8 *)&response.msg); - if (response.msg.h.numAnswers) - if (SendLLQ(d, &response, e->cli) < 0) LogErr("UpdateAnswerList", "SendLLQ"); + if (SendLLQ(d, &response, e->cli) < 0) LogMsg("Error: SendEvents - SendLLQ"); } mDNSlocal void PrintLLQTable(DaemonInfo *d) @@ -1401,38 +1438,69 @@ mDNSlocal void PrintLLQTable(DaemonInfo *d) // Send events to clients as a result of a change in the zone mDNSlocal void GenLLQEvents(DaemonInfo *d) { - LLQEntry *e, *tmp; + LLQEntry **e; int i, sd; struct timeval t; - char addr[32]; + VLog("Generating LLQ Events"); gettimeofday(&t, NULL); sd = ConnectToServer(d); if (sd < 0) { Log("GenLLQEvents: ConnectToServer failed"); return; } - + + // get all answers up to date for (i = 0; i < LLQ_TABLESIZE; i++) { - e = d->LLQTable[i]; - while(e) + AnswerListElem *a = d->AnswerTable[i]; + while(a) { - if (e->expire < t.tv_sec) - { - inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); - VLog("Expiring LLQ %##s from %s", e->qname.c, addr); - tmp = e; - e = e->next; - DeleteLLQ(d, tmp); - } + UpdateAnswerList(d, a, sd); + a = a->next; + } + } + + // for each established LLQ, send events + for (i = 0; i < LLQ_TABLESIZE; i++) + { + e = &d->LLQTable[i]; + while(*e) + { + if ((*e)->expire < t.tv_sec) DeleteLLQ(d, *e); else { - CacheRecord *tmp, *answers = AnswerQuestion(d, e, sd); - UpdateAnswerList(d, e, answers); - while (answers) { tmp = answers; answers = answers->next; free(tmp); } - e = e->next; + if ((*e)->state == Established && (*e)->AnswerList->EventList) SendEvents(d, *e); + e = &(*e)->next; } - } + } } + + // now that all LLQs are updated, we move Add events from the Event list to the Known Answer list, and free Removes + for (i = 0; i < LLQ_TABLESIZE; i++) + { + AnswerListElem *a = d->AnswerTable[i]; + while(a) + { + if (a->EventList) + { + CacheRecord *cr = a->EventList, *tmp; + while (cr) + { + tmp = cr; + cr = cr->next; + if ((signed)tmp->resrec.rroriginalttl < 0) free(tmp); + else + { + tmp->next = a->KnownAnswers; + a->KnownAnswers = tmp; + tmp->resrec.rroriginalttl = 0; + } + } + a->EventList = NULL; + } + a = a->next; + } + } + close(sd); } @@ -1506,14 +1574,43 @@ mDNSlocal void *LLQEventMonitor(void *DInfoPtr) if (!ptr) Log("LLQEventMonitor: response to query did not contain SOA"); } } - + +mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e) + { + int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE; + AnswerListElem *a = d->AnswerTable[bucket]; + while (a && (a->type != e->qtype ||!SameDomainName(&a->name, &e->qname))) a = a->next; + if (!a) + { + a = malloc(sizeof(*a)); + if (!a) { LogErr("SetAnswerList", "malloc"); return; } + AssignDomainName(&a->name, &e->qname); + a->type = e->qtype; + a->refcount = 0; + a->KnownAnswers = NULL; + a->EventList = NULL; + a->next = d->AnswerTable[bucket]; + d->AnswerTable[bucket] = a; + + // to get initial answer list, call UpdateAnswerList and move cache records from EventList to KnownAnswers + UpdateAnswerList(d, a, -1); + a->KnownAnswers = a->EventList; + a->EventList = NULL; + } + + e->AnswerList = a; + a->refcount ++; + } + // Allocate LLQ entry, insert into table mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, mDNSu32 lease) { char addr[32]; struct timeval t; - int bucket; - LLQEntry *e = malloc(sizeof(*e)); + int bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE; + LLQEntry *e; + + e = malloc(sizeof(*e)); if (!e) { LogErr("NewLLQ", "malloc"); return NULL; } inet_ntop(AF_INET, &cli.sin_addr, addr, 32); @@ -1525,7 +1622,7 @@ mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qn e->qtype = qtype; memset(e->id, 0, 8); e->state = RequestReceived; - e->KnownAnswers = NULL; + e->AnswerList = NULL; if (lease < LLQ_MIN_LEASE) lease = LLQ_MIN_LEASE; else if (lease > LLQ_MAX_LEASE) lease = LLQ_MIN_LEASE; @@ -1534,7 +1631,6 @@ mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qn e->lease = lease; // add to table - bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE; e->next = d->LLQTable[bucket]; d->LLQTable[bucket] = e; @@ -1603,9 +1699,10 @@ mDNSlocal void LLQCompleteHandshake(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); if (!end) { Log("Error: putQuestion"); return; } - if (e->state != Established) e->KnownAnswers = AnswerQuestion(d, e, -1); // only fetch KA list the first time through + if (e->state != Established) { SetAnswerList(d, e); e->state = Established; } + if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32); - for (ptr = e->KnownAnswers; ptr; ptr = ptr->next) + for (ptr = e->AnswerList->KnownAnswers; ptr; ptr = ptr->next) { if (verbose) GetRRDisplayString_rdb(&ptr->resrec, &ptr->resrec.rdata->u, rrbuf); VLog("%s Intitial Answer - %s", addr, rrbuf); @@ -1820,7 +1917,7 @@ mDNSlocal void *UDPUpdateRequestForkFn(void *vptr) if (reply) free(reply); free(req); - return NULL; + pthread_exit(NULL); } //!!!KRS this needs to be changed to use non-blocking sockets @@ -1847,9 +1944,10 @@ mDNSlocal int RecvUDPRequest(int sd, DaemonInfo *d) return err; } - if (IsLLQAck(&req->pkt)) return 0; // !!!KRS need to do acks + retrans + if (IsLLQAck(&req->pkt)) { free(req); return 0; } // !!!KRS need to do acks + retrans if (pthread_create(&tid, NULL, UDPUpdateRequestForkFn, req)) { LogErr("RecvUDPRequest", "pthread_create"); free(req); return -1; } + pthread_detach(tid); return 0; } @@ -1888,7 +1986,7 @@ mDNSlocal void *TCPRequestForkFn(void *vptr) free(req); if (in) free(in); if (out) free(out); - return NULL; + pthread_exit(NULL); } mDNSlocal int RecvTCPRequest(int sd, DaemonInfo *d) @@ -1905,6 +2003,7 @@ mDNSlocal int RecvTCPRequest(int sd, DaemonInfo *d) if (req->sd < 0) { LogErr("RecvTCPRequest", "accept"); return -1; } if (clilen != sizeof(req->cliaddr)) { Log("Client address of unknown size %d", clilen); free(req); return -1; } if (pthread_create(&tid, NULL, TCPRequestForkFn, req)) { LogErr("RecvTCPRequest", "pthread_create"); free(req); return -1; } + pthread_detach(tid); return 0; } @@ -1978,15 +2077,18 @@ mDNSlocal void HndlSignal(int sig) int main(int argc, char *argv[]) { pthread_t LLQtid; - DaemonInfo d; - bzero(&d, sizeof(DaemonInfo)); + DaemonInfo *d; + + d = malloc(sizeof(*d)); + if (!d) { LogErr("main", "malloc"); exit(1); } + bzero(d, sizeof(DaemonInfo)); if (signal(SIGTERM, HndlSignal) == SIG_ERR) perror("Can't catch SIGTERM"); if (signal(INFO_SIGNAL, HndlSignal) == SIG_ERR) perror("Can't catch SIGINFO"); if (signal(SIGINT, HndlSignal) == SIG_ERR) perror("Can't catch SIGINT"); if (signal(SIGPIPE, SIG_IGN ) == SIG_ERR) perror("Can't ignore SIGPIPE"); - if (ProcessArgs(argc, argv, &d) < 0) exit(1); + if (ProcessArgs(argc, argv, d) < 0) exit(1); if (!foreground) { @@ -1998,14 +2100,19 @@ int main(int argc, char *argv[]) } } - if (InitLeaseTable(&d) < 0) exit(1); - if (SetupSockets(&d) < 0) exit(1); - if (SetUpdateSRV(&d) < 0) exit(1); + if (InitLeaseTable(d) < 0) exit(1); + if (SetupSockets(d) < 0) exit(1); + if (SetUpdateSRV(d) < 0) exit(1); - if (pthread_create(&LLQtid, NULL, LLQEventMonitor, &d)) { LogErr("main", "pthread_create"); } - else ListenForUpdates(&d); + if (pthread_create(&LLQtid, NULL, LLQEventMonitor, d)) { LogErr("main", "pthread_create"); } + else + { + pthread_detach(LLQtid); + ListenForUpdates(d); + } - if (ClearUpdateSRV(&d) < 0) exit(1); // clear update srv's even if ListenForUpdates or pthread_create returns an error + if (ClearUpdateSRV(d) < 0) exit(1); // clear update srv's even if ListenForUpdates or pthread_create returns an error + free(d); exit(0); + } - diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c index f15a88a..3970b4b 100755 --- a/mDNSPosix/mDNSPosix.c +++ b/mDNSPosix/mDNSPosix.c @@ -37,6 +37,12 @@ Change History (most recent first): $Log: mDNSPosix.c,v $ +Revision 1.71 2005/02/26 01:29:12 cheshire +Ignore multicasts accidentally delivered to our unicast receiving socket + +Revision 1.70 2005/02/04 00:39:59 cheshire +Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it + Revision 1.69 2004/12/18 02:03:28 cheshire Need to #include "dns_sd.h" @@ -284,6 +290,7 @@ First checkin #include #include #include +#include #include // platform support for UTC time #if USES_NETLINK @@ -497,16 +504,21 @@ mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int s // different capabilities of our target platforms. reject = mDNSfalse; - if (intf) + if (!intf) + { + // Ignore multicasts accidentally delivered to our unicast receiving socket + if (mDNSAddrIsDNSMulticast(&destAddr)) packetLen = -1; + } + else { if ( packetInfo.ipi_ifname[0] != 0 ) reject = (strcmp(packetInfo.ipi_ifname, intf->intfName) != 0); else if ( packetInfo.ipi_ifindex != -1 ) reject = (packetInfo.ipi_ifindex != intf->index); if (reject) { - verbosedebugf("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d", + verbosedebugf("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d/%d", &senderAddr, &destAddr, packetInfo.ipi_ifname, packetInfo.ipi_ifindex, - &intf->coreIntf.ip, intf->intfName, intf->index); + &intf->coreIntf.ip, intf->intfName, intf->index, skt); packetLen = -1; num_pkts_rejected++; if (num_pkts_rejected > (num_pkts_accepted + 1) * (num_registered_interfaces + 1) * 2) @@ -520,8 +532,8 @@ mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int s } else { - verbosedebugf("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d", - &senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index); + verbosedebugf("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d/%d", + &senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index, skt); num_pkts_accepted++; } } @@ -610,6 +622,32 @@ mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel GetUserSpecifiedRFC1034ComputerName( namelabel); } +mDNSexport int ParseDNSServers(mDNS *m, const char *filePath) + { + char line[256]; + char nameserver[16]; + char keyword[10]; + int numOfServers = 0; + FILE *fp = fopen(filePath, "r"); + if (fp == NULL) return -1; + while (fgets(line,sizeof(line),fp)) + { + struct in_addr ina; + line[255]='\0'; // just to be safe + if (sscanf(line,"%10s %15s", keyword, nameserver) != 2) continue; // it will skip whitespaces + if (strncmp(keyword,"nameserver",10)) continue; + if (inet_aton(nameserver, (struct in_addr *)&ina) != 0) + { + mDNSAddr DNSAddr; + DNSAddr.type = mDNSAddrType_IPv4; + DNSAddr.ip.v4.NotAnInteger = ina.s_addr; + mDNS_AddDNSServer(m, &DNSAddr, NULL); + numOfServers++; + } + } + return (numOfServers > 0) ? 0 : -1; + } + // Searches the interface list looking for the named interface. // Returns a pointer to if it found, or NULL otherwise. mDNSlocal PosixNetworkInterface *SearchForInterfaceByName(mDNS *const m, const char *intfName) @@ -626,7 +664,7 @@ mDNSlocal PosixNetworkInterface *SearchForInterfaceByName(mDNS *const m, const c return intf; } -extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index) +mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index) { PosixNetworkInterface *intf; @@ -702,7 +740,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf assert(*sktPtr == -1); // Open the socket... - if (intfAddr->sa_family == AF_INET) *sktPtr = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (intfAddr->sa_family == AF_INET ) *sktPtr = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); #if HAVE_IPV6 else if (intfAddr->sa_family == AF_INET6) *sktPtr = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); #endif @@ -1328,6 +1366,9 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m) // Tell mDNS core about the network interfaces on this machine. if (err == mStatus_NoError) err = SetupInterfaceList(m); + // Tell mDNS core about DNS Servers + if (err == mStatus_NoError) ParseDNSServers(m, uDNS_SERVERS_FILE); + if (err == mStatus_NoError) { err = WatchForInterfaceChange(m); @@ -1360,7 +1401,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) #endif } -extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m) +mDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m) { int err; ClearInterfaceList(m); diff --git a/mDNSPosix/mDNSPosix.h b/mDNSPosix/mDNSPosix.h index 0ee54dd..a5af557 100755 --- a/mDNSPosix/mDNSPosix.h +++ b/mDNSPosix/mDNSPosix.h @@ -24,6 +24,9 @@ Change History (most recent first): $Log: mDNSPosix.h,v $ +Revision 1.17 2005/02/04 00:39:59 cheshire +Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it + Revision 1.16 2004/11/30 22:37:01 cheshire Update copyright dates and add "Mode: C; tab-width: 4" headers @@ -117,6 +120,8 @@ struct mDNS_PlatformSupport_struct #endif }; +#define uDNS_SERVERS_FILE "/etc/resolv.conf" +extern int ParseDNSServers(mDNS *m, const char *filePath); extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m); // See comment in implementation. diff --git a/mDNSResponder.sln b/mDNSResponder.sln new file mode 100755 index 0000000..423805f --- /dev/null +++ b/mDNSResponder.sln @@ -0,0 +1,100 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLL", "mDNSWindows\DLL\dnssd.vcproj", "{AB581101-18F0-46F6-B56A-83A6B1EA657E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mDNSResponder", "mDNSWindows\SystemService\Service.vcproj", "{C1D98254-BA27-4427-A3BE-A68CA2CC5F69}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NSPTool", "mDNSWindows\NSPTool\NSPTool.vcproj", "{208B3A9F-1CA0-4D1D-9D6C-C61616F94705}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdnsNSP", "mDNSWindows\mdnsNSP\mdnsNSP.vcproj", "{F4F15529-F0EB-402F-8662-73C5797EE557}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPlugin", "Clients\ExplorerPlugin\ExplorerPlugin.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizard", "Clients\PrinterSetupWizard\PrinterSetupWizard.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLL.NET", "mDNSWindows\DLL.NET\dnssd_NET.vcproj", "{9C6701E2-82B7-44B7-9B5E-3897D9153F79}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ControlPanel", "mDNSWindows\ControlPanel\ControlPanel.vcproj", "{F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizardLocRes", "Clients\PrinterSetupWizard\PrinterSetupWizardLocRes.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizardRes", "Clients\PrinterSetupWizard\PrinterSetupWizardRes.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginLocRes", "Clients\ExplorerPlugin\ExplorerPluginLocRes.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginRes", "Clients\ExplorerPlugin\ExplorerPluginRes.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dns-sd", "Clients\DNS-SD.VisualStudio\dns-sd.vcproj", "{AA230639-E115-4A44-AA5A-44A61235BA50}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug + ConfigName.1 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + {F4F15529-F0EB-402F-8662-73C5797EE557}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E} + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E} + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E} + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E} + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E} + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E} + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E} + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug.ActiveCfg = Debug|Win32 + {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug.Build.0 = Debug|Win32 + {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release.ActiveCfg = Release|Win32 + {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release.Build.0 = Release|Win32 + {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug.ActiveCfg = Debug|Win32 + {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug.Build.0 = Debug|Win32 + {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release.ActiveCfg = Release|Win32 + {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release.Build.0 = Release|Win32 + {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug.ActiveCfg = Debug|Win32 + {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug.Build.0 = Debug|Win32 + {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release.ActiveCfg = Release|Win32 + {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release.Build.0 = Release|Win32 + {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug.ActiveCfg = Debug|Win32 + {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug.Build.0 = Debug|Win32 + {F4F15529-F0EB-402F-8662-73C5797EE557}.Release.ActiveCfg = Release|Win32 + {F4F15529-F0EB-402F-8662-73C5797EE557}.Release.Build.0 = Release|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.ActiveCfg = Debug|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.Build.0 = Debug|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.ActiveCfg = Release|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.Build.0 = Release|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.ActiveCfg = Debug|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.Build.0 = Debug|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.ActiveCfg = Release|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.Build.0 = Release|Win32 + {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Debug.ActiveCfg = Debug|Win32 + {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Debug.Build.0 = Debug|Win32 + {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Release.ActiveCfg = Release|Win32 + {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Release.Build.0 = Release|Win32 + {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug.ActiveCfg = Debug|Win32 + {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug.Build.0 = Debug|Win32 + {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release.ActiveCfg = Release|Win32 + {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release.Build.0 = Release|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.ActiveCfg = Debug|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.Build.0 = Debug|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.ActiveCfg = Release|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.Build.0 = Release|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.ActiveCfg = Debug|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.Build.0 = Debug|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.ActiveCfg = Release|Win32 + {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.Build.0 = Release|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.ActiveCfg = Debug|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.Build.0 = Debug|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.ActiveCfg = Release|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.Build.0 = Release|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.ActiveCfg = Debug|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.Build.0 = Debug|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.ActiveCfg = Release|Win32 + {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.Build.0 = Release|Win32 + {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug.ActiveCfg = Debug|Win32 + {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug.Build.0 = Debug|Win32 + {AA230639-E115-4A44-AA5A-44A61235BA50}.Release.ActiveCfg = Release|Win32 + {AA230639-E115-4A44-AA5A-44A61235BA50}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/mDNSShared/PlatformCommon.c b/mDNSShared/PlatformCommon.c index 9bee556..3baee26 100644 --- a/mDNSShared/PlatformCommon.c +++ b/mDNSShared/PlatformCommon.c @@ -24,6 +24,9 @@ Change History (most recent first): $Log: PlatformCommon.c,v $ +Revision 1.5 2005/02/01 19:33:30 ksekar + Keychain format too restrictive + Revision 1.4 2005/01/19 19:19:21 ksekar Need a way to turn off domain discovery @@ -96,7 +99,6 @@ mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const fi { char buf [MAX_ESCAPED_DOMAIN_NAME]; char secret[MAX_ESCAPED_DOMAIN_NAME] = ""; - int slen; mStatus err; FILE *f = fopen(filename, "r"); @@ -122,8 +124,7 @@ mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const fi 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); - err = mDNS_SetSecretForZone(m, domain, domain, secret, slen, mDNStrue); + err = mDNS_SetSecretForZone(m, domain, domain, secret); if (err) LogMsg("ERROR: mDNS_SetSecretForZone returned %d for domain %##s", err, domain->c); } diff --git a/mDNSShared/dns-sd.1 b/mDNSShared/dns-sd.1 index a8a602b..3611200 100644 --- a/mDNSShared/dns-sd.1 +++ b/mDNSShared/dns-sd.1 @@ -20,6 +20,12 @@ .\" @APPLE_LICENSE_HEADER_END@ .\" .\" $Log: dns-sd.1,v $ +.\" Revision 1.4 2005/02/16 02:29:32 cheshire +.\" Update terminology +.\" +.\" Revision 1.3 2005/02/10 22:35:28 cheshire +.\" Update name +.\" .\" Revision 1.2 2004/09/24 18:33:05 cheshire .\" Update man pages to clarify that mDNS and dns-sd are not intended for script use .\" @@ -34,7 +40,7 @@ .\" .Sh NAME .Nm dns-sd -.Nd Multicast DNS Service Discovery (mDNS-SD) Test Tool \" For whatis +.Nd Multicast DNS (mDNS) & DNS Service Discovery (DNS-SD) Test Tool \" For whatis .\" .Sh SYNOPSIS .Nm Fl R Ar name type domain port Op Ar key=value ... @@ -160,7 +166,7 @@ print. .Pp To advertise the existence of LPR printing service on port 515 on this machine, such that it will be discovered by the Mac OS X printing software -and other mDNS-SD compatible printing clients, use: +and other DNS-SD compatible printing clients, use: .Pp .Dl Nm Fl R Ns \ \&"My Test\&" _printer._tcp. \&. 515 pdl=application/postscript .Pp @@ -171,7 +177,7 @@ network. .Pp Similarly, to advertise a web page being served by an HTTP server on port 80 on this machine, such that it will show up in the -Rendezvous list in Safari and other mDNS-SD compatible Web clients, use: +Bonjour list in Safari and other DNS-SD compatible Web clients, use: .Pp .Dl Nm Fl R Ns \ \&"My Test\&" _http._tcp \&. 80 path=/path-to-page.html .Pp diff --git a/mDNSShared/dns_sd.h b/mDNSShared/dns_sd.h index 4f22f67..81e0856 100755 --- a/mDNSShared/dns_sd.h +++ b/mDNSShared/dns_sd.h @@ -165,7 +165,7 @@ enum kDNSServiceType_HINFO = 13, /* Host information. */ kDNSServiceType_MINFO = 14, /* Mailbox information. */ kDNSServiceType_MX = 15, /* Mail routing information. */ - kDNSServiceType_TXT = 16, /* Text strings. */ + kDNSServiceType_TXT = 16, /* One or more text strings. */ kDNSServiceType_RP = 17, /* Responsible person. */ kDNSServiceType_AFSDB = 18, /* AFS cell database. */ kDNSServiceType_X25 = 19, /* X_25 calling address. */ @@ -232,8 +232,13 @@ enum }; -/* Maximum length, in bytes, of a domain name represented as an escaped C-String */ -/* including the final trailing dot, and the C-String terminating NULL at the end */ +/* Maximum length, in bytes, of a service name represented as a */ +/* literal C-String, including the terminating NULL at the end. */ + +#define kDNSServiceMaxServiceName 64 + +/* Maximum length, in bytes, of a domain name represented as an *escaped* C-String */ +/* including the final trailing dot, and the C-String terminating NULL at the end. */ #define kDNSServiceMaxDomainName 1005 @@ -257,11 +262,18 @@ enum * it is, by definition, just a single literal string. Any characters in that string * represent exactly what they are. The "regtype" portion is, technically speaking, * escaped, but since legal regtypes are only allowed to contain letters, digits, - * and hyphens, the issue is moot. The "domain" portion is also escaped, though - * most domains in use on the public Internet today, like regtypes, don't contain - * any characters that need to be escaped. As DNS-SD becomes more popular, rich-text - * domains for service discovery will become common, so software should be written - * to cope with domains with escaping. + * and hyphens, there is nothing to escape, so the issue is moot. The "domain" + * portion is also escaped, though most domains in use on the public Internet + * today, like regtypes, don't contain any characters that need to be escaped. + * As DNS-SD becomes more popular, rich-text domains for service discovery will + * become common, so software should be written to cope with domains with escaping. + * + * The servicename may be up to 63 bytes of UTF-8 text (not counting the C-String + * terminating NULL at the end). The regtype is of the form _service._tcp or + * _service._udp, where the "service" part is 1-14 characters, which may be + * letters, digits, or hyphens. The domain part of the three-part name may be + * any legal domain, providing that the resulting servicename+regtype+domain + * name does not exceed 255 bytes. * * For most software, these issues are transparent. When browsing, the discovered * servicenames should simply be displayed as-is. When resolving, the discovered @@ -510,9 +522,9 @@ DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains * flags: Currently unused, reserved for future use. * * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will - * indicate the failure that occurred (including name conflicts, if the - * kDNSServiceFlagsNoAutoRename flag was passed to the - * callout.) Other parameters are undefined if errorCode is nonzero. + * indicate the failure that occurred (including name conflicts, + * if the kDNSServiceFlagsNoAutoRename flag was used when registering.) + * Other parameters are undefined if errorCode is nonzero. * * name: The service name registered (if the application did not specify a name in * DNSServiceRegister(), this indicates what name was automatically chosen). @@ -555,13 +567,18 @@ typedef void (DNSSD_API *DNSServiceRegisterReply) * will pass 0). See flag definitions above for details. * * name: If non-NULL, specifies the service name to be registered. - * Most applications will not specify a name, in which case the - * computer name is used (this name is communicated to the client via - * the callback). + * Most applications will not specify a name, in which case the computer + * name is used (this name is communicated to the client via the callback). + * If a name is specified, it must be 1-63 bytes of UTF-8 text. + * If the name is longer than 63 bytes it will be automatically truncated + * to a legal length, unless the NoAutoRename flag is set, + * in which case kDNSServiceErr_BadParam will be returned. * * regtype: The service type followed by the protocol, separated by a dot - * (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - * New service types should be registered at htp://www.dns-sd.org/ServiceTypes.html. + * (e.g. "_ftp._tcp"). The service type must be an underscore, followed + * by 1-14 characters, which may be letters, digits, or hyphens. + * The transport protocol must be "_tcp" or "_udp". New service types + * should be registered at . * * domain: If non-NULL, specifies the domain on which to advertise the service. * Most applications will not specify a domain, instead automatically @@ -581,9 +598,12 @@ typedef void (DNSSD_API *DNSServiceRegisterReply) * * txtLen: The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL. * - * txtRecord: The txt record rdata. May be NULL. Note that a non-NULL txtRecord - * MUST be a properly formatted DNS TXT record, i.e. - * ... + * txtRecord: The TXT record rdata. A non-NULL txtRecord MUST be a properly formatted DNS + * TXT record, i.e. ... + * Passing NULL for the txtRecord is allowed as a synonym for txtLen=1, txtRecord="", + * i.e. it creates a TXT record of length one containing a single empty string. + * RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty + * string is the smallest legal DNS TXT record. * * callBack: The function to be called when the registration completes or asynchronously * fails. The client MAY pass NULL for the callback - The client will NOT be notified @@ -844,9 +864,9 @@ DNSServiceErrorType DNSSD_API DNSServiceBrowse * Note: When the desired results have been returned, the client MUST terminate the resolve by calling * DNSServiceRefDeallocate(). * - * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record and - * a single TXT record (the TXT record may be empty.) To resolve non-standard services with multiple - * SRV or TXT records, DNSServiceQueryRecord() should be used. + * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record + * and a single TXT record. To resolve non-standard services with multiple SRV or TXT records, + * DNSServiceQueryRecord() should be used. * * DNSServiceResolveReply Callback Parameters: * @@ -1317,7 +1337,7 @@ typedef struct _TXTRecordRef_t { char privatedata[16]; } TXTRecordRef; * * bufferLen: The size of the storage provided in the "buffer" parameter. * - * buffer: The storage used to hold the TXTRecord data. + * buffer: Optional caller-supplied storage used to hold the TXTRecord data. * This storage must remain valid for as long as * the TXTRecordRef. */ diff --git a/mDNSShared/dnssd_clientstub.c b/mDNSShared/dnssd_clientstub.c index d06b5d2..8cf98d3 100755 --- a/mDNSShared/dnssd_clientstub.c +++ b/mDNSShared/dnssd_clientstub.c @@ -28,6 +28,9 @@ Change History (most recent first): $Log: dnssd_clientstub.c,v $ +Revision 1.45 2005/02/01 01:25:06 shersche +Define sleep() to be Sleep() for Windows compatibility + Revision 1.44 2005/01/27 22:57:56 cheshire Fix compile errors on gcc4 @@ -38,7 +41,7 @@ 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 - Rendevzous calls leak sockets if mDNSResponder is not running + 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, @@ -78,7 +81,7 @@ Revision 1.30 2004/09/16 23:14:24 cheshire Changes for Windows compatibility Revision 1.29 2004/09/16 21:46:38 ksekar - Need SPI for LoginWindow to associate a UID with a Wide Area Rendezvous domain + Need SPI for LoginWindow to associate a UID with a Wide Area domain Revision 1.28 2004/08/11 17:10:04 cheshire Fix signed/unsigned warnings @@ -186,6 +189,8 @@ Update to APSL 2.0 // conversion in expression" #pragma warning(disable:4152) +#define sleep(X) Sleep((X) * 1000) + static int g_initWinsock = 0; #endif diff --git a/mDNSShared/dnssd_ipc.h b/mDNSShared/dnssd_ipc.h index ca0014b..58c0ec3 100644 --- a/mDNSShared/dnssd_ipc.h +++ b/mDNSShared/dnssd_ipc.h @@ -27,6 +27,9 @@ Change History (most recent first): $Log: dnssd_ipc.h,v $ +Revision 1.19 2005/02/02 02:25:22 cheshire + /var/run/mDNSResponder should be /var/run/mdnsd on Linux + Revision 1.18 2005/01/27 22:57:56 cheshire Fix compile errors on gcc4 @@ -47,7 +50,7 @@ Revision 1.13 2004/09/16 23:14:25 cheshire Changes for Windows compatibility Revision 1.12 2004/09/16 21:46:38 ksekar - Need SPI for LoginWindow to associate a UID with a Wide Area Rendezvous domain + Need SPI for LoginWindow to associate a UID with a Wide Area domain Revision 1.11 2004/08/10 06:24:56 cheshire Use types with precisely defined sizes for 'op' and 'reg_index', for better @@ -118,7 +121,9 @@ Update to APSL 2.0 # define dnssd_sockaddr_t struct sockaddr_in #else # define AF_DNSSD AF_LOCAL -# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder" +# ifndef MDNS_UDS_SERVERPATH +# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder" +# endif # define LISTENQ 100 // longest legal control path length # define MAX_CTLPATH 256 diff --git a/mDNSShared/mDNS.1 b/mDNSShared/mDNS.1 index 71c3daf..b02dd17 100644 --- a/mDNSShared/mDNS.1 +++ b/mDNSShared/mDNS.1 @@ -20,6 +20,12 @@ .\" @APPLE_LICENSE_HEADER_END@ .\" .\" $Log: mDNS.1,v $ +.\" Revision 1.7 2005/02/16 02:29:32 cheshire +.\" Update terminology +.\" +.\" Revision 1.6 2005/02/10 22:35:28 cheshire +.\" Update name +.\" .\" Revision 1.5 2004/09/24 18:33:05 cheshire .\" Update man pages to clarify that mDNS and dns-sd are not intended for script use .\" @@ -43,7 +49,7 @@ .\" .Sh NAME .Nm mDNS -.Nd Multicast DNS Service Discovery (mDNS-SD) Test Tool \" For whatis +.Nd Multicast DNS (mDNS) & DNS Service Discovery (DNS-SD) Test Tool \" For whatis .\" .Sh SYNOPSIS .Nm Fl R Ar name type domain port Op Ar key=value ... @@ -173,7 +179,7 @@ print. .Pp To advertise the existence of LPR printing service on port 515 on this machine, such that it will be discovered by the Mac OS X printing software -and other mDNS-SD compatible printing clients, use: +and other DNS-SD compatible printing clients, use: .Pp .Dl Nm Fl R Ns \ \&"My Test\&" _printer._tcp. \&. 515 pdl=application/postscript .Pp @@ -184,7 +190,7 @@ network. .Pp Similarly, to advertise a web page being served by an HTTP server on port 80 on this machine, such that it will show up in the -Rendezvous list in Safari and other mDNS-SD compatible Web clients, use: +Bonjour list in Safari and other DNS-SD compatible Web clients, use: .Pp .Dl Nm Fl R Ns \ \&"My Test\&" _http._tcp \&. 80 path=/path-to-page.html .Pp diff --git a/mDNSShared/mDNSResponder.8 b/mDNSShared/mDNSResponder.8 index 8e7a23f..352ad6d 100644 --- a/mDNSShared/mDNSResponder.8 +++ b/mDNSShared/mDNSResponder.8 @@ -20,6 +20,9 @@ .\" @APPLE_LICENSE_HEADER_END@ .\" .\" $Log: mDNSResponder.8,v $ +.\" Revision 1.6 2005/02/10 22:35:28 cheshire +.\" Update name +.\" .\" Revision 1.5 2004/06/29 02:41:38 cheshire .\" Add note that mDNSResponder is called mdnsd on some systems .\" @@ -92,11 +95,11 @@ For information on DNS Service Discovery, see .Pp For information on how to use the Multicast DNS and the DNS Service Discovery APIs on Mac OS X and other platforms, see -.Pa http://developer.apple.com/macosx/rendezvous/ +.Pa http://developer.apple.com/bonjour/ .Pp For the source code to .Nm , see -.Pa http://developer.apple.com/darwin/projects/rendezvous/ +.Pa http://developer.apple.com/darwin/projects/bonjour/ .\" .Sh BUGS .Nm diff --git a/mDNSShared/uds_daemon.c b/mDNSShared/uds_daemon.c index e14db7a..964d2fc 100644 --- a/mDNSShared/uds_daemon.c +++ b/mDNSShared/uds_daemon.c @@ -24,6 +24,57 @@ Change History (most recent first): $Log: uds_daemon.c,v $ +Revision 1.180 2005/03/10 00:13:12 cheshire + DNSServiceBrowse no longer returning error codes for invalid types +In handle_browse_request(), mStatus err was being set correctly if an error occurred, +but the end of the function returned mStatus_NoError intead of err. + +Revision 1.179 2005/03/04 02:47:26 ksekar + SCPreference domains disappear from enumeration when moving out from firewall + +Revision 1.178 2005/02/25 19:35:38 ksekar + Non-local empty string registration failures should not return errors to caller + +Revision 1.177 2005/02/25 03:05:41 cheshire +Change "broken pipe" message to debugf() + +Revision 1.176 2005/02/24 18:44:45 ksekar + Printer Sharing does not get re-registered with wide-area + +Revision 1.175 2005/02/21 21:31:25 ksekar + changed LogMsg to debugf + +Revision 1.174 2005/02/20 01:41:17 cheshire +Fix compiler signed/unsigned warning + +Revision 1.173 2005/02/18 01:26:42 cheshire + "Could not write data to client after 60 seconds" message could be more helpful +Log additional information about failed client + +Revision 1.172 2005/02/18 00:58:35 cheshire + "Could not write data to client after 60 seconds" message could be more helpful + +Revision 1.171 2005/02/18 00:43:12 cheshire + mDNSResponder should auto-truncate service names that are too long + +Revision 1.170 2005/02/16 01:15:02 cheshire +Improve LogOperation() debugging messages for DNSServiceBrowse and DNSServiceRegister + +Revision 1.169 2005/02/08 01:57:14 cheshire +More detailed error reporting in udsserver_init() + +Revision 1.168 2005/02/03 00:44:37 cheshire + DNSServiceUpdateRecord returns kDNSServiceErr_Invalid when rdlen=0, rdata=NULL + +Revision 1.167 2005/02/02 02:19:32 cheshire +Add comment explaining why unlink(MDNS_UDS_SERVERPATH); fails + +Revision 1.166 2005/02/01 19:58:52 ksekar +Shortened cryptic "broken pipe" syslog message + +Revision 1.165 2005/02/01 19:56:47 ksekar +Moved LogMsg from daemon.c to uds_daemon.c, cleaned up wording + Revision 1.164 2005/01/28 06:07:55 cheshire Don't use deliver_error() from within handle_regrecord_request() @@ -288,7 +339,7 @@ Revision 1.82 2004/09/16 23:14:25 cheshire Changes for Windows compatibility Revision 1.81 2004/09/16 21:46:38 ksekar - Need SPI for LoginWindow to associate a UID with a Wide Area Rendezvous domain + Need SPI for LoginWindow to associate a UID with a Wide Area domain Revision 1.80 2004/09/16 01:58:23 cheshire Fix compiler warnings @@ -770,7 +821,7 @@ static void browse_termination_callback(void *context); static void browse_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord); static void handle_regservice_request(request_state *request); static void regservice_termination_callback(void *context); -static void process_service_registration(ServiceRecordSet *const srs); +static void process_service_registration(ServiceRecordSet *const srs, mDNSBool SuppressError); static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result); static mStatus handle_add_request(request_state *rstate); static mStatus handle_update_request(request_state *rstate); @@ -812,6 +863,32 @@ static void handle_setdomain_request(request_state *rstate); #define PID_FILE "/var/run/mDNSResponder.pid" #endif +mDNSlocal void LogClientInfo(request_state *req) + { + void *t = req->termination_context; + if (t) + { + if (req->terminate == regservice_termination_callback) + { + service_instance *ptr; + for (ptr = ((service_info *)t)->instances; ptr; ptr = ptr->next) + 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("%3d: DNSServiceBrowse %##s", req->sd, blist->q.qname.c); + } + else if (req->terminate == resolve_termination_callback) + LogMsgNoIdent("%3d: DNSServiceResolve %##s", req->sd, ((resolve_termination_t *)t)->qsrv.qname.c); + else if (req->terminate == question_termination_callback) + LogMsgNoIdent("%3d: DNSServiceQueryRecord %##s", req->sd, ((DNSQuestion *) t)->qname.c); + else if (req->terminate == enum_termination_callback) + LogMsgNoIdent("%3d: DNSServiceEnumerateDomains %##s", req->sd, ((enum_termination_t *) t)->all->question.qname.c); + } + } + static void FatalError(char *errmsg) { LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno())); @@ -839,7 +916,10 @@ int udsserver_init(void) } if ((listenfd = socket(AF_DNSSD, SOCK_STREAM, 0)) == dnssd_InvalidSocket) + { + my_perror("ERROR: socket(AF_DNSSD, SOCK_STREAM, 0); failed"); goto error; + } bzero(&laddr, sizeof(laddr)); @@ -850,7 +930,10 @@ int udsserver_init(void) laddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); if (ret < 0) + { + my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed"); goto error; + } } #else { @@ -866,7 +949,10 @@ int udsserver_init(void) ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); umask(mask); if (ret < 0) + { + my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed"); goto error; + } } #endif @@ -880,10 +966,10 @@ int udsserver_init(void) #else if (fcntl(listenfd, F_SETFL, O_NONBLOCK) != 0) #endif - { + { my_perror("ERROR: could not set listen socket to non-blocking mode"); goto error; - } + } if (listen(listenfd, LISTENQ) != 0) { @@ -933,7 +1019,11 @@ int udsserver_exit(void) dnssd_close(listenfd); #if !defined(USE_TCP_LOOPBACK) - unlink(MDNS_UDS_SERVERPATH); + // Currently, we're unable to remove /var/run/mdnsd because we've changed to userid "nobody" + // to give up unnecessary privilege, but we need to be root to remove this Unix Domain Socket. + // It would be nice if we could find a solution to this problem + if (unlink(MDNS_UDS_SERVERPATH)) + debugf("Unable to remove %s", MDNS_UDS_SERVERPATH); #endif return 0; @@ -974,17 +1064,18 @@ mDNSs32 udsserver_idle(mDNSs32 nextevent) } } 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) - { - LogMsg("Could not write data to client after %ld seconds - aborting connection", MAX_TIME_BLOCKED / mDNSPlatformOneSecond); - abort_request(req); - result = t_terminated; - } - else if (nextevent - now > mDNSPlatformOneSecond) nextevent = now + mDNSPlatformOneSecond; // try again in a second - } + { + 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) + { + LogMsg("Could not write data to client %d after %ld seconds - aborting connection", req->sd, MAX_TIME_BLOCKED / mDNSPlatformOneSecond); + LogClientInfo(req); + abort_request(req); + result = t_terminated; + } + else if (nextevent - now > mDNSPlatformOneSecond) nextevent = now + mDNSPlatformOneSecond; // try again in a second + } if (result == t_terminated || result == t_error) //since we're already doing a list traversal, we unlink the request manunally instead of calling unlink_request() { @@ -1038,28 +1129,7 @@ void udsserver_info(mDNS *const m) LogMsgNoIdent("Cache currently contains %lu records; %lu referenced by active questions", CacheUsed, CacheActive); for (req = all_requests; req; req=req->next) - { - void *t = req->termination_context; - if (!t) continue; - if (req->terminate == regservice_termination_callback) - { - service_instance *ptr; - for (ptr = ((service_info *)t)->instances; ptr; ptr = ptr->next) - 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("%3d: DNSServiceBrowse %##s", req->sd, blist->q.qname.c); - } - else if (req->terminate == resolve_termination_callback) - LogMsgNoIdent("%3d: DNSServiceResolve %##s", req->sd, ((resolve_termination_t *)t)->qsrv.qname.c); - else if (req->terminate == question_termination_callback) - LogMsgNoIdent("%3d: DNSServiceQueryRecord %##s", req->sd, ((DNSQuestion *) t)->qname.c); - else if (req->terminate == enum_termination_callback) - LogMsgNoIdent("%3d: DNSServiceEnumerateDomains %##s", req->sd, ((enum_termination_t *) t)->all->question.qname.c); - } + LogClientInfo(req); now = mDNS_TimeNow(m); LogMsgNoIdent("Timenow 0x%08lX (%ld)", (mDNSu32)now, now); @@ -1822,7 +1892,7 @@ static void handle_browse_request(request_state *request) domainname typedn, d, temp; mDNSs32 NumSubTypes; char *ptr; - mStatus err; + mStatus err = mStatus_NoError; DNameListElem *search_domain_list, *sdom; browser_info_t *info = NULL; @@ -1874,7 +1944,7 @@ static void handle_browse_request(request_state *request) request->termination_context = info; request->terminate = browse_termination_callback; - LogOperation("%3d: DNSServiceBrowse(%##s%s) START", request->sd, info->regtype.c, domain); + LogOperation("%3d: DNSServiceBrowse(\"%##s\", \"%s\") START", request->sd, info->regtype.c, domain); if (domain[0]) { if (!MakeDomainNameFromDNSNameString(&d, domain)) { err = mStatus_BadParamErr; goto error; } @@ -1897,7 +1967,7 @@ static void handle_browse_request(request_state *request) mDNS_FreeDNameList(search_domain_list); } - deliver_error(request, mStatus_NoError); + deliver_error(request, err); return; error: @@ -2073,7 +2143,8 @@ mDNSexport void udsserver_default_reg_domain_changed(const domainname *d, mDNSBo { request_state *rstate; service_info *info; - + + LogMsg("%s registration domain %##s", add ? "Adding" : "Removing", d->c); for (rstate = all_requests; rstate; rstate = rstate->next) { if (rstate->terminate != regservice_termination_callback) continue; @@ -2105,7 +2176,7 @@ mDNSexport void udsserver_default_reg_domain_changed(const domainname *d, mDNSBo prev = si; si = si->next; } - if (!si) LogMsg("udsserver_default_reg_domain_changed - domain %##s not registered", d->c); + if (!si) debugf("udsserver_default_reg_domain_changed - domain %##s not registered", d->c); // normal if registration failed } } } @@ -2115,7 +2186,8 @@ static void handle_regservice_request(request_state *request) { DNSServiceFlags flags; uint32_t ifi; - char name[256], domain[MAX_ESCAPED_DOMAIN_NAME], host[MAX_ESCAPED_DOMAIN_NAME]; + char name[1024]; // Lots of spare space for extra-long names that we'll auto-truncate down to 63 bytes + char domain[MAX_ESCAPED_DOMAIN_NAME], host[MAX_ESCAPED_DOMAIN_NAME]; char *ptr; domainname d, srv; mStatus result; @@ -2145,7 +2217,7 @@ static void handle_regservice_request(request_state *request) service->InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(gmDNS, ifi); 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 || + if (get_string(&ptr, name, sizeof(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) @@ -2155,7 +2227,13 @@ static void handle_regservice_request(request_state *request) service->port.b[1] = *ptr++; service->txtlen = get_short(&ptr); - service->txtdata = get_rdata(&ptr, service->txtlen); + if (service->txtlen) + { + service->txtdata = mallocL("txtdata", service->txtlen); + if (!service->txtdata) { my_perror("ERROR: malloc"); result = mStatus_NoMemoryErr; goto finish; } + memcpy(service->txtdata, get_rdata(&ptr, service->txtlen), service->txtlen); + } + else service->txtdata = NULL; // Check for sub-types after the service type service->num_subtypes = ChopSubTypes(service->type_as_string); // Note: Modifies regtype string to remove trailing subtypes @@ -2173,6 +2251,12 @@ static void handle_regservice_request(request_state *request) } else { + // If the client is allowing AutoRename, then truncate name to legal length before converting it to a DomainLabel + if ((flags & kDNSServiceFlagsNoAutoRename) == 0) + { + int newlen = TruncateUTF8ToLength((mDNSu8*)name, mDNSPlatformStrLen(name), MAX_DOMAIN_LABEL); + name[newlen] = 0; + } if (!MakeDomainLabelFromLiteralString(&service->name, name)) { LogMsg("ERROR: handle_regservice_request - name bad %s", name); goto bad_param; } service->autoname = mDNSfalse; @@ -2209,7 +2293,8 @@ static void handle_regservice_request(request_state *request) count+1, srv.c, mDNSVal16(service->port)); } - LogOperation("%3d: DNSServiceRegister(%##s, %u) START", request->sd, srv.c, mDNSVal16(service->port)); + LogOperation("%3d: DNSServiceRegister(\"%s\", \"%s\", \"%s\", \"%s\", %u) START", + request->sd, name, service->type_as_string, domain, host, mDNSVal16(service->port)); result = register_service_instance(request, &d); if (!result && !*domain) @@ -2247,11 +2332,19 @@ bad_param: static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result) { mStatus err; + mDNSBool SuppressError = mDNSfalse; service_instance *instance = srs->ServiceContext; (void)m; // Unused if (!srs) { LogMsg("regservice_callback: srs is NULL %d", result); return; } if (!instance) { LogMsg("regservice_callback: srs->ServiceContext is NULL %d", result); return; } + if (instance->request && instance->request->service_registration) + { + service_info *info = instance->request->service_registration; + if (info->default_domain && !instance->default_local) SuppressError = mDNStrue; + // don't send errors up to client for wide-area, empty-string registrations + } + if (result == mStatus_NoError) LogOperation("%3d: DNSServiceRegister(%##s, %u) REGISTERED ", instance->sd, srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port)); else if (result == mStatus_MemFree) @@ -2272,7 +2365,7 @@ static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mSta srs->RR_TXT.AllowRemoteQuery = mDNStrue; for (e = instance->srs.Extras; e; e = e->next) e->r.AllowRemoteQuery = mDNStrue; } - process_service_registration(srs); + process_service_registration(srs, SuppressError); if (instance->autoname && CountPeerRegistrations(m, srs) == 0) RecordUpdatedNiceLabel(m, 0); // Successfully got new name, tell user immediately return; @@ -2311,7 +2404,7 @@ static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mSta 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 (!SuppressError && deliver_async_error(rs, reg_service_reply, result) < 0) { abort_request(rs); unlink_request(rs); @@ -2325,7 +2418,7 @@ static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mSta 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 (!SuppressError && deliver_async_error(rs, reg_service_reply, result) < 0) { abort_request(rs); unlink_request(rs); @@ -2423,6 +2516,12 @@ static mStatus update_record(AuthRecord *rr, uint16_t rdlen, char *rdata, uint32 if (!newrd) FatalError("ERROR: malloc"); newrd->MaxRDLength = (mDNSu16) rdsize; memcpy(&newrd->u, rdata, rdlen); + + // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct, + // since RFC 1035 specifies a TXT record as "One or more s", not "Zero or more s". + // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here. + if (rr->resrec.rrtype == kDNSType_TXT && rdlen == 0) { rdlen = 1; newrd->u.txt.c[0] = 0; } + result = mDNS_Update(gmDNS, rr, ttl, rdlen, newrd, update_callback); if (result) { LogMsg("ERROR: mDNS_Update - %ld", result); freeL("handle_update_request", newrd); } return result; @@ -2493,7 +2592,7 @@ static void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd) if (oldrd != &rr->rdatastorage) freeL("update_callback", oldrd); } -static void process_service_registration(ServiceRecordSet *const srs) +static void process_service_registration(ServiceRecordSet *const srs, mDNSBool SuppressError) { reply_state *rep; transfer_state send_result; @@ -2505,7 +2604,7 @@ static void process_service_registration(ServiceRecordSet *const srs) 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) + if (SuppressError && deliver_async_error(req, reg_service_reply, err) < 0) { abort_request(req); unlink_request(req); @@ -2574,6 +2673,7 @@ static void regservice_termination_callback(void *context) if (mDNS_DeregisterService(gmDNS, &p->srs)) free_service_instance(p); } info->request->service_registration = NULL; // clear pointer from request back to info + if (info->txtdata) { freeL("txtdata", info->txtdata); info->txtdata = NULL; } freeL("service_info", info); } @@ -2833,12 +2933,14 @@ static void enum_result_callback(mDNS *const m, DNSQuestion *question, const Res (void)m; // Unused if (answer->rrtype != kDNSType_PTR) return; + if (!AddRecord && de->type != mDNS_DomainTypeBrowse) return; + if (AddRecord) { flags |= kDNSServiceFlagsAdd; if (de->type == mDNS_DomainTypeRegistrationDefault || de->type == mDNS_DomainTypeBrowseDefault) flags |= kDNSServiceFlagsDefault; - } + } ConvertDomainNameToCString(&answer->rdata->u.name, domain); // note that we do NOT propagate specific interface indexes to the client - for example, a domain we learn from // a machine's system preferences may be discovered on the LocalOnly interface, but should be browsed on the @@ -3178,7 +3280,7 @@ static int send_msg(reply_state *rs) #if !defined(PLATFORM_NO_EPIPE) if (dnssd_errno() == EPIPE) { - LogMsg("%3d: broken pipe - cleanup will be handled by run-loop read wakeup", rs->sd); + debugf("%3d: broken pipe", rs->sd); rs->ts = t_terminated; rs->request->ts = t_terminated; return t_terminated; diff --git a/mDNSWindows/ControlPanel/ConfigDialog.cpp b/mDNSWindows/ControlPanel/ConfigDialog.cpp new file mode 100755 index 0000000..092331a --- /dev/null +++ b/mDNSWindows/ControlPanel/ConfigDialog.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ConfigDialog.cpp,v $ +Revision 1.2 2005/03/03 19:55:21 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + + +#include "ConfigDialog.h" +#include "ControlPanel.h" + + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +IMPLEMENT_DYNCREATE(CConfigDialog, CDialog) + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigDialog::CConfigDialog +//--------------------------------------------------------------------------------------------------------------------------- + +CConfigDialog::CConfigDialog() + : CDialog(CConfigDialog::IDD, NULL) +{ + //{{AFX_DATA_INIT(CConfigDialog) + //}}AFX_DATA_INIT +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigDialog::DoDataExchange +//--------------------------------------------------------------------------------------------------------------------------- + +void CConfigDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CConfigDialog) + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CConfigDialog, CDialog) + //{{AFX_MSG_MAP(CConfigDialog) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() diff --git a/mDNSWindows/ControlPanel/ConfigDialog.h b/mDNSWindows/ControlPanel/ConfigDialog.h new file mode 100755 index 0000000..868746b --- /dev/null +++ b/mDNSWindows/ControlPanel/ConfigDialog.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ConfigDialog.h,v $ +Revision 1.2 2005/03/03 19:55:21 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#pragma once + +#include "stdafx.h" +#include "resource.h" + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigDialog +//--------------------------------------------------------------------------------------------------------------------------- + +class CConfigDialog : public CDialog +{ +public: + + CConfigDialog(); + +protected: + + //{{AFX_DATA(CConfigDialog) + enum { IDD = IDR_APPLET }; + //}}AFX_DATA + + //{{AFX_VIRTUAL(CConfigDialog) + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + //{{AFX_MSG(CConfigDialog) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + DECLARE_DYNCREATE(CConfigDialog) +}; diff --git a/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp b/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp new file mode 100755 index 0000000..07160cf --- /dev/null +++ b/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ConfigPropertySheet.cpp,v $ +Revision 1.3 2005/03/03 19:55:22 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#include "ConfigPropertySheet.h" +#include +#include + +// Custom events + +#define WM_DATAREADY ( WM_USER + 0x100 ) +#define WM_REGISTRYCHANGED ( WM_USER + 0x101 ) + + +IMPLEMENT_DYNCREATE(CConfigPropertySheet, CPropertySheet) + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::CConfigPropertySheet +//--------------------------------------------------------------------------------------------------------------------------- + +CConfigPropertySheet::CConfigPropertySheet() +: + CPropertySheet(), + m_browseDomainsRef( NULL ), + m_regDomainsRef( NULL ), + m_thread( NULL ), + m_threadExited( NULL ) +{ + AddPage(&m_firstPage); + AddPage(&m_secondPage); + AddPage(&m_thirdPage); + + InitializeCriticalSection( &m_lock ); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::~CConfigPropertySheet +//--------------------------------------------------------------------------------------------------------------------------- + +CConfigPropertySheet::~CConfigPropertySheet() +{ + DeleteCriticalSection( &m_lock ); +} + + +BEGIN_MESSAGE_MAP(CConfigPropertySheet, CPropertySheet) + //{{AFX_MSG_MAP(CConfigPropertySheet) + //}}AFX_MSG_MAP + ON_MESSAGE( WM_DATAREADY, OnDataReady ) + ON_MESSAGE( WM_REGISTRYCHANGED, OnRegistryChanged ) +END_MESSAGE_MAP() + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::OnInitDialog +//--------------------------------------------------------------------------------------------------------------------------- + +BOOL +CConfigPropertySheet::OnInitDialog() +{ + OSStatus err; + + BOOL b = CPropertySheet::OnInitDialog(); + + err = SetupBrowsing(); + require_noerr( err, exit ); + + err = SetupRegistryNotifications(); + require_noerr( err, exit ); + +exit: + + return b; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::OnCommand +//--------------------------------------------------------------------------------------------------------------------------- + +BOOL +CConfigPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam) +{ + // Check if OK or Cancel was hit + + if ( ( wParam == ID_WIZFINISH ) || ( wParam == IDOK ) || ( wParam == IDCANCEL ) ) + { + OnEndDialog(); + } + + return CPropertySheet::OnCommand(wParam, lParam); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::OnDataReady +//--------------------------------------------------------------------------------------------------------------------------- + +LONG +CConfigPropertySheet::OnDataReady(WPARAM inWParam, LPARAM inLParam) +{ + if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam))) + { + dlog( kDebugLevelError, "OnSocket: window error\n" ); + } + else + { + SOCKET sock = (SOCKET) inWParam; + + if ( m_browseDomainsRef && DNSServiceRefSockFD( m_browseDomainsRef ) == (int) sock ) + { + DNSServiceProcessResult( m_browseDomainsRef ); + } + else if ( m_regDomainsRef && DNSServiceRefSockFD( m_regDomainsRef ) == (int) sock ) + { + DNSServiceProcessResult( m_regDomainsRef ); + } + } + + return 0; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::OnRegistryChanged +//--------------------------------------------------------------------------------------------------------------------------- + +afx_msg LONG +CConfigPropertySheet::OnRegistryChanged( WPARAM inWParam, LPARAM inLParam ) +{ + DEBUG_UNUSED( inWParam ); + DEBUG_UNUSED( inLParam ); + + if ( GetActivePage() == &m_firstPage ) + { + m_firstPage.OnRegistryChanged(); + } + + return 0; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::OnEndDialog +//--------------------------------------------------------------------------------------------------------------------------- + +void +CConfigPropertySheet::OnEndDialog() +{ + OSStatus err; + + err = TearDownRegistryNotifications(); + check_noerr( err ); + + err = TearDownBrowsing(); + check_noerr( err ); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::SetupBrowsing +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CConfigPropertySheet::SetupBrowsing() +{ + OSStatus err; + + // Start browsing for browse domains + + err = DNSServiceEnumerateDomains( &m_browseDomainsRef, kDNSServiceFlagsBrowseDomains, 0, BrowseDomainsReply, this ); + require_noerr( err, exit ); + + err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, WM_DATAREADY, FD_READ|FD_CLOSE ); + require_noerr( err, exit ); + + // Start browsing for registration domains + + err = DNSServiceEnumerateDomains( &m_regDomainsRef, kDNSServiceFlagsRegistrationDomains, 0, RegDomainsReply, this ); + require_noerr( err, exit ); + + err = WSAAsyncSelect( DNSServiceRefSockFD( m_regDomainsRef ), m_hWnd, WM_DATAREADY, FD_READ|FD_CLOSE ); + require_noerr( err, exit ); + +exit: + + if ( err ) + { + TearDownBrowsing(); + } + + return err; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::TearDownBrowsing +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CConfigPropertySheet::TearDownBrowsing() +{ + OSStatus err = kNoErr; + + if ( m_browseDomainsRef ) + { + err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, 0, 0 ); + check_noerr( err ); + + DNSServiceRefDeallocate( m_browseDomainsRef ); + + m_browseDomainsRef = NULL; + } + + if ( m_regDomainsRef ) + { + err = WSAAsyncSelect( DNSServiceRefSockFD( m_regDomainsRef ), m_hWnd, 0, 0 ); + check_noerr( err ); + + DNSServiceRefDeallocate( m_regDomainsRef ); + + m_regDomainsRef = NULL; + } + + return err; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::SetupRegistryNotifications +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CConfigPropertySheet::SetupRegistryNotifications() +{ + unsigned int threadId; + OSStatus err; + + check( m_threadExited == NULL ); + check( m_thread == NULL ); + + err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\State\\Hostnames", &m_statusKey ); + require_noerr( err, exit ); + + m_threadExited = CreateEvent( NULL, FALSE, FALSE, NULL ); + err = translate_errno( m_threadExited, (OSStatus) GetLastError(), kUnknownErr ); + require_noerr( err, exit ); + + // Create thread with _beginthreadex() instead of CreateThread() to avoid memory leaks when using static run-time + // libraries. See . + + m_thread = (HANDLE) _beginthreadex_compat( NULL, 0, WatchRegistry, this, 0, &threadId ); + err = translate_errno( m_thread, (OSStatus) GetLastError(), kUnknownErr ); + require_noerr( err, exit ); + +exit: + + if ( err ) + { + TearDownRegistryNotifications(); + } + + return err; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::TearDownRegistryNotifications +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CConfigPropertySheet::TearDownRegistryNotifications() +{ + OSStatus err = kNoErr; + + if ( m_statusKey ) + { + EnterCriticalSection( &m_lock ); + + RegCloseKey( m_statusKey ); + m_statusKey = NULL; + + LeaveCriticalSection( &m_lock ); + } + + if ( m_threadExited ) + { + err = WaitForSingleObject( m_threadExited, 5 * 1000 ); + require_noerr( err, exit ); + } + +exit: + + if ( m_threadExited ) + { + CloseHandle( m_threadExited ); + m_threadExited = NULL; + } + + if ( m_thread ) + { + CloseHandle( m_thread ); + m_thread = NULL; + } + + return err; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::DecodeDomainName +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CConfigPropertySheet::DecodeDomainName( const char * raw, CString & decoded ) +{ + char nextLabel[128] = "\0"; + char decodedDomainString[kDNSServiceMaxDomainName]; + char * buffer = (char *) raw; + int labels = 0, i; + char text[64]; + const char *label[128]; + OSStatus err; + + // Initialize + + decodedDomainString[0] = '\0'; + + // Count the labels + + while ( *buffer ) + { + label[labels++] = buffer; + buffer = (char *) GetNextLabel(buffer, text); + } + + buffer = (char*) raw; + + for (i = 0; i < labels; i++) + { + buffer = (char *)GetNextLabel(buffer, nextLabel); + strcat(decodedDomainString, nextLabel); + strcat(decodedDomainString, "."); + } + + // Remove trailing dot from domain name. + + decodedDomainString[ strlen( decodedDomainString ) - 1 ] = '\0'; + + // Convert to Unicode + + err = UTF8StringToStringObject( decodedDomainString, decoded ); + + return err; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::GetNextLabel +//--------------------------------------------------------------------------------------------------------------------------- + +const char* +CConfigPropertySheet::GetNextLabel( const char * cstr, char label[64] ) +{ + char *ptr = label; + while (*cstr && *cstr != '.') // While we have characters in the label... + { + char c = *cstr++; + if (c == '\\') + { + c = *cstr++; + if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1])) + { + int v0 = cstr[-1] - '0'; // then interpret as three-digit decimal + int v1 = cstr[ 0] - '0'; + int v2 = cstr[ 1] - '0'; + int val = v0 * 100 + v1 * 10 + v2; + if (val <= 255) { c = (char)val; cstr += 2; } // If valid three-digit decimal value, use it + } + } + *ptr++ = c; + if (ptr >= label+64) return(NULL); + } + if (*cstr) cstr++; // Skip over the trailing dot (if present) + *ptr++ = 0; + return(cstr); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::BrowseDomainsReply +//--------------------------------------------------------------------------------------------------------------------------- + +void DNSSD_API +CConfigPropertySheet::BrowseDomainsReply + ( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char * replyDomain, + void * context + ) +{ + CConfigPropertySheet * self = reinterpret_cast(context); + CString decoded; + OSStatus err; + + DEBUG_UNUSED( sdRef ); + DEBUG_UNUSED( interfaceIndex ); + + if ( errorCode ) + { + goto exit; + } + + check( replyDomain ); + + // Ignore local domains + + if ( strcmp( replyDomain, "local." ) == 0 ) + { + goto exit; + } + + + + err = self->DecodeDomainName( replyDomain, decoded ); + require_noerr( err, exit ); + + // Remove trailing '.' + + decoded.TrimRight( '.' ); + + if ( flags & kDNSServiceFlagsAdd ) + { + self->m_browseDomains.push_back( decoded ); + } + else + { + self->m_browseDomains.remove( decoded ); + } + +exit: + + return; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::RegDomainsReply +//--------------------------------------------------------------------------------------------------------------------------- + +void DNSSD_API +CConfigPropertySheet::RegDomainsReply + ( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char * replyDomain, + void * context + ) +{ + CConfigPropertySheet * self = reinterpret_cast(context); + CString decoded; + OSStatus err; + + DEBUG_UNUSED( sdRef ); + DEBUG_UNUSED( interfaceIndex ); + + if ( errorCode ) + { + goto exit; + } + + check( replyDomain ); + + // Ignore local domains + + if ( strcmp( replyDomain, "local." ) == 0 ) + { + goto exit; + } + + err = self->DecodeDomainName( replyDomain, decoded ); + require_noerr( err, exit ); + + // Remove trailing '.' + + decoded.TrimRight( '.' ); + + if ( flags & kDNSServiceFlagsAdd ) + { + if ( self->GetActivePage() == &self->m_secondPage ) + { + self->m_secondPage.OnAddRegistrationDomain( decoded ); + } + + self->m_regDomains.push_back( decoded ); + } + else + { + if ( self->GetActivePage() == &self->m_secondPage ) + { + self->m_secondPage.OnRemoveRegistrationDomain( decoded ); + } + + self->m_regDomains.remove( decoded ); + } + +exit: + + return; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet::WatchRegistry +//--------------------------------------------------------------------------------------------------------------------------- + +unsigned WINAPI +CConfigPropertySheet::WatchRegistry ( LPVOID inParam ) +{ + bool done = false; + + CConfigPropertySheet * self = reinterpret_cast(inParam); + check( self ); + + while ( !done ) + { + RegNotifyChangeKeyValue( self->m_statusKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, NULL, FALSE ); + + EnterCriticalSection( &self->m_lock ); + + done = ( self->m_statusKey == NULL ) ? true : false; + + if ( !done ) + { + self->PostMessage( WM_REGISTRYCHANGED, 0, 0 ); + } + + LeaveCriticalSection( &self->m_lock ); + } + + SetEvent( self->m_threadExited ); + + return 0; +} diff --git a/mDNSWindows/ControlPanel/ConfigPropertySheet.h b/mDNSWindows/ControlPanel/ConfigPropertySheet.h new file mode 100755 index 0000000..a954f18 --- /dev/null +++ b/mDNSWindows/ControlPanel/ConfigPropertySheet.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ConfigPropertySheet.h,v $ +Revision 1.4 2005/03/03 19:55:21 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#ifndef _ConfigPropertySheet_h +#define _ConfigPropertySheet_h + +#include "stdafx.h" +#include "FirstPage.h" +#include "SecondPage.h" +#include "ThirdPage.h" + +#include +#include +#include + + +//--------------------------------------------------------------------------------------------------------------------------- +// CConfigPropertySheet +//--------------------------------------------------------------------------------------------------------------------------- + +class CConfigPropertySheet : public CPropertySheet +{ +public: + + CConfigPropertySheet(); + virtual ~CConfigPropertySheet(); + + typedef std::list StringList; + + StringList m_browseDomains; + StringList m_regDomains; + +protected: + + CFirstPage m_firstPage; + CSecondPage m_secondPage; + CThirdPage m_thirdPage; + + //{{AFX_VIRTUAL(CConfigPropertySheet) + //}}AFX_VIRTUAL + + DECLARE_DYNCREATE(CConfigPropertySheet) + + //{{AFX_MSG(CConfigPropertySheet) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + afx_msg BOOL OnInitDialog(); + afx_msg BOOL OnCommand( WPARAM wParam, LPARAM lParam ); + afx_msg LONG OnDataReady( WPARAM inWParam, LPARAM inLParam ); + afx_msg LONG OnRegistryChanged( WPARAM inWParam, LPARAM inLParam ); + void OnEndDialog(); + +private: + + OSStatus + SetupBrowsing(); + + OSStatus + TearDownBrowsing(); + + OSStatus + SetupRegistryNotifications(); + + OSStatus + TearDownRegistryNotifications(); + + OSStatus + DecodeDomainName( const char * raw, CString & decoded ); + + const char* + GetNextLabel( const char * cstr, char label[64] ); + + static void DNSSD_API + BrowseDomainsReply + ( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char * replyDomain, + void * context + ); + + static void DNSSD_API + RegDomainsReply + ( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + const char * replyDomain, + void * context + ); + + // This thread will watch for registry changes + + static unsigned WINAPI + WatchRegistry + ( + LPVOID inParam + ); + + HKEY m_statusKey; + HANDLE m_thread; + HANDLE m_threadExited; + DNSServiceRef m_browseDomainsRef; + DNSServiceRef m_regDomainsRef; + CRITICAL_SECTION m_lock; +}; + + +#endif diff --git a/mDNSWindows/ControlPanel/ControlPanel.cpp b/mDNSWindows/ControlPanel/ControlPanel.cpp new file mode 100755 index 0000000..03db2cb --- /dev/null +++ b/mDNSWindows/ControlPanel/ControlPanel.cpp @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ControlPanel.cpp,v $ +Revision 1.2 2005/03/03 19:55:22 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + + +#include "ControlPanel.h" +#include "ConfigDialog.h" +#include "ConfigPropertySheet.h" +#include "resource.h" + +#include + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +static CCPApp theApp; + + +//--------------------------------------------------------------------------------------------------------------------------- +// GetControlPanelApp +//--------------------------------------------------------------------------------------------------------------------------- + +CCPApp* +GetControlPanelApp() +{ + CCPApp * pApp = (CCPApp*) AfxGetApp(); + + check( pApp ); + check( pApp->IsKindOf( RUNTIME_CLASS( CCPApp ) ) ); + + return pApp; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CPlApplet +//--------------------------------------------------------------------------------------------------------------------------- + +LONG APIENTRY +CPlApplet(HWND hWndCPl, UINT uMsg, LONG lParam1, LONG lParam2) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + CCPApp * pApp = GetControlPanelApp(); + + return ( LONG ) pApp->OnCplMsg(hWndCPl, uMsg, lParam1, lParam2); +} + + +IMPLEMENT_DYNAMIC(CCPApplet, CCmdTarget); + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApplet::CCPApplet +//--------------------------------------------------------------------------------------------------------------------------- + +CCPApplet::CCPApplet(UINT resourceId, UINT descId, CRuntimeClass * uiClass) +: + m_resourceId(resourceId), + m_descId(descId), + m_uiClass(uiClass), + m_pageNumber(0) +{ + check( uiClass ); + check( uiClass->IsDerivedFrom( RUNTIME_CLASS( CDialog ) ) || + uiClass->IsDerivedFrom( RUNTIME_CLASS( CPropertySheet ) ) ); + + m_name.LoadString(resourceId); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApplet::~CCPApplet +//--------------------------------------------------------------------------------------------------------------------------- + +CCPApplet::~CCPApplet() +{ +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApplet::OnStartParms +//--------------------------------------------------------------------------------------------------------------------------- + +LRESULT +CCPApplet::OnStartParms(CWnd * pParentWnd, LPCTSTR extra) +{ + DEBUG_UNUSED( pParentWnd ); + + if ( extra ) + { + m_pageNumber = ::_ttoi( extra ) - 1; + } + + return 0; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApplet::OnRun +//--------------------------------------------------------------------------------------------------------------------------- + +LRESULT +CCPApplet::OnRun(CWnd* pParentWnd) +{ + LRESULT lResult = 1; + CWnd * pWnd = (CWnd*) m_uiClass->CreateObject(); + + if ( pWnd ) + { + lResult = ERROR_SUCCESS; + + if ( pWnd->IsKindOf( RUNTIME_CLASS( CPropertySheet ) ) ) + { + CPropertySheet * pSheet = (CPropertySheet*) pWnd; + + pSheet->Construct(m_name, pParentWnd, m_pageNumber); + + pSheet->DoModal(); + } + else + { + check( pWnd->IsKindOf( RUNTIME_CLASS( CDialog ) ) ); + + CDialog * pDialog = (CDialog*) pWnd; + + pDialog->DoModal(); + } + + delete pWnd; + } + + return lResult; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApplet::OnInquire +//--------------------------------------------------------------------------------------------------------------------------- + +LRESULT +CCPApplet::OnInquire(CPLINFO* pInfo) +{ + pInfo->idIcon = m_resourceId; + pInfo->idName = m_resourceId; + pInfo->idInfo = m_descId; + pInfo->lData = reinterpret_cast(this); + + return 0; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApplet::OnNewInquire +//--------------------------------------------------------------------------------------------------------------------------- + +LRESULT +CCPApplet::OnNewInquire(NEWCPLINFO* pInfo) +{ + DEBUG_UNUSED( pInfo ); + + return 1; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApplet::OnSelect +//--------------------------------------------------------------------------------------------------------------------------- + +LRESULT +CCPApplet::OnSelect() +{ + return 0; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApplet::OnStop +//--------------------------------------------------------------------------------------------------------------------------- + +LRESULT +CCPApplet::OnStop() +{ + return 0; +} + + +IMPLEMENT_DYNAMIC(CCPApp, CWinApp); + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApp::CCPApp +//--------------------------------------------------------------------------------------------------------------------------- + +CCPApp::CCPApp() +{ + debug_initialize( kDebugOutputTypeWindowsEventLog, "DNS-SD Control Panel", GetModuleHandle( NULL ) ); + debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelInfo ); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApp::~CCPApp +//--------------------------------------------------------------------------------------------------------------------------- + +CCPApp::~CCPApp() +{ + while ( !m_applets.IsEmpty() ) + { + delete m_applets.RemoveHead(); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApp::AddApplet +//--------------------------------------------------------------------------------------------------------------------------- + +void +CCPApp::AddApplet( CCPApplet * applet ) +{ + check( applet ); + + m_applets.AddTail( applet ); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApp::OnInit +//--------------------------------------------------------------------------------------------------------------------------- + +LRESULT +CCPApp::OnInit() +{ + CCPApplet * applet; + + try + { + applet = new CCPApplet( IDR_APPLET, IDS_APPLET_DESCRIPTION, RUNTIME_CLASS( CConfigPropertySheet ) ); + } + catch (...) + { + applet = NULL; + } + + require_action( applet, exit, kNoMemoryErr ); + + AddApplet( applet ); + +exit: + + return m_applets.GetCount(); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApp::OnExit +//--------------------------------------------------------------------------------------------------------------------------- + +LRESULT +CCPApp::OnExit() +{ + return 1; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApp::OnCplMsg +//--------------------------------------------------------------------------------------------------------------------------- + +LRESULT +CCPApp::OnCplMsg(HWND hWndCPl, UINT uMsg, LONG lParam1, LONG lParam2) +{ + LRESULT lResult = 1; + + switch ( uMsg ) + { + case CPL_INIT: + { + lResult = OnInit(); + } + break; + + case CPL_EXIT: + { + lResult = OnExit(); + } + break; + + case CPL_GETCOUNT: + { + lResult = m_applets.GetCount(); + } + break; + + default: + { + POSITION pos = m_applets.FindIndex( lParam1 ); + check( pos ); + + CCPApplet * applet = m_applets.GetAt( pos ); + check( applet ); + + switch (uMsg) + { + case CPL_INQUIRE: + { + LPCPLINFO pInfo = reinterpret_cast(lParam2); + lResult = applet->OnInquire(pInfo); + } + break; + + case CPL_NEWINQUIRE: + { + LPNEWCPLINFO pInfo = reinterpret_cast(lParam2); + lResult = applet->OnNewInquire(pInfo); + } + break; + + case CPL_STARTWPARMS: + { + CWnd * pParentWnd = CWnd::FromHandle(hWndCPl); + LPCTSTR lpszExtra = reinterpret_cast(lParam2); + lResult = applet->OnStartParms(pParentWnd, lpszExtra); + } + break; + + case CPL_DBLCLK: + { + CWnd* pParentWnd = CWnd::FromHandle(hWndCPl); + lResult = applet->OnRun(pParentWnd); + } + break; + + case CPL_SELECT: + { + lResult = applet->OnSelect(); + } + break; + + case CPL_STOP: + { + lResult = applet->OnStop(); + } + break; + + default: + { + // TRACE(_T("Warning, Received an unknown control panel message:%d\n"), uMsg); + lResult = 1; + } + break; + } + } + break; + } + + return lResult; +} diff --git a/mDNSWindows/ControlPanel/ControlPanel.def b/mDNSWindows/ControlPanel/ControlPanel.def new file mode 100755 index 0000000..ddae9e7 --- /dev/null +++ b/mDNSWindows/ControlPanel/ControlPanel.def @@ -0,0 +1,35 @@ +; +; Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. +; +; @APPLE_LICENSE_HEADER_START@ +; +; This file contains Original Code and/or Modifications of Original Code +; as defined in and that are subject to the Apple Public Source License +; Version 2.0 (the 'License'). You may not use this file except in +; compliance with the License. Please obtain a copy of the License at +; http://www.opensource.apple.com/apsl/ and read it before using this +; file. +; +; The Original Code and all software distributed under the License are +; distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +; Please see the License for the specific language governing rights and +; limitations under the License. +; +; @APPLE_LICENSE_HEADER_END@ +; +; Change History (most recent first): +; +; $Log: ControlPanel.def,v $ +; Revision 1.3 2005/03/03 19:55:22 shersche +; ControlPanel source code isn't saving CVS log info +; +; +; + +LIBRARY "Bonjour" + +EXPORTS + CPlApplet diff --git a/mDNSWindows/ControlPanel/ControlPanel.h b/mDNSWindows/ControlPanel/ControlPanel.h new file mode 100755 index 0000000..538fbf0 --- /dev/null +++ b/mDNSWindows/ControlPanel/ControlPanel.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ControlPanel.h,v $ +Revision 1.2 2005/03/03 19:55:21 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + + +#pragma once + +#include "stdafx.h" + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApplet +//--------------------------------------------------------------------------------------------------------------------------- + +class CCPApplet : public CCmdTarget +{ +public: + + CCPApplet( UINT nResourceID, UINT nDescriptionID, CRuntimeClass* pUIClass ); + + virtual ~CCPApplet(); + +protected: + + virtual LRESULT OnRun(CWnd* pParentWnd); + virtual LRESULT OnStartParms(CWnd* pParentWnd, LPCTSTR lpszExtra); + virtual LRESULT OnInquire(CPLINFO* pInfo); + virtual LRESULT OnNewInquire(NEWCPLINFO* pInfo); + virtual LRESULT OnSelect(); + virtual LRESULT OnStop(); + + CRuntimeClass * m_uiClass; + UINT m_resourceId; + UINT m_descId; + CString m_name; + int m_pageNumber; + + friend class CCPApp; + + DECLARE_DYNAMIC(CCPApplet); +}; + + +//--------------------------------------------------------------------------------------------------------------------------- +// CCPApp +//--------------------------------------------------------------------------------------------------------------------------- + +class CCPApp : public CWinApp +{ +public: + + CCPApp(); + virtual ~CCPApp(); + + void AddApplet( CCPApplet* pApplet ); + +protected: + + CList m_applets; + + friend LONG APIENTRY + CPlApplet(HWND hWndCPl, UINT uMsg, LONG lParam1, LONG lParam2); + + virtual LRESULT OnCplMsg(HWND hWndCPl, UINT msg, LPARAM lp1, LPARAM lp2); + virtual LRESULT OnInit(); + virtual LRESULT OnExit(); + + DECLARE_DYNAMIC(CCPApp); +}; + + +CCPApp * GetControlPanelApp(); diff --git a/mDNSWindows/ControlPanel/ControlPanel.rc b/mDNSWindows/ControlPanel/ControlPanel.rc new file mode 100755 index 0000000..db16d91 --- /dev/null +++ b/mDNSWindows/ControlPanel/ControlPanel.rc @@ -0,0 +1,280 @@ +// 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 + +///////////////////////////////////////////////////////////////////////////// +// +// 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", "Bonjour Configuration Applet" + VALUE "FileVersion", MASTER_PROD_VERS_STR + VALUE "InternalName", "Bonjour.cpl" + VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "Bonjour.cpl" + VALUE "ProductName", MASTER_PROD_NAME + VALUE "ProductVersion", MASTER_PROD_VERS_STR + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif\r\n" + "#include ""res\\ControlPanel.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_APPLET ICON "res\\controlpanel.ico" +IDI_FAILURE ICON "res\\failure.ico" +IDI_SUCCESS ICON "res\\success.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDR_APPLET_PAGE1 DIALOGEX 0, 0, 262, 140 +STYLE DS_SETFONT | WS_CHILD | WS_CAPTION +CAPTION "Hostname" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + LTEXT "Enter a hostname for this computer. Other computers on the Internet will be able to reach your computer using this hostname.", + IDC_STATIC,7,19,248,28 + LTEXT "Hostname:",IDC_STATIC,15,55,35,8 + EDITTEXT IDC_EDIT1,52,53,187,14,ES_AUTOHSCROLL + PUSHBUTTON "Password...",IDC_BUTTON1,52,72,67,14 + ICON IDI_FAILURE,IDC_FAILURE,240,50,21,20,SS_CENTERIMAGE | + SS_REALSIZEIMAGE + ICON IDI_SUCCESS,IDC_SUCCESS,240,50,21,20,SS_CENTERIMAGE | + SS_REALSIZEIMAGE | NOT WS_VISIBLE +END + +IDR_APPLET_PAGE2 DIALOGEX 0, 0, 262, 140 +STYLE DS_SETFONT | WS_CHILD | WS_CAPTION +CAPTION "Registration" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + CONTROL "Domain:",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,13,54,42,10 + COMBOBOX IDC_COMBO2,59,53,189,46,CBS_DROPDOWN | CBS_SORT | + WS_DISABLED | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Password...",IDC_BUTTON1,59,72,65,14 + LTEXT "Check the box and enter a registration domain to enable Bonjour advertising beyond the local subnet. ", + IDC_STATIC,14,20,233,23 +END + +IDR_SECRET DIALOGEX 0, 0, 251, 90 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Password" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,139,69,50,14 + PUSHBUTTON "Cancel",IDCANCEL,194,69,50,14 + LTEXT "Name:",IDC_STATIC,9,28,22,8 + EDITTEXT IDC_SECRET_NAME,36,26,208,14,ES_AUTOHSCROLL + LTEXT "Secret:",IDC_STATIC,9,44,24,8 + EDITTEXT IDC_SECRET,36,42,208,14,ES_PASSWORD | ES_AUTOHSCROLL + LTEXT "Enter a Password if your DNS server requires authentication.", + IDC_STATIC,7,7,237,15 +END + +IDR_APPLET_PAGE3 DIALOGEX 0, 0, 262, 140 +STYLE DS_SETFONT | WS_CHILD | WS_CAPTION +CAPTION "Browsing" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + LTEXT "Choose which domains to browse using Wide-Area Bonjour", + -1,7,16,248,12 + CONTROL "",IDC_BROWSE_LIST,"SysListView32",LVS_REPORT | + LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | + WS_TABSTOP,7,37,248,57 + PUSHBUTTON "Add",IDC_ADD_BROWSE_DOMAIN,152,100,50,14 + PUSHBUTTON "Remove",IDC_REMOVE_BROWSE_DOMAIN,205,100,50,14 +END + +IDR_ADD_BROWSE_DOMAIN DIALOGEX 0, 0, 230, 95 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Add Browse Domain" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,117,74,50,14 + PUSHBUTTON "Cancel",IDCANCEL,173,74,50,14 + COMBOBOX IDC_COMBO1,35,42,188,30,CBS_DROPDOWN | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + LTEXT "Domain:",IDC_STATIC,7,43,27,8 + LTEXT "The following domain will be added to your list of Bonjour browse domains.", + IDC_STATIC,7,15,216,16 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDR_APPLET_PAGE1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 255 + TOPMARGIN, 7 + BOTTOMMARGIN, 133 + END + + IDR_APPLET_PAGE2, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 255 + TOPMARGIN, 7 + BOTTOMMARGIN, 133 + END + + IDR_SECRET, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 244 + TOPMARGIN, 7 + BOTTOMMARGIN, 83 + END + + IDR_APPLET_PAGE3, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 255 + TOPMARGIN, 7 + BOTTOMMARGIN, 133 + END + + IDR_ADD_BROWSE_DOMAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 223 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDR_APPLET "Bonjour" + IDS_APPLET_DESCRIPTION "Wide-Area Bonjour Control Panel" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif +#include "res\ControlPanel.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/mDNSWindows/ControlPanel/ControlPanel.vcproj b/mDNSWindows/ControlPanel/ControlPanel.vcproj new file mode 100755 index 0000000..e322593 --- /dev/null +++ b/mDNSWindows/ControlPanel/ControlPanel.vcproj @@ -0,0 +1,333 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mDNSWindows/ControlPanel/FirstPage.cpp b/mDNSWindows/ControlPanel/FirstPage.cpp new file mode 100755 index 0000000..9dfe401 --- /dev/null +++ b/mDNSWindows/ControlPanel/FirstPage.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: FirstPage.cpp,v $ +Revision 1.3 2005/03/07 18:27:42 shersche + Fix problem when ControlPanel commits changes to the browse domain list + +Revision 1.2 2005/03/03 19:55:22 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#include "FirstPage.h" +#include "resource.h" + +#include "ConfigPropertySheet.h" +#include "SharedSecret.h" + +#define MAX_KEY_LENGTH 255 + + +IMPLEMENT_DYNCREATE(CFirstPage, CPropertyPage) + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::CFirstPage +//--------------------------------------------------------------------------------------------------------------------------- + +CFirstPage::CFirstPage() +: + CPropertyPage(CFirstPage::IDD), + m_ignoreHostnameChange( false ), + m_statusKey( NULL ) +{ + //{{AFX_DATA_INIT(CFirstPage) + //}}AFX_DATA_INIT + + OSStatus err; + + err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\State\\Hostnames", &m_statusKey ); + check_noerr( err ); + + err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\Hostnames", &m_setupKey ); + check_noerr( err ); +} + +CFirstPage::~CFirstPage() +{ + if ( m_statusKey ) + { + RegCloseKey( m_statusKey ); + m_statusKey = NULL; + } + + if ( m_setupKey ) + { + RegCloseKey( m_setupKey ); + m_setupKey = NULL; + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::DoDataExchange +//--------------------------------------------------------------------------------------------------------------------------- + +void CFirstPage::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CFirstPage) + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_EDIT1, m_hostnameControl); + DDX_Control(pDX, IDC_FAILURE, m_failureIcon); + DDX_Control(pDX, IDC_SUCCESS, m_successIcon); +} + +BEGIN_MESSAGE_MAP(CFirstPage, CPropertyPage) + //{{AFX_MSG_MAP(CFirstPage) + //}}AFX_MSG_MAP + ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedSharedSecret) + ON_EN_CHANGE(IDC_EDIT1, OnEnChangeHostname) +END_MESSAGE_MAP() + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::OnEnChangedHostname +//--------------------------------------------------------------------------------------------------------------------------- + +void CFirstPage::OnEnChangeHostname() +{ + if ( !m_ignoreHostnameChange ) + { + SetModified( TRUE ); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::OnBnClickedSharedSecret +//--------------------------------------------------------------------------------------------------------------------------- + +void CFirstPage::OnBnClickedSharedSecret() +{ + CString name; + + m_hostnameControl.GetWindowText( name ); + + CSharedSecret dlg; + + dlg.m_secretName = name; + + if ( dlg.DoModal() == IDOK ) + { + dlg.Commit(); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::SetModified +//--------------------------------------------------------------------------------------------------------------------------- + +void CFirstPage::SetModified( BOOL bChanged ) +{ + m_modified = bChanged ? true : false; + + CPropertyPage::SetModified( bChanged ); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::OnSetActive +//--------------------------------------------------------------------------------------------------------------------------- + +BOOL +CFirstPage::OnSetActive() +{ + TCHAR name[kDNSServiceMaxDomainName + 1]; + DWORD nameLen = ( kDNSServiceMaxDomainName + 1 ) * sizeof( TCHAR ); + DWORD err; + + BOOL b = CPropertyPage::OnSetActive(); + + m_modified = FALSE; + + if ( m_setupKey ) + { + err = RegQueryValueEx( m_setupKey, L"", NULL, NULL, (LPBYTE) name, &nameLen ); + + if ( !err ) + { + m_ignoreHostnameChange = true; + m_hostnameControl.SetWindowText( name ); + m_ignoreHostnameChange = false; + } + } + + // Check the status of this hostname + + err = CheckStatus(); + check_noerr( err ); + + return b; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::OnOK +//--------------------------------------------------------------------------------------------------------------------------- + +void +CFirstPage::OnOK() +{ + if ( m_modified ) + { + Commit(); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::Commit +//--------------------------------------------------------------------------------------------------------------------------- + +void +CFirstPage::Commit() +{ + DWORD enabled = 1; + CString name; + DWORD err; + + m_hostnameControl.GetWindowText( name ); + + // Convert to lower case + + name.MakeLower(); + + // Remove trailing dot + + name.TrimRight( '.' ); + + err = RegSetValueEx( m_setupKey, L"", 0, REG_SZ, (LPBYTE) (LPCTSTR) name, ( name.GetLength() + 1 ) * sizeof( TCHAR ) ); + require_noerr( err, exit ); + + err = RegSetValueEx( m_setupKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) ); + require_noerr( err, exit ); + +exit: + + return; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::CheckStatus +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CFirstPage::CheckStatus() +{ + DWORD status = 0; + DWORD dwSize = sizeof( DWORD ); + OSStatus err; + + // Get the status field + + err = RegQueryValueEx( m_statusKey, L"Status", NULL, NULL, (LPBYTE) &status, &dwSize ); + require_noerr( err, exit ); + + ShowStatus( status ); + +exit: + + return kNoErr; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::ShowStatus +//--------------------------------------------------------------------------------------------------------------------------- + +void +CFirstPage::ShowStatus( DWORD status ) +{ + if ( status ) + { + m_failureIcon.ShowWindow( SW_HIDE ); + m_successIcon.ShowWindow( SW_SHOW ); + } + else + { + m_failureIcon.ShowWindow( SW_SHOW ); + m_successIcon.ShowWindow( SW_HIDE ); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage::OnRegistryChanged +//--------------------------------------------------------------------------------------------------------------------------- + +void +CFirstPage::OnRegistryChanged() +{ + CheckStatus(); +} diff --git a/mDNSWindows/ControlPanel/FirstPage.h b/mDNSWindows/ControlPanel/FirstPage.h new file mode 100755 index 0000000..6d875e1 --- /dev/null +++ b/mDNSWindows/ControlPanel/FirstPage.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: FirstPage.h,v $ +Revision 1.3 2005/03/07 18:27:42 shersche + Fix problem when ControlPanel commits changes to the browse domain list + +Revision 1.2 2005/03/03 19:55:21 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#pragma once + +#include "stdafx.h" +#include "resource.h" + +#include +#include "afxwin.h" + + +//--------------------------------------------------------------------------------------------------------------------------- +// CFirstPage +//--------------------------------------------------------------------------------------------------------------------------- + +class CFirstPage : public CPropertyPage +{ +public: + CFirstPage(); + ~CFirstPage(); + +protected: + //{{AFX_DATA(CFirstPage) + enum { IDD = IDR_APPLET_PAGE1 }; + //}}AFX_DATA + + //{{AFX_VIRTUAL(CFirstPage) + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + DECLARE_DYNCREATE(CFirstPage) + + //{{AFX_MSG(CFirstPage) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnBnClickedSharedSecret(); + void OnRegistryChanged(); +private: + + afx_msg BOOL OnSetActive(); + afx_msg void OnOK(); + + void SetModified( BOOL bChanged = TRUE ); + void Commit(); + + OSStatus CheckStatus(); + void ShowStatus( DWORD status ); + + CEdit m_hostnameControl; + bool m_ignoreHostnameChange; + bool m_modified; + HKEY m_statusKey; + HKEY m_setupKey; + +public: + + afx_msg void OnEnChangeHostname(); + CStatic m_failureIcon; + CStatic m_successIcon; +}; diff --git a/mDNSWindows/ControlPanel/SecondPage.cpp b/mDNSWindows/ControlPanel/SecondPage.cpp new file mode 100755 index 0000000..a330e84 --- /dev/null +++ b/mDNSWindows/ControlPanel/SecondPage.cpp @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: SecondPage.cpp,v $ +Revision 1.3 2005/03/03 19:55:22 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#include "SecondPage.h" +#include "resource.h" + +#include "ConfigPropertySheet.h" +#include "SharedSecret.h" + +#include + +IMPLEMENT_DYNCREATE(CSecondPage, CPropertyPage) + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::CSecondPage +//--------------------------------------------------------------------------------------------------------------------------- + +CSecondPage::CSecondPage() +: + CPropertyPage(CSecondPage::IDD) +{ + //{{AFX_DATA_INIT(CSecondPage) + //}}AFX_DATA_INIT +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::~CSecondPage +//--------------------------------------------------------------------------------------------------------------------------- + +CSecondPage::~CSecondPage() +{ +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::DoDataExchange +//--------------------------------------------------------------------------------------------------------------------------- + +void CSecondPage::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSecondPage) + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CHECK1, m_advertiseServicesButton); + DDX_Control(pDX, IDC_BUTTON1, m_sharedSecretButton); + DDX_Control(pDX, IDC_COMBO2, m_regDomainsBox); +} + +BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage) + //{{AFX_MSG_MAP(CSecondPage) + //}}AFX_MSG_MAP + ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedSharedSecret) + ON_BN_CLICKED(IDC_CHECK1, OnBnClickedAdvertise) + ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelChange) + ON_CBN_EDITCHANGE(IDC_COMBO1, OnCbnEditChange) + ON_CBN_EDITCHANGE(IDC_COMBO2, OnCbnEditChange) + ON_CBN_SELCHANGE(IDC_COMBO2, OnCbnSelChange) + +END_MESSAGE_MAP() + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::SetModified +//--------------------------------------------------------------------------------------------------------------------------- + +void CSecondPage::SetModified( BOOL bChanged ) +{ + m_modified = bChanged; + + CPropertyPage::SetModified( bChanged ); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::OnSetActive +//--------------------------------------------------------------------------------------------------------------------------- + +BOOL +CSecondPage::OnSetActive() +{ + CConfigPropertySheet * psheet; + HKEY key = NULL; + DWORD dwSize; + DWORD enabled; + DWORD err; + BOOL b = CPropertyPage::OnSetActive(); + + psheet = reinterpret_cast(GetParent()); + require_quiet( psheet, exit ); + + m_modified = FALSE; + + // Clear out what's there + + EmptyComboBox( m_regDomainsBox ); + + // Now populate the registration domain box + + err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key ); + require_noerr( err, exit ); + + err = Populate( m_regDomainsBox, key, psheet->m_regDomains ); + check_noerr( err ); + + dwSize = sizeof( DWORD ); + err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize ); + m_advertiseServicesButton.SetCheck( ( !err && enabled ) ? BST_CHECKED : BST_UNCHECKED ); + m_regDomainsBox.EnableWindow( ( !err && enabled ) ); + m_sharedSecretButton.EnableWindow( (!err && enabled ) ); + + RegCloseKey( key ); + +exit: + + return b; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::OnOK +//--------------------------------------------------------------------------------------------------------------------------- + +void +CSecondPage::OnOK() +{ + if ( m_modified ) + { + Commit(); + } +} + + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::Commit +//--------------------------------------------------------------------------------------------------------------------------- + +void +CSecondPage::Commit() +{ + HKEY key = NULL; + DWORD err; + + err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key ); + require_noerr( err, exit ); + + err = Commit( m_regDomainsBox, key, m_advertiseServicesButton.GetCheck() == BST_CHECKED ); + check_noerr( err ); + +exit: + + if ( key ) + { + RegCloseKey( key ); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::Commit +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CSecondPage::Commit( CComboBox & box, HKEY key, DWORD enabled ) +{ + CString selected; + OSStatus err = kNoErr; + + // Get selected text + + box.GetWindowText( selected ); + + // If we haven't seen this string before, add the string to the box and + // the registry + + if ( ( selected.GetLength() > 0 ) && ( box.FindStringExact( -1, selected ) == CB_ERR ) ) + { + CString string; + + box.AddString( selected ); + + err = RegQueryString( key, L"UserDefined", string ); + check_noerr( err ); + + if ( string.GetLength() ) + { + string += L"," + selected; + } + else + { + string = selected; + } + + err = RegSetValueEx( key, L"UserDefined", 0, REG_SZ, (LPBYTE) (LPCTSTR) string, ( string.GetLength() + 1) * sizeof( TCHAR ) ); + check_noerr ( err ); + } + + // Save selected text in registry. This will trigger mDNSResponder to setup + // DynDNS config again + + err = RegSetValueEx( key, L"", 0, REG_SZ, (LPBYTE) (LPCTSTR) selected, ( selected.GetLength() + 1 ) * sizeof( TCHAR ) ); + check_noerr( err ); + + err = RegSetValueEx( key, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) ); + check_noerr( err ); + + return err; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::OnBnClickedSharedSecret +//--------------------------------------------------------------------------------------------------------------------------- + +void CSecondPage::OnBnClickedSharedSecret() +{ + CString string; + + m_regDomainsBox.GetWindowText( string ); + + CSharedSecret dlg; + + dlg.m_secretName = string; + + dlg.DoModal(); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::OnBnClickedAdvertise +//--------------------------------------------------------------------------------------------------------------------------- + +void CSecondPage::OnBnClickedAdvertise() +{ + int state; + + state = m_advertiseServicesButton.GetCheck(); + + m_regDomainsBox.EnableWindow( state ); + m_sharedSecretButton.EnableWindow( state ); + + SetModified( TRUE ); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::OnCbnSelChange +//--------------------------------------------------------------------------------------------------------------------------- + +void CSecondPage::OnCbnSelChange() +{ + SetModified( TRUE ); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::OnCbnEditChange +//--------------------------------------------------------------------------------------------------------------------------- + +void CSecondPage::OnCbnEditChange() +{ + SetModified( TRUE ); +} + + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::OnAddRegistrationDomain +//--------------------------------------------------------------------------------------------------------------------------- + +void +CSecondPage::OnAddRegistrationDomain( CString & domain ) +{ + int index = m_regDomainsBox.FindStringExact( -1, domain ); + + if ( index == CB_ERR ) + { + m_regDomainsBox.AddString( domain ); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::OnRemoveRegistrationDomain +//--------------------------------------------------------------------------------------------------------------------------- + +void +CSecondPage::OnRemoveRegistrationDomain( CString & domain ) +{ + int index = m_regDomainsBox.FindStringExact( -1, domain ); + + if ( index != CB_ERR ) + { + m_regDomainsBox.DeleteString( index ); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::EmptyComboBox +//--------------------------------------------------------------------------------------------------------------------------- + +void +CSecondPage::EmptyComboBox( CComboBox & box ) +{ + while ( box.GetCount() > 0 ) + { + box.DeleteString( 0 ); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::Populate +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CSecondPage::Populate( CComboBox & box, HKEY key, StringList & l ) +{ + TCHAR rawString[kDNSServiceMaxDomainName + 1]; + DWORD rawStringLen; + CString string; + OSStatus err; + + err = RegQueryString( key, L"UserDefined", string ); + + if ( !err && string.GetLength() ) + { + bool done = false; + + while ( !done ) + { + CString tok; + + tok = string.SpanExcluding( L"," ); + + box.AddString( tok ); + + if ( tok != string ) + { + // Get rid of that string and comma + + string = string.Right( string.GetLength() - tok.GetLength() - 1 ); + } + else + { + done = true; + } + } + } + + StringList::iterator it; + + for ( it = l.begin(); it != l.end(); it++ ) + { + if ( box.FindStringExact( -1, *it ) == CB_ERR ) + { + box.AddString( *it ); + } + } + + // Now look to see if there is a selected string, and if so, + // select it + + rawString[0] = '\0'; + + rawStringLen = sizeof( rawString ); + + err = RegQueryValueEx( key, L"", 0, NULL, (LPBYTE) rawString, &rawStringLen ); + + string = rawString; + + if ( !err && ( string.GetLength() != 0 ) ) + { + // See if it's there + + if ( box.SelectString( -1, string ) == CB_ERR ) + { + // If not, add it + + box.AddString( string ); + } + + box.SelectString( -1, string ); + } + + return err; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::CreateKey +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CSecondPage::CreateKey( CString & name, DWORD enabled ) +{ + HKEY key = NULL; + OSStatus err; + + err = RegCreateKey( HKEY_LOCAL_MACHINE, (LPCTSTR) name, &key ); + require_noerr( err, exit ); + + err = RegSetValueEx( key, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) ); + check_noerr( err ); + +exit: + + if ( key ) + { + RegCloseKey( key ); + } + + return err; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage::RegQueryString +//--------------------------------------------------------------------------------------------------------------------------- + +OSStatus +CSecondPage::RegQueryString( HKEY key, CString valueName, CString & value ) +{ + TCHAR * string; + DWORD stringLen; + int i; + OSStatus err; + + stringLen = 1024; + string = NULL; + i = 0; + + do + { + if ( string ) + { + free( string ); + } + + string = (TCHAR*) malloc( stringLen ); + require_action( string, exit, err = kUnknownErr ); + + err = RegQueryValueEx( key, valueName, 0, NULL, (LPBYTE) string, &stringLen ); + + i++; + } + while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) ); + + value = string; + +exit: + + if ( string ) + { + free( string ); + } + + return err; +} diff --git a/mDNSWindows/ControlPanel/SecondPage.h b/mDNSWindows/ControlPanel/SecondPage.h new file mode 100755 index 0000000..a8d1f09 --- /dev/null +++ b/mDNSWindows/ControlPanel/SecondPage.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: SecondPage.h,v $ +Revision 1.3 2005/03/03 19:55:21 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#pragma once + +#include "stdafx.h" +#include "resource.h" + +#include +#include + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSecondPage +//--------------------------------------------------------------------------------------------------------------------------- + +class CSecondPage : public CPropertyPage +{ +public: + CSecondPage(); + ~CSecondPage(); + +protected: + + //{{AFX_DATA(CSecondPage) + enum { IDD = IDR_APPLET_PAGE2 }; + //}}AFX_DATA + + //{{AFX_VIRTUAL(CSecondPage) + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + DECLARE_DYNCREATE(CSecondPage) + + //{{AFX_MSG(CSecondPage) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + + afx_msg void OnBnClickedSharedSecret(); + afx_msg void OnBnClickedAdvertise(); + + void OnAddRegistrationDomain( CString & domain ); + void OnRemoveRegistrationDomain( CString & domain ); + +private: + + typedef std::list StringList; + + afx_msg BOOL + OnSetActive(); + + afx_msg void + OnOK(); + + void + EmptyComboBox + ( + CComboBox & box + ); + + OSStatus + Populate( + CComboBox & box, + HKEY key, + StringList & l + ); + + void + SetModified( BOOL bChanged = TRUE ); + + void + Commit(); + + OSStatus + Commit( CComboBox & box, HKEY key, DWORD enabled ); + + OSStatus + CreateKey( CString & name, DWORD enabled ); + + OSStatus + RegQueryString( HKEY key, CString valueName, CString & value ); + + CComboBox m_regDomainsBox; + CButton m_advertiseServicesButton; + CButton m_sharedSecretButton; + BOOL m_modified; + +public: + afx_msg void OnCbnSelChange(); + afx_msg void OnCbnEditChange(); +}; diff --git a/mDNSWindows/ControlPanel/SharedSecret.cpp b/mDNSWindows/ControlPanel/SharedSecret.cpp new file mode 100755 index 0000000..6c42aca --- /dev/null +++ b/mDNSWindows/ControlPanel/SharedSecret.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: SharedSecret.cpp,v $ +Revision 1.2 2005/03/03 19:55:22 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + + +// SharedSecret.cpp : implementation file +// + +#include "stdafx.h" +#include "SharedSecret.h" + +#include +#include + +//--------------------------------------------------------------------------------------------------------------------------- +// Private declarations +//--------------------------------------------------------------------------------------------------------------------------- + +static BOOL +InitLsaString + ( + PLSA_UNICODE_STRING pLsaString, + LPCWSTR pwszString + ); + +// SharedSecret dialog + +IMPLEMENT_DYNAMIC(CSharedSecret, CDialog) + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSharedSecret::CSharedSecret +//--------------------------------------------------------------------------------------------------------------------------- + +CSharedSecret::CSharedSecret(CWnd* pParent /*=NULL*/) + : CDialog(CSharedSecret::IDD, pParent) + , m_secret(_T("")) + , m_secretName(_T("")) +{ +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSharedSecret::~CSharedSecret +//--------------------------------------------------------------------------------------------------------------------------- + +CSharedSecret::~CSharedSecret() +{ +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSharedSecret::DoDataExchange +//--------------------------------------------------------------------------------------------------------------------------- + +void CSharedSecret::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Text(pDX, IDC_SECRET, m_secret); + DDX_Text(pDX, IDC_SECRET_NAME, m_secretName); +} + + +BEGIN_MESSAGE_MAP(CSharedSecret, CDialog) +END_MESSAGE_MAP() + + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSharedSecret::Commit +//--------------------------------------------------------------------------------------------------------------------------- + +void +CSharedSecret::Commit() +{ + LSA_OBJECT_ATTRIBUTES attrs; + LSA_HANDLE handle = NULL; + NTSTATUS res; + LSA_UNICODE_STRING lucKeyName; + LSA_UNICODE_STRING lucPrivateData; + BOOL ok; + OSStatus err; + + // If there isn't a trailing dot, add one because the mDNSResponder + // presents names with the trailing dot. + + if ( m_secretName.ReverseFind( '.' ) != m_secretName.GetLength() ) + { + m_secretName += '.'; + } + + // attrs are reserved, so initialize to zeroes. + + ZeroMemory(&attrs, sizeof( attrs ) ); + + // Get a handle to the Policy object on the local system + + res = LsaOpenPolicy( NULL, &attrs, POLICY_ALL_ACCESS, &handle ); + err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr ); + require_noerr( err, exit ); + + // Intializing PLSA_UNICODE_STRING structures + + ok = InitLsaString( &lucKeyName, m_secretName ); + err = translate_errno( ok, errno_compat(), kUnknownErr ); + require_noerr( err, exit ); + + ok = InitLsaString( &lucPrivateData, m_secret ); + err = translate_errno( ok, errno_compat(), kUnknownErr ); + require_noerr( err, exit ); + + // Store the private data. + + res = LsaStorePrivateData( handle, &lucKeyName, &lucPrivateData ); + err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr ); + require_noerr( err, exit ); + +exit: + + if ( handle ) + { + LsaClose( handle ); + handle = NULL; + } + + return; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// InitLsaString +//--------------------------------------------------------------------------------------------------------------------------- + +static BOOL +InitLsaString + ( + PLSA_UNICODE_STRING pLsaString, + LPCWSTR pwszString + ) +{ + size_t dwLen = 0; + BOOL ret = FALSE; + + if ( pLsaString == NULL ) + { + goto exit; + } + + if ( pwszString != NULL ) + { + dwLen = wcslen(pwszString); + + // String is too large + if (dwLen > 0x7ffe) + { + goto exit; + } + } + + // Store the string. + + pLsaString->Buffer = (WCHAR *) pwszString; + pLsaString->Length = (USHORT) dwLen * sizeof(WCHAR); + pLsaString->MaximumLength = (USHORT)(dwLen+1) * sizeof(WCHAR); + + ret = TRUE; + +exit: + + return ret; +} diff --git a/mDNSWindows/ControlPanel/SharedSecret.h b/mDNSWindows/ControlPanel/SharedSecret.h new file mode 100755 index 0000000..07e79e1 --- /dev/null +++ b/mDNSWindows/ControlPanel/SharedSecret.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: SharedSecret.h,v $ +Revision 1.2 2005/03/03 19:55:21 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + + +#pragma once + +#include "resource.h" + + +//--------------------------------------------------------------------------------------------------------------------------- +// CSharedSecret +//--------------------------------------------------------------------------------------------------------------------------- + +class CSharedSecret : public CDialog +{ + DECLARE_DYNAMIC(CSharedSecret) + +public: + CSharedSecret(CWnd* pParent = NULL); // standard constructor + virtual ~CSharedSecret(); + +// Dialog Data + enum { IDD = IDR_SECRET }; + + void + Commit(); + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() + +public: + CString m_secret; + CString m_secretName; +}; diff --git a/mDNSWindows/ControlPanel/ThirdPage.cpp b/mDNSWindows/ControlPanel/ThirdPage.cpp new file mode 100755 index 0000000..bfb56bd --- /dev/null +++ b/mDNSWindows/ControlPanel/ThirdPage.cpp @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ThirdPage.cpp,v $ +Revision 1.3 2005/03/07 18:27:42 shersche + Fix problem when ControlPanel commits changes to the browse domain list + +Revision 1.2 2005/03/03 19:55:22 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#include "ThirdPage.h" +#include "resource.h" + +#include "ConfigPropertySheet.h" +#include "SharedSecret.h" + +#include + +#define MAX_KEY_LENGTH 255 + + +IMPLEMENT_DYNCREATE(CThirdPage, CPropertyPage) + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage::CThirdPage +//--------------------------------------------------------------------------------------------------------------------------- + +CThirdPage::CThirdPage() +: + CPropertyPage(CThirdPage::IDD) +{ + //{{AFX_DATA_INIT(CThirdPage) + //}}AFX_DATA_INIT + + m_firstTime = true; +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage::~CThirdPage +//--------------------------------------------------------------------------------------------------------------------------- + +CThirdPage::~CThirdPage() +{ +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage::DoDataExchange +//--------------------------------------------------------------------------------------------------------------------------- + +void CThirdPage::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CThirdPage) + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_BROWSE_LIST, m_browseListCtrl); + DDX_Control(pDX, IDC_REMOVE_BROWSE_DOMAIN, m_removeButton); +} + +BEGIN_MESSAGE_MAP(CThirdPage, CPropertyPage) + //{{AFX_MSG_MAP(CThirdPage) + //}}AFX_MSG_MAP + ON_BN_CLICKED(IDC_ADD_BROWSE_DOMAIN, OnBnClickedAddBrowseDomain) + ON_BN_CLICKED(IDC_REMOVE_BROWSE_DOMAIN, OnBnClickedRemoveBrowseDomain) + ON_NOTIFY(LVN_ITEMCHANGED, IDC_BROWSE_LIST, OnLvnItemchangedBrowseList) +END_MESSAGE_MAP() + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage::SetModified +//--------------------------------------------------------------------------------------------------------------------------- + +void CThirdPage::SetModified( BOOL bChanged ) +{ + m_modified = bChanged; + + CPropertyPage::SetModified( bChanged ); +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage::OnSetActive +//--------------------------------------------------------------------------------------------------------------------------- + +BOOL +CThirdPage::OnSetActive() +{ + CConfigPropertySheet * psheet; + HKEY key = NULL; + HKEY subKey = NULL; + DWORD dwSize; + DWORD enabled; + DWORD err; + TCHAR subKeyName[MAX_KEY_LENGTH]; + DWORD cSubKeys = 0; + DWORD cbMaxSubKey; + DWORD cchMaxClass; + int nIndex; + DWORD i; + BOOL b = CPropertyPage::OnSetActive(); + + psheet = reinterpret_cast(GetParent()); + require_quiet( psheet, exit ); + + m_modified = FALSE; + + if ( m_firstTime ) + { + m_browseListCtrl.SetExtendedStyle((m_browseListCtrl.GetStyle() & (~LVS_EX_GRIDLINES))|LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT); + + m_browseListCtrl.InsertColumn(0, L"", LVCFMT_LEFT, 20 ); + m_browseListCtrl.InsertColumn(1, L"", LVCFMT_LEFT, 345); + + m_firstTime = false; + } + + m_initialized = false; + + // Clear out what's there + + m_browseListCtrl.DeleteAllItems(); + + // Now populate the browse domain box + + err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key ); + require_noerr( err, exit ); + + // Get information about this node + + err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL ); + require_noerr( err, exit ); + + for ( i = 0; i < cSubKeys; i++) + { + dwSize = MAX_KEY_LENGTH; + + err = RegEnumKeyEx( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL ); + require_noerr( err, exit ); + + err = RegOpenKey( key, subKeyName, &subKey ); + require_noerr( err, exit ); + + dwSize = sizeof( DWORD ); + err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize ); + require_noerr( err, exit ); + + nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L""); + m_browseListCtrl.SetItemText( nIndex, 1, subKeyName ); + m_browseListCtrl.SetCheck( nIndex, enabled ); + + RegCloseKey( subKey ); + subKey = NULL; + } + + m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this ); + + m_removeButton.EnableWindow( FALSE ); + +exit: + + if ( subKey ) + { + RegCloseKey( subKey ); + } + + if ( key ) + { + RegCloseKey( key ); + } + + m_initialized = true; + + return b; +} + + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage::OnOK +//--------------------------------------------------------------------------------------------------------------------------- + +void +CThirdPage::OnOK() +{ + if ( m_modified ) + { + Commit(); + } +} + + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage::Commit +//--------------------------------------------------------------------------------------------------------------------------- + +void +CThirdPage::Commit() +{ + HKEY key = NULL; + HKEY subKey = NULL; + TCHAR subKeyName[MAX_KEY_LENGTH]; + DWORD cSubKeys = 0; + DWORD cbMaxSubKey; + DWORD cchMaxClass; + DWORD dwSize; + int i; + DWORD err; + + err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key ); + require_noerr( err, exit ); + + // First, remove all the entries that are there + + err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL ); + require_noerr( err, exit ); + + for ( i = 0; i < (int) cSubKeys; i++ ) + { + dwSize = MAX_KEY_LENGTH; + + err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL ); + require_noerr( err, exit ); + + err = RegDeleteKey( key, subKeyName ); + require_noerr( err, exit ); + } + + // Now re-populate + + for ( i = 0; i < m_browseListCtrl.GetItemCount(); i++ ) + { + DWORD enabled = (DWORD) m_browseListCtrl.GetCheck( i ); + + err = RegCreateKey( key, m_browseListCtrl.GetItemText( i, 1 ), &subKey ); + require_noerr( err, exit ); + + err = RegSetValueEx( subKey, L"Enabled", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) ); + require_noerr( err, exit ); + + RegCloseKey( subKey ); + subKey = NULL; + } + +exit: + + if ( subKey ) + { + RegCloseKey( subKey ); + } + + if ( key ) + { + RegCloseKey( key ); + } +} + + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage::OnBnClickedAddBrowseDomain +//--------------------------------------------------------------------------------------------------------------------------- + +void +CThirdPage::OnBnClickedAddBrowseDomain() +{ + CAddBrowseDomain dlg( GetParent() ); + + if ( ( dlg.DoModal() == IDOK ) && ( dlg.m_text.GetLength() > 0 ) ) + { + int nIndex; + + nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L""); + m_browseListCtrl.SetItemText( nIndex, 1, dlg.m_text ); + m_browseListCtrl.SetCheck( nIndex, 1 ); + + m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this ); + + m_browseListCtrl.Invalidate(); + + SetModified( TRUE ); + } +} + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage::OnBnClickedRemoveBrowseDomain +//--------------------------------------------------------------------------------------------------------------------------- + +void +CThirdPage::OnBnClickedRemoveBrowseDomain() +{ + UINT selectedCount = m_browseListCtrl.GetSelectedCount(); + int nItem = -1; + UINT i; + + // Update all of the selected items. + + for ( i = 0; i < selectedCount; i++ ) + { + nItem = m_browseListCtrl.GetNextItem( -1, LVNI_SELECTED ); + check( nItem != -1 ); + + m_browseListCtrl.DeleteItem( nItem ); + + SetModified( TRUE ); + } + + m_removeButton.EnableWindow( FALSE ); +} + + +void +CThirdPage::OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult) +{ + if ( m_browseListCtrl.GetSelectedCount() ) + { + m_removeButton.EnableWindow( TRUE ); + } + + if ( m_initialized ) + { + NM_LISTVIEW * pNMListView = (NM_LISTVIEW*)pNMHDR; + + BOOL bPrevState = (BOOL) ( ( ( pNMListView->uOldState & LVIS_STATEIMAGEMASK ) >> 12 ) - 1 ); + + if ( bPrevState < 0 ) + { + bPrevState = 0; + } + + + BOOL bChecked = ( BOOL ) ( ( ( pNMListView->uNewState & LVIS_STATEIMAGEMASK ) >> 12) - 1 ); + + if ( bChecked < 0 ) + { + bChecked = 0; + } + + if ( bPrevState != bChecked ) + { + SetModified( TRUE ); + } + } + + *pResult = 0; +} + + + +int CALLBACK +CThirdPage::SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + CString str1; + CString str2; + int ret = 0; + + CThirdPage * self = reinterpret_cast( lParamSort ); + require_quiet( self, exit ); + + str1 = self->m_browseListCtrl.GetItemText( (int) lParam1, 1 ); + str2 = self->m_browseListCtrl.GetItemText( (int) lParam2, 1 ); + + ret = str1.Compare( str2 ); + +exit: + + return ret; +} + + +// CAddBrowseDomain dialog + +IMPLEMENT_DYNAMIC(CAddBrowseDomain, CDialog) +CAddBrowseDomain::CAddBrowseDomain(CWnd* pParent /*=NULL*/) + : CDialog(CAddBrowseDomain::IDD, pParent) +{ +} + +CAddBrowseDomain::~CAddBrowseDomain() +{ +} + +void CAddBrowseDomain::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_COMBO1, m_comboBox); +} + + +BOOL +CAddBrowseDomain::OnInitDialog() +{ + CConfigPropertySheet * psheet; + CConfigPropertySheet::StringList::iterator it; + + BOOL b = CDialog::OnInitDialog(); + + psheet = reinterpret_cast(GetParent()); + require_quiet( psheet, exit ); + + for ( it = psheet->m_browseDomains.begin(); it != psheet->m_browseDomains.end(); it++ ) + { + CString text = *it; + + if ( m_comboBox.FindStringExact( -1, *it ) == CB_ERR ) + { + m_comboBox.AddString( *it ); + } + } + +exit: + + return b; +} + + +void +CAddBrowseDomain::OnOK() +{ + m_comboBox.GetWindowText( m_text ); + + CDialog::OnOK(); +} + + + +BEGIN_MESSAGE_MAP(CAddBrowseDomain, CDialog) +END_MESSAGE_MAP() + diff --git a/mDNSWindows/ControlPanel/ThirdPage.h b/mDNSWindows/ControlPanel/ThirdPage.h new file mode 100755 index 0000000..9fe7420 --- /dev/null +++ b/mDNSWindows/ControlPanel/ThirdPage.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ThirdPage.h,v $ +Revision 1.2 2005/03/03 19:55:21 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#pragma once + +#include "stdafx.h" +#include "resource.h" + +#include +#include +#include "afxcmn.h" +#include "afxwin.h" + + + +//--------------------------------------------------------------------------------------------------------------------------- +// CThirdPage +//--------------------------------------------------------------------------------------------------------------------------- + +class CThirdPage : public CPropertyPage +{ +public: + CThirdPage(); + ~CThirdPage(); + +protected: + + //{{AFX_DATA(CThirdPage) + enum { IDD = IDR_APPLET_PAGE3 }; + //}}AFX_DATA + + //{{AFX_VIRTUAL(CThirdPage) + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + DECLARE_DYNCREATE(CThirdPage) + + //{{AFX_MSG(CThirdPage) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + + typedef std::list StringList; + + afx_msg BOOL + OnSetActive(); + + afx_msg void + OnOK(); + + void + SetModified( BOOL bChanged = TRUE ); + + void + Commit(); + + BOOL m_modified; + +public: +private: + static int CALLBACK + SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); + + CListCtrl m_browseListCtrl; + bool m_initialized; + bool m_firstTime; + +public: + + afx_msg void OnBnClickedAddBrowseDomain(); + afx_msg void OnBnClickedRemoveBrowseDomain(); + afx_msg void OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult); + CButton m_removeButton; +}; + + +//--------------------------------------------------------------------------------------------------------------------------- +// CAddBrowseDomain +//--------------------------------------------------------------------------------------------------------------------------- + +class CAddBrowseDomain : public CDialog +{ + DECLARE_DYNAMIC(CAddBrowseDomain) + +public: + CAddBrowseDomain(CWnd* pParent = NULL); // standard constructor + virtual ~CAddBrowseDomain(); + +// Dialog Data + enum { IDD = IDR_ADD_BROWSE_DOMAIN }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); + virtual void OnOK(); + DECLARE_MESSAGE_MAP() +public: + CComboBox m_comboBox; + CString m_text; +}; diff --git a/mDNSWindows/ControlPanel/res/ControlPanel.rc2 b/mDNSWindows/ControlPanel/res/ControlPanel.rc2 new file mode 100755 index 0000000..e3f7422 --- /dev/null +++ b/mDNSWindows/ControlPanel/res/ControlPanel.rc2 @@ -0,0 +1,13 @@ +// +// CPL_PP.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... + +///////////////////////////////////////////////////////////////////////////// diff --git a/mDNSWindows/ControlPanel/res/controlpanel.ico b/mDNSWindows/ControlPanel/res/controlpanel.ico new file mode 100755 index 0000000000000000000000000000000000000000..e5150f50e6a952321b76eda4d76dff65aaa98972 GIT binary patch literal 11854 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 Z+?9I%UHXeF&;K2(^qX3EPV?_r{}-(*Q*{6U literal 0 HcmV?d00001 diff --git a/mDNSWindows/ControlPanel/res/failure.ico b/mDNSWindows/ControlPanel/res/failure.ico new file mode 100755 index 0000000000000000000000000000000000000000..f0b8f2bd480040c16a8d5cc9761580a17be73724 GIT binary patch literal 894 zcmZQzU<5(|0R|u`!H~hsz#zuJz@P!dKp_SNAO?wp0Z?u*fd32(aD?AIaAjx=thx|t z{(}LMEkG$uK$3cdVpL<1#gVN*7Kb_(E4-XWZP*e8B+SX%ESWAgyv$PzAoj~A iMnqvBhF|t!w&Fa&>6l=zVXGdk_OFC`bH_OL?YjWn>UCuR literal 0 HcmV?d00001 diff --git a/mDNSWindows/ControlPanel/resource.h b/mDNSWindows/ControlPanel/resource.h new file mode 100755 index 0000000..1fbf6a5 --- /dev/null +++ b/mDNSWindows/ControlPanel/resource.h @@ -0,0 +1,41 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ControlPanel.rc +// +#define IDR_APPLET 131 +#define IDR_APPLET_PAGE1 131 +#define IDS_APPLET_DESCRIPTION 132 +#define IDR_APPLET_PAGE2 132 +#define IDR_SECRET 133 +#define IDR_APPLET_PAGE3 134 +#define IDI_FAILURE 140 +#define IDI_SUCCESS 141 +#define IDD_ADD_BROWSE_DOMAIN 142 +#define IDR_ADD_BROWSE_DOMAIN 142 +#define IDC_EDIT1 1000 +#define IDC_BUTTON1 1001 +#define IDC_COMBO1 1002 +#define IDC_CHECK1 1003 +#define IDC_COMBO2 1004 +#define IDC_EDIT2 1005 +#define IDC_SECRET 1005 +#define IDC_COMBO3 1007 +#define IDC_FAILURE 1008 +#define IDC_SUCCESS 1009 +#define IDC_SECRET_NAME 1010 +#define IDC_LIST1 1011 +#define IDC_BROWSE_LIST 1011 +#define IDC_BUTTON2 1012 +#define IDC_REMOVE_BROWSE_DOMAIN 1012 +#define IDC_ADD_BROWSE_DOMAIN 1013 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 143 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1014 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/mDNSWindows/ControlPanel/stdafx.cpp b/mDNSWindows/ControlPanel/stdafx.cpp new file mode 100755 index 0000000..ad80318 --- /dev/null +++ b/mDNSWindows/ControlPanel/stdafx.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: stdafx.cpp,v $ +Revision 1.2 2005/03/03 19:55:22 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#include "stdafx.h" + + diff --git a/mDNSWindows/ControlPanel/stdafx.h b/mDNSWindows/ControlPanel/stdafx.h new file mode 100755 index 0000000..6bdeb92 --- /dev/null +++ b/mDNSWindows/ControlPanel/stdafx.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: stdafx.h,v $ +Revision 1.2 2005/03/03 19:55:21 shersche + ControlPanel source code isn't saving CVS log info + + +*/ + +#pragma once + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. +#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. +#define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +// Step 3: We want to see one image, but not a tile +#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. +#define _WIN32_IE 0x0500 // Change this to the appropriate value to target IE 5.0 or later. +#endif + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +// turns off MFC's hiding of some common and often safely ignored warning messages +#define _AFX_ALL_WARNINGS + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT +#include +#include // Control Panel Applet functions and defines +#include // MFC Template support diff --git a/mDNSWindows/DLL.NET/Stdafx.cpp b/mDNSWindows/DLL.NET/Stdafx.cpp index 7014ab0..b09cb84 100755 --- a/mDNSWindows/DLL.NET/Stdafx.cpp +++ b/mDNSWindows/DLL.NET/Stdafx.cpp @@ -1,36 +1,38 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - +/* + * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + $Log: Stdafx.cpp,v $ +Revision 1.2 2005/02/05 02:37:01 cheshire +Convert newlines to Unix-style (ASCII 10) + Revision 1.1 2004/06/26 04:01:22 shersche Initial revision - - - */ - -// stdafx.cpp : source file that includes just the standard includes -// dotNET.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" + + */ + +// stdafx.cpp : source file that includes just the standard includes +// dotNET.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/mDNSWindows/DLL.NET/Stdafx.h b/mDNSWindows/DLL.NET/Stdafx.h index 397a0d1..7eeb488 100755 --- a/mDNSWindows/DLL.NET/Stdafx.h +++ b/mDNSWindows/DLL.NET/Stdafx.h @@ -1,40 +1,45 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - +/* + * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + $Log: Stdafx.h,v $ +Revision 1.3 2005/02/05 02:40:59 cheshire +Convert newlines to Unix-style (ASCII 10) + +Revision 1.2 2005/02/05 02:37:01 cheshire +Convert newlines to Unix-style (ASCII 10) + Revision 1.1 2004/06/26 04:01:22 shersche Initial revision - - - */ - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, -// but are changed infrequently - -#pragma once - -#using -#using - + + */ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +#using +#using + diff --git a/mDNSWindows/DLL.NET/dnssd_NET.cpp b/mDNSWindows/DLL.NET/dnssd_NET.cpp index 3aee79c..36a5452 100755 --- a/mDNSWindows/DLL.NET/dnssd_NET.cpp +++ b/mDNSWindows/DLL.NET/dnssd_NET.cpp @@ -37,7 +37,7 @@ Revision 1.7 2004/09/11 00:36:40 shersche Bug #: 3786226 Revision 1.6 2004/09/02 21:20:56 cheshire - Rendezvous DLL.NET crashes on null record + DLL.NET crashes on null record Revision 1.5 2004/07/27 07:12:56 shersche make TextRecord an instantiable class object diff --git a/mDNSWindows/DLL.NET/dnssd_NET.h b/mDNSWindows/DLL.NET/dnssd_NET.h index 312d7b6..6faeb3d 100755 --- a/mDNSWindows/DLL.NET/dnssd_NET.h +++ b/mDNSWindows/DLL.NET/dnssd_NET.h @@ -30,16 +30,19 @@ * (not into any common system area where it might interfere with other * applications using a future completed version of these APIs). * If you plan to do this, please be sure to inform us by sending email - * to rendezvous@apple.com to let us know. - * You may want to discuss what you're doing on the Rendezvous mailing + * to bonjour@apple.com to let us know. + * You may want to discuss what you're doing on the Bonjour mailing * list to see if others in similar positions have any suggestions for you: * - * + * * Change History (most recent first): $Log: dnssd_NET.h,v $ +Revision 1.8 2005/02/10 22:35:33 cheshire + Update name + Revision 1.7 2004/12/16 19:56:12 cheshire Update comments diff --git a/mDNSWindows/DLL.NET/dnssd_NET.rc b/mDNSWindows/DLL.NET/dnssd_NET.rc index c6340ee..3e783c3 100755 --- a/mDNSWindows/DLL.NET/dnssd_NET.rc +++ b/mDNSWindows/DLL.NET/dnssd_NET.rc @@ -81,9 +81,9 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Apple Computer, Inc." - VALUE "FileDescription", "dnssd.NET Dynamic Link Library" + VALUE "FileDescription", "Bonjour.NET Client Library" VALUE "FileVersion", MASTER_PROD_VERS_STR - VALUE "InternalName", "dnssd.NET" + VALUE "InternalName", "dnssd.NET.dll" VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT VALUE "OriginalFilename", "dnssd.NET.dll" VALUE "ProductName", MASTER_PROD_NAME diff --git a/mDNSWindows/DLL/dll.rc b/mDNSWindows/DLL/dll.rc index 7f85063..7e714b7 100644 --- a/mDNSWindows/DLL/dll.rc +++ b/mDNSWindows/DLL/dll.rc @@ -70,9 +70,9 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Apple Computer, Inc." - VALUE "FileDescription", "dnssd Dynamic Link Library" + VALUE "FileDescription", "Bonjour Client Library" VALUE "FileVersion", MASTER_PROD_VERS_STR - VALUE "InternalName", "dnssd" + VALUE "InternalName", "dnssd.dll" VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT VALUE "OriginalFilename", "dnssd.dll" VALUE "ProductName", MASTER_PROD_NAME diff --git a/mDNSWindows/DLL/dnssd.vcproj b/mDNSWindows/DLL/dnssd.vcproj index c8aac78..3975048 100644 --- a/mDNSWindows/DLL/dnssd.vcproj +++ b/mDNSWindows/DLL/dnssd.vcproj @@ -65,7 +65,7 @@ diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp b/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp index 0435f61..ab5f100 100644 --- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp +++ b/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp @@ -23,6 +23,9 @@ Change History (most recent first): $Log: ChooserDialog.cpp,v $ +Revision 1.3 2005/02/10 22:35:35 cheshire + Update name + Revision 1.2 2004/07/13 21:24:26 rpantos Fix for . @@ -244,7 +247,6 @@ static const KnownServiceEntry kKnownServiceTable[] = { "_printer._tcp.", "Printer (LPR)", "lpr://", false }, { "_ptp._tcp.", "Picture Transfer (PTP)", "ptp://", false }, { "_register._tcp", "DNS Service Discovery", "", false }, - { "_rendezvouspong._tcp", "RendezvousPong", "", false }, { "_rfb._tcp.", "Remote Frame Buffer", "", false }, { "_riousbprint._tcp.", "Remote I/O USB Printer Protocol", "", false }, { "_rtsp._tcp.", "Real Time Stream Control Protocol", "", false }, diff --git a/mDNSWindows/Java/makefile b/mDNSWindows/Java/makefile index 1b57da4..b590e30 100644 --- a/mDNSWindows/Java/makefile +++ b/mDNSWindows/Java/makefile @@ -20,6 +20,12 @@ # @APPLE_LICENSE_HEADER_END@ # # $Log: makefile,v $ +# Revision 1.6 2005/02/10 22:35:36 cheshire +# Update name +# +# Revision 1.5 2005/02/08 23:47:51 shersche +# Build into proper directories for installer +# # Revision 1.4 2004/12/16 22:38:00 shersche # Compile DNSSDException.java first to avoid build errors, copy output to appropriate "buildroot" folder # @@ -78,11 +84,13 @@ DEBUG=0 CFLAGS_DEBUG = -Zi -DMDNS_DEBUGMSGS=2 OBJDIR = objects\debug BUILDDIR = build\debug +INSTALLDIR = root\"Program Files"\Bonjour LIBDIR = ..\DLL\Debug !else CFLAGS_DEBUG = -Os -DMDNS_DEBUGMSGS=0 OBJDIR = objects\prod BUILDDIR = build\prod +INSTALLDIR = root\"Program Files"\Bonjour LIBDIR = ..\DLL\Release !endif @@ -100,19 +108,12 @@ 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 + @if not exist root mkdir root + @if not exist root\"Program Files" mkdir root\"Program Files" + @if not exist $(INSTALLDIR) mkdir $(INSTALLDIR) + copy $(BUILDDIR)\dns_sd.jar $(INSTALLDIR) + copy $(BUILDDIR)\jdns_sd.dll $(INSTALLDIR) # clean removes targets and objects clean: diff --git a/mDNSWindows/RegNames.h b/mDNSWindows/RegNames.h new file mode 100644 index 0000000..5a02c2f --- /dev/null +++ b/mDNSWindows/RegNames.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: RegNames.h,v $ +Revision 1.1 2005/03/03 02:31:37 shersche +Consolidates all registry key names and can safely be included in any component that needs it + + +*/ + +//---------------------------------------------------------------------------------------- +// Registry Constants +//---------------------------------------------------------------------------------------- + +#if defined(UNICODE) + +# define kServiceName L"Bonjour Service" +# define kServiceDynDNSBrowseDomains L"BrowseDomains" +# define kServiceDynDNSHostNames L"HostNames" +# define kServiceDynDNSRegistrationDomains L"RegistrationDomains" +# define kServiceDynDNSDomains L"Domains" // value is comma separated list of domains +# define kServiceDynDNSEnabled L"Enabled" +# define kServiceDynDNSStatus L"Status" +# define kServiceManageLLRouting L"ManageLLRouting" +# define kServiceCacheEntryCount L"CacheEntryCount" +# define kServiceManageFirewall L"ManageFirewall" + +# else + +# define kServiceName "Bonjour Service" +# 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" +# define kServiceManageLLRouting "ManageLLRouting" +# define kServiceCacheEntryCount "CacheEntryCount" +# define kServiceManageFirewall "ManageFirewall" + +#endif diff --git a/mDNSWindows/SystemService/Prefix.h b/mDNSWindows/SystemService/Prefix.h index 59d18e8..150aa3b 100644 --- a/mDNSWindows/SystemService/Prefix.h +++ b/mDNSWindows/SystemService/Prefix.h @@ -30,7 +30,7 @@ Revision 1.2 2004/04/30 02:40:23 bradley Define DNS_SD_CLIENT_ENABLED=0 so DNSSD.c can be included without linking the client IPC code. Revision 1.1 2004/01/30 02:58:39 bradley -mDNSResponder Windows Service. Provides global Rendezvous support with an IPC interface. +mDNSResponder Windows Service. Provides global Bonjour support with an IPC interface. */ diff --git a/mDNSWindows/SystemService/Service.c b/mDNSWindows/SystemService/Service.c index bfbf6a4..451c239 100644 --- a/mDNSWindows/SystemService/Service.c +++ b/mDNSWindows/SystemService/Service.c @@ -23,6 +23,21 @@ Change History (most recent first): $Log: Service.c,v $ +Revision 1.29 2005/03/06 05:21:56 shersche + Fix corrupt UTF-8 name when non-ASCII system name used, enabled unicode support + +Revision 1.28 2005/03/03 02:27:24 shersche +Include the RegNames.h header file for names of registry keys + +Revision 1.27 2005/03/02 20:12:59 shersche +Update name + +Revision 1.26 2005/02/15 08:00:27 shersche + Update name + +Revision 1.25 2005/02/10 22:35:36 cheshire + Update name + Revision 1.24 2005/01/27 20:02:43 cheshire udsSupportRemoveFDFromEventLoop() needs to close the SocketRef as well @@ -57,7 +72,7 @@ Revision 1.16 2004/09/16 18:49:34 shersche Remove the XP SP2 check before attempting to manage the firewall. There is a race condition in the SP2 updater such that upon first reboot after the upgrade, mDNSResponder might not know that it is running under SP2 yet. This necessitates a second reboot before the firewall is managed. Removing the check will cause mDNSResponder to try and manage the firewall everytime it boots up, if and only if it hasn't managed the firewall a previous time. Revision 1.15 2004/09/15 17:13:33 shersche -Change Firewall name from "Apple mDNSResponder" to "Rendezvous" +Change Firewall name Revision 1.14 2004/09/15 09:37:25 shersche Add SharedAccess to dependency list, call CheckFirewall after sending status back to SCM @@ -114,7 +129,7 @@ Revision 1.1 2004/06/18 04:16:41 rpantos Move up one level. Revision 1.1 2004/01/30 02:58:39 bradley -mDNSResponder Windows Service. Provides global Rendezvous support with an IPC interface. +mDNSResponder Windows Service. Provides global Bonjour support with an IPC interface. */ @@ -124,6 +139,7 @@ mDNSResponder Windows Service. Provides global Rendezvous support with an IPC in #include "CommonServices.h" #include "DebugServices.h" +#include "RegNames.h" #include "uds_daemon.h" #include "GenLinkedList.h" @@ -151,13 +167,9 @@ mDNSResponder Windows Service. Provides global Rendezvous support with an IPC in // Constants //=========================================================================================================================== -#define DEBUG_NAME "[Server] " -#define kServiceName "Apple mDNSResponder" -#define kServiceFirewallName L"Rendezvous" -#define kServiceDependencies "Tcpip\0winmgmt\0\0" -#define kServiceManageLLRouting "ManageLLRouting" -#define kServiceCacheEntryCount "CacheEntryCount" -#define kServiceManageFirewall "ManageFirewall" +#define DEBUG_NAME "[Server] " +#define kServiceFirewallName L"Bonjour" +#define kServiceDependencies TEXT("Tcpip\0winmgmt\0\0") #define kDNSServiceCacheEntryCountDefault 512 #define RR_CACHE_SIZE 500 @@ -211,30 +223,33 @@ typedef struct Win32EventSource //=========================================================================================================================== // Prototypes //=========================================================================================================================== - +#if defined(UNICODE) +int __cdecl wmain( int argc, LPTSTR argv[] ); +#else int __cdecl main( int argc, char *argv[] ); +#endif static void Usage( void ); static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ); -static OSStatus InstallService( const char *inName, const char *inDisplayName, const char *inDescription, const char *inPath ); -static OSStatus RemoveService( const char *inName ); +static OSStatus InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR inDescription, LPCTSTR inPath ); +static OSStatus RemoveService( LPCTSTR inName ); static OSStatus SetServiceParameters(); static OSStatus GetServiceParameters(); static OSStatus CheckFirewall(); -static OSStatus SetServiceInfo( SC_HANDLE inSCM, const char *inServiceName, const char *inDescription ); +static OSStatus SetServiceInfo( SC_HANDLE inSCM, LPCTSTR inServiceName, LPCTSTR inDescription ); static void ReportStatus( int inType, const char *inFormat, ... ); -static OSStatus RunDirect( int argc, char *argv[] ); +static OSStatus RunDirect( int argc, LPTSTR argv[] ); -static void WINAPI ServiceMain( DWORD argc, LPSTR argv[] ); +static void WINAPI ServiceMain( DWORD argc, LPTSTR argv[] ); static OSStatus ServiceSetupEventLogging( void ); static DWORD WINAPI ServiceControlHandler( DWORD inControl, DWORD inEventType, LPVOID inEventData, LPVOID inContext ); -static OSStatus ServiceRun( int argc, char *argv[] ); +static OSStatus ServiceRun( int argc, LPTSTR argv[] ); static void ServiceStop( void ); -static OSStatus ServiceSpecificInitialize( int argc, char *argv[] ); -static OSStatus ServiceSpecificRun( int argc, char *argv[] ); +static OSStatus ServiceSpecificInitialize( int argc, LPTSTR argv[] ); +static OSStatus ServiceSpecificRun( int argc, LPTSTR argv[] ); static OSStatus ServiceSpecificStop( void ); -static void ServiceSpecificFinalize( int argc, char *argv[] ); +static void ServiceSpecificFinalize( int argc, LPTSTR argv[] ); static mStatus EventSourceFinalize(Win32EventSource * source); static void EventSourceLock(); static void EventSourceUnlock(); @@ -245,6 +260,15 @@ static OSStatus GetRouteDestination(DWORD * ifIndex, DWORD * address); static bool HaveLLRoute(PMIB_IPFORWARDROW rowExtant); static OSStatus SetLLRoute(); +#if defined(UNICODE) +# define StrLen(X) wcslen(X) +# define StrCmp(X,Y) wcscmp(X,Y) +#else +# define StrLen(X) strlen(X) +# define StrCmp(X,Y) strcmp(X,Y) +#endif + + #define kLLNetworkAddr "169.254.0.0" #define kLLNetworkAddrMask "255.255.0.0" @@ -286,8 +310,11 @@ DEBUG_LOCAL GenLinkedList gEventSources; //=========================================================================================================================== // main //=========================================================================================================================== - +#if defined(UNICODE) +int __cdecl wmain( int argc, wchar_t * argv[] ) +#else int __cdecl main( int argc, char *argv[] ) +#endif { OSStatus err; BOOL ok; @@ -296,7 +323,7 @@ int __cdecl main( int argc, char *argv[] ) debug_initialize( kDebugOutputTypeMetaConsole ); debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose ); - + // Default to automatically starting the service dispatcher if no extra arguments are specified. start = ( argc <= 1 ); @@ -305,20 +332,20 @@ int __cdecl main( int argc, char *argv[] ) for( i = 1; i < argc; ++i ) { - if( strcmp( argv[ i ], "-install" ) == 0 ) // Install + if( StrCmp( argv[ i ], TEXT("-install") ) == 0 ) // Install { - char desc[ 256 ]; + TCHAR desc[ 256 ]; desc[ 0 ] = 0; - LoadStringA( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) ); - err = InstallService( kServiceName, kServiceName, desc, argv[ 0 ] ); + LoadString( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) ); + err = InstallService( kServiceName, kServiceName, desc, argv[0] ); if( err ) { ReportStatus( EVENTLOG_ERROR_TYPE, "install service failed (%d)\n", err ); goto exit; } } - else if( strcmp( argv[ i ], "-remove" ) == 0 ) // Remove + else if( StrCmp( argv[ i ], TEXT("-remove") ) == 0 ) // Remove { err = RemoveService( kServiceName ); if( err ) @@ -327,11 +354,11 @@ int __cdecl main( int argc, char *argv[] ) goto exit; } } - else if( strcmp( argv[ i ], "-start" ) == 0 ) // Start + else if( StrCmp( argv[ i ], TEXT("-start") ) == 0 ) // Start { start = TRUE; } - else if( strcmp( argv[ i ], "-server" ) == 0 ) // Server + else if( StrCmp( argv[ i ], TEXT("-server") ) == 0 ) // Server { err = RunDirect( argc, argv ); if( err ) @@ -340,26 +367,12 @@ int __cdecl main( int argc, char *argv[] ) } goto exit; } - else if( strcmp( argv[ i ], "-q" ) == 0 ) // Quiet Mode (toggle) + else if( StrCmp( argv[ i ], TEXT("-q") ) == 0 ) // Quiet Mode (toggle) { gServiceQuietMode = !gServiceQuietMode; } - else if( strcmp( argv[ i ], "-remote" ) == 0 ) // Allow Remote Connections - { - gServiceAllowRemote = true; - } - else if( strcmp( argv[ i ], "-cache" ) == 0 ) // Number of mDNS cache entries - { - if( i <= argc ) - { - ReportStatus( EVENTLOG_ERROR_TYPE, "-cache used, but number of cache entries not specified\n" ); - err = kParamErr; - goto exit; - } - gServiceCacheEntryCount = atoi( argv[ ++i ] ); - } - else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || // Help - ( strcmp( argv[ i ], "-h" ) == 0 ) ) + else if( ( StrCmp( argv[ i ], TEXT("-help") ) == 0 ) || // Help + ( StrCmp( argv[ i ], TEXT("-h") ) == 0 ) ) { Usage(); err = 0; @@ -450,7 +463,7 @@ exit: // InstallService //=========================================================================================================================== -static OSStatus InstallService( const char *inName, const char *inDisplayName, const char *inDescription, const char *inPath ) +static OSStatus InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR inDescription, LPCTSTR inPath ) { OSStatus err; SC_HANDLE scm; @@ -513,7 +526,7 @@ exit: // RemoveService //=========================================================================================================================== -static OSStatus RemoveService( const char *inName ) +static OSStatus RemoveService( LPCTSTR inName ) { OSStatus err; SC_HANDLE scm; @@ -576,7 +589,7 @@ static OSStatus SetServiceParameters() DWORD value; DWORD valueLen = sizeof(DWORD); DWORD type; - const char * s; + LPCTSTR s; OSStatus err; HKEY key; @@ -585,7 +598,7 @@ static OSStatus SetServiceParameters() // // Add/Open Parameters section under service entry in registry // - s = "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters"; + s = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters"); err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key ); require_noerr( err, exit ); @@ -623,7 +636,7 @@ static OSStatus GetServiceParameters() DWORD value; DWORD valueLen; DWORD type; - const char * s; + LPCTSTR s; OSStatus err; HKEY key; @@ -632,7 +645,7 @@ static OSStatus GetServiceParameters() // // Add/Open Parameters section under service entry in registry // - s = "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters"; + s = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters"); err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key ); require_noerr( err, exit ); @@ -670,7 +683,7 @@ static OSStatus CheckFirewall() DWORD value; DWORD valueLen; DWORD type; - const char * s; + LPCTSTR s; HKEY key = NULL; OSStatus err = kUnknownErr; @@ -680,7 +693,7 @@ static OSStatus CheckFirewall() // the case, then we need to manipulate the firewall // so networking works correctly. - s = "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters"; + s = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters"); err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key ); require_noerr( err, exit ); @@ -722,7 +735,7 @@ exit: // SetServiceInfo //=========================================================================================================================== -static OSStatus SetServiceInfo( SC_HANDLE inSCM, const char *inServiceName, const char *inDescription ) +static OSStatus SetServiceInfo( SC_HANDLE inSCM, LPCTSTR inServiceName, LPCTSTR inDescription ) { OSStatus err; SC_LOCK lock; @@ -759,7 +772,7 @@ static OSStatus SetServiceInfo( SC_HANDLE inSCM, const char *inServiceName, cons // Change the description. - description.lpDescription = (char *) inDescription; + description.lpDescription = (LPTSTR) inDescription; ok = ChangeServiceConfig2( service, SERVICE_CONFIG_DESCRIPTION, &description ); err = translate_errno( ok, (OSStatus) GetLastError(), kParamErr ); require_noerr( err, exit ); @@ -811,7 +824,7 @@ static void ReportStatus( int inType, const char *inFormat, ... ) vsprintf( s, inFormat, args ); array[ 0 ] = s; - ok = ReportEvent( gServiceEventSource, (WORD) inType, 0, 0x20000001L, NULL, 1, 0, array, NULL ); + ok = ReportEventA( gServiceEventSource, (WORD) inType, 0, 0x20000001L, NULL, 1, 0, array, NULL ); check_translated_errno( ok, GetLastError(), kUnknownErr ); } else @@ -829,7 +842,7 @@ static void ReportStatus( int inType, const char *inFormat, ... ) // RunDirect //=========================================================================================================================== -static OSStatus RunDirect( int argc, char *argv[] ) +static OSStatus RunDirect( int argc, LPTSTR argv[] ) { OSStatus err; BOOL initialized; @@ -872,11 +885,11 @@ exit: // ServiceMain //=========================================================================================================================== -static void WINAPI ServiceMain( DWORD argc, LPSTR argv[] ) +static void WINAPI ServiceMain( DWORD argc, LPTSTR argv[] ) { OSStatus err; BOOL ok; - char desc[ 256 ]; + TCHAR desc[ 256 ]; err = ServiceSetupEventLogging(); check_noerr( err ); @@ -901,7 +914,7 @@ static void WINAPI ServiceMain( DWORD argc, LPSTR argv[] ) // Setup the description. This should be done by the installer, but it doesn't support that yet. desc[ 0 ] = '\0'; - LoadStringA( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) ); + LoadString( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) ); err = SetServiceInfo( NULL, kServiceName, desc ); check_noerr( err ); @@ -947,25 +960,25 @@ static OSStatus ServiceSetupEventLogging( void ) { OSStatus err; HKEY key; - const char * s; + LPCTSTR s; DWORD typesSupported; - char path[ MAX_PATH ]; + TCHAR path[ MAX_PATH ]; DWORD n; key = NULL; // Add/Open source name as a sub-key under the Application key in the EventLog registry key. - s = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" kServiceName; + s = TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\") kServiceName; err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key ); require_noerr( err, exit ); // Add the name to the EventMessageFile subkey. - + path[ 0 ] = '\0'; GetModuleFileName( NULL, path, MAX_PATH ); - n = (DWORD)( strlen( path ) + 1 ); - err = RegSetValueEx( key, "EventMessageFile", 0, REG_EXPAND_SZ, (const LPBYTE) path, n ); + n = (DWORD) ( ( StrLen( path ) + 1 ) * sizeof( TCHAR ) ); + err = RegSetValueEx( key, TEXT("EventMessageFile"), 0, REG_EXPAND_SZ, (const LPBYTE) path, n ); require_noerr( err, exit ); // Set the supported event types in the TypesSupported subkey. @@ -977,7 +990,7 @@ static OSStatus ServiceSetupEventLogging( void ) | EVENTLOG_INFORMATION_TYPE | EVENTLOG_AUDIT_SUCCESS | EVENTLOG_AUDIT_FAILURE; - err = RegSetValueEx( key, "TypesSupported", 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) ); + err = RegSetValueEx( key, TEXT("TypesSupported"), 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) ); require_noerr( err, exit ); // Set up the event source. @@ -1047,7 +1060,7 @@ static DWORD WINAPI ServiceControlHandler( DWORD inControl, DWORD inEventType, L // ServiceRun //=========================================================================================================================== -static OSStatus ServiceRun( int argc, char *argv[] ) +static OSStatus ServiceRun( int argc, LPTSTR argv[] ) { OSStatus err; BOOL initialized; @@ -1119,7 +1132,7 @@ static void ServiceStop( void ) // ServiceSpecificInitialize //=========================================================================================================================== -static OSStatus ServiceSpecificInitialize( int argc, char *argv[] ) +static OSStatus ServiceSpecificInitialize( int argc, LPTSTR argv[] ) { OSStatus err; @@ -1164,7 +1177,7 @@ exit: // ServiceSpecificRun //=========================================================================================================================== -static OSStatus ServiceSpecificRun( int argc, char *argv[] ) +static OSStatus ServiceSpecificRun( int argc, LPTSTR argv[] ) { DWORD result; @@ -1201,7 +1214,7 @@ exit: // ServiceSpecificFinalize //=========================================================================================================================== -static void ServiceSpecificFinalize( int argc, char *argv[] ) +static void ServiceSpecificFinalize( int argc, LPTSTR argv[] ) { DEBUG_UNUSED( argc ); DEBUG_UNUSED( argv ); diff --git a/mDNSWindows/SystemService/Service.rc b/mDNSWindows/SystemService/Service.rc index 8300753..5c0103a 100644 --- a/mDNSWindows/SystemService/Service.rc +++ b/mDNSWindows/SystemService/Service.rc @@ -44,9 +44,9 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Apple Computer, Inc." - VALUE "FileDescription", "mDNSResponder" + VALUE "FileDescription", "Bonjour Service" VALUE "FileVersion", MASTER_PROD_VERS_STR - VALUE "InternalName", "mDNSResponder" + VALUE "InternalName", "mDNSResponder.exe" VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT VALUE "OriginalFilename", "mDNSResponder.exe" VALUE "ProductName", MASTER_PROD_NAME diff --git a/mDNSWindows/SystemService/Service.vcproj b/mDNSWindows/SystemService/Service.vcproj index dc458fd..cbc4e14 100644 --- a/mDNSWindows/SystemService/Service.vcproj +++ b/mDNSWindows/SystemService/Service.vcproj @@ -20,7 +20,7 @@ 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;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE=""""" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;DEBUG=1;MDNS_DEBUGMSGS=0;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE="""";UNICODE;_UNICODE" StringPooling="TRUE" MinimalRebuild="TRUE" ExceptionHandling="FALSE" @@ -63,14 +63,14 @@ Update Windows build to 1.0.0.58 + +Revision 1.29 2005/03/02 20:11:45 shersche +Update name + +Revision 1.28 2005/03/02 03:57:51 shersche +Bump to 1.0.0.57 + +Revision 1.27 2005/02/23 03:12:27 shersche +Bump to 1.0.0.56 + +Revision 1.26 2005/02/15 23:20:18 shersche +Bump to 1.0.0.55 and update name + +Revision 1.25 2005/02/10 22:35:29 cheshire + Update name + +Revision 1.24 2005/02/08 23:32:24 shersche +Bump to 1.0.0.54 + +Revision 1.23 2005/02/02 02:08:28 shersche +Bump to version 1.0.0.53 + Revision 1.22 2005/01/25 17:15:52 shersche Bump to 1.0.0.51. Add legal copyright string. @@ -94,13 +118,13 @@ First checked in. #ifndef WINRESVERS_H #define WINRESVERS_H -#define MASTER_PROD_NAME "Rendezvous" +#define MASTER_PROD_NAME "Bonjour" // Define the product version for mDNSResponder on Windows -#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 MASTER_PROD_VERS 1,0,0,58 +#define MASTER_PROD_VERS_STR "1,0,0,58" +#define MASTER_PROD_VERS_STR2 "1.0.0.58" +#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.0.58" // Define the legal copyright #define MASTER_LEGAL_COPYRIGHT "Copyright (C) 2003-2005 Apple Computer, Inc." diff --git a/mDNSWindows/dDNS.c b/mDNSWindows/dDNS.c index e2e2d58..08cbc88 100755 --- a/mDNSWindows/dDNS.c +++ b/mDNSWindows/dDNS.c @@ -49,9 +49,9 @@ static DNameListElem *DefBrowseList = mDNSNULL; // cache of answers to above 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; +static domainname dDNSRegDomain; // Default wide-area zone for service registration +static DNameListElem * dDNSBrowseDomains; // Default wide-area zone for legacy ("empty string") browses +static domainname dDNSHostname; mStatus dDNS_SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa) @@ -401,68 +401,96 @@ mDNSlocal mStatus RegisterSearchDomains( mDNS *const m ) return mStatus_NoError; } + +mDNSlocal void RegisterBrowseDomainPTR(mDNS *m, const domainname *d, int type) + { + // allocate/register legacy and non-legacy _browse PTR record + mStatus err; + 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); + 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; + } + } + // 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; - } + 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); } } +mDNSlocal void SetSCPrefsBrowseDomains(mDNS *m, DNameListElem * browseDomains, mDNSBool add) + { + DNameListElem * browseDomain; + + for ( browseDomain = browseDomains; browseDomain; browseDomain = browseDomain->next ) + { + if ( !browseDomain->name.c[0] ) + { + LogMsg("SetSCPrefsBrowseDomains bad DDNS browse domain: %s", browseDomain->name.c[0] ? browseDomain->name.c : "(unknown)"); + } + else + { + SetSCPrefsBrowseDomain(m, &browseDomain->name, add); + } + } + } 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; + mDNSAddr r; + DNameListElem * BrowseDomains; + domainname RegDomain, fqdn; // get fqdn, zone from SCPrefs - dDNSPlatformGetConfig(&fqdn, &RegDomain, &BrowseDomain); + dDNSPlatformGetConfig(&fqdn, &RegDomain, &BrowseDomains); // YO if (!fqdn.c[0] && !RegDomain.c[0]) ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &fqdn, &RegDomain); @@ -484,12 +512,25 @@ mStatus dDNS_Setup( mDNS *const m ) } } - if (!SameDomainName(&BrowseDomain, &dDNSBrowseDomain)) - { - if (dDNSBrowseDomain.c[0]) SetSCPrefsBrowseDomain(m, &dDNSBrowseDomain, mDNSfalse); - AssignDomainName(&dDNSBrowseDomain, &BrowseDomain); - if (dDNSBrowseDomain.c[0]) SetSCPrefsBrowseDomain(m, &dDNSBrowseDomain, mDNStrue); - } + // Add new browse domains to internal list + + if ( BrowseDomains ) + { + SetSCPrefsBrowseDomains( m, BrowseDomains, mDNStrue ); + } + + // Remove old browse domains from internal list + + if ( dDNSBrowseDomains ) + { + SetSCPrefsBrowseDomains( m, dDNSBrowseDomains, mDNSfalse ); + mDNS_FreeDNameList( dDNSBrowseDomains ); + } + + // Replace the old browse domains array with the new array + + dDNSBrowseDomains = BrowseDomains; + if (!SameDomainName(&fqdn, &dDNSHostname)) { diff --git a/mDNSWindows/dDNS.h b/mDNSWindows/dDNS.h index e9d7a36..e1b148e 100755 --- a/mDNSWindows/dDNS.h +++ b/mDNSWindows/dDNS.h @@ -61,7 +61,7 @@ extern mStatus dDNS_SetupAddr( mDNSAddr *ip, const struct sockaddr * const sa ); // 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 dDNSPlatformGetConfig(domainname *const fqdn, domainname *const regDomain, DNameListElem ** browseDomains); extern void dDNSPlatformSetNameStatus(domainname *const dname, mStatus status); extern void dDNSPlatformSetSecretForDomain( mDNS *m, const domainname *domain ); extern DNameListElem * dDNSPlatformGetSearchDomainList( void ); diff --git a/mDNSWindows/loclibrary.c b/mDNSWindows/loclibrary.c index 78f16a4..7a90e66 100755 --- a/mDNSWindows/loclibrary.c +++ b/mDNSWindows/loclibrary.c @@ -31,6 +31,7 @@ * ---------------------------------------------------------------------- */ +#include "DebugServices.h" #include #include #include "isocode.h" @@ -40,6 +41,7 @@ #include #include + #ifdef __cplusplus extern "c" { #endif @@ -109,25 +111,62 @@ static void _setLanguageIfNeeded(void) { static char appPathNameA[MAX_PATH] = ""; -int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locFileLen) { - if (!strcmp(appPathNameA,"")) { - GetModuleFileNameA(module, appPathNameA, MAX_PATH); +int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locFileLen) +{ + int ret = 0; + + if ( !strcmp( appPathNameA, "" ) ) + { + char folder[MAX_PATH]; + char * app; + + GetModuleFileNameA( module, folder, MAX_PATH ); + + // Get folder string + + app = strrchr( folder, '\\' ); + require_action( app, exit, ret = 0 ); + + *app++ = '\0'; + + snprintf( appPathNameA, MAX_PATH, "%s\\Resources\\%s", folder, app ); } - return PathForResourceWithPathA (appPathNameA, name, locFile, locFileLen); + ret = PathForResourceWithPathA (appPathNameA, name, locFile, locFileLen); + +exit: + return ret; } 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); +int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, int locFileLen) +{ + int ret = 0; + + if ( !wcscmp( appPathNameW, L"" ) ) + { + wchar_t folder[MAX_PATH]; + wchar_t * app; + + GetModuleFileNameW( module, folder, MAX_PATH); + + // Get folder string + + app = wcsrchr( folder, '\\' ); + require_action( app, exit, ret = 0 ); + + *app++ = '\0'; + + swprintf( appPathNameW, MAX_PATH, L"%ls\\Resources\\%ls", folder, app ); } -OutputDebugString( appPathNameW ); + ret = PathForResourceWithPathW (appPathNameW, name, locFile, locFileLen); + +exit: - return PathForResourceWithPathW (appPathNameW, name, locFile, locFileLen); + return ret; } @@ -204,7 +243,7 @@ int PathForResourceWithPathW (const wchar_t *path, const wchar_t *nm, } // fall back on DEFAULT_LANG_CODE if still no good - swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls.Resources\\%s.lproj\\%ls", + 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 diff --git a/mDNSWindows/mDNSWin32.c b/mDNSWindows/mDNSWin32.c index 7d4ea02..6e7bb36 100755 --- a/mDNSWindows/mDNSWin32.c +++ b/mDNSWindows/mDNSWin32.c @@ -23,6 +23,42 @@ Change History (most recent first): $Log: mDNSWin32.c,v $ +Revision 1.83 2005/03/07 18:27:42 shersche + Fix problem when ControlPanel commits changes to the browse domain list + +Revision 1.82 2005/03/06 05:20:24 shersche + Fix corrupt UTF-8 name when non-ASCII system name used, enabled unicode support + +Revision 1.81 2005/03/04 22:44:53 shersche + mDNSResponder did not notice changes to DNS server config + +Revision 1.80 2005/03/03 21:07:38 shersche + mDNSResponder doesn't handle multiple browse domains + +Revision 1.79 2005/03/03 02:29:00 shersche +Use the RegNames.h header file for registry key names + +Revision 1.78 2005/03/02 04:04:17 shersche +Support for multiple browse domains + +Revision 1.77 2005/02/25 20:02:18 shersche + Call ProcessingThreadDynDNSConfigChanged() when interface list changes + +Revision 1.76 2005/02/23 02:59:20 shersche + Check to see if locks have been initialized before using them. + +Revision 1.75 2005/02/16 02:36:25 shersche + Use IPv6 if interface has no routable IPv4 address + +Revision 1.74 2005/02/08 06:06:16 shersche + Implement mDNSPlatformTCPConnect, mDNSPlatformTCPCloseConnection, mDNSPlatformTCPRead, mDNSPlatformTCPWrite + +Revision 1.73 2005/02/01 19:35:43 ksekar +Removed obsolete arguments from mDNS_SetSecretForZone + +Revision 1.72 2005/02/01 01:38:53 shersche +Handle null DynDNS configuration more gracefully + Revision 1.71 2005/01/27 22:57:57 cheshire Fix compile errors on gcc4 @@ -297,6 +333,7 @@ Multicast DNS platform plugin for Win32 #include "CommonServices.h" #include "DebugServices.h" +#include "RegNames.h" #include #include @@ -323,8 +360,6 @@ Multicast DNS platform plugin for Win32 #define MDNS_WINDOWS_USE_IPV6_IF_ADDRS 1 #define MDNS_WINDOWS_ENABLE_IPV4 1 #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" @@ -336,9 +371,11 @@ Multicast DNS platform plugin for Win32 #define kWaitListInterfaceListChangedEvent ( WAIT_OBJECT_0 + 1 ) #define kWaitListWakeupEvent ( WAIT_OBJECT_0 + 2 ) #define kWaitListComputerDescriptionEvent ( WAIT_OBJECT_0 + 3 ) -#define kWaitListDynDNSEvent ( WAIT_OBJECT_0 + 4 ) -#define kWaitListFixedItemCount 5 + MDNS_WINDOWS_ENABLE_IPV4 + MDNS_WINDOWS_ENABLE_IPV6 +#define kWaitListTCPIPEvent ( WAIT_OBJECT_0 + 4 ) +#define kWaitListDynDNSEvent ( WAIT_OBJECT_0 + 5 ) +#define kWaitListFixedItemCount 6 + MDNS_WINDOWS_ENABLE_IPV4 + MDNS_WINDOWS_ENABLE_IPV6 +#define kRegistryMaxKeyLength 255 #if( !TARGET_OS_WINDOWS_CE ) static GUID kWSARecvMsgGUID = WSAID_WSARECVMSG; @@ -375,6 +412,7 @@ mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE * mDNSlocal void ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *inIFD, SocketRef inSock ); mDNSlocal void ProcessingThreadInterfaceListChanged( mDNS *inMDNS ); mDNSlocal void ProcessingThreadComputerDescriptionChanged( mDNS * inMDNS ); +mDNSlocal void ProcessingThreadTCPIPConfigChanged( mDNS * inMDNS ); mDNSlocal void ProcessingThreadDynDNSConfigChanged( mDNS * inMDNS ); @@ -391,6 +429,18 @@ struct mDNSPlatformInterfaceInfo mDNSAddr ip; }; +typedef struct mDNSTCPConnectionData mDNSTCPConnectionData; +struct mDNSTCPConnectionData +{ + SocketRef sock; + BOOL connected; + TCPConnectionCallback callback; + void * context; + HANDLE pendingEvent; + mDNSTCPConnectionData * next; +}; + + mDNSexport mStatus mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID ); mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo ); @@ -410,11 +460,14 @@ mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInter 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 mStatus StringToAddress( mDNSAddr * ip, LPSTR string ); +mDNSlocal mStatus RegQueryString( HKEY key, LPCSTR param, LPSTR * string, DWORD * stringLen, DWORD * enabled ); mDNSlocal struct ifaddrs* myGetIfAddrs(int refresh); +mDNSlocal OSStatus TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize ); +mDNSlocal OSStatus WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize ); mDNSlocal OSStatus ConvertUTF8ToLsaString( const char * input, PLSA_UNICODE_STRING output ); mDNSlocal OSStatus ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char ** output ); +mDNSlocal void FreeTCPConnectionData( mDNSTCPConnectionData * data ); #ifdef __cplusplus } @@ -430,6 +483,9 @@ mDNSlocal OSStatus ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char ** mDNSlocal mDNS_PlatformSupport gMDNSPlatformSupport; mDNSs32 mDNSPlatformOneSecond = 0; +mDNSlocal mDNSTCPConnectionData * gTCPConnectionList = NULL; +mDNSlocal int gTCPConnections = 0; +mDNSlocal BOOL gWaitListChanged = FALSE; #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS ) @@ -462,6 +518,8 @@ mStatus mDNSPlatformInit( mDNS * const inMDNS ) int supported; struct sockaddr_in sa4; struct sockaddr_in6 sa6; + int sa4len; + int sa6len; dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" ); @@ -507,6 +565,10 @@ mStatus mDNSPlatformInit( mDNS * const inMDNS ) sa4.sin_addr.s_addr = INADDR_ANY; err = SetupSocket( inMDNS, (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4 ); check_noerr( err ); + sa4len = sizeof( sa4 ); + err = getsockname( inMDNS->p->unicastSock4, (struct sockaddr*) &sa4, &sa4len ); + require_noerr( err, exit ); + inMDNS->UnicastPort4.NotAnInteger = sa4.sin_port; inMDNS->p->unicastSock4ReadEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); err = translate_errno( inMDNS->p->unicastSock4ReadEvent, (mStatus) GetLastError(), kUnknownErr ); require_noerr( err, exit ); @@ -553,6 +615,11 @@ mStatus mDNSPlatformInit( mDNS * const inMDNS ) if ( inMDNS->p->unicastSock6 != INVALID_SOCKET ) { + sa6len = sizeof( sa6 ); + err = getsockname( inMDNS->p->unicastSock6, (struct sockaddr*) &sa6, &sa6len ); + require_noerr( err, exit ); + inMDNS->UnicastPort6.NotAnInteger = sa6.sin6_port; + err = WSAEventSelect( inMDNS->p->unicastSock6, inMDNS->p->unicastSock6ReadEvent, FD_READ ); require_noerr( err, exit ); @@ -740,9 +807,11 @@ exit: void mDNSPlatformLock( const mDNS * const inMDNS ) { check( inMDNS ); - check( inMDNS->p->lockInitialized ); - EnterCriticalSection( &inMDNS->p->lock ); + if ( inMDNS->p->lockInitialized ) + { + EnterCriticalSection( &inMDNS->p->lock ); + } } //=========================================================================================================================== @@ -753,20 +822,23 @@ void mDNSPlatformUnlock( const mDNS * const inMDNS ) { check( inMDNS ); check( inMDNS->p ); - check( inMDNS->p->lockInitialized ); - check( inMDNS->p->threadID ); + + if ( inMDNS->p->lockInitialized ) + { + check( inMDNS->p->threadID ); - // Signal a wakeup event if when called from a task other than the mDNS task since if we are called from mDNS task, - // we'll loop back and call mDNS_Execute anyway. Signaling is needed to re-evaluate the wakeup via mDNS_Execute. + // Signal a wakeup event if when called from a task other than the mDNS task since if we are called from mDNS task, + // we'll loop back and call mDNS_Execute anyway. Signaling is needed to re-evaluate the wakeup via mDNS_Execute. - if( GetCurrentThreadId() != inMDNS->p->threadID ) - { - BOOL wasSet; + if( GetCurrentThreadId() != inMDNS->p->threadID ) + { + BOOL wasSet; - wasSet = SetEvent( inMDNS->p->wakeupEvent ); - check_translated_errno( wasSet, GetLastError(), kUnknownErr ); + wasSet = SetEvent( inMDNS->p->wakeupEvent ); + check_translated_errno( wasSet, GetLastError(), kUnknownErr ); + } + LeaveCriticalSection( &inMDNS->p->lock ); } - LeaveCriticalSection( &inMDNS->p->lock ); } //=========================================================================================================================== @@ -1049,14 +1121,80 @@ mStatus void * inContext, int * outSock ) { - DEBUG_UNUSED( inDstIP ); - DEBUG_UNUSED( inDstPort ); + u_long on = 1; // "on" for setsockopt + struct sockaddr_in saddr; + mDNSTCPConnectionData * tcd = NULL; + mStatus err = mStatus_NoError; + DEBUG_UNUSED( inInterfaceID ); - DEBUG_UNUSED( inCallback ); - DEBUG_UNUSED( inContext ); - DEBUG_UNUSED( outSock ); - return( mStatus_UnsupportedErr ); + *outSock = INVALID_SOCKET; + + if ( inDstIP->type != mDNSAddrType_IPv4 ) + { + LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: operation not supported"); + return mStatus_UnknownErr; + } + + // Setup connection data object + + tcd = (mDNSTCPConnectionData*) malloc( sizeof( mDNSTCPConnectionData ) ); + require_action( tcd, exit, err = mStatus_NoMemoryErr ); + memset( tcd, 0, sizeof( mDNSTCPConnectionData ) ); + + tcd->sock = INVALID_SOCKET; + tcd->callback = inCallback; + tcd->context = inContext; + + bzero(&saddr, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = inDstPort.NotAnInteger; + memcpy(&saddr.sin_addr, &inDstIP->ip.v4.NotAnInteger, sizeof(saddr.sin_addr)); + + // Create the socket + + tcd->sock = socket(AF_INET, SOCK_STREAM, 0); + err = translate_errno( tcd->sock != INVALID_SOCKET, WSAGetLastError(), mStatus_UnknownErr ); + require_noerr( err, exit ); + + // Set it to be non-blocking + + err = ioctlsocket( tcd->sock, FIONBIO, &on ); + err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr ); + require_noerr( err, exit ); + + // Try and do connect + + err = connect( tcd->sock, ( struct sockaddr* ) &saddr, sizeof( saddr ) ); + require_action( !err || ( WSAGetLastError() == WSAEWOULDBLOCK ), exit, err = mStatus_ConnFailed ); + tcd->connected = !err ? TRUE : FALSE; + tcd->pendingEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + err = translate_errno( tcd->pendingEvent, GetLastError(), mStatus_UnknownErr ); + require_noerr( err, exit ); + err = WSAEventSelect( tcd->sock, tcd->pendingEvent, FD_CONNECT|FD_READ|FD_CLOSE ); + require_noerr( err, exit ); + + // Bookkeeping + + tcd->next = gTCPConnectionList; + gTCPConnectionList = tcd; + gTCPConnections++; + gWaitListChanged = TRUE; + + *outSock = (int) tcd->sock; + +exit: + + if ( !err ) + { + err = tcd->connected ? mStatus_ConnEstablished : mStatus_ConnPending; + } + else if ( tcd ) + { + FreeTCPConnectionData( tcd ); + } + + return err; } //=========================================================================================================================== @@ -1065,7 +1203,33 @@ mStatus void mDNSPlatformTCPCloseConnection( int inSock ) { - DEBUG_UNUSED( inSock ); + mDNSTCPConnectionData * tcd = gTCPConnectionList; + mDNSTCPConnectionData * last = NULL; + + while ( tcd ) + { + if ( tcd->sock == ( SOCKET ) inSock ) + { + if ( last == NULL ) + { + gTCPConnectionList = tcd->next; + } + else + { + last->next = tcd->next; + } + + FreeTCPConnectionData( tcd ); + + gTCPConnections--; + gWaitListChanged = TRUE; + + break; + } + + last = tcd; + tcd = tcd->next; + } } //=========================================================================================================================== @@ -1074,11 +1238,21 @@ void mDNSPlatformTCPCloseConnection( int inSock ) int mDNSPlatformReadTCP( int inSock, void *inBuffer, int inBufferSize ) { - DEBUG_UNUSED( inSock ); - DEBUG_UNUSED( inBuffer ); - DEBUG_UNUSED( inBufferSize ); - - return( -1 ); + int nread; + OSStatus err; + + nread = recv( inSock, inBuffer, inBufferSize, 0); + err = translate_errno( ( nread >= 0 ) || ( WSAGetLastError() == WSAEWOULDBLOCK ), WSAGetLastError(), mStatus_UnknownErr ); + require_noerr( err, exit ); + + if ( nread < 0 ) + { + nread = 0; + } + +exit: + + return nread; } //=========================================================================================================================== @@ -1087,32 +1261,51 @@ int mDNSPlatformReadTCP( int inSock, void *inBuffer, int inBufferSize ) int mDNSPlatformWriteTCP( int inSock, const char *inMsg, int inMsgSize ) { - DEBUG_UNUSED( inSock ); - DEBUG_UNUSED( inMsg ); - DEBUG_UNUSED( inMsgSize ); - - return( -1 ); -} + int nsent; + OSStatus err; + nsent = send( inSock, inMsg, inMsgSize, 0 ); + + err = translate_errno( ( nsent >= 0 ) || ( WSAGetLastError() == WSAEWOULDBLOCK ), WSAGetLastError(), mStatus_UnknownErr ); + require_noerr( err, exit ); + + if ( nsent < 0) + { + nsent = 0; + } + +exit: + + return nsent; +} //=========================================================================================================================== // dDNSPlatformGetConfig //=========================================================================================================================== void -dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, domainname *const browseDomain) +dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, DNameListElem ** browseDomains) { - char * name = NULL; + LPSTR name = NULL; + char subKeyName[kRegistryMaxKeyLength + 1]; + DWORD cSubKeys = 0; + DWORD cbMaxSubKey; + DWORD cchMaxClass; DWORD dwSize; DWORD enabled; HKEY key; + HKEY subKey = NULL; + domainname dname; + DWORD i; OSStatus err; // Initialize - fqdn->c[0] = regDomain->c[0] = browseDomain->c[0] = 0; + fqdn->c[0] = regDomain->c[0] = '\0'; + + *browseDomains = NULL; - err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSHostNames, &key ); + err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup\\") kServiceDynDNSHostNames, &key ); require_noerr( err, exit ); err = RegQueryString( key, "", &name, &dwSize, &enabled ); @@ -1136,16 +1329,51 @@ dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, doma name = NULL; } - err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key ); + err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains, &key ); require_noerr( err, exit ); - err = RegQueryString( key, "", &name, &dwSize, &enabled ); - if ( !err && ( name[0] != '\0' ) && enabled ) + // Get information about this node + + err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL ); + require_noerr( err, exit ); + + for ( i = 0; i < cSubKeys; i++) { - if ( !MakeDomainNameFromDNSNameString( browseDomain, name ) || !browseDomain->c[0] ) + DWORD enabled; + + dwSize = kRegistryMaxKeyLength; + + err = RegEnumKeyExA( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL ); + + if ( !err ) { - dlog( kDebugLevelError, "bad DDNS browse domain in registry: %s", name[0] ? name : "(unknown)"); - } + err = RegOpenKeyExA( key, subKeyName, 0, KEY_READ, &subKey ); + require_noerr( err, exit ); + + dwSize = sizeof( DWORD ); + err = RegQueryValueExA( subKey, "Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize ); + + if ( !err && ( subKeyName[0] != '\0' ) && enabled ) + { + if ( !MakeDomainNameFromDNSNameString( &dname, subKeyName ) || !dname.c[0] ) + { + dlog( kDebugLevelError, "bad DDNS browse domain in registry: %s", subKeyName[0] ? subKeyName : "(unknown)"); + } + else + { + DNameListElem * browseDomain = (DNameListElem*) malloc( sizeof( DNameListElem ) ); + require_action( browseDomain, exit, err = mStatus_NoMemoryErr ); + + AssignDomainName(&browseDomain->name, &dname); + browseDomain->next = *browseDomains; + + *browseDomains = browseDomain; + } + } + + RegCloseKey( subKey ); + subKey = NULL; + } } if ( key ) @@ -1154,13 +1382,7 @@ dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, doma key = NULL; } - if ( name ) - { - free( name ); - name = NULL; - } - - err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key ); + err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains, &key ); require_noerr( err, exit ); err = RegQueryString( key, "", &name, &dwSize, &enabled ); @@ -1174,6 +1396,11 @@ dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, doma exit: + if ( subKey ) + { + RegCloseKey( subKey ); + } + if ( key ) { RegCloseKey( key ); @@ -1194,7 +1421,7 @@ void dDNSPlatformSetNameStatus(domainname *const dname, mStatus status) { char uname[MAX_ESCAPED_DOMAIN_NAME]; - char name[MAX_ESCAPED_DOMAIN_NAME + 256]; + LPCTSTR name; HKEY key = NULL; mStatus err; char * p; @@ -1211,10 +1438,11 @@ dDNSPlatformSetNameStatus(domainname *const dname, mStatus status) } check( strlen( p ) <= MAX_ESCAPED_DOMAIN_NAME ); - sprintf( name, "SYSTEM\\CurrentControlSet\\Services\\%s\\Parameters\\DynDNS\\State\\HostNames", kServiceName ); + name = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\State\\HostNames"); err = RegCreateKey( HKEY_LOCAL_MACHINE, name, &key ); require_noerr( err, exit ); + status = ( status ) ? 0 : 1; err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &status, sizeof(DWORD) ); require_noerr( err, exit ); @@ -1285,7 +1513,7 @@ dDNSPlatformSetSecretForDomain( mDNS *m, const domainname * domain ) err = ConvertLsaStringToUTF8( secret, &converted ); require_noerr( err, exit ); - mDNS_SetSecretForZone( m, d, d, converted, (mDNSu32) strlen( converted ) + 1, mDNStrue ); + mDNS_SetSecretForZone( m, d, d, converted ); exit: @@ -1330,7 +1558,7 @@ dDNSPlatformGetSearchDomainList( void ) HKEY key; mStatus err; - err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", &key ); + err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &key ); require_noerr( err, exit ); err = RegQueryString( key, "SearchList", &searchList, &searchListLen, NULL ); @@ -1847,16 +2075,18 @@ mDNSlocal mStatus SetupNiceName( mDNS * const inMDNS ) { mStatus err = 0; char tempString[ 256 ]; + char utf8[ 256 ]; check( inMDNS ); // Set up the nice name. tempString[ 0 ] = '\0'; + utf8[0] = '\0'; // First try and open the registry key that contains the computer description value if (inMDNS->p->descKey == NULL) { - const char * s = "SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters"; + LPCTSTR s = TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters"); err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &inMDNS->p->descKey); check_translated_errno( err == 0, errno_compat(), kNameErr ); @@ -1869,33 +2099,51 @@ mDNSlocal mStatus SetupNiceName( mDNS * const inMDNS ) // if we opened it... if (inMDNS->p->descKey != NULL) { - DWORD type; - DWORD valueLen = sizeof(tempString); + TCHAR desc[256]; + DWORD descSize = sizeof( desc ); // look for the computer description - err = RegQueryValueEx(inMDNS->p->descKey, "srvcomment", 0, &type, (LPBYTE) &tempString, &valueLen); - check_translated_errno( err == 0, errno_compat(), kNameErr ); + err = RegQueryValueEx(inMDNS->p->descKey, TEXT("srvcomment"), 0, NULL, (LPBYTE) &desc, &descSize); + + if ( !err ) + { + err = TCHARtoUTF8( desc, utf8, sizeof( utf8 ) ); + } + + if ( err ) + { + utf8[ 0 ] = '\0'; + } } // if we can't find it in the registry, then use the hostname of the machine - if (err || ( tempString[ 0] == '\0' ) ) + if ( err || ( utf8[ 0 ] == '\0' ) ) { err = gethostname( tempString, sizeof( tempString ) - 1 ); check_translated_errno( err == 0, errno_compat(), kNameErr ); + + if( !err ) + { + err = WindowsLatin1toUTF8( tempString, utf8, sizeof( utf8 ) ); + } + + if ( err ) + { + utf8[ 0 ] = '\0'; + } } // if we can't get the hostname - if( err || ( tempString[ 0 ] == '\0' ) ) + if ( err || ( utf8[ 0 ] == '\0' ) ) { // Invalidate name so fall back to a default name. - strcpy( tempString, kMDNSDefaultName ); + strcpy( utf8, kMDNSDefaultName ); } - tempString[ sizeof( tempString ) - 1 ] = '\0'; - - inMDNS->nicelabel.c[ 0 ] = (mDNSu8) (strlen( tempString ) < MAX_DOMAIN_LABEL ? strlen( tempString ) : MAX_DOMAIN_LABEL); - memcpy( &inMDNS->nicelabel.c[ 1 ], tempString, inMDNS->nicelabel.c[ 0 ] ); + utf8[ sizeof( utf8 ) - 1 ] = '\0'; + inMDNS->nicelabel.c[ 0 ] = (mDNSu8) (strlen( utf8 ) < MAX_DOMAIN_LABEL ? strlen( utf8 ) : MAX_DOMAIN_LABEL); + memcpy( &inMDNS->nicelabel.c[ 1 ], utf8, inMDNS->nicelabel.c[ 0 ] ); dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] ); @@ -2229,9 +2477,10 @@ mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS ) mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD ) { - mStatus err; - mDNSInterfaceData * ifd; + mDNSInterfaceData * ifd; + mDNSInterfaceData * p; SocketRef sock; + mStatus err; ifd = NULL; dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface\n" ); @@ -2263,50 +2512,35 @@ mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI // but we cut the packet rate in half. At this time, reducing the packet rate is more important than v6-only // devices on a large configured network, so we are willing to make that sacrifice. - ifd->interfaceInfo.McastTxRx = mDNStrue; - -#if( MDNS_WINDOWS_EXCLUDE_IPV4_ROUTABLE_IPV6 ) - if( inIFA->ifa_addr->sa_family != AF_INET ) + ifd->interfaceInfo.McastTxRx = mDNStrue; + ifd->interfaceInfo.InterfaceID = NULL; + + for( p = inMDNS->p->interfaceList; p; p = p->next ) { - const mDNSInterfaceData * p; - - for( p = inMDNS->p->interfaceList; p; p = p->next ) + if ( strcmp( p->name, ifd->name ) == 0 ) { - if( ( p->interfaceInfo.ip.type == mDNSAddrType_IPv4 ) && - ( ( p->interfaceInfo.ip.ip.v4.b[ 0 ] != 169 ) && ( p->interfaceInfo.ip.ip.v4.b[ 1 ] != 254 ) ) && - ( strcmp( p->name, inIFA->ifa_name ) == 0 ) ) + if (!ifd->interfaceInfo.InterfaceID) + { + p->scopeID = ifd->scopeID; + ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) p; + } + + if ( ( inIFA->ifa_addr->sa_family != AF_INET ) && + ( p->interfaceInfo.ip.type == mDNSAddrType_IPv4 ) && + ( p->interfaceInfo.ip.ip.v4.b[ 0 ] != 169 || p->interfaceInfo.ip.ip.v4.b[ 1 ] != 254 ) ) { ifd->interfaceInfo.McastTxRx = mDNSfalse; - break; } + + break; } } -#endif - // If this is an IPv6 interface, search for its IPv4 equivalent and use that InterfaceID. This causes the IPv4 - // interface to send both A and AAAA records so we can publish IPv6 support without doubling the packet rate. - // Note: this search only works because we register all IPv4 interfaces before IPv6 interfaces. - - ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ifd; - -#if( MDNS_WINDOWS_AAAA_OVER_IPV4 ) - if( inIFA->ifa_addr->sa_family != AF_INET ) + if ( !ifd->interfaceInfo.InterfaceID ) { - mDNSInterfaceData * ipv4IFD; - - for( ipv4IFD = inMDNS->p->interfaceList; ipv4IFD; ipv4IFD = ipv4IFD->next ) - { - if( strcmp( ipv4IFD->name, ifd->name ) == 0 ) - { - ipv4IFD->scopeID = ifd->scopeID; - ifd->interfaceInfo.McastTxRx = mDNSfalse; - ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ipv4IFD; - break; - } - } + ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ifd; } -#endif - + // Set up a socket for this interface (if needed). if( ifd->interfaceInfo.McastTxRx ) @@ -2712,11 +2946,25 @@ mDNSlocal mStatus SetupNotifications( mDNS * const inMDNS ) require_noerr( err, exit ); } + // This will catch all changes to tcp/ip networking, including changes to the domain search list + + inMDNS->p->tcpipChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + err = translate_errno( inMDNS->p->tcpipChangedEvent, (mStatus) GetLastError(), kUnknownErr ); + require_noerr( err, exit ); + + err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &inMDNS->p->tcpipKey ); + require_noerr( err, exit ); + + err = RegNotifyChangeKeyValue(inMDNS->p->tcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->tcpipChangedEvent, TRUE); + require_noerr( err, exit ); + + // This will catch all changes to ddns configuration + 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 ); + err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\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); @@ -2754,6 +3002,12 @@ mDNSlocal mStatus TearDownNotifications( mDNS * const inMDNS ) inMDNS->p->descKey = NULL; } + if ( inMDNS->p->tcpipChangedEvent != NULL ) + { + CloseHandle( inMDNS->p->tcpipChangedEvent ); + inMDNS->p->tcpipChangedEvent = NULL; + } + if ( inMDNS->p->ddnsChangedEvent != NULL ) { CloseHandle( inMDNS->p->ddnsChangedEvent ); @@ -2876,11 +3130,19 @@ mDNSlocal unsigned WINAPI ProcessingThread( LPVOID inParam ) // Main processing loop. + gWaitListChanged = FALSE; + for( ;; ) { // Give the mDNS core a chance to do its work and determine next event time. mDNSs32 interval = mDNS_Execute(m) - mDNS_TimeNow(m); + + if ( gWaitListChanged ) + { + break; + } + if (m->p->idleThreadCallback) { interval = m->p->idleThreadCallback(m, interval); @@ -2929,6 +3191,14 @@ mDNSlocal unsigned WINAPI ProcessingThread( LPVOID inParam ) ProcessingThreadComputerDescriptionChanged( m ); break; } + else if ( result == kWaitListTCPIPEvent ) + { + // + // The TCP/IP might have changed + // + ProcessingThreadTCPIPConfigChanged( m ); + break; + } else if ( result == kWaitListDynDNSEvent ) { // @@ -2950,7 +3220,8 @@ mDNSlocal unsigned WINAPI ProcessingThread( LPVOID inParam ) { HANDLE signaledObject; int n = 0; - mDNSInterfaceData * ifd; + mDNSInterfaceData * ifd; + mDNSTCPConnectionData * tcd; signaledObject = waitList[ waitItemIndex ]; @@ -2979,6 +3250,26 @@ mDNSlocal unsigned WINAPI ProcessingThread( LPVOID inParam ) } } + for ( tcd = gTCPConnectionList; tcd; tcd = tcd->next ) + { + if ( tcd->pendingEvent == signaledObject ) + { + mDNSBool connect = FALSE; + + if ( !tcd->connected ) + { + tcd->connected = mDNStrue; + connect = mDNStrue; + } + + tcd->callback( ( int ) tcd->sock, tcd->context, connect ); + + ++n; + + break; + } + } + check( n > 0 ); } else @@ -3052,11 +3343,12 @@ exit: mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **outWaitList, int *outWaitListCount ) { - mStatus err; - int waitListCount; - HANDLE * waitList; - HANDLE * waitItemPtr; - mDNSInterfaceData * ifd; + mStatus err; + int waitListCount; + HANDLE * waitList; + HANDLE * waitItemPtr; + mDNSInterfaceData * ifd; + mDNSTCPConnectionData * tcd; dlog( kDebugLevelTrace, DEBUG_NAME "thread setting up wait list\n" ); check( inMDNS ); @@ -3066,7 +3358,7 @@ mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o // Allocate an array to hold all the objects to wait on. - waitListCount = kWaitListFixedItemCount + inMDNS->p->interfaceCount; + waitListCount = kWaitListFixedItemCount + inMDNS->p->interfaceCount + gTCPConnections; waitList = (HANDLE *) malloc( waitListCount * sizeof( *waitList ) ); require_action( waitList, exit, err = mStatus_NoMemoryErr ); waitItemPtr = waitList; @@ -3077,6 +3369,7 @@ mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o *waitItemPtr++ = inMDNS->p->interfaceListChangedEvent; *waitItemPtr++ = inMDNS->p->wakeupEvent; *waitItemPtr++ = inMDNS->p->descChangedEvent; + *waitItemPtr++ = inMDNS->p->tcpipChangedEvent; *waitItemPtr++ = inMDNS->p->ddnsChangedEvent; // Append all the dynamic wait items to the list. @@ -3092,6 +3385,12 @@ mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o { *waitItemPtr++ = ifd->readPendingEvent; } + + for ( tcd = gTCPConnectionList; tcd; tcd = tcd->next ) + { + *waitItemPtr++ = tcd->pendingEvent; + } + check( (int)( waitItemPtr - waitList ) == waitListCount ); *outWaitList = waitList; @@ -3324,6 +3623,33 @@ mDNSlocal void ProcessingThreadComputerDescriptionChanged( mDNS *inMDNS ) } +//=========================================================================================================================== +// ProcessingThreadTCPIPConfigChanged +//=========================================================================================================================== +mDNSlocal void ProcessingThreadTCPIPConfigChanged( mDNS * inMDNS ) +{ + mStatus err; + + dlog( kDebugLevelInfo, DEBUG_NAME "TCP/IP config has changed\n" ); + check( inMDNS ); + + mDNSPlatformLock( inMDNS ); + + err = dDNS_Setup( inMDNS ); + check_noerr( err ); + + // and reset the event handler + + if ( ( inMDNS->p->tcpipKey != NULL ) && ( inMDNS->p->tcpipChangedEvent ) ) + { + err = RegNotifyChangeKeyValue( inMDNS->p->tcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->tcpipChangedEvent, TRUE ); + check_noerr( err ); + } + + mDNSPlatformUnlock( inMDNS ); +} + + //=========================================================================================================================== // ProcessingThreadDynDNSConfigChanged //=========================================================================================================================== @@ -3340,6 +3666,7 @@ mDNSlocal void ProcessingThreadDynDNSConfigChanged( mDNS *inMDNS ) check_noerr( err ); // and reset the event handler + if ((inMDNS->p->ddnsKey != NULL) && (inMDNS->p->ddnsChangedEvent)) { err = RegNotifyChangeKeyValue(inMDNS->p->ddnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->ddnsChangedEvent, TRUE); @@ -4106,7 +4433,7 @@ exit: //=========================================================================================================================== static mStatus -RegQueryString( HKEY key, const char * valueName, char ** string, DWORD * stringLen, DWORD * enabled ) +RegQueryString( HKEY key, LPCSTR valueName, LPSTR * string, DWORD * stringLen, DWORD * enabled ) { DWORD type; int i; @@ -4126,17 +4453,19 @@ RegQueryString( HKEY key, const char * valueName, char ** string, DWORD * string *string = (char*) malloc( *stringLen ); require_action( *string, exit, err = mStatus_NoMemoryErr ); - err = RegQueryValueEx( key, valueName, 0, &type, (LPBYTE) *string, stringLen ); + err = RegQueryValueExA( key, valueName, 0, &type, (LPBYTE) *string, stringLen ); i++; } while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) ); + require_noerr_quiet( err, exit ); + if ( enabled ) { DWORD dwSize = sizeof( DWORD ); - err = RegQueryValueEx( key, "Enabled", NULL, NULL, (LPBYTE) enabled, &dwSize ); + err = RegQueryValueEx( key, TEXT("Enabled"), NULL, NULL, (LPBYTE) enabled, &dwSize ); check_noerr( err ); err = kNoErr; @@ -4152,7 +4481,7 @@ exit: // StringToAddress //=========================================================================================================================== -static mStatus StringToAddress( mDNSAddr * ip, const char * string ) +static mStatus StringToAddress( mDNSAddr * ip, LPSTR string ) { struct sockaddr_in6 sa6; struct sockaddr_in sa4; @@ -4162,7 +4491,7 @@ static mStatus StringToAddress( mDNSAddr * ip, const char * string ) sa6.sin6_family = AF_INET6; dwSize = sizeof( sa6 ); - err = WSAStringToAddress( (LPSTR) string, AF_INET6, NULL, (struct sockaddr*) &sa6, &dwSize ); + err = WSAStringToAddressA( string, AF_INET6, NULL, (struct sockaddr*) &sa6, &dwSize ); if ( err == mStatus_NoError ) { @@ -4174,7 +4503,7 @@ static mStatus StringToAddress( mDNSAddr * ip, const char * string ) sa4.sin_family = AF_INET; dwSize = sizeof( sa4 ); - err = WSAStringToAddress( (LPSTR) string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize ); + err = WSAStringToAddressA( string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize ); require_noerr( err, exit ); err = dDNS_SetupAddr( ip, (struct sockaddr*) &sa4 ); @@ -4211,6 +4540,67 @@ myGetIfAddrs(int refresh) } +//=========================================================================================================================== +// TCHARtoUTF8 +//=========================================================================================================================== + +mDNSlocal OSStatus +TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize ) +{ +#if( defined( UNICODE ) || defined( _UNICODE ) ) + OSStatus err; + int len; + + len = WideCharToMultiByte( CP_UTF8, 0, inString, -1, inBuffer, (int) inBufferSize, NULL, NULL ); + err = translate_errno( len > 0, errno_compat(), kUnknownErr ); + require_noerr( err, exit ); + +exit: + return( err ); +#else + return( WindowsLatin1toUTF8( inString, inBuffer, inBufferSize ) ); +#endif +} + + +//=========================================================================================================================== +// WindowsLatin1toUTF8 +//=========================================================================================================================== + +mDNSlocal OSStatus +WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize ) +{ + OSStatus err; + WCHAR * utf16; + int len; + + utf16 = NULL; + + // Windows doesn't support going directly from Latin-1 to UTF-8 so we have to go from Latin-1 to UTF-16 first. + + len = MultiByteToWideChar( CP_ACP, 0, inString, -1, NULL, 0 ); + err = translate_errno( len > 0, errno_compat(), kUnknownErr ); + require_noerr( err, exit ); + + utf16 = (WCHAR *) malloc( len * sizeof( *utf16 ) ); + require_action( utf16, exit, err = kNoMemoryErr ); + + len = MultiByteToWideChar( CP_ACP, 0, inString, -1, utf16, len ); + err = translate_errno( len > 0, errno_compat(), kUnknownErr ); + require_noerr( err, exit ); + + // Now convert the temporary UTF-16 to UTF-8. + + len = WideCharToMultiByte( CP_UTF8, 0, utf16, -1, inBuffer, (int) inBufferSize, NULL, NULL ); + err = translate_errno( len > 0, errno_compat(), kUnknownErr ); + require_noerr( err, exit ); + +exit: + if( utf16 ) free( utf16 ); + return( err ); +} + + //=========================================================================================================================== // ConvertUTF8ToLsaString //=========================================================================================================================== @@ -4297,3 +4687,26 @@ exit: return err; } + + +//=========================================================================================================================== +// FreeTCPConnectionData +//=========================================================================================================================== + +mDNSlocal void +FreeTCPConnectionData( mDNSTCPConnectionData * data ) +{ + check( data ); + + if ( data->pendingEvent ) + { + CloseHandle( data->pendingEvent ); + } + + if ( data->sock != INVALID_SOCKET ) + { + closesocket( data->sock ); + } + + free( data ); +} diff --git a/mDNSWindows/mDNSWin32.h b/mDNSWindows/mDNSWin32.h index e94150e..f5c9c26 100755 --- a/mDNSWindows/mDNSWin32.h +++ b/mDNSWindows/mDNSWin32.h @@ -23,6 +23,12 @@ Change History (most recent first): $Log: mDNSWin32.h,v $ +Revision 1.22 2005/03/04 22:44:53 shersche + mDNSResponder did not notice changes to DNS server config + +Revision 1.21 2005/03/03 02:29:00 shersche +Use the RegNames.h header file for registry key names + Revision 1.20 2005/01/25 08:12:52 shersche Enable Unicast and add Dynamic DNS support. Bug #: 3947417 @@ -185,10 +191,12 @@ struct mDNS_PlatformSupport_struct HANDLE quitEvent; HANDLE interfaceListChangedEvent; HANDLE descChangedEvent; // Computer description changed event + HANDLE tcpipChangedEvent; // TCP/IP config changed HANDLE ddnsChangedEvent; // DynDNS config changed HANDLE wakeupEvent; HANDLE initEvent; HKEY descKey; + HKEY tcpipKey; HKEY ddnsKey; mStatus initStatus; SocketRef interfaceListChangedSocket; @@ -264,19 +272,6 @@ int getifaddrs( struct ifaddrs **outAddrs ); 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 diff --git a/mDNSWindows/mdnsNSP/mdnsNSP.c b/mDNSWindows/mdnsNSP/mdnsNSP.c index 34311f1..c690459 100644 --- a/mDNSWindows/mdnsNSP/mdnsNSP.c +++ b/mDNSWindows/mdnsNSP/mdnsNSP.c @@ -23,6 +23,19 @@ Change History (most recent first): $Log: mdnsNSP.c,v $ +Revision 1.10 2005/02/23 22:16:07 shersche +Unregister the NSP before registering to workaround an installer problem during upgrade installs + +Revision 1.9 2005/02/01 01:45:55 shersche +Change mdnsNSP timeout to 2 seconds + +Revision 1.8 2005/01/31 23:27:25 shersche + Don't try and resolve .local hostnames that are referenced in the hosts file + +Revision 1.7 2005/01/28 23:50:13 shersche + Implement DllRegisterServer,DllUnregisterServer so mdnsNSP.dll can self-register +Bug #: 3942551 + Revision 1.6 2004/12/06 01:56:53 shersche Use the DNS types and classes defined in dns_sd.h Bug #: 3789425 @@ -93,6 +106,24 @@ struct Query bool addrValid; }; +#define BUFFER_INITIAL_SIZE 4192 +#define ALIASES_INITIAL_SIZE 5 + +typedef struct HostsFile +{ + int m_bufferSize; + char * m_buffer; + FILE * m_fp; +} HostsFile; + + +typedef struct HostsFileInfo +{ + struct hostent m_host; + struct HostsFileInfo * m_next; +} HostsFileInfo; + + #if 0 #pragma mark == Prototypes == #endif @@ -104,7 +135,10 @@ struct Query // DLL Exports BOOL WINAPI DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved ); +STDAPI DllRegisterServer( void ); +STDAPI DllRegisterServer( void ); + // NSP SPIs int WSPAPI NSPCleanup( LPGUID inProviderID ); @@ -186,6 +220,15 @@ DEBUG_LOCAL size_t QueryCopyQuerySetSize( QueryRef inRef, const WSAQUERYSETW *in #define dlog_query_set( LEVEL, SET ) #endif +DEBUG_LOCAL BOOL InHostsTable( const char * name ); +DEBUG_LOCAL BOOL IsLocalName( HostsFileInfo * node ); +DEBUG_LOCAL BOOL IsSameName( HostsFileInfo * node, const char * name ); +DEBUG_LOCAL OSStatus HostsFileOpen( HostsFile ** self, const char * fname ); +DEBUG_LOCAL OSStatus HostsFileClose( HostsFile * self ); +DEBUG_LOCAL void HostsFileInfoFree( HostsFileInfo * info ); +DEBUG_LOCAL OSStatus HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo ); + + #if 0 #pragma mark == Globals == #endif @@ -195,13 +238,15 @@ DEBUG_LOCAL size_t QueryCopyQuerySetSize( QueryRef inRef, const WSAQUERYSETW *in //=========================================================================================================================== // {B600E6E9-553B-4a19-8696-335E5C896153} -// GUID kmdnsNSPGUID = { 0xb600e6e9, 0x553b, 0x4a19, { 0x86, 0x96, 0x33, 0x5e, 0x5c, 0x89, 0x61, 0x53 } }; - +DEBUG_LOCAL HINSTANCE gInstance = NULL; +DEBUG_LOCAL wchar_t * gNSPName = L"mdnsNSP"; +DEBUG_LOCAL GUID gNSPGUID = { 0xb600e6e9, 0x553b, 0x4a19, { 0x86, 0x96, 0x33, 0x5e, 0x5c, 0x89, 0x61, 0x53 } }; DEBUG_LOCAL LONG gRefCount = 0; DEBUG_LOCAL CRITICAL_SECTION gLock; DEBUG_LOCAL bool gLockInitialized = false; DEBUG_LOCAL bool gDNSSDInitialized = false; DEBUG_LOCAL QueryRef gQueryList = NULL; +DEBUG_LOCAL HostsFileInfo * gHostsFileInfo = NULL; #if 0 #pragma mark - @@ -219,6 +264,8 @@ BOOL APIENTRY DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved ) switch( inReason ) { case DLL_PROCESS_ATTACH: + gInstance = inInstance; + gHostsFileInfo = NULL; debug_initialize( kDebugOutputTypeWindowsEventLog, "mDNS NSP", inInstance ); debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelInfo ); dlog( kDebugLevelTrace, "\n" ); @@ -226,6 +273,8 @@ BOOL APIENTRY DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved ) break; case DLL_PROCESS_DETACH: + HostsFileInfoFree( gHostsFileInfo ); + gHostsFileInfo = NULL; dlog( kDebugLevelVerbose, "%s: process detach\n", __ROUTINE__ ); break; @@ -244,6 +293,68 @@ BOOL APIENTRY DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved ) return( TRUE ); } + +//=========================================================================================================================== +// DllRegisterServer +//=========================================================================================================================== + +STDAPI DllRegisterServer( void ) +{ + WSADATA wsd; + WCHAR path[ MAX_PATH ]; + HRESULT err; + + dlog( kDebugLevelTrace, "DllRegisterServer\n" ); + + err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + + // Unregister before registering to workaround an installer + // problem during upgrade installs. + + WSCUnInstallNameSpace( &gNSPGUID ); + + err = GetModuleFileNameW( gInstance, path, sizeof( path ) ); + err = translate_errno( err != 0, errno_compat(), kUnknownErr ); + require_noerr( err, exit ); + + err = WSCInstallNameSpace( gNSPName, path, NS_DNS, 1, &gNSPGUID ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + +exit: + + WSACleanup(); + return( err ); +} + +//=========================================================================================================================== +// DllUnregisterServer +//=========================================================================================================================== + +STDAPI DllUnregisterServer( void ) +{ + WSADATA wsd; + HRESULT err; + + dlog( kDebugLevelTrace, "DllUnregisterServer\n" ); + + err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + + err = WSCUnInstallNameSpace( &gNSPGUID ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + +exit: + + WSACleanup(); + return err; +} + + //=========================================================================================================================== // NSPStartup // @@ -486,8 +597,22 @@ DEBUG_LOCAL int WSPAPI exit, err = WSASERVICE_NOT_FOUND ); } } + else + { + // + // + // Check to see if the name of this host is in the hosts table. If so, + // don't try and resolve it + + char translated[ kDNSServiceMaxDomainName ]; + int n; + + n = WideCharToMultiByte( CP_UTF8, 0, name, -1, translated, sizeof( translated ), NULL, NULL ); + require_action( n > 0, exit, err = WSASERVICE_NOT_FOUND ); + require_action( InHostsTable( translated ) == FALSE, exit, err = WSASERVICE_NOT_FOUND ); + } - // The name ends in .local, .0.8.e.f.ip6.arpa, or .254.169.in-addr.arpa so start the resolve operation. Lazy initialize DNS-SD if needed. + // The name ends in .local ( and isn't in the hosts table ), .0.8.e.f.ip6.arpa, or .254.169.in-addr.arpa so start the resolve operation. Lazy initialize DNS-SD if needed. NSPLock(); if( !gDNSSDInitialized ) @@ -548,7 +673,7 @@ DEBUG_LOCAL int WSPAPI // Wait for data or a cancel. Release the lock while waiting. This is safe because we've retained the query. NSPUnlock(); - waitResult = WaitForMultipleObjects( obj->waitCount, obj->waitHandles, FALSE, 5 * 1000 ); + waitResult = WaitForMultipleObjects( obj->waitCount, obj->waitHandles, FALSE, 2 * 1000 ); NSPLock(); require_action_quiet( waitResult != ( WAIT_OBJECT_0 + 1 ), exit, err = WSA_E_CANCELLED ); err = translate_errno( waitResult == WAIT_OBJECT_0, (OSStatus) GetLastError(), WSASERVICE_NOT_FOUND ); @@ -1438,3 +1563,424 @@ void DebugDumpQuerySet( DebugLevel inLevel, const WSAQUERYSETW *inQuerySet ) } } #endif + + +//=========================================================================================================================== +// InHostsTable +//=========================================================================================================================== + +DEBUG_LOCAL BOOL +InHostsTable( const char * name ) +{ + HostsFileInfo * node; + BOOL ret = FALSE; + OSStatus err; + + check( name ); + + if ( gHostsFileInfo == NULL ) + { + TCHAR systemDirectory[MAX_PATH]; + TCHAR hFileName[MAX_PATH]; + HostsFile * hFile; + + GetSystemDirectory( systemDirectory, sizeof( systemDirectory ) ); + sprintf( hFileName, "%s\\drivers\\etc\\hosts", systemDirectory ); + err = HostsFileOpen( &hFile, hFileName ); + require_noerr( err, exit ); + + while ( HostsFileNext( hFile, &node ) == 0 ) + { + if ( IsLocalName( node ) ) + { + node->m_next = gHostsFileInfo; + gHostsFileInfo = node; + } + else + { + HostsFileInfoFree( node ); + } + } + + HostsFileClose( hFile ); + } + + for ( node = gHostsFileInfo; node; node = node->m_next ) + { + if ( IsSameName( node, name ) ) + { + ret = TRUE; + break; + } + } + +exit: + + return ret; +} + + +//=========================================================================================================================== +// IsLocalName +//=========================================================================================================================== + +DEBUG_LOCAL BOOL +IsLocalName( HostsFileInfo * node ) +{ + BOOL ret = TRUE; + + check( node ); + + if ( strstr( node->m_host.h_name, ".local" ) == NULL ) + { + int i; + + for ( i = 0; node->m_host.h_aliases[i]; i++ ) + { + if ( strstr( node->m_host.h_aliases[i], ".local" ) ) + { + goto exit; + } + } + + ret = FALSE; + } + +exit: + + return ret; +} + + +//=========================================================================================================================== +// IsSameName +//=========================================================================================================================== + +DEBUG_LOCAL BOOL +IsSameName( HostsFileInfo * node, const char * name ) +{ + BOOL ret = TRUE; + + check( node ); + check( name ); + + if ( strcmp( node->m_host.h_name, name ) != 0 ) + { + int i; + + for ( i = 0; node->m_host.h_aliases[i]; i++ ) + { + if ( strcmp( node->m_host.h_aliases[i], name ) == 0 ) + { + goto exit; + } + } + + ret = FALSE; + } + +exit: + + return ret; +} + + +//=========================================================================================================================== +// HostsFileOpen +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus +HostsFileOpen( HostsFile ** self, const char * fname ) +{ + OSStatus err = kNoErr; + + *self = (HostsFile*) malloc( sizeof( HostsFile ) ); + require_action( *self, exit, err = kNoMemoryErr ); + memset( *self, 0, sizeof( HostsFile ) ); + + (*self)->m_bufferSize = BUFFER_INITIAL_SIZE; + (*self)->m_buffer = (char*) malloc( (*self)->m_bufferSize ); + require_action( (*self)->m_buffer, exit, err = kNoMemoryErr ); + + // check malloc + + (*self)->m_fp = fopen( fname, "r" ); + require_action( (*self)->m_fp, exit, err = kUnknownErr ); + +exit: + + if ( err && *self ) + { + HostsFileClose( *self ); + *self = NULL; + } + + return err; +} + + +//=========================================================================================================================== +// HostsFileClose +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus +HostsFileClose( HostsFile * self ) +{ + check( self ); + + if ( self->m_buffer ) + { + free( self->m_buffer ); + self->m_buffer = NULL; + } + + if ( self->m_fp ) + { + fclose( self->m_fp ); + self->m_fp = NULL; + } + + free( self ); + + return kNoErr; +} + + +//=========================================================================================================================== +// HostsFileInfoFree +//=========================================================================================================================== + +DEBUG_LOCAL void +HostsFileInfoFree( HostsFileInfo * info ) +{ + while ( info ) + { + HostsFileInfo * next = info->m_next; + + if ( info->m_host.h_addr_list ) + { + if ( info->m_host.h_addr_list[0] ) + { + free( info->m_host.h_addr_list[0] ); + info->m_host.h_addr_list[0] = NULL; + } + + free( info->m_host.h_addr_list ); + info->m_host.h_addr_list = NULL; + } + + if ( info->m_host.h_aliases ) + { + int i; + + for ( i = 0; info->m_host.h_aliases[i]; i++ ) + { + free( info->m_host.h_aliases[i] ); + } + + free( info->m_host.h_aliases ); + } + + if ( info->m_host.h_name ) + { + free( info->m_host.h_name ); + info->m_host.h_name = NULL; + } + + free( info ); + + info = next; + } +} + + +//=========================================================================================================================== +// HostsFileNext +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus +HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo ) +{ + struct sockaddr_in6 addr_6; + struct sockaddr_in addr_4; + int numAliases = ALIASES_INITIAL_SIZE; + char * line; + char * tok; + int dwSize; + int idx; + int i; + short family; + OSStatus err = kNoErr; + + check( self ); + check( self->m_fp ); + check( hInfo ); + + idx = 0; + + *hInfo = (HostsFileInfo*) malloc( sizeof( HostsFileInfo ) ); + require_action( *hInfo, exit, err = kNoMemoryErr ); + memset( *hInfo, 0, sizeof( HostsFileInfo ) ); + + for ( ; ; ) + { + line = fgets( self->m_buffer + idx, self->m_bufferSize - idx, self->m_fp ); + + if ( line == NULL ) + { + err = 1; + goto exit; + } + + // If there's no eol and no eof, then we didn't get the whole line + + if ( !strchr( line, '\n' ) && !feof( self->m_fp ) ) + { + int bufferSize; + char * buffer; + + /* Try and allocate space for longer line */ + + bufferSize = self->m_bufferSize * 2; + buffer = (char*) realloc( self->m_buffer, bufferSize ); + require_action( buffer, exit, err = kNoMemoryErr ); + self->m_bufferSize = bufferSize; + self->m_buffer = buffer; + idx = (int) strlen( self->m_buffer ); + + continue; + } + + line = self->m_buffer; + idx = 0; + + if (*line == '#') + { + continue; + } + + // Get rid of either comments or eol characters + + if (( tok = strpbrk(line, "#\n")) != NULL ) + { + *tok = '\0'; + } + + // Make sure there is some whitespace on this line + + if (( tok = strpbrk(line, " \t")) == NULL ) + { + continue; + } + + // Create two strings, where p == the IP Address and tok is the name list + + *tok++ = '\0'; + + while ( *tok == ' ' || *tok == '\t') + { + tok++; + } + + // Now we have the name + + (*hInfo)->m_host.h_name = (char*) malloc( strlen( tok ) + 1 ); + require_action( (*hInfo)->m_host.h_name, exit, err = kNoMemoryErr ); + strcpy( (*hInfo)->m_host.h_name, tok ); + + // Now create the address (IPv6/IPv4) + + addr_6.sin6_family = family = AF_INET6; + dwSize = sizeof( addr_6 ); + + if ( WSAStringToAddress( line, AF_INET6, NULL, ( struct sockaddr*) &addr_6, &dwSize ) != 0 ) + { + addr_4.sin_family = family = AF_INET; + dwSize = sizeof( addr_4 ); + + if (WSAStringToAddress( line, AF_INET, NULL, ( struct sockaddr*) &addr_4, &dwSize ) != 0 ) + { + continue; + } + } + + (*hInfo)->m_host.h_addr_list = (char**) malloc( sizeof( char**) * 2 ); + require_action( (*hInfo)->m_host.h_addr_list, exit, err = kNoMemoryErr ); + + if ( family == AF_INET6 ) + { + (*hInfo)->m_host.h_length = (short) sizeof( addr_6.sin6_addr ); + (*hInfo)->m_host.h_addr_list[0] = (char*) malloc( (*hInfo)->m_host.h_length ); + require_action( (*hInfo)->m_host.h_addr_list[0], exit, err = kNoMemoryErr ); + memmove( (*hInfo)->m_host.h_addr_list[0], &addr_6.sin6_addr, sizeof( addr_6.sin6_addr ) ); + + } + else + { + (*hInfo)->m_host.h_length = (short) sizeof( addr_4.sin_addr ); + (*hInfo)->m_host.h_addr_list[0] = (char*) malloc( (*hInfo)->m_host.h_length ); + require_action( (*hInfo)->m_host.h_addr_list[0], exit, err = kNoMemoryErr ); + memmove( (*hInfo)->m_host.h_addr_list[0], &addr_4.sin_addr, sizeof( addr_4.sin_addr ) ); + } + + (*hInfo)->m_host.h_addr_list[1] = NULL; + (*hInfo)->m_host.h_addrtype = family; + + // Now get the aliases + + if ((tok = strpbrk(tok, " \t")) != NULL) + { + *tok++ = '\0'; + } + + i = 0; + + (*hInfo)->m_host.h_aliases = (char**) malloc( sizeof(char**) * numAliases ); + require_action( (*hInfo)->m_host.h_aliases, exit, err = kNoMemoryErr ); + (*hInfo)->m_host.h_aliases[0] = NULL; + + while ( tok && *tok ) + { + // Skip over the whitespace, waiting for the start of the next alias name + + if (*tok == ' ' || *tok == '\t') + { + tok++; + continue; + } + + // Check to make sure we don't exhaust the alias buffer + + if ( i >= ( numAliases - 1 ) ) + { + numAliases = numAliases * 2; + (*hInfo)->m_host.h_aliases = (char**) realloc( (*hInfo)->m_host.h_aliases, numAliases * sizeof( char** ) ); + require_action( (*hInfo)->m_host.h_aliases, exit, err = kNoMemoryErr ); + } + + (*hInfo)->m_host.h_aliases[i] = (char*) malloc( strlen( tok ) + 1 ); + require_action( (*hInfo)->m_host.h_aliases[i], exit, err = kNoMemoryErr ); + + strcpy( (*hInfo)->m_host.h_aliases[i], tok ); + + if (( tok = strpbrk( tok, " \t")) != NULL ) + { + *tok++ = '\0'; + } + + (*hInfo)->m_host.h_aliases[++i] = NULL; + } + + break; + } + +exit: + + if ( err && ( *hInfo ) ) + { + HostsFileInfoFree( *hInfo ); + *hInfo = NULL; + } + + return err; +} diff --git a/mDNSWindows/mdnsNSP/mdnsNSP.def b/mDNSWindows/mdnsNSP/mdnsNSP.def index 16f4f18..338e5a5 100644 --- a/mDNSWindows/mdnsNSP/mdnsNSP.def +++ b/mDNSWindows/mdnsNSP/mdnsNSP.def @@ -23,6 +23,10 @@ ; Change History (most recent first): ; ; $Log: mdnsNSP.def,v $ +; Revision 1.3 2005/01/28 23:48:46 shersche +; Export DllRegisterServer, DllUnregisterServer which can be called from the Installer or regsvr32 +; Bug #: 3942551 +; ; Revision 1.2 2004/07/13 21:24:28 rpantos ; Fix for . ; @@ -40,3 +44,5 @@ LIBRARY mdnsNSP EXPORTS NSPStartup NSPCleanup + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE diff --git a/mDNSWindows/mdnsNSP/mdnsNSP.rc b/mDNSWindows/mdnsNSP/mdnsNSP.rc index 4fae1d8..847c02a 100644 --- a/mDNSWindows/mdnsNSP/mdnsNSP.rc +++ b/mDNSWindows/mdnsNSP/mdnsNSP.rc @@ -72,9 +72,9 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Apple Computer, Inc." - VALUE "FileDescription", "mdnsNSP Dynamic Link Library" + VALUE "FileDescription", "Bonjour Namespace Provider" VALUE "FileVersion", MASTER_PROD_VERS_STR - VALUE "InternalName", "mdnsNSP" + VALUE "InternalName", "mdnsNSP.dll" VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT VALUE "OriginalFilename", "mdnsNSP.dll" VALUE "ProductName", MASTER_PROD_NAME diff --git a/mDNSWindows/mdnsNSP/mdnsNSP.vcproj b/mDNSWindows/mdnsNSP/mdnsNSP.vcproj index f8aac54..4648cff 100644 --- a/mDNSWindows/mdnsNSP/mdnsNSP.vcproj +++ b/mDNSWindows/mdnsNSP/mdnsNSP.vcproj @@ -64,7 +64,7 @@ -- 2.47.2