From f5e6e86cb0d7e0c7608c30d93ecb200173f29055 Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 5 May 2005 00:06:58 +0000 Subject: [PATCH] mDNSResponder-107.1.tar.gz --- Clients/ExplorerPlugin/ExplorerBarWindow.cpp | 29 +- .../ExplorerPlugin/ExplorerPluginLocRes.rc | 2 +- .../ExplorerPluginLocRes.vcproj | 14 +- Clients/ExplorerPlugin/ExplorerPluginRes.rc | 1 - .../ExplorerPlugin/ExplorerPluginRes.vcproj | 10 +- Clients/ExplorerPlugin/res/globe.bmp | Bin 824 -> 0 bytes Clients/ExplorerPlugin/resource_res.h | 1 - Clients/PrinterSetupWizard/FirstPage.cpp | 15 +- .../PrinterSetupWizardApp.cpp | 5 +- .../PrinterSetupWizardLocRes.rc | 37 +- .../PrinterSetupWizardLocRes.vcproj | 14 +- .../PrinterSetupWizardRes.vcproj | 14 +- .../PrinterSetupWizardSheet.cpp | 61 +- .../PrinterSetupWizardSheet.h | 5 +- Clients/PrinterSetupWizard/SecondPage.cpp | 94 +- Clients/PrinterSetupWizard/SecondPage.h | 7 + Clients/PrinterSetupWizard/ThirdPage.cpp | 56 +- Clients/PrinterSetupWizard/UtilTypes.h | 29 +- .../PrinterSetupWizard/res/NetworkPrinter.ico | Bin 77214 -> 82726 bytes Clients/PrinterSetupWizard/res/Print.ico | Bin 77214 -> 82726 bytes Clients/dns-sd.c | 12 +- Makefile | 2 +- mDNSCore/DNSCommon.c | 31 +- mDNSCore/DNSCommon.h | 5 +- mDNSCore/mDNS.c | 5 +- mDNSCore/mDNSEmbeddedAPI.h | 12 +- mDNSCore/uDNS.c | 34 +- mDNSCore/uDNS.h | 10 +- mDNSMacOS9/mDNSLibraryResources.r | 13 +- ...iceDiscoveryPref.icns => BonjourPref.icns} | Bin 38889 -> 39196 bytes mDNSMacOSX/PreferencePane/BonjourPref.tiff | Bin 0 -> 2430 bytes .../DNSServiceDiscoveryPref.tiff | Bin 17394 -> 0 bytes mDNSMacOSX/daemon.c | 40 +- mDNSMacOSX/mDNSMacOSX.c | 21 +- .../mDNSResponder.pbproj/project.pbxproj | 12 +- mDNSPosix/Makefile | 18 +- mDNSPosix/dnsextd.c | 91 +- mDNSPosix/mDNSUNP.c | 148 ++- mDNSPosix/mDNSUNP.h | 26 +- mDNSResponder.sln | 1 + mDNSShared/PlatformCommon.c | 6 +- mDNSShared/dns_sd.h | 2 + mDNSShared/dnssd_clientlib.c | 23 +- mDNSShared/dnssd_clientstub.c | 11 +- mDNSShared/dnssd_ipc.h | 8 +- mDNSShared/uds_daemon.c | 26 +- mDNSWindows/ControlPanel/ControlPanel.rc | 25 +- mDNSWindows/ControlPanel/FirstPage.cpp | 31 +- mDNSWindows/ControlPanel/SecondPage.cpp | 78 +- mDNSWindows/ControlPanel/SecondPage.h | 4 + mDNSWindows/ControlPanel/SharedSecret.cpp | 39 +- mDNSWindows/ControlPanel/SharedSecret.h | 8 +- mDNSWindows/ControlPanel/resource.h | 2 + mDNSWindows/DLL/dnssd.vcproj | 6 +- mDNSWindows/Installer/Main.ism | Bin 195584 -> 0 bytes mDNSWindows/Installer/SDK.ism | Bin 189952 -> 0 bytes mDNSWindows/SystemService/Service.c | 147 ++- mDNSWindows/SystemServiceTest/Prefix.h | 47 - mDNSWindows/SystemServiceTest/Tool.c | 851 ------------------ mDNSWindows/SystemServiceTest/Tool.mcp | Bin 210145 -> 0 bytes mDNSWindows/SystemServiceTest/Tool2002.vcproj | 191 ---- mDNSWindows/WinVersRes.h | 32 +- mDNSWindows/dDNS.c | 30 +- mDNSWindows/dDNS.h | 5 + mDNSWindows/loclibrary.c | 24 +- mDNSWindows/mDNSWin32.c | 577 +++++++++--- mDNSWindows/mdnsNSP/mdnsNSP.c | 213 +++-- 67 files changed, 1613 insertions(+), 1648 deletions(-) delete mode 100755 Clients/ExplorerPlugin/res/globe.bmp rename mDNSMacOSX/PreferencePane/{DNSServiceDiscoveryPref.icns => BonjourPref.icns} (56%) create mode 100644 mDNSMacOSX/PreferencePane/BonjourPref.tiff delete mode 100644 mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff delete mode 100644 mDNSWindows/Installer/Main.ism delete mode 100644 mDNSWindows/Installer/SDK.ism delete mode 100644 mDNSWindows/SystemServiceTest/Prefix.h delete mode 100644 mDNSWindows/SystemServiceTest/Tool.c delete mode 100644 mDNSWindows/SystemServiceTest/Tool.mcp delete mode 100644 mDNSWindows/SystemServiceTest/Tool2002.vcproj diff --git a/Clients/ExplorerPlugin/ExplorerBarWindow.cpp b/Clients/ExplorerPlugin/ExplorerBarWindow.cpp index a68880b..d4ea5c1 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.21 2005/04/06 01:13:07 shersche + Use the product icon instead of globe icon for 'About' link. + +Revision 1.20 2005/03/18 02:43:02 shersche + Use standard IE website icon for 'About Bonjour', only using globe icon if standard icon cannot be loaded + +Revision 1.19 2005/03/16 03:46:27 shersche + Use Bonjour icon for all discovered sites + Revision 1.18 2005/02/26 01:24:05 shersche Remove display lines in tree control @@ -143,6 +152,10 @@ static char THIS_FILE[] = __FILE__; #define kTXTRecordKeyPath "path" +// IE Icon resource + +#define kIEIconResource 32529 + #if 0 #pragma mark == Prototypes == @@ -205,6 +218,7 @@ int ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct ) { AFX_MANAGE_STATE( AfxGetStaticModuleState() ); + HINSTANCE module = NULL; OSStatus err; CRect rect; CBitmap bitmap; @@ -231,7 +245,7 @@ int ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct ) mServiceHandlers.Add( e ); s.LoadString( IDS_ABOUT ); - m_about = mTree.InsertItem( s, 1, 1 ); + m_about = mTree.InsertItem( s, 0, 0 ); err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e ); require_noerr( err, exit ); @@ -241,17 +255,22 @@ int ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct ) m_serviceRefs.push_back(e->ref); - m_imageList.Create( 16, 16, ILC_COLORDDB, 2, 0); - bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_GLOBE ) ) ); - m_imageList.Add( &bitmap, (CBitmap*) NULL ); - bitmap.Detach(); + m_imageList.Create( 16, 16, ILC_MASK | ILC_COLOR16, 2, 0); + bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_LOGO ) ) ); m_imageList.Add( &bitmap, (CBitmap*) NULL ); + bitmap.Detach(); mTree.SetImageList(&m_imageList, TVSIL_NORMAL); exit: + if ( module ) + { + FreeLibrary( module ); + module = NULL; + } + // Cannot talk to the mDNSResponder service. Show the error message and exit (with kNoErr so they can see it). if ( err ) { diff --git a/Clients/ExplorerPlugin/ExplorerPluginLocRes.rc b/Clients/ExplorerPlugin/ExplorerPluginLocRes.rc index 7e025f2..34cf048 100755 --- a/Clients/ExplorerPlugin/ExplorerPluginLocRes.rc +++ b/Clients/ExplorerPlugin/ExplorerPluginLocRes.rc @@ -177,7 +177,7 @@ END STRINGTABLE BEGIN IDS_ABOUT "About Bonjour" - IDS_ABOUT_URL "http://www.apple.com/macosx/features/rendezvous" + IDS_ABOUT_URL "http://www.apple.com/macosx/features/bonjour" IDS_NAME "Bonjour" IDS_WEB_SITES "Web Sites" IDS_PRINTERS "Printers" diff --git a/Clients/ExplorerPlugin/ExplorerPluginLocRes.vcproj b/Clients/ExplorerPlugin/ExplorerPluginLocRes.vcproj index bcb0269..35f32be 100755 --- a/Clients/ExplorerPlugin/ExplorerPluginLocRes.vcproj +++ b/Clients/ExplorerPlugin/ExplorerPluginLocRes.vcproj @@ -13,7 +13,7 @@ + CommandLine="if not exist Debug\ExplorerPlugin.Resources mkdir Debug\ExplorerPlugin.Resources +if not exist Debug\ExplorerPlugin.Resources\en.lproj mkdir Debug\ExplorerPlugin.Resources\en.lproj"/> +if not exist "Release\Root\Program Files\Bonjour\ExplorerPlugin.Resources" mkdir "Release\Root\Program Files\Bonjour\ExplorerPlugin.Resources" +if not exist "Release\Root\Program Files\Bonjour\ExplorerPlugin.Resources\en.lproj" mkdir "Release\Root\Program Files\Bonjour\ExplorerPlugin.Resources\en.lproj""/> + CommandLine="if not exist Debug\ExplorerPlugin.Resources mkdir Debug\ExplorerPlugin.Resources"/> +if not exist "Release\Root\Program Files\Bonjour\ExplorerPlugin.Resources" mkdir "Release\Root\Program Files\Bonjour\ExplorerPlugin.Resources""/> 9$+*mOAE!yMxo5=X7f>ox9Du;ca+*@nnC1AKsrgA3opL=felS51-t< z0G&h;@arHipXNE}>Pi1Rc)xN<%992#@l3I{Ne4+EhFeX@fEiI+XVr*ZW1kKsx$-ln-G0hlgN4! zCW+T;zc~BLNXsW?PM&c8ND=L6FAOlC9G~R(!t_k-!pLjAu1>nYQ(o*;6)lgv2$?_7 z)74?LhQaES8+eXq<3UqsvT9}gja&Oz-CQd1t)K5;ii;lggQcOTena^tp^dIilT%d` zQWrG7Umkf$Xi6OLjn4Y}65rKSIbI84N{ASGz8@vGS8XKLw1#&t43rZ6kKC$zj`nL4 za;U4NQsQ;P8u%47^%V-u!5q80=`*JO(j=yEb>4P$+?-WF$Tz6F0@9E5NxXlJmQ|El zT8e2xm*o$Rcvj%kz?lHzx72uso|(VjYW!FdTtEHdbT*56aAm{0#Tl4O#f5BI$Yy}p ze+=c(ELdBV4R39~TmX~y15a|?wA Remove info icon from first page + Revision 1.3 2005/01/25 08:58:08 shersche Load icons at run-time from resource DLLs Bug #: 3911084 @@ -77,18 +80,6 @@ void CFirstPage::DoDataExchange(CDataExchange* pDX) BOOL CFirstPage::OnSetActive() { - static bool firstTime = true; - - if ( firstTime ) - { - CStatic * image = (CStatic*) GetDlgItem( IDC_INFO ); - check( image ); - - image->SetIcon( LoadIcon( GetNonLocalizedResources(), MAKEINTRESOURCE( IDI_INFO ) ) ); - - firstTime = false; - } - CPropertySheet* psheet = (CPropertySheet*) GetParent(); psheet->SetWizardButtons(PSWIZB_NEXT); diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp b/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp index 08a0505..7b65443 100644 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp @@ -23,6 +23,9 @@ Change History (most recent first): $Log: PrinterSetupWizardApp.cpp,v $ +Revision 1.8 2005/04/13 17:43:39 shersche + Change "PrinterWizard.dll" to "PrinterWizardResources.dll" + Revision 1.7 2005/02/15 07:50:09 shersche Update name @@ -123,7 +126,7 @@ BOOL CPrinterSetupWizardApp::InitInstance() // Load Resources - res = PathForResource( NULL, L"PrinterWizard.dll", resource, MAX_PATH ); + res = PathForResource( NULL, L"PrinterWizardResources.dll", resource, MAX_PATH ); err = translate_errno( res != 0, kUnknownErr, kUnknownErr ); require_noerr( err, exit ); diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc b/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc index 7a2842f..56319c3 100755 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc @@ -79,11 +79,11 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US IDD_ABOUTBOX DIALOGEX 0, 0, 235, 55 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "About Printer Setup Wizard" +CAPTION "About Printer Wizard" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN ICON 128,IDC_STATIC,11,17,20,20 - LTEXT "Printer Setup Wizard Version 1.0",IDC_STATIC,40,10,119, + LTEXT "Printer Wizard Version 1.0",IDC_STATIC,40,10,119, 8,SS_NOPREFIX LTEXT "Copyright (C) 2002",IDC_STATIC,40,25,119,8 DEFPUSHBUTTON "OK",IDOK,178,7,50,16,WS_GROUP @@ -93,7 +93,7 @@ IDD_PRINTERSETUPWIZARD_DIALOG DIALOGEX 0, 0, 320, 200 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Printer Setup Wizard" +CAPTION "Bonjour Printer Wizard" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,263,7,50,16 @@ -123,12 +123,11 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Bonjour Printer Wizard" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "Welcome to the Bonjour Printer Setup Wizard", + LTEXT "Welcome to the Bonjour Printer Wizard", IDC_GREETING,114,7,171,46 - LTEXT "Click next to continue.",IDC_STATIC,115,188,143,8 + LTEXT "To continue, click Next.",IDC_STATIC,115,188,143,8 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 + IDC_STATIC,114,60,171,62 END IDD_THIRD_PAGE DIALOGEX 0, 0, 290, 154 @@ -143,9 +142,9 @@ BEGIN CONTROL "",IDC_PRINTER_MANUFACTURER,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,2,58,105,76 - ICON 1017,1,0,0,20,27 + ICON 1017,1,3,5,20,27 LTEXT "",IDC_PRINTER_NAME,40,5,173,8 - LTEXT "The Bonjour Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer.", + LTEXT "The Bonjour Printer Wizard has auto-selected the following printer settings. To continue installing this printer, click Next.", IDC_PRINTER_SELECTION_TEXT,40,18,243,33 CONTROL "Use this printer as the default printer", IDC_DEFAULT_PRINTER,"Button",BS_AUTOCHECKBOX | @@ -160,20 +159,20 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Completing the Bonjour Printer Wizard",IDC_GOODBYE, 116,7,171,27 - LTEXT "You have successfully completed the Bonjour Printer Wizard. The printer has the following settings:", - IDC_STATIC,116,42,158,31 + LTEXT "You are ready to complete the Bonjour Printer Wizard. The printer has the following settings:", + IDC_STATIC,116,42,171,31 LTEXT "Name:",IDC_STATIC,116,78,22,8 LTEXT "Manufacturer:",IDC_STATIC,116,91,47,8 LTEXT "Model:",IDC_STATIC,116,104,22,8 LTEXT "Protocol:",IDC_STATIC,116,117,38,8 LTEXT "Default:",IDC_STATIC,116,130,27,8 - LTEXT "",IDC_PRINTER_NAME,172,78,113,8 + LTEXT "",IDC_PRINTER_NAME,172,78,113,8,SS_ENDELLIPSIS LTEXT "",IDC_PRINTER_MANUFACTURER,172,91,113,8 LTEXT "",IDC_PRINTER_MODEL,172,104,113,8 LTEXT "",IDC_PRINTER_PROTOCOL,172,117,113,8 LTEXT "",IDC_PRINTER_DEFAULT,172,130,113,8 - LTEXT "To close this wizard, click Finish.",IDC_STATIC,116,187, - 103,8 + LTEXT "To complete the installation, click Finish.",IDC_STATIC,116,187, + 171,8 END IDD_DIALOG1 DIALOGEX 0, 0, 265, 130 @@ -236,15 +235,15 @@ END STRINGTABLE BEGIN - IDS_ABOUTBOX "&About Printer Setup Wizard..." - IDS_GOODBYE "Completing the Bonjour Printer Setup Wizard." - IDS_GREETING "Welcome to the Bonjour Printer Setup Wizard" + IDS_ABOUTBOX "&About Bonjour Printer Wizard..." + IDS_GOODBYE "Completing the Bonjour Printer Wizard." + IDS_GREETING "Welcome to the Bonjour Printer Wizard" IDS_BROWSE_TITLE "Browse for Bonjour Printers" IDS_BROWSE_SUBTITLE "Select the printer you want to use from the list below." IDS_CAPTION "Bonjour Printer Wizard" - IDS_GOODBYE_GOOD1 "You have successfully completed the Bonjour Printer Wizard. The printer has the following settings:" + IDS_GOODBYE_GOOD1 "You are ready to complete 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_GOODBYTE_GOOD2 "To complete the installation, click Finish." IDS_INSTALL_TITLE "Install Bonjour Printer" IDS_INSTALL_SUBTITLE "The manufacturer and model determine which printer software to use." END diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj b/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj index c97e842..c8ea960 100755 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj @@ -12,7 +12,7 @@ +if not exist "Release\Root\Program Files\Bonjour\PrinterWizard.Resources" mkdir "Release\Root\Program Files\Bonjour\PrinterWizard.Resources" +if not exist "Release\Root\Program Files\Bonjour\PrinterWizard.Resources\en.lproj" mkdir "Release\Root\Program Files\Bonjour\PrinterWizard.Resources\en.lproj""/> + CommandLine="if not exist Debug\PrinterWizard.Resources mkdir Debug\PrinterWizard.Resources"/> +if not exist "Release\Root\Program Files\Bonjour\PrinterWizard.Resources" mkdir "Release\Root\Program Files\Bonjour\PrinterWizard.Resources""/> Generic PCL not selected when printers advertise multiple text records + Revision 1.29 2005/02/14 20:48:37 shersche Default pdl key to "application/postscript" @@ -445,7 +448,7 @@ CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * s pInfo.pPortName = printer->portName.GetBuffer(); pInfo.pDriverName = printer->modelName.GetBuffer(); pInfo.pComment = printer->displayModelName.GetBuffer(); - pInfo.pLocation = service->location.GetBuffer(); + pInfo.pLocation = q->location.GetBuffer(); pInfo.pDevMode = NULL; pInfo.pDevMode = NULL; pInfo.pSepFile = L""; @@ -489,9 +492,12 @@ CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service { DEBUG_UNUSED( service ); + Queue * q = service->SelectedQueue(); HANDLE hPrinter = NULL; PRINTER_INFO_2 pInfo; OSStatus err; + + check( q ); // // add the printer @@ -502,7 +508,7 @@ CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service pInfo.pPortName = printer->portName.GetBuffer(); pInfo.pDriverName = printer->modelName.GetBuffer(); pInfo.pPrintProcessor = L"winprint"; - pInfo.pLocation = service->location.GetBuffer(); + pInfo.pLocation = q->location.GetBuffer(); pInfo.pComment = printer->displayModelName.GetBuffer(); pInfo.Attributes = PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL; @@ -886,8 +892,6 @@ CPrinterSetupWizardSheet::OnResolve( CPrinterSetupWizardSheet * self; Service * service; Queue * q; - uint32_t qpriority = kDefaultPriority; - CString qname; int idx; OSStatus err; @@ -925,13 +929,6 @@ CPrinterSetupWizardSheet::OnResolve( // service->portNumber = ntohs(inPort); - // - // parse the text record. - // - - err = self->ParseTextRecord( service, inTXTSize, inTXT, qname, qpriority ); - require_noerr( err, exit ); - if ( service->qtotal == 1 ) { // @@ -948,10 +945,13 @@ CPrinterSetupWizardSheet::OnResolve( require_action( q, exit, err = E_OUTOFMEMORY ); + // + // parse the text record. + // + + err = self->ParseTextRecord( service, q, inTXTSize, inTXT ); + require_noerr( err, exit ); - q->name = qname; - q->priority = qpriority; - service->queues.push_back( q ); // @@ -1033,7 +1033,7 @@ CPrinterSetupWizardSheet::OnQuery( require_action( q, exit, err = E_OUTOFMEMORY ); - err = service->printer->window->ParseTextRecord( service, inRDLen, inTXT, q->name, q->priority ); + err = service->printer->window->ParseTextRecord( service, q, inRDLen, inTXT ); require_noerr( err, exit ); // @@ -1512,8 +1512,11 @@ exit: OSStatus -CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, CString & qname, uint32_t & qpriority ) +CPrinterSetupWizardSheet::ParseTextRecord( Service * service, Queue * q, uint16_t inTXTSize, const char * inTXT ) { + check( service ); + check( q ); + // Use TXTRecord APIs declared in dns_sd.h bool qtotalDefined = false; @@ -1524,11 +1527,11 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize // Default to queue "lp" - qname = L"lp"; + q->name = L"lp"; // Default pdl key to be "application/postscript" - service->pdl = L"application/postscript"; + q->pdl = L"application/postscript"; if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "rp", &len ) ) != NULL ) { @@ -1537,7 +1540,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize memcpy( buf, val, len ); buf[len] = '\0'; - err = UTF8StringToStringObject( buf, qname ); + err = UTF8StringToStringObject( buf, q->name ); require_noerr( err, exit ); } @@ -1548,7 +1551,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize memcpy( buf, val, len ); buf[len] = '\0'; - err = UTF8StringToStringObject( buf, service->pdl ); + err = UTF8StringToStringObject( buf, q->pdl ); require_noerr( err, exit ); } @@ -1560,7 +1563,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize memcpy( buf, val, len ); buf[len] = '\0'; - err = UTF8StringToStringObject( buf, service->usb_MFG ); + err = UTF8StringToStringObject( buf, q->usb_MFG ); require_noerr( err, exit ); } @@ -1572,7 +1575,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize memcpy( buf, val, len ); buf[len] = '\0'; - err = UTF8StringToStringObject( buf, service->usb_MDL ); + err = UTF8StringToStringObject( buf, q->usb_MDL ); require_noerr( err, exit ); } @@ -1583,7 +1586,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize memcpy( buf, val, len ); buf[len] = '\0'; - err = UTF8StringToStringObject( buf, service->description ); + err = UTF8StringToStringObject( buf, q->description ); require_noerr( err, exit ); } @@ -1594,7 +1597,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize memcpy( buf, val, len ); buf[len] = '\0'; - err = UTF8StringToStringObject( buf, service->product ); + err = UTF8StringToStringObject( buf, q->product ); require_noerr( err, exit ); } @@ -1605,7 +1608,7 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize memcpy( buf, val, len ); buf[len] = '\0'; - err = UTF8StringToStringObject( buf, service->location ); + err = UTF8StringToStringObject( buf, q->location ); require_noerr( err, exit ); } @@ -1627,20 +1630,20 @@ CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize memcpy( buf, val, len ); buf[len] = '\0'; - qpriority = atoi( buf ); + q->priority = 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" + // record. We'll check to see if the q->name is "TEXT" // and if so, we're going to modify it to be "lp" so // that we don't use the wrong queue - if ( !err && !qtotalDefined && ( qname == L"TEXT" ) ) + if ( !err && !qtotalDefined && ( q->name == L"TEXT" ) ) { - qname = "lp"; + q->name = "lp"; } return err; diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h index cf7f096..3bf77a6 100644 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: PrinterSetupWizardSheet.h,v $ +Revision 1.9 2005/04/13 17:46:22 shersche + Generic PCL not selected when printers advertise multiple text records + Revision 1.8 2005/02/08 18:53:33 shersche Remove qtotalDefined parameter from ParseTextRecord() @@ -241,7 +244,7 @@ private: StopResolve( Service * service ); OSStatus - ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, CString & qname, uint32_t & qpriority ); + ParseTextRecord( Service * service, Queue * q, uint16_t inTXTSize, const char * inTXT ); OSStatus LoadPrinterNames(); diff --git a/Clients/PrinterSetupWizard/SecondPage.cpp b/Clients/PrinterSetupWizard/SecondPage.cpp index 63665ee..f5647a6 100644 --- a/Clients/PrinterSetupWizard/SecondPage.cpp +++ b/Clients/PrinterSetupWizard/SecondPage.cpp @@ -23,6 +23,12 @@ Change History (most recent first): $Log: SecondPage.cpp,v $ +Revision 1.15 2005/04/13 17:46:22 shersche + Generic PCL not selected when printers advertise multiple text records + +Revision 1.14 2005/03/20 20:08:37 shersche + Second screen should not select a printer by default + Revision 1.13 2005/02/15 07:50:10 shersche Update name @@ -131,6 +137,13 @@ CSecondPage::InitBrowseList() // disable the printer information box // SetPrinterInformationState( FALSE ); + m_descriptionField.SetWindowText( L"" ); + m_locationField.SetWindowText( L"" ); + + // + // and wait for the user to either hit the mouse or keyboard before selecting an item + // + m_gotChoice = false; exit: @@ -182,6 +195,9 @@ CSecondPage::OnSetActive() Printer * printer; Printers::iterator it; OSStatus err = kNoErr; + BOOL b; + + b = CPropertyPage::OnSetActive(); psheet = reinterpret_cast(GetParent()); require_action( psheet, exit, err = kUnknownErr ); @@ -207,7 +223,7 @@ CSecondPage::OnSetActive() exit: - return CPropertyPage::OnSetActive(); + return b; } @@ -220,6 +236,8 @@ CSecondPage::OnKillActive() BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage) ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList) + ON_NOTIFY(NM_CLICK, IDC_BROWSE_LIST, OnNmClickBrowseList) + ON_NOTIFY(TVN_KEYDOWN, IDC_BROWSE_LIST, OnTvnKeyDownBrowseList) ON_WM_SETCURSOR() END_MESSAGE_MAP() @@ -245,11 +263,6 @@ CSecondPage::OnAddPrinter( m_browseList.SetItemData( printer->item, (DWORD_PTR) printer ); m_browseList.SortChildren(TVI_ROOT); - - if ( printer->name == m_selectedName ) - { - m_browseList.SelectItem( printer->item ); - } // // if the searching item is still in the list @@ -333,9 +346,14 @@ CSecondPage::OnResolveService( Service * service ) { CPrinterSetupWizardSheet * psheet = reinterpret_cast(GetParent()); require_quiet( psheet, exit ); - + check( service ); + Queue * q = service->SelectedQueue(); + + check( q ); + + // // and set it to selected // @@ -347,8 +365,8 @@ CSecondPage::OnResolveService( Service * service ) // SetPrinterInformationState( TRUE ); - m_descriptionField.SetWindowText( service->description ); - m_locationField.SetWindowText( service->location ); + m_descriptionField.SetWindowText( q->description ); + m_locationField.SetWindowText( q->location ); // // reset the cursor @@ -366,15 +384,43 @@ void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult) { LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR); CPrinterSetupWizardSheet * psheet; + Printer * printer; int err = 0; - HTREEITEM item = m_browseList.GetSelectedItem(); - require_quiet( item, exit ); - psheet = reinterpret_cast(GetParent()); - require_action( psheet, exit, err = kUnknownErr ); + require_action( psheet, exit, err = kUnknownErr ); + + // The strange code here is to workaround a bug in the CTreeCtrl, whereupon the item + // we selected isn't passed through correctly to this callback routine. + + if ( !m_gotChoice ) + { + printer = psheet->GetSelectedPrinter(); + + // If we really haven't selected a printer, then re-select NULL and exit + + if ( !printer ) + { + m_browseList.SelectItem( NULL ); - Printer * printer; + goto exit; + } + + // If we already have selected a printer, fake like we've clicked on it, but only + // if the CTreeCtrl hasn't already selected it + + else if ( printer->item != m_browseList.GetSelectedItem() ) + { + m_gotChoice = true; + + m_browseList.SelectItem( printer->item ); + + goto exit; + } + } + + HTREEITEM item = m_browseList.GetSelectedItem(); + require_quiet( item, exit ); printer = reinterpret_cast(m_browseList.GetItemData( item ) ); require_quiet( printer, exit ); @@ -410,6 +456,26 @@ exit: } +void CSecondPage::OnNmClickBrowseList(NMHDR *pNMHDR, LRESULT *pResult) +{ + DEBUG_UNUSED( pNMHDR ); + + m_gotChoice = true; + + *pResult = 0; +} + + +void CSecondPage::OnTvnKeyDownBrowseList( NMHDR * pNMHDR, LRESULT * pResult) +{ + DEBUG_UNUSED( pNMHDR ); + + m_gotChoice = true; + + *pResult = 0; +} + + void CSecondPage::LoadTextAndDisableWindow( CString & text ) { diff --git a/Clients/PrinterSetupWizard/SecondPage.h b/Clients/PrinterSetupWizard/SecondPage.h index aa08260..5cf1852 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.8 2005/03/20 20:08:37 shersche + Second screen should not select a printer by default + 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. @@ -95,6 +98,8 @@ public: bool m_waiting; afx_msg void OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnNmClickBrowseList(NMHDR * pNMHDR, LRESULT * pResult); + afx_msg void OnTvnKeyDownBrowseList(NMHDR * pNMHDR, LRESULT * pResult ); OSStatus OnAddPrinter( @@ -126,4 +131,6 @@ private: CStatic m_descriptionField; CStatic m_locationLabel; CStatic m_locationField; + + bool m_gotChoice; }; diff --git a/Clients/PrinterSetupWizard/ThirdPage.cpp b/Clients/PrinterSetupWizard/ThirdPage.cpp index acd8d3c..8da4d40 100644 --- a/Clients/PrinterSetupWizard/ThirdPage.cpp +++ b/Clients/PrinterSetupWizard/ThirdPage.cpp @@ -23,6 +23,15 @@ Change History (most recent first): $Log: ThirdPage.cpp,v $ +Revision 1.23 2005/04/18 02:33:47 shersche + Default printer option cannot be deselected + +Revision 1.22 2005/04/13 17:46:22 shersche + Generic PCL not selected when printers advertise multiple text records + +Revision 1.21 2005/03/30 02:09:55 shersche +Auto-resize the column width to account for differing fonts and font sizes + Revision 1.20 2005/03/05 02:27:45 shersche Generic drivers don't do color @@ -1039,20 +1048,27 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print CString text; OSStatus err = kNoErr; + check( printer ); + check( service ); + + Queue * q = service->SelectedQueue(); + + check( q ); + // // first look to see if we have a usb_MFG descriptor // - if (service->usb_MFG.GetLength() > 0) + if ( q->usb_MFG.GetLength() > 0) { - manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( service->usb_MFG ) ); + manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( q->usb_MFG ) ); } if ( manufacturer == NULL ) { - service->product.Remove('('); - service->product.Remove(')'); + q->product.Remove('('); + q->product.Remove(')'); - manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( service->product ) ); + manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( q->product ) ); } // @@ -1060,17 +1076,17 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print // if ( manufacturer != NULL ) { - if (service->usb_MDL.GetLength() > 0) + if ( q->usb_MDL.GetLength() > 0 ) { - model = MatchModel ( manufacturer, ConvertToModelName ( service->usb_MDL ) ); + model = MatchModel ( manufacturer, ConvertToModelName ( q->usb_MDL ) ); } - if ( ( model == NULL ) && ( service->product.GetLength() > 0 ) ) + if ( ( model == NULL ) && ( q->product.GetLength() > 0 ) ) { - service->product.Remove('('); - service->product.Remove(')'); + q->product.Remove('('); + q->product.Remove(')'); - model = MatchModel ( manufacturer, ConvertToModelName ( service->product ) ); + model = MatchModel ( manufacturer, ConvertToModelName ( q->product ) ); } if ( model != NULL ) @@ -1254,12 +1270,18 @@ CThirdPage::MatchGeneric( Printer * printer, Service * service, Manufacturer ** DEBUG_UNUSED( printer ); + check( service ); + + Queue * q = service->SelectedQueue(); + + check( q ); + Manufacturers::iterator iter = m_manufacturers.find( kGenericManufacturer ); require_action_quiet( iter != m_manufacturers.end(), exit, ok = FALSE ); *manufacturer = iter->second; - pdl = service->pdl; + pdl = q->pdl; pdl.MakeLower(); if ( pdl.Find( kPDLPCLKey ) != -1 ) @@ -1323,11 +1345,11 @@ OSStatus CThirdPage::OnInitPage() // selection notice // header.LoadString(IDS_MANUFACTURER_HEADING); - m_manufacturerListCtrl.InsertColumn(0, header, LVCFMT_LEFT, 138); + m_manufacturerListCtrl.InsertColumn(0, header, LVCFMT_LEFT, -1 ); m_manufacturerSelected = NULL; header.LoadString(IDS_MODEL_HEADING); - m_modelListCtrl.InsertColumn(0, header, LVCFMT_LEFT, 247); + m_modelListCtrl.InsertColumn(0, header, LVCFMT_LEFT, -1 ); m_modelSelected = NULL; return (err); @@ -1431,6 +1453,8 @@ CThirdPage::PopulateUI(Manufacturers & manufacturers) nIndex = m_manufacturerListCtrl.InsertItem(0, manufacturer->name); m_manufacturerListCtrl.SetItemData(nIndex, (DWORD_PTR) manufacturer); + + m_manufacturerListCtrl.SetColumnWidth( 0, LVSCW_AUTOSIZE_USEHEADER ); } return 0; @@ -1471,6 +1495,8 @@ void CThirdPage::OnLvnItemchangedManufacturer(NMHDR *pNMHDR, LRESULT *pResult) int nItem = m_modelListCtrl.InsertItem( 0, model->displayName ); m_modelListCtrl.SetItemData(nItem, (DWORD_PTR) model); + + m_modelListCtrl.SetColumnWidth( 0, LVSCW_AUTOSIZE_USEHEADER ); } m_modelListCtrl.SetRedraw(TRUE); @@ -1531,7 +1557,7 @@ void CThirdPage::OnBnClickedDefaultPrinter() printer = psheet->GetSelectedPrinter(); require_quiet( printer, exit ); - printer->deflt = m_defaultPrinterCtrl.GetState() ? true : false; + printer->deflt = ( m_defaultPrinterCtrl.GetCheck() == BST_CHECKED ) ? true : false; exit: diff --git a/Clients/PrinterSetupWizard/UtilTypes.h b/Clients/PrinterSetupWizard/UtilTypes.h index 5e2fe19..4496e0c 100644 --- a/Clients/PrinterSetupWizard/UtilTypes.h +++ b/Clients/PrinterSetupWizard/UtilTypes.h @@ -23,6 +23,12 @@ Change History (most recent first): $Log: UtilTypes.h,v $ +Revision 1.13 2005/04/13 17:46:22 shersche + Generic PCL not selected when printers advertise multiple text records + +Revision 1.12 2005/03/16 03:12:28 shersche + Generic PCL driver isn't selected correctly on Win2K + Revision 1.11 2005/03/05 02:27:46 shersche Generic drivers don't do color @@ -149,6 +155,9 @@ namespace PrinterSetupWizard ~Service(); + Queue* + SelectedQueue(); + void EmptyQueues(); @@ -163,12 +172,6 @@ namespace PrinterSetupWizard DNSServiceRef serviceRef; CString hostname; unsigned short portNumber; - CString pdl; - CString usb_MFG; - CString usb_MDL; - CString description; - CString location; - CString product; CString protocol; unsigned short qtotal; @@ -194,6 +197,12 @@ namespace PrinterSetupWizard CString name; uint32_t priority; + CString pdl; + CString usb_MFG; + CString usb_MDL; + CString description; + CString location; + CString product; }; @@ -269,6 +278,12 @@ namespace PrinterSetupWizard EmptyQueues(); } + inline Queue* + Service::SelectedQueue() + { + return queues.front(); + } + inline void Service::EmptyQueues() { @@ -301,7 +316,7 @@ namespace PrinterSetupWizard { Model * model = *it; - if ( model->name = name ) + if ( model->name == name ) { return model; } diff --git a/Clients/PrinterSetupWizard/res/NetworkPrinter.ico b/Clients/PrinterSetupWizard/res/NetworkPrinter.ico index 22130b3de3ee242e78b347bc07d177cf3cd44a10..b737f473253cde006f562cdca30f025db8646439 100644 GIT binary patch literal 82726 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 diff --git a/Clients/PrinterSetupWizard/res/Print.ico b/Clients/PrinterSetupWizard/res/Print.ico index 22130b3de3ee242e78b347bc07d177cf3cd44a10..b737f473253cde006f562cdca30f025db8646439 100644 GIT binary patch literal 82726 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 diff --git a/Clients/dns-sd.c b/Clients/dns-sd.c index 699a932..2fdc66f 100644 --- a/Clients/dns-sd.c +++ b/Clients/dns-sd.c @@ -550,7 +550,7 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef, for (i = 0; i < argc; i++) { unsigned char *len = ptr++; - *len = strlen(argv[i]); + *len = (unsigned char) strlen(argv[i]); strcpy((char*)ptr, argv[i]); ptr += *len; } @@ -558,7 +558,7 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef, printf("Registering Service %s.%s%s", nam, typ, dom); if (host && *host) printf(" host %s", host); printf(" port %s %s\n", port, txt); - return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, ptr-txt, txt, reg_reply, NULL)); + return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, (uint16_t) (ptr-txt), txt, reg_reply, NULL)); } int main(int argc, char **argv) @@ -584,6 +584,14 @@ int main(int argc, char **argv) printf("Using LocalOnly\n"); } + if (argc > 2 && !strcmp(argv[1], "-i") && atoi(argv[2])) + { + opinterface = atoi(argv[2]); + argc -= 2; + argv += 2; + printf("Using interface %d\n", opinterface); + } + if (argc < 2) goto Fail; // Minimum command line is the command name and one argument operation = getfirstoption( argc, argv, "EFBLQRPAUNTMI", &optind); if (operation == -1) goto Fail; diff --git a/Makefile b/Makefile index 0497542..924853b 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ include /Developer/Makefiles/pb_makefiles/platform.make -MVERS = "mDNSResponder-107" +MVERS = "mDNSResponder-107.1" install: cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) diff --git a/mDNSCore/DNSCommon.c b/mDNSCore/DNSCommon.c index a2039b9..2ce2489 100644 --- a/mDNSCore/DNSCommon.c +++ b/mDNSCore/DNSCommon.c @@ -23,6 +23,15 @@ Change History (most recent first): $Log: DNSCommon.c,v $ +Revision 1.90 2005/03/21 00:33:51 shersche + Fix build warnings on Win32 platform + +Revision 1.89 2005/03/17 18:59:38 ksekar + Properly parse multiple LLQ Options per packet on Windows + +Revision 1.88 2005/03/16 00:42:32 ksekar + Long-lived queries not working on Windows + Revision 1.87 2005/02/25 04:21:00 cheshire mDNS -F returns the same domain multiple times with different casing @@ -1028,7 +1037,7 @@ mDNSexport void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichT while (val >= divisor * 10) { divisor *= 10; chars++; } - name->c[0] = TruncateUTF8ToLength(name->c+1, name->c[0], MAX_DOMAIN_LABEL - chars); + name->c[0] = (mDNSu8) 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]] = '-'; } @@ -1342,14 +1351,14 @@ mDNSlocal mDNSu8 *putOptRData(mDNSu8 *ptr, const mDNSu8 *limit, ResourceRecord * nput += 2 * sizeof(mDNSu16); if (opt->opt == kDNSOpt_LLQ) { - if (ptr + sizeof(LLQOptData) > limit) goto space_err; + if (ptr + LLQ_OPTLEN > limit) goto space_err; ptr = putVal16(ptr, opt->OptData.llq.vers); ptr = putVal16(ptr, opt->OptData.llq.llqOp); ptr = putVal16(ptr, opt->OptData.llq.err); mDNSPlatformMemCopy(opt->OptData.llq.id, ptr, 8); // 8-byte id ptr += 8; ptr = putVal32(ptr, opt->OptData.llq.lease); - nput += sizeof(LLQOptData); + nput += LLQ_OPTLEN; } else if (opt->opt == kDNSOpt_Lease) { @@ -1377,11 +1386,10 @@ mDNSlocal mDNSu16 getVal16(const mDNSu8 **ptr) mDNSlocal const mDNSu8 *getOptRdata(const mDNSu8 *ptr, const mDNSu8 *limit, ResourceRecord *rr, mDNSu16 pktRDLen) { int nread = 0; - rdataOpt *opt; - - while (nread < pktRDLen) + rdataOpt *opt = (rdataOpt *)rr->rdata->u.data; + + while (nread < pktRDLen && (mDNSu8 *)opt < rr->rdata->u.data + MaximumRDSize - sizeof(rdataOpt)) { - opt = (rdataOpt *)(rr->rdata->u.data + nread); // space for opt + optlen if (nread + (2 * sizeof(mDNSu16)) > rr->rdata->MaxRDLength) goto space_err; opt->opt = getVal16(&ptr); @@ -1389,7 +1397,7 @@ mDNSlocal const mDNSu8 *getOptRdata(const mDNSu8 *ptr, const mDNSu8 *limit, Reso nread += 2 * sizeof(mDNSu16); if (opt->opt == kDNSOpt_LLQ) { - if ((unsigned)(limit - ptr) < sizeof(LLQOptData)) goto space_err; + if ((unsigned)(limit - ptr) < LLQ_OPTLEN) goto space_err; opt->OptData.llq.vers = getVal16(&ptr); opt->OptData.llq.llqOp = getVal16(&ptr); opt->OptData.llq.err = getVal16(&ptr); @@ -1399,7 +1407,7 @@ mDNSlocal const mDNSu8 *getOptRdata(const mDNSu8 *ptr, const mDNSu8 *limit, Reso if (opt->OptData.llq.lease > 0x70000000UL / mDNSPlatformOneSecond) opt->OptData.llq.lease = 0x70000000UL / mDNSPlatformOneSecond; ptr += sizeof(mDNSOpaque32); - nread += sizeof(LLQOptData); + nread += LLQ_OPTLEN; } else if (opt->opt == kDNSOpt_Lease) { @@ -1412,6 +1420,7 @@ mDNSlocal const mDNSu8 *getOptRdata(const mDNSu8 *ptr, const mDNSu8 *limit, Reso nread += sizeof(mDNSs32); } else { LogMsg("ERROR: getOptRdata - unknown opt %d", opt->opt); return mDNSNULL; } + opt++; // increment pointer into rdatabody } rr->rdlength = pktRDLen; @@ -1629,8 +1638,8 @@ mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease) opt->RecordType = kDNSRecordTypeKnownUnique; // to avoid warnings in other layers opt->rrtype = kDNSType_OPT; - opt->rdlength = LEASE_OPT_SIZE; - opt->rdestimate = LEASE_OPT_SIZE; + opt->rdlength = LEASE_OPT_RDLEN; + opt->rdestimate = LEASE_OPT_RDLEN; optRD = &rr.resrec.rdata->u.opt; optRD->opt = kDNSOpt_Lease; diff --git a/mDNSCore/DNSCommon.h b/mDNSCore/DNSCommon.h index 1b11e11..13b7ca8 100644 --- a/mDNSCore/DNSCommon.h +++ b/mDNSCore/DNSCommon.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: DNSCommon.h,v $ +Revision 1.32 2005/03/21 00:33:51 shersche + Fix build warnings on Win32 platform + Revision 1.31 2005/02/18 00:43:11 cheshire mDNSResponder should auto-truncate service names that are too long @@ -314,7 +317,7 @@ extern const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8 *pt extern const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end); extern const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage * const msg, const mDNSu8 *ptr, - const mDNSu8 * const end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *largecr); + const mDNSu8 * end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *largecr); extern const mDNSu8 *skipQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end); diff --git a/mDNSCore/mDNS.c b/mDNSCore/mDNS.c index d89a42b..e68c865 100755 --- a/mDNSCore/mDNS.c +++ b/mDNSCore/mDNS.c @@ -45,6 +45,9 @@ Change History (most recent first): $Log: mDNS.c,v $ +Revision 1.523 2005/03/21 00:33:51 shersche + Fix build warnings on Win32 platform + Revision 1.522 2005/03/04 21:48:12 cheshire Fractional time rounded down instead of up on platforms with coarse clock granularity @@ -3136,7 +3139,7 @@ mDNSlocal void SendResponses(mDNS *const m) newptr = PutResourceRecordTTL(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, m->SleepState ? 0 : rr->resrec.rroriginalttl); rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear cache flush bit back to normal state if (!newptr && m->omsg.h.numAnswers) break; - rr->RequireGoodbye = !m->SleepState; + rr->RequireGoodbye = (mDNSu8) (!m->SleepState); if (rr->LastAPTime == m->timenow) numAnnounce++; else numAnswer++; responseptr = newptr; } diff --git a/mDNSCore/mDNSEmbeddedAPI.h b/mDNSCore/mDNSEmbeddedAPI.h index 852322f..70439f3 100755 --- a/mDNSCore/mDNSEmbeddedAPI.h +++ b/mDNSCore/mDNSEmbeddedAPI.h @@ -60,6 +60,9 @@ Change History (most recent first): $Log: mDNSEmbeddedAPI.h,v $ +Revision 1.282 2005/03/16 00:42:32 ksekar + Long-lived queries not working on Windows + Revision 1.281 2005/02/25 17:47:44 ksekar SendServiceRegistration fails on wake from sleep @@ -1367,6 +1370,11 @@ typedef packedstruct mDNSu32 lease; } LLQOptData; +#define LLQ_OPTLEN ((3 * sizeof(mDNSu16)) + 8 + sizeof(mDNSu32)) +// Windows adds pad bytes to sizeof(LLQOptData). Use this macro when setting length fields or validating option rdata from +// off the wire. Use sizeof(LLQOptData) when dealing with structures (e.g. memcpy). Never memcpy between on-the-wire +// representation and a structure + // NOTE: rdataOpt format may be repeated an arbitrary number of times in a single resource record typedef packedstruct { @@ -1773,8 +1781,8 @@ typedef struct #define kLLQOp_Refresh 2 #define kLLQOp_Event 3 -#define LLQ_OPT_SIZE (2 * sizeof(mDNSu16)) + sizeof(LLQOptData) -#define LEASE_OPT_SIZE (2 * sizeof(mDNSu16)) + sizeof(mDNSs32) +#define LLQ_OPT_RDLEN ((2 * sizeof(mDNSu16)) + LLQ_OPTLEN) +#define LEASE_OPT_RDLEN (2 * sizeof(mDNSu16)) + sizeof(mDNSs32) // LLQ Errror Codes enum diff --git a/mDNSCore/uDNS.c b/mDNSCore/uDNS.c index e9d0991..f4ca818 100755 --- a/mDNSCore/uDNS.c +++ b/mDNSCore/uDNS.c @@ -23,6 +23,16 @@ Change History (most recent first): $Log: uDNS.c,v $ +Revision 1.206 2005/03/31 02:19:55 cheshire + Fix build warnings +Reviewed by: Scott Herscher + +Revision 1.205 2005/03/21 00:33:51 shersche + Fix build warnings on Win32 platform + +Revision 1.204 2005/03/16 00:42:32 ksekar + Long-lived queries not working on Windows + Revision 1.203 2005/03/04 03:00:03 ksekar Retransmissions happen too early, causing registrations to conflict with themselves @@ -2425,7 +2435,7 @@ mDNSlocal void SetUpdateExpiration(mDNS *m, DNSMessage *msg, const mDNSu8 *end, if (!ptr) break; if (lcr.r.resrec.rrtype == kDNSType_OPT) { - if (lcr.r.resrec.rdlength < LEASE_OPT_SIZE) continue; + if (lcr.r.resrec.rdlength < LEASE_OPT_RDLEN) continue; if (lcr.r.resrec.rdata->u.opt.opt != kDNSOpt_Lease) continue; lease = lcr.r.resrec.rdata->u.opt.OptData.lease; break; @@ -2616,13 +2626,13 @@ mDNSlocal mDNSu8 *putLLQ(DNSMessage *const msg, mDNSu8 *ptr, DNSQuestion *questi // format opt rr (fields not specified are zero-valued) ubzero(&rr, sizeof(AuthRecord)); mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL); - opt->rdlength = LLQ_OPT_SIZE; - opt->rdestimate = LLQ_OPT_SIZE; + opt->rdlength = LLQ_OPT_RDLEN; + opt->rdestimate = LLQ_OPT_RDLEN; optRD = &rr.resrec.rdata->u.opt; optRD->opt = kDNSOpt_LLQ; - optRD->optlen = sizeof(LLQOptData); - umemcpy(&optRD->OptData.llq, data, sizeof(LLQOptData)); + optRD->optlen = LLQ_OPTLEN; + umemcpy(&optRD->OptData.llq, data, sizeof(*data)); ptr = PutResourceRecordTTLJumbo(msg, ptr, &msg->h.numAdditionals, opt, 0); if (!ptr) { LogMsg("ERROR: putLLQ - PutResourceRecordTTLJumbo"); return mDNSNULL; } @@ -2636,17 +2646,19 @@ mDNSlocal mDNSBool getLLQAtIndex(mDNS *m, DNSMessage *msg, const mDNSu8 *end, LL int i; const mDNSu8 *ptr; + ubzero(&lcr, sizeof(lcr)); + ptr = LocateAdditionals(msg, end); if (!ptr) return mDNSfalse; - + // find the last additional for (i = 0; i < msg->h.numAdditionals; i++) // { ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); if (!ptr) return mDNSfalse; } //!!!KRS workaround for LH server bug, which puts OPT as first additional { ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); if (!ptr) return mDNSfalse; if (lcr.r.resrec.rrtype == kDNSType_OPT) break; } if (lcr.r.resrec.rrtype != kDNSType_OPT) return mDNSfalse; - if (lcr.r.resrec.rdlength < (index + 1) * LLQ_OPT_SIZE) return mDNSfalse; // rdata too small - umemcpy(llq, (mDNSu8 *)&lcr.r.resrec.rdata->u.opt.OptData.llq + (index * sizeof(LLQOptData)), sizeof(LLQOptData)); // !!! Should convert to host byte order? + if (lcr.r.resrec.rdlength < (index + 1) * LLQ_OPT_RDLEN) return mDNSfalse; // rdata too small + umemcpy(llq, (mDNSu8 *)&lcr.r.resrec.rdata->u.opt.OptData.llq + (index * sizeof(*llq)), sizeof(*llq)); return mDNStrue; } @@ -3949,6 +3961,8 @@ mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs) AuthRecord *srv = &srs->RR_SRV; mDNSu32 i; + privport = zeroIPPort; + if (!rInfo->ns.ip.v4.NotAnInteger) { LogMsg("SendServiceRegistration - NS not set!"); return; } id = newMessageID(u); @@ -4950,14 +4964,14 @@ mDNSexport void uDNS_Init(mDNS *const m) m->uDNS_info.nextevent = m->timenow_last + 0x78000000; } -mDNSexport void uDNS_Sleep(mDNS *m) +mDNSexport void uDNS_Sleep(mDNS *const m) { SuspendLLQs(m, mDNStrue); SleepServiceRegistrations(m); SleepRecordRegistrations(m); } -mDNSexport void uDNS_Wake(mDNS *m) +mDNSexport void uDNS_Wake(mDNS *const m) { RestartQueries(m); WakeServiceRegistrations(m); diff --git a/mDNSCore/uDNS.h b/mDNSCore/uDNS.h index 85b68d5..616d712 100755 --- a/mDNSCore/uDNS.h +++ b/mDNSCore/uDNS.h @@ -23,6 +23,10 @@ Change History (most recent first): $Log: uDNS.h,v $ +Revision 1.31 2005/03/31 02:19:56 cheshire + Fix build warnings +Reviewed by: Scott Herscher + Revision 1.30 2005/03/04 03:00:03 ksekar Retransmissions happen too early, causing registrations to conflict with themselves @@ -147,9 +151,9 @@ extern mStatus uDNS_StartQuery(mDNS *const m, DNSQuestion *const question); extern mDNSBool uDNS_IsActiveQuery(DNSQuestion *const question, uDNS_GlobalInfo *u); // returns true if OK to call StopQuery extern mStatus uDNS_StopQuery(mDNS *const m, DNSQuestion *const question); -extern void uDNS_Init(mDNS *m); -extern void uDNS_Sleep(mDNS *m); -extern void uDNS_Wake(mDNS *m); +extern void uDNS_Init(mDNS *const m); +extern void uDNS_Sleep(mDNS *const m); +extern void uDNS_Wake(mDNS *const m); #define uDNS_Close uDNS_Sleep // uDNS_UpdateRecord diff --git a/mDNSMacOS9/mDNSLibraryResources.r b/mDNSMacOS9/mDNSLibraryResources.r index a518d9d..ab3b345 100644 --- a/mDNSMacOS9/mDNSLibraryResources.r +++ b/mDNSMacOS9/mDNSLibraryResources.r @@ -23,6 +23,9 @@ Change History (most recent first): $Log: mDNSLibraryResources.r,v $ +Revision 1.32 2005/05/05 00:06:58 ksekar +Update version string to 1.0a107.1 + Revision 1.31 2005/03/15 02:14:14 cheshire mDNSResponder-107 @@ -134,15 +137,15 @@ like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code resource 'vers' (1, purgeable) { - 0x01, 0x00, alpha, 107, verUS, - "1.0a107", - "Multicast DNS & DNS Service Discovery 1.0a107" + 0x01, 0x00, alpha, 107.1, verUS, + "1.0a107.1", + "Multicast DNS & DNS Service Discovery 1.0a107.1" }; resource 'vers' (2, purgeable) { - 0x01, 0x00, alpha, 107, verUS, - "1.0a107", + 0x01, 0x00, alpha, 107.1, verUS, + "1.0a107.1", "developer.apple.com/darwin/projects/bonjour/" }; diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns b/mDNSMacOSX/PreferencePane/BonjourPref.icns similarity index 56% rename from mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns rename to mDNSMacOSX/PreferencePane/BonjourPref.icns index 028a3a2d883e2a9be53e1bdd6b96c0cc57520edb..97b560f6e303dff0cf5b1151c411dd18d4eafae0 100644 GIT binary patch delta 5845 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 TznELR<@KV?VF36s!RzziY3ZbN literal 0 HcmV?d00001 diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff deleted file mode 100644 index 985ae197b065eec4b20bd10cd963749f05e48bb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17394 zcmYhCX*kqh8^?dMm>G;&?ECyI$y!5pV(k0AM5Gx?_E5=IGh@$A2rY(GvL_Xi#x6-h z@|S7`S&BjwrSbIgd2`;K>zwO8_qo64e6H{9-~cECfSDu>0G)N^h53*vrWEJ4Q`%D4 z40C@M-D*!Yk!;HVm$rqNqlA3xQ?7dQB@PFRY)`wkpL%@aaH)Nun_l%)xXum7Gj8n* zKQ9?GoP*r;4+!U2Rl5eecbwL~=~Uw$;-P=Xv*B31XQ)S8Bm$1$V_q>I-t^*d!;T2j zNm-9Pg}6Ii$t)k*C={q0h?I*}fP;w8|vCh?aR-4GpW2?0s73OLvk2>l7^FU!zZip6g>tFe4NI}o>N zUxlGqtG|{>>M&U+c>aYpg(tX}RHMEbjA9inB&HcaBsyy8X z&d)z6FZ}pB>cW3!_pu)O%x*q^^1(m+fM{-;b(%H{1&8&}Mr5H+gBegnFP-Rw&Gtu| zJMiL_vi16rCNQB2d3#@KLBSP{#X$O=uX)9S>UnD3n-z}!5R&mq=6X_Cwhv<52FhoX znQz3_pVs{8?G-octrPtl+&B>^A$@6QmEHURP4``E$z}z zS9}h?LA@%RO%by=#m&+2K{}^~7Xb~OgdR{z_dbkgz0mI^l3gX)t-$)IplQZxP{+dr z6s>cd-YDxBn>T;D#8+PlY8v;QSdGT{PyRII{t3Q4RPIl9o`A8qIU0xilf>+k%p46P z+<$nzDYzliXm11&v*U}ZEVIU8(&Db*i~`fePFx=gq?A%`c&~8cf{?r4D=U^h=2R^& zjTTWW#3Rb?1>fu5ze6~yNFpOXwwdFvd7hbc!!F5pd{5-qaO-9m9U&56~+ zI1&2D(Twr+Wx~{L-5~09*)dmYIi!uBT4oR7d;y>xVx?)Py!Ad*e7=@QExg6e(TYt+ z8wun{)Nnn0>gS9Wj)#SvH@zwBO+R`A3E{;4DdQx??4c{i&KnQvz4krkiGM+!rn+}V z-JnwEcP<-8z5KKHT<_iAily|uiJ5#3%^BjaN(qMy?v&B(>@BhD?XdoJktEVur@*>- zSQ29du5>CmSzA@dw2j~;Q!|)LTja}T#Ut<47{l=#19OxaVZO}-?sW!DiKU{DHAmYh zlTzL7MHuh}IW65&7rG;BXClg#w^56B9ZG;Q0P@YNf+jRk;VcuPv&D3vL3;GlV^u#j zup3fhgF9|HrdvqMG52FQ79W>Mu09%1mHHI$H5;G0(PbI0n@#&DF(w!R$~@Ly(9Fo+ z1jDW0?8{kB)JVt$+Su3}Jb>scD{P6dwk|_8cs$)Y_7cLtDs)W;?Cc9~)>E&vpMW99 z-=j&?DE?W(9PEnk${sjXxils-AfA&t?la~1j<|);@ zUToXIl3#JsuiP?7W~d&4be+njjicOf{;)KX0_{8p%Rkh^MFtXS+kI%1E|)1yQb^5( zRXucic~K^h9w1gDqp~5ob6m(-XHiRun-nrXmM{>Q|mt5QT(=t zw~8%bJaAKqFmGGp+Tmk|$ln*&94&LR4b%*7(7n6WQ9535&sNFfVD)m3MoFitE$fb%qWeE}X$+>o++J{Y1MYT`mj;#YQ+bh}`O{0oVa+2%^EYEcccmpsmYvj;ttuI7@hc!x z&6TSlvCe|AFBTWE=rU7oJb0Hvm_PV0e-D%m?&!ZVl|s$0bN&>>3# zH#zTK4 z_}$=KB|P{2aRAlIl|)QmGke!`C5j`FK%3TQpt&NUC`jfyTKFL=8p9|pvC8oF?_E#_ z!j6m01?}_EOzP9k`Hg!QYzcF)=nS>?&*ek(_aAwA*P@qONV=f4Gycj%by9sBmqDvJ93(%vbN+xy$tjkrJi7uWyJ{rG8l z^8KGn>s^HXveT-gX)D;Sm9r`1YMKiptuJ$HJCtK;&gQrCII`H}w`@h}fLkyi^K_ao zoc0Mu>4}w5oVz_9NZXORV+dQV`qtZw2W(PUai$s~ZHyNMr8D4LS#7Z%$yX zLI+x~PSV&HQ}3Hd*kyC8JQ6m%#)L!+1(%So&5-12s0n9_DLMjl0s&i95DuIy3;^H2 z06=BwhBfd-JP0HFdXAH~xq~TPbkKh`(s?WsO;{W?B45PHsJ2!)0_1C0w)XNX%|D|N z3r;=H&+hWog^8H#^Bs)8$PVB?;N{UB%3sM5!4nDWa{^IX0tG}7{9yrgV}Z(Zf>|Mt z*%yU~Q=F!${Vd<*F<`Or#*V|GFZOM(G4*#diO-zDa5|49tQul2O+0mo2cIp19_4ow z-?59vb?-o<7(D)nlKEy9ke^Ax5W>F^7`?n!Y1_{4cwT&Wwm1N9qkta9kduTEbX_zI&#Hf?1!KgFhlsz9{o|v-k?b z#4(24^l&T~BS;E9$X194yzs1(ij~p`*L;3PoD#)Ol*tewvz28U=_VS|qwV}*Eid_- z37Zs^0yX>_D}g9GA(@LpXWt9;mkDDmgii+m*)M_7nvSfJ9T!<)84mCGy2vTnxTF>? z*F8+P5K%)lG}ui{h7-H?8zjkb0RR9>Ym;Imm?Z$@i~mL^Uq2r*pMlN4CY{!Tdo7PY zh_F1XZy9DwU<+xov6>XbCTU;VWiwR$XDIjq35>5ZyOJq^AUOq$^aM#b__-7w_DS6b zPWVD)&hksXI^Pv+%0yks-5!?^oAD!bmIx%kqK#bhJ8qscwf=u|s9e!0|UiJ-vEjYpT3t@|=%|%++g!7AX zMrAwzKi;pq`AY9BRp^_D@S&oWSF+=4hY#^G|K5!d>gI5rx5k)0kYNhLtDP~F33(8-@k=+D{C$@UOMzb>H9 zeXdr>P`;P2sIjuJ}h80ALT2Ey42>4k8QS#W~Ps z5hR@gLuNqtQGhQm@!Z@u@?BIZPFN?!sN0)fxo@t0Uw0C7ar2QX{)l0WjA@C&ukFyV z9m7X2Pslcv3d*d6Gvu$$l^{jk`Ns?w&NL_3xIX8$On6~GVSbjlV1$vy{3ZiG8Ih0_ zBHBb6#l%d~g{&);&YP%fvUO)Gjoy3R3YF1+Z=z*Wsd7R^Rf4eqrF=mG+5kl*u_P0; zR|cKCz>#VIr41hIH>#H9W{Ty4FP!NLe6g!yTc(63+52AlDcsfvYyVCs?hCvVR{k%6qMK~Oki4oM|L;63n6fB2`JSCQx6!sobh)Dl6*FQC1& z8ySH9S_WgC0hChW95VQVGy-}#nuJd<5%NiTV`3Ps;(2~0cDFb$V*{^u zO|UPUyYi@dQc?w3E0;MXIV}?qVxS-DUu6CJsL8Zcsq7K*+6^`fsyB&zDB8U<3;-#I z0e}Yx&0@<6kvpJ}$I{*6u*%=XP4WT{Z3W7anrs!R%4RI6uE2 z+JNxH2!FL46@=VO>Q8J}1%OZ)Q>2xiMj7@3e4a;_Et6x z~VenuG~s_ay)LS2+}8a*`KQVM#aho?u{S6L8g6}%DqWlVE9ka^jAqKw_Bn|@D1;(a^H-e`mFH z+{^wRrZftTOSwI0ia<_(GG^bbFYmtA($pX*{HyS($YU=8zFe}sS-iGc^h>iCV|$eS zL{^6F0r_i~h{6iz}u^FM!@seXgCDpkaLSIz9Mp~Ah|r0V`)xrg^4H)JA!pM>nU z3EaPG&xUaIAPWuh0{48}JkKUF0aOz5s>s^28-X&R4lPHy2WB4>=Y>9HLgG6bTHZ$) zX=HM-RWR%ydgUix#ArNwVc=f*v5wq3siy&wmF^eRs`$t~dw3ZD;&MSzJ`ShnXJ7m^RN_|hz?7lEsNj5;L?|HA?kx@p?f>^Sy+Gl#&$ zi??NwPu{l3JHlEF!;5M9Alc`MEOIg+4aWSVO#d*Q-gM`uMth`aC3#s~dBEVIAebO) zrefc{DU2MC6}rBWBzB(XV~wa*-LS#c{)Dq%wUphM4+?$I>RH6i$@rdBJ?oMRxjwt|HHN^})mk zxBbsPJ6;8P>jIMTfV9~eu}LU6hO01?YQ@foRji*2#S7u5QGhD&@M0zPQ! z7MDKS!4FyNMpu32qvt45!4A#4;guW zcf$DoZ%>VJb#AjmCr$VR3Hu?0%{?yCBKQrKUOEwZjeFn&_hCO?};Sgg{7D3a#3?O)*mpjyFT;E80UWkoe>F&XsXfih3(jg&GG1@0bo zjyr^5^F^vEMP-L2OIKDFl6|1B_{ol^9q%M{r{A=#G4edt%_J+;&f`$D`2ikL#SrOZ zo@aI)d}qeEFtwz4(`;5`kEj1l)IMpAE7zYwI}vke{1(TMZ-pcYu5atwQ!6~a&iwWaI3Xj0Xv3+w<8S!FH@?}*yERB>i| zbXmzRNBHY}k20pJl1CZu=UJbqk$;`?g7?e-|9kQBgS){`3HCKw#4qpX zm#lf$c$RB&ub$S%UfPh;jx~2oToS9?Cd}u}oVF$79O9LOYSipyD|2eO_XDET_c1+^ zhd(L{$iNOL$g^Qk%eon$>Awx;rcu!l1A_(S0W{?niX^%(&JL5v+vt*l2IOGb-kGR; z=4W{FeJN9GO``fi-a+epbfdFHPr-=HiJ*CGr6mptWEu~Q`Je1HCqSY&8o9te!cw)Q z8>%hqpT8RGzrs*n%H6D*&;&;|xH}gwkE9OmtMv3yQ&D4wXDC9*oQ%w?8I_WrL@yzj ztAUQ^s`2}w6S9m~>Ud{Y3s<&aE~>0mlBOhU#;htxe!;6e@2Bxjc9GlF-N8zXXlWAv z9Rt&Pkhf9A$8@VjlllkJ)?T$$&Q(@A>C zZKSBmHVK8X0bY>h0=rKXp$TUqXuxM+Q9IZsACO)g`{*t^r_$+Pdn*fU;H9OW?Q-%xE$)dJ@PznNrLc@3c=yxF=1R9E$3l4nFK9Nm@{yHA&ehtTX? zV0FLOpa&$y(3Vw3Y27v{kOMOq+5mDQBOHEzQZK2JV`#=aOqd@sf|>l|aLZclGMkH7 z;tu+oVjKdt7mFnOI45Tubd+hv>ybv0H-dbi0ej&o$Gx<3ar>Ciz7vGDIsEthn-MSm zMr18M6+Wox+ow+2d&yURq`K!CrK~l>RcqDEWgHL1ytZHgc6G+Bv$mw@=5X zaz;F4XqlG;Qgc<)bX@;lah=Z{wm>xV!0reJ$^PPDA#c^S;xCRxUApyf50YiIQ}!nL zBa=pZY+*vl802lqqtmiO(toNS?%zwa&Q}yJ+|HMMw3X>^CRBCz4SH3x9YgIeU&syl;o3orp=E)uun-81=S<5xN)4ux#6=t<7BK6U3md$DQPqvJ%Z$!-~3&#CV!) z<%2&}S&Nsa8lF{ja`4?dZc$8>j|F!lcvLgiNw(HKGvwLjtdlepR`R?*#XQ4!zO*%O zN#-}+3T`2_QfTL}2dEJN42yisn7te>bJ})la3^Ld`M^#{u0}-9l>>aev3J`Yl`bSr zj!Cmqpm`g=#hB#%XIFK?!Xx)1kvr7)C(hMgxK%^w7)zL8&*Ha%j|k+>4*HpW90EOS z03Cy#WSf?thh_|iYUC`ixsw1%6EwtqzUiCxhwZLLGjxgH2kUJO>L% zhW;HqY6!pc`oaAt{8OztlaPjQ1s;Stl}#@%8_yR-FU8?zXK(^$PXXb+{CC|!VLt*_ z#SSn#^^TN&`%i8!fon(G*i7>_fnAT>CVh&F`{4clT_QDuHzD}Y(#+RwFKYTdfdm8R zeZK!hsR#yWJUA4%)}3%K_tmm-{{tJz1<&FFGXXf@hZlPH4!9+k|EL~zXTR@zT*j>wF?gsf3jB437y!t@zhV%$HC^7X4o z)Z`&_2gB%bazjTm>99aU&zLbVUkiKx1=gpOzN2qS)1lq2g?XW#J8J-TkCNts;M{g; z&VMrMiWsqQVDBi*><#kw1zlWMry+zPXwqD7+9rPCUPuOQqq#Smj$xD8eyH1%G+?pl&4$!8s{06ElAyafWko2;HA(Xryxy8;2!akmrYgmy)lifE zefxKg00zruJ~w-4M|)aTI~XRmr-CXc;?j$XHR{PfJB>X% zGo$CfRiGnJ5coe2&{s2d)Lz!O%3o>h&Zp87yWmXrZGRnk*|*gy0+9AcxOF>ZC?Iqm zm+IS|u>-Rx1t8W=7(riHqI~*}L07(UPqXQBlttIN)r%dQ$8EOSo#P!0>#k`_o4p$Y ziMKnN4S|QXutFF5ZV`Ozd3~RO0uw=Ef+=BaBn86N+FUFcD_vyn=u3L3ch)h$Sku{J zv@{0L{AyjEY9E_zEegukToO_>hZk)i6NYKFMyhYVx0}=|;nl$AObNwI$btwRuy9mD zanc|}j{W1HFF}ufY zHb%3z{sq?3*~IimLzAKbodH3BnQhfu)>m!ihfQf)U65G&+ltgWy`!UcB6{d$yAx7< zW)|k1_PrAm_JW)YCUIQXtGSX_b?3l%ke{4arq+*Z4QKiEa%|HGcsuoy)uuV)f&)%3p7~iZg8Nc`A7M zt&EGu5fM!fcRq{ELKO>_2UX?7%Tuwu*FVT6s}*pS_okiWX?52B&pOiJ>tpdcgj z?Tt0TS#EkW?!Pv3)m_)jY4vQwcKPldK;1W~<~aP)Z84lW3>WOA;@KQ_j;}8R<9ra} z%nOK`!HEZGK>>&%W7<$0vOghxnF=4mBiAp(n{nyuaqvhia@sH1nI|12(rdW5Vo?AI zC=ku$zVvLI_BrEzO~&nO#JCR)&JvKneOwOWUP)((LXxCi+37ZFs~g04TWvz9g8ASt ztyBg?U2dK49h|(Bs`-KTkD)?SNOxrKJ@b}OSGTKCOOpekO?E!T?7urAUw36FbFvM92El2HK+-f0D1{_vNYh1OurV=U8Jf)Gp^+glYe?o% zy3g9C--+kmv4Eodw(m>Z_DKE;n%s=FI^x{E@2SVWWh-8HviQs_yoOu3i~!`{>vS}# zKZ8itbtgCniLaWIrk#-Qr;{_|0GQ45{=yKR^M|4qe00)rQAiFK zF6G&AqE&h`c&g1d2gOy?mZ{JN9Ap4IVHrN#pZ$qdeaisx^91VtF6xf|wF_@MU?Y9o zVKkb0(YiTOvgvsNwKi2N44)M5($I07iNO>%Z8Ulp z3<)gtLjJbo61)yqG)>Q!T~>6UeN2HCoT29&p(jSW8M*lE+&yYRMpXu7RC7N&&-1}s z&9y7*pVe!2T0>#%Xgd6v*VM^Ct}CBLOVrOnoE{pT39-A|hlYsxa1moZz?ZVV&LF!( zX^~f&r!$xTb}w$CivQR^6z;$k4t-erL^_Ym#eLLllS#f+hZwzHWqlgqGK?ghr{szi z1_hrPdMtF_+-vHxs%`(7O-tnO9_a^P)5%9dO9Q7KXh9-H;O0!)KaWtvvG(Xx>&LhM z1yD~HfGRk^pe-;k$ff#$?4!X?-%37p{xMrU1|`}q;5R-n&3OZk_nBUB1CFHKIr7on z>4CPws%XA9Ba{A0E*W*o(9i~I?Z5_eUw|TOrOx%>B_b|tjT4_PjzP4ArvHA!7daiO z_>}2985{?BIn_GO^+`~;{y!G^)RZR;;!xxAVO97oH@CwF+jJTrTR~F{Qj|@NxSqb9 zbNaVRSV{5soIleOM$nQ!TyoE=#V(9C!+;v=vpbQ+YJd3;ouJ=?oj9;ST+W<0F%_|s zUpVm&qT&bC=&00dz!>_7qO@)wL}4jRVn{aWBA&}e3|^Dy^`@O2BZ~MWe2TvPve!{a z=@_mxk#}uaTK0nK-XE`^OCOkKdizL;xwN3hO+P!knP)&L#wxT&X%`IGmfS2 z=tkEBtaVfFjR_=6K8j9&!gr{VH!NvfTe{7F_cbs(=HP^`_~{y=lOi}ID!te&p1i9F z`*%P)R6~6OL=_IPbGAuGcp2RO9Z?R{-L^m7=f4gwPiMWh?Puwha8Puqg%FFmA3L-thven`IEk58oX8Z zCF$T*MG-g+e$}k&dt@X~63g>5LuQy|2)%cmE7oLpD4G%=QnoLcw#0~Xrv3&Zker02 zmyS4%^Wt#Rm&e2({>ZOkP_3QAW33%p6MxJR8vHzxPV|2-Vz&P7<*vIb0}D@!296k#sf~PNYhCaOCRc7^iea%MmdlcQr3~@GlHm)27mlQf-#Vd<+zschSnyR%pgRu@)6;82bwBGz z@$fusAb}DB^h#X=p)2$oz6RB@-nvID)3^mBZuFa?mD4ju`i`x^5E`ExuJ10 zUfChbZcflJ@(&nDSTwI6zCWPaI&#E0nDe|;jn{Jg+M1h>bkE@ef9ln9!ONPCh~#mJ ztBlT7-A=M-HH(Ik=ryLHdf?v~j$hzw498(O0*t7)uo@T4kxy-}!C~l08KSoIe>s{- zcXnIdH3p!Oc(<$qFMUI#R~Cs*lT@ABdMmI)3v!!h_{No_tSv#-LeCycRG$9%J6 zY#u-20q@*Uf_i2|B9GHaBB3dd+l2Y)KbP&fXCb;OQK@x7Ai={FWp?2T+hO)F;#kH< z&@Y9*NKpW$w&m>^uu;Y(kgj)zUctY0Ij~}}QIL8)HkcFX&#yqpxITTK6E^?P)0tDT zm}W?2E$tQ;R4f|VQ(s!Dw)r0k`)Wk7TZNgEz0N5IqlCR*a9q!%zxo~N34KFrPdEST zZsg7)wb8GadKp+2h`e4J?@^4SA0A47Z7o^BN!hrrNo$K!IT-FB+ zXu=B;GqekDFJu+(9M_@!S=KgOM?XB|7nvW&@!3G`dh}Op2Ss~1GTY{RMABEqFK?#5 zTu)R!_*^kzB)wBSQDg9@fGI*3X%R^=}|Kki{CFzKX?|` zFhy9T=Hy!=P8Pk;C{xc<)!23PL7v{t?wRs>-E!WG(0{ly5nsVQs+E{VzW$@+YMFi; z9FF;-@r{J5ytnqe!RF6e5eUeJ3mOfR-pfG4NRVc&Wj+YY^lBIY(&>VRq;4A+BE_Db zB8$KeiP|~kSUBOp5K^~U0gr|GliHYXm{f@hxs=v8%fKq@Jb2}2>`*&DIU{B3z zr!m`Xj7n(IDIQe5yb*~J1*NC(K$&Gn4}OLgx-x*z{~qq73_27R?oNkp zA}}aXqoiuIoOTO*vSQlunrZRM(TonN?9P4;)c&#>PF~VlR9}shX-v!4ZUaiy^1w(L zXk5L}y9^CJKAa&uu2be(TYe&2(-|Q)q67U@IUqhxQ{8LB<~faU|fd9FFAdI`4y3IbXp+- z#(=`+aD1K2gORB`VsWRZsV< zogpzNv7m=49kPi)4X>QxI&ec+IFbUt6E^^oIoD{2w`#1HVFlQk5?5ULEz{EU7PBjP zd=QRoJ#)cHP20*#@2c03kOOEN(LNQD=VC2o9_oRZI{yAdD2X2gJ;W@SGviGV+^JN2 zNIh?#?9aj9n&{rJhtC`Sh5jWnR00kx*__yejkP!#SwV7(3;LkXn= z{F;FAePKpec=m%=51c<<+>Sde!~%H4ziQ&+S7x;Y%wn=vJ(&;%5;Xg9%n;xsagx4n z$=z+P>_XEUP~_jze^O)qAI}@kvjG{{(~FySIO2&j3n>pCzH%JRS6SFU%y$TMow8I~ zha6H*JJea)(yLvF%slirwfCYw4-P#47A53#Hw7hhBMFYGbs-^poJU$l%8h$+T?G2D z5Vv+cC!(MCOYgIXB=4hOFNbm^rqAov-{d*cu0d zadH>{df)&`+F~dLGrvHDL^A<(FkX=!^a`7vAyoy4qW~MsHRuTeoyIGZQ*JxmxIa*T0pXE%eiW@trJun53)8#IeC1J6 zGZ83CIM8hCj3zBi1CMjkZmgZK1~6S!tqUk*{?VsTv_DP{U(cqy)gW7c=Dr49i<`sB z?eM#hOkvl$jm`qXg??q zpIue`S`+gV)?^}ncF_69t(-U8Rf}AmeF^Ky4m}P!YFfJP)OD8#Qn%;SiX_%OUDW03 zgt>~K+{(EVm#$9zu?nsMo<2r|e{FKGKR$A!d2$wb@?pRoRQX#+Tc{Ml6#kfQ6Yvs9 zzh&~t(CSJk{p0|T73*k6BbOTc{*6r*1ZS&VWOkNGB|XSDe69YNTQa^Nz5K?=c%m1$qWzaD=O z5-b*WNXaB^BK)1mo9gZ;bD^OQPQ)cKN>G%Q=piOk94U)UPAsq|0X*}(1$Slg(s(zf zMOA1-tK*rk3$t8^$}X*hFFf2M8lZy)z;|0p1E^7C@lebp;EMYjDg5;1vnEQCp;IBe zJSwm0pe*LP4B$|y9gob6UB|>fSP_%0K6c=nh~u_ww37Ua5jVd(zfCgsOAWqq0tSA2 zrl{LDf<_@)P~oOXZbvwmhM-c(idM?6RvGQ2B~FrC3fP8NCI+Ba34*Fn`bS|vA7-*F1ZqIp3wW|1 z1k%VeUoNN|!JUl`B}$=zMC?_ZRP&%*P{x&@yKxJhUiJ#cx%X96?}83Iv#w1?0y{sF zo(NG$gf9v>t7R(b@?%;qPZeAk5(o#h2_`LkU>}jK&)?0FqKEQOrbHlQ0((k0OjWX* zB%mOQ0VnNP$Kh-arp{l?cDBpum?9}@8T=w8qou!4YsS1l;Et}A;|90-HU za3t6;-G3V(Z4%j9X7q7E2oHfhE=a-JL(FlLs)7&%fjuff`fc4UkGYM)F~=?z((% zYkc^EwU(iNcvaXixp)-~XZ^0}E)io{0)0umtOQ%~Hy#s?Bn81+G>K=tvWF<}(K%8k zs(fz~j%}&(yX8u<#nCC*I93ON-G^n|jiG%+b#ug79f+k&1Sn~Iw^5oVtJm!RGHDXh zoWw<%>H+Oi>HZF-Y9dBcPvwS<>vjo8b9uDx^wee_c4IhoI7qm;rb4f z0GHsKIXE2juc2*;4VMtXSST_c%?S6V&7oizEUmyEg5chc#{+db-GV$n67gVzPB+$@ zJ&q$^cOd-(I#8fe(5mQC@GedkP z%(s&WfyZ~`%&(nbKMuHSbY&~>^hB5D*~gKiiLYc_311`eVOHcox`>z>xyKA&*30X_pD?861#8V9(-6SE7!IMVUYXDbrZS zB^~BQVD~tN7DQxCa}}4O$##ykyU;~V1Pjn0IRlVAnDP~UD6Wbb8ASVbg6YajIvK;d z9z$a+k?qkXMF{4vlN3WoU`)J{JC?muO5rRXA&?+Lk|~9fcMk=~GsHCm;vRun=fkqn zc{q`r788ur-NN9o#OE&z!Y_`=C|MRUu;HtIVoA@A2UBdxHz4klXqMG6#w?cz8dDN2 z4QwJzIMUz_qLL#``g435Pxs;>>;MQEjudO{EPWcIvm-_Nk18{YW*U3bn$F6!Bn=#L ztK@Lo=JOL5z`988N{7_S{SXs<0{cK(?CCVRO4>H&=mtW0Y+u^5R;rDz&7PJ@leek9 zWvh5c+R6OLom4~gs6u068+Rv)9a+KzhV1rJbtba>2T-z1tW2Z9nRu0yY;Go(4)ets z`bR#NIf1>1A=?w!s~DCifxV6;`4QNgSQ;hIYd4SdNyl9IlB{PvE^HFLCBW?1z zc-LPlF4&viC+S&FQ4nsaDYq^7>=)DSs@o)lZ)^&7Y zXWFnGtys6>+9#U?@+?eu0ZkU6GoN|T$9cs|Bm>e2Y<~kv2hdyoI=lXH5C{5OLHf8y zvEH$`UzH`hkr&WG`}M4CTN4f@CYHeZua@$gPa;v8`J#c%;$9(AZ%J!}^w3rLR7X~RUR#&cFmAta?`Jw#ND@CDq&3v$Oo1EZeK8oLBh?_tv(CITi z{M5V0AIJ4s6it73-DH_p$B{rAEW94)BlE9I=wK~v8Tvl8gRujPuc`9&N$z;sRyGTJ zn%Z#n+Icz$Qkc<1Ov+EIrJL1U4lvKzU#CcPO82+EW_!M?sQnx#+b? z-3tWT)B6+-dY8Fd@}ssh1{)_=*BL}$a}7YaZ&3E%ble}85*m>7C9rxCnZ7H;%-$m}v z>)Pr-VuI7AyBySxI(%Aqc9TdmSz$uVK(@zCwT~1I?h-%#=rq4XF8{4~{@<+v1c^Em zmAaGo+ME5gbiNJ~NPpRfS_(gsj1aq{%%fL6P7{k^`CZh-yW`!MZug z!Jn5ELEb07zo7PgO+J0~a{C+1N3Ea3ZreL>ys{263kpl2x(>Mjx68(CqA>w(^_joS zz0q6kn%$y+SkY*()^&#^fwIYOaT>s2_k#`JJ;0KHB-x~~hh%?HtIe8z{r0tTb+}S% z!*;MSQm&u+w9;*1Lp*T*037?P2S?=S~htmEe|NPT!xvtubv3V7oL(>hQ`eD%=TT>^3B z&b;nxO_ZP_ozWl`O>O<$&har@Hx*5nC=czD%@8w)HjrJh}6_mH5(p+*y+cd$c$IfBWLl>Zltf z*Rl2J6kidgRL_4pm!5gZ`tk;c%wXW~60+k|ejw8s9P-sQI5afVr-Fg;#1DT}<=2-i z&GuhClI(ZgIMznd?14a*Y(z?@W3v3y+{x}P8-C`x+`N`MU*KZd?2z`rjmlBiFNpxh zYNv)X{!d0m7R$4gD(5Z`&Me*i!;8jjbT-OaIB`k?dqJY{wq?G zEbc2eo_WCiI_bdu_0lTO4%I)F4E*0G`rFKU^IL1T>)Ugq+iv&WVGaDBEW-Zb`(Bx( zuwRkQG7O&>J|wkXmW*xEW9VyI(}I6w*>Ip^*5jR zp?_@g13ekW#)kD#GHkL950t;9GMv0EvHQZee8Jj>_q@xW&#&{AOIhDl`Mo9bfo)|v ze~yt9_m4?2=Nu=RUTa#sJf!#f%u{wMSqi{Z->mUNSoYI?_sd^v^Gsu2C^uO7{#5Qe zWO>4((>3~Pfu|UzQDrZ!cnvQ#19+g2N$IePO`Y*@laiP!Xc@n6&uBpE*_~*VA5n@Fni(g zKuh_-p8jUD`FsbM8I>n)U@&E}l;U`j)>GJJprvH@tbzGG1OFpk_n(XkNw=L^FTOnP z@ME!@cuQCJ1Zy~qg?s%>)JdJPdD^6F(cYDXdZ|}-PkzF}z{kkIzzp1{$H>qCBp8v{Okg$(@Z^kB zjLcAR;Ep~IKR$Y9N^(gb)YnV_@KbLJ*5VGYW`<7#JiEF>w89U|>)efYAU`X!5lH diff --git a/mDNSMacOSX/daemon.c b/mDNSMacOSX/daemon.c index 97ef560..de12870 100644 --- a/mDNSMacOSX/daemon.c +++ b/mDNSMacOSX/daemon.c @@ -36,6 +36,12 @@ Change History (most recent first): $Log: daemon.c,v $ +Revision 1.257 2005/03/28 19:28:55 cheshire +Fix minor typos in LogOperation() messages + +Revision 1.256 2005/03/17 22:01:22 cheshire +Tidy up alignment of lines to make code more readable + Revision 1.255 2005/03/09 00:48:43 cheshire QU packets getting sent too early on wake from sleep Move "m->p->NetworkChanged = 0;" line from caller to callee @@ -899,8 +905,8 @@ mDNSlocal void AbortClient(mach_port_t ClientMachPort, void *m) while (qptr) { if (m && m != x) - LogMsg("%5d: DNSServiceBrowser(%##s) STOP; WARNING m %p != x %p", ClientMachPort, qptr->q.qname.c, m, x); - else LogOperation("%5d: DNSServiceBrowser(%##s) STOP", ClientMachPort, qptr->q.qname.c); + LogMsg("%5d: DNSServiceBrowse(%##s) STOP; WARNING m %p != x %p", ClientMachPort, qptr->q.qname.c, m, x); + else LogOperation("%5d: DNSServiceBrowse(%##s) STOP", ClientMachPort, qptr->q.qname.c); mDNS_StopBrowse(&mDNSStorage, &qptr->q); freePtr = qptr; qptr = qptr->next; @@ -922,8 +928,8 @@ mDNSlocal void AbortClient(mach_port_t ClientMachPort, void *m) DNSServiceResolver *x = *l; *l = (*l)->next; if (m && m != x) - LogMsg("%5d: DNSServiceResolver(%##s) STOP; WARNING m %p != x %p", ClientMachPort, x->i.name.c, m, x); - else LogOperation("%5d: DNSServiceResolver(%##s) STOP", ClientMachPort, x->i.name.c); + LogMsg("%5d: DNSServiceResolve(%##s) STOP; WARNING m %p != x %p", ClientMachPort, x->i.name.c, m, x); + else LogOperation("%5d: DNSServiceResolve(%##s) STOP", ClientMachPort, x->i.name.c); mDNS_StopResolveService(&mDNSStorage, &x->q); freeL("DNSServiceResolver", x); return; @@ -973,19 +979,21 @@ mDNSlocal void AbortClientWithLogMessage(mach_port_t c, char *reason, char *msg, while (b && b->ClientMachPort != c) b = b->next; while (l && l->ClientMachPort != c) l = l->next; while (r && r->ClientMachPort != c) r = r->next; - if (e) LogMsg("%5d: DomainEnumeration(%##s) %s%s", c, e->dom.qname.c, reason, msg); + + if (e) LogMsg("%5d: DomainEnumeration(%##s) %s%s", c, e->dom.qname.c, reason, msg); else if (b) - { - for (qptr = b->qlist; qptr; qptr = qptr->next) - LogMsg("%5d: Browser(%##s) %s%s", c, qptr->q.qname.c, reason, msg); - } - else if (l) LogMsg("%5d: Resolver(%##s) %s%s", c, l->i.name.c, reason, msg); + { + for (qptr = b->qlist; qptr; qptr = qptr->next) + LogMsg("%5d: Browser(%##s) %s%s", c, qptr->q.qname.c, reason, msg); + } + else if (l) LogMsg("%5d: Resolver(%##s) %s%s", c, l->i.name.c, reason, msg); else if (r) - { - ServiceInstance *si; - for (si = r->regs; si; si = si->next) LogMsg("%5d: Registration(%##s) %s%s", c, si->srs.RR_SRV.resrec.name->c, reason, msg); - } - else LogMsg("%5d: (%s) %s, but no record of client can be found!", c, reason, msg); + { + ServiceInstance *si; + for (si = r->regs; si; si = si->next) + LogMsg("%5d: Registration(%##s) %s%s", c, si->srs.RR_SRV.resrec.name->c, reason, msg); + } + else LogMsg("%5d: (%s) %s, but no record of client can be found!", c, reason, msg); AbortClient(c, m); } @@ -1407,7 +1415,7 @@ mDNSexport kern_return_t provide_DNSServiceResolverResolve_rpc(mach_port_t unuse DNSServiceResolverList = x; // Do the operation - LogOperation("%5d: DNSServiceResolver(%##s) START", client, x->i.name.c); + LogOperation("%5d: DNSServiceResolve(%##s) START", client, x->i.name.c); err = mDNS_StartResolveService(&mDNSStorage, &x->q, &x->i, FoundInstanceInfo, x); if (err) { AbortClient(client, x); errormsg = "mDNS_StartResolveService"; goto fail; } diff --git a/mDNSMacOSX/mDNSMacOSX.c b/mDNSMacOSX/mDNSMacOSX.c index 8d553ca..2b3e4ea 100644 --- a/mDNSMacOSX/mDNSMacOSX.c +++ b/mDNSMacOSX/mDNSMacOSX.c @@ -24,6 +24,12 @@ Change History (most recent first): $Log: mDNSMacOSX.c,v $ +Revision 1.310 2005/04/07 00:49:58 cheshire + PPP connection disables Bonjour ".local" lookups + +Revision 1.309 2005/03/23 05:53:29 cheshire +Fix %s where it should have been %##s in debugf & LogMsg calls + 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 @@ -2141,9 +2147,12 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) else v6Loopback = ifa; else { - AddInterfaceToList(m, ifa, utc); - if (ifa->ifa_addr->sa_family == AF_INET) foundav4 = mDNStrue; - else foundav6 = mDNStrue; + NetworkInterfaceInfoOSX *i = AddInterfaceToList(m, ifa, utc); + if (i && i->Multicast) + { + if (ifa->ifa_addr->sa_family == AF_INET) foundav4 = mDNStrue; + else foundav6 = mDNStrue; + } } } } @@ -2588,7 +2597,7 @@ mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceR { if (SameDomainName(&ptr->ar.resrec.rdata->u.name, &answer->rdata->u.name)) { - debugf("Deregistering PTR %s -> %s", ptr->ar.resrec.name->c, ptr->ar.resrec.rdata->u.name.c); + debugf("Deregistering PTR %##s -> %##s", ptr->ar.resrec.name->c, ptr->ar.resrec.rdata->u.name.c); dereg = &ptr->ar; if (prev) prev->next = ptr->next; else slElem->AuthRecs = ptr->next; @@ -2755,7 +2764,7 @@ mDNSlocal mStatus RegisterSearchDomains(mDNS *const m, CFDictionaryRef dict) { AuthRecord *dereg = &arList->ar; arList = arList->next; - debugf("Deregistering PTR %s -> %s", dereg->resrec.name->c, dereg->resrec.rdata->u.name.c); + debugf("Deregistering PTR %##s -> %##s", dereg->resrec.name->c, dereg->resrec.rdata->u.name.c); err = mDNS_Deregister(m, dereg); if (err) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err); } @@ -3304,7 +3313,7 @@ mDNSlocal void FoundLegacyBrowseDomain(mDNS *const m, DNSQuestion *question, con prev = ptr; ptr = ptr->next; } - LogMsg("FoundLegacyBrowseDomain: Got remove event for domain %s not in list", answer->rdata->u.name.c); + LogMsg("FoundLegacyBrowseDomain: Got remove event for domain %##s not in list", answer->rdata->u.name.c); } } diff --git a/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj b/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj index 3fe2b31..37d071d 100644 --- a/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj +++ b/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj @@ -1705,7 +1705,7 @@ CFBundleGetInfoString CFBundleIconFile - DNSServiceDiscoveryPref + BonjourPref CFBundleIdentifier com.apple.preference.bonjour CFBundleInfoDictionaryVersion @@ -1723,7 +1723,7 @@ NSMainNibFile DNSServiceDiscoveryPref NSPrefPaneIconFile - DNSServiceDiscoveryPref.tiff + BonjourPref.tiff NSPrefPaneIconLabel Bonjour NSPrincipalClass @@ -1912,14 +1912,14 @@ }; FF260A3207B4466900CE10E5 = { isa = PBXFileReference; - name = DNSServiceDiscoveryPref.icns; - path = PreferencePane/DNSServiceDiscoveryPref.icns; + name = BonjourPref.icns; + path = PreferencePane/BonjourPref.icns; refType = 2; }; FF260A3307B4466900CE10E5 = { isa = PBXFileReference; - name = DNSServiceDiscoveryPref.tiff; - path = PreferencePane/DNSServiceDiscoveryPref.tiff; + name = BonjourPref.tiff; + path = PreferencePane/BonjourPref.tiff; refType = 2; }; FF260A3407B4466900CE10E5 = { diff --git a/mDNSPosix/Makefile b/mDNSPosix/Makefile index 638b56d..4ef7ccf 100755 --- a/mDNSPosix/Makefile +++ b/mDNSPosix/Makefile @@ -24,6 +24,18 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # $Log: Makefile,v $ +# Revision 1.59 2005/04/14 21:07:10 rpantos +# Bug #: 4089257, Clean build broken for Java support on POSIX +# Submitted by: Roger Pantos +# Reviewed by: Kiren Sekar +# +# Revision 1.58 2005/04/08 21:37:57 ksekar +# get_ifi_info doesn't return IPv6 interfaces on Linux +# +# Revision 1.57 2005/03/17 04:02:28 cheshire +# mDNSResponder won't compile with gcc4 on Tiger +# Changed Makefile to link using gcc instead of libtool +# # Revision 1.56 2005/02/02 02:25:21 cheshire # /var/run/mDNSResponder should be /var/run/mdnsd on Linux # @@ -253,7 +265,7 @@ endif else ifeq ($(os),linux) -CFLAGS_OS = -DNOT_HAVE_SA_LEN -DUSES_NETLINK +CFLAGS_OS = -DNOT_HAVE_SA_LEN -DUSES_NETLINK -DHAVE_LINUX JAVACFLAGS_OS += -I$(JDK)/include/linux OPTIONALTARG = nss_mdns OPTINSTALL = InstalledNSS @@ -301,7 +313,7 @@ else ifeq ($(os),tiger) CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Wdeclaration-after-statement CC = @gcc-4.0 -LD = libtool -dynamic +LD = $(CC) -dynamiclib LIBFLAGS = -lSystem LDSUFFIX = dylib JDK = /System/Library/Frameworks/JavaVM.framework/Home @@ -509,8 +521,8 @@ Java: setup $(BUILDDIR)/dns_sd.jar $(BUILDDIR)/libjdns_sd.$(LDSUFFIX) JAVASRC = $(SHAREDDIR)/Java JARCONTENTS = $(OBJDIR)/com/apple/dnssd/DNSSDService.class \ - $(OBJDIR)/com/apple/dnssd/DNSRecord.class \ $(OBJDIR)/com/apple/dnssd/DNSSDException.class \ + $(OBJDIR)/com/apple/dnssd/DNSRecord.class \ $(OBJDIR)/com/apple/dnssd/TXTRecord.class \ $(OBJDIR)/com/apple/dnssd/DNSSDRegistration.class \ $(OBJDIR)/com/apple/dnssd/BaseListener.class \ diff --git a/mDNSPosix/dnsextd.c b/mDNSPosix/dnsextd.c index 687507e..8903d81 100644 --- a/mDNSPosix/dnsextd.c +++ b/mDNSPosix/dnsextd.c @@ -24,6 +24,12 @@ Change History (most recent first): $Log: dnsextd.c,v $ +Revision 1.35 2005/03/17 03:57:43 cheshire +LEASE_OPT_SIZE is now LEASE_OPT_RDLEN; LLQ_OPT_SIZE is now LLQ_OPT_RDLEN + +Revision 1.34 2005/03/16 18:47:37 ksekar + dnsextd doesn't clean up on exit + Revision 1.33 2005/03/11 19:09:02 ksekar Fixed ZERO_LLQID macro @@ -529,7 +535,7 @@ mDNSlocal mDNSs32 GetPktLease(PktMsg *pkt) if (!ptr) { Log("Unable to read additional record"); break; } if (lcr.r.resrec.rrtype == kDNSType_OPT) { - if (lcr.r.resrec.rdlength < LEASE_OPT_SIZE) continue; + if (lcr.r.resrec.rdlength < LEASE_OPT_RDLEN) continue; if (lcr.r.resrec.rdata->u.opt.opt != kDNSOpt_Lease) continue; lease = (mDNSs32)lcr.r.resrec.rdata->u.opt.OptData.lease; break; @@ -975,37 +981,30 @@ mDNSlocal void DeleteRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone) if (reply) free(reply); } -// iterate over table, deleting expired records -mDNSlocal void DeleteExpiredRecords(DaemonInfo *d) +// iterate over table, deleting expired records (or all records if DeleteAll is true) +mDNSlocal void DeleteRecords(DaemonInfo *d, mDNSBool DeleteAll) { int i; - RRTableElem *ptr, *prev, *fptr; + RRTableElem **ptr, *fptr; struct timeval now; - if (gettimeofday(&now, NULL)) { LogErr("DeleteExpiredRecords ", "gettimeofday"); return; } - if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteExpiredRecords", "pthread_mutex_lock"); return; } + if (gettimeofday(&now, NULL)) { LogErr("DeleteRecords ", "gettimeofday"); return; } + if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteRecords", "pthread_mutex_lock"); return; } for (i = 0; i < d->nbuckets; i++) { - ptr = d->table[i]; - prev = NULL; - while (ptr) + ptr = &d->table[i]; + while (*ptr) { - if (ptr->expire - now.tv_sec < 0) + if (DeleteAll || (*ptr)->expire - now.tv_sec < 0) { // delete record from server - DeleteRecord(d, &ptr->rr, &ptr->zone); - if (prev) prev->next = ptr->next; - else d->table[i] = ptr->next; - fptr = ptr; - ptr = ptr->next; + DeleteRecord(d, &(*ptr)->rr, &(*ptr)->zone); + fptr = *ptr; + *ptr = (*ptr)->next; free(fptr); d->nelems--; } - else - { - prev = ptr; - ptr = ptr->next; - } + else ptr = &(*ptr)->next; } } pthread_mutex_unlock(&d->tablelock); @@ -1184,8 +1183,8 @@ mDNSlocal void FormatLLQOpt(AuthRecord *opt, int opcode, mDNSu8 *id, mDNSs32 lea { bzero(opt, sizeof(*opt)); mDNS_SetupResourceRecord(opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL); - opt->resrec.rdlength = LLQ_OPT_SIZE; - opt->resrec.rdestimate = LLQ_OPT_SIZE; + opt->resrec.rdlength = LLQ_OPT_RDLEN; + opt->resrec.rdestimate = LLQ_OPT_RDLEN; opt->resrec.rdata->u.opt.opt = kDNSOpt_LLQ; opt->resrec.rdata->u.opt.optlen = sizeof(LLQOptData); opt->resrec.rdata->u.opt.OptData.llq.vers = kLLQ_Vers; @@ -1414,6 +1413,28 @@ mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e) if (SendLLQ(d, &response, e->cli) < 0) LogMsg("Error: SendEvents - SendLLQ"); } +mDNSlocal void PrintLLQAnswers(DaemonInfo *d) + { + int i; + char rrbuf[80]; + + Log("Printing LLQ Answer Table contents"); + + for (i = 0; i < LLQ_TABLESIZE; i++) + { + AnswerListElem *a = d->AnswerTable[i]; + while(a) + { + int ancount = 0; + const CacheRecord *rr = a->KnownAnswers; + while (rr) { ancount++; rr = rr->next; } + Log("%p : Question %##s; type %d; referenced by %d LLQs; %d answers:", a, a->name.c, a->type, a->refcount, ancount); + for (rr = a->KnownAnswers; rr; rr = rr->next) Log("\t%s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, rrbuf)); + a = a->next; + } + } + } + mDNSlocal void PrintLLQTable(DaemonInfo *d) { LLQEntry *e; @@ -1427,9 +1448,19 @@ mDNSlocal void PrintLLQTable(DaemonInfo *d) e = d->LLQTable[i]; while(e) { - inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); - Log("LLQ from %##s type %d lease %d (%d remaining)", - addr, e->qname.c, e->qtype, e->lease, LLQLease(e)); + char *state; + + switch (e->state) + { + case RequestReceived: state = "RequestReceived"; break; + case ChallengeSent: state = "ChallengeSent"; break; + case Established: state = "Established"; break; + default: state = "unknown"; + } + inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); + + Log("LLQ from %s in state %s; %##s; type %d; orig lease %d; remaining lease %d; AnswerList %p)", + addr, state, e->qname.c, e->qtype, e->lease, LLQLease(e), e->AnswerList); e = e->next; } } @@ -1832,7 +1863,7 @@ mDNSlocal int RecvLLQ(DaemonInfo *d, PktMsg *pkt) // validate OPT if (opt.r.resrec.rrtype != kDNSType_OPT) { Log("Malformatted LLQ from %s: last Additional not an Opt RR", addr); goto end; } - if (opt.r.resrec.rdlength < pkt->msg.h.numQuestions * LLQ_OPT_SIZE) { Log("Malformatted LLQ from %s: Opt RR to small (%d bytes for %d questions)", addr, opt.r.resrec.rdlength, pkt->msg.h.numQuestions); } + if (opt.r.resrec.rdlength < pkt->msg.h.numQuestions * LLQ_OPT_RDLEN) { Log("Malformatted LLQ from %s: Opt RR to small (%d bytes for %d questions)", addr, opt.r.resrec.rdlength, pkt->msg.h.numQuestions); } // dispatch each question for (i = 0; i < pkt->msg.h.numQuestions; i++) @@ -1880,7 +1911,7 @@ mDNSlocal mDNSBool IsLLQRequest(PktMsg *pkt) } if (lcr.r.resrec.rrtype == kDNSType_OPT && - lcr.r.resrec.rdlength >= LLQ_OPT_SIZE && + lcr.r.resrec.rdlength >= LLQ_OPT_RDLEN && lcr.r.resrec.rdata->u.opt.opt == kDNSOpt_LLQ) { result = mDNStrue; goto end; } @@ -2030,7 +2061,7 @@ mDNSlocal int ListenForUpdates(DaemonInfo *d) if (gettimeofday(&timenow, NULL)) { LogErr("ListenForUpdates", "gettimeofday"); return -1; } if (timenow.tv_sec >= NextTableCheck) { - DeleteExpiredRecords(d); + DeleteRecords(d, mDNSfalse); NextTableCheck = timenow.tv_sec + EXPIRATION_INTERVAL; } timeout.tv_sec = NextTableCheck - timenow.tv_sec; @@ -2044,8 +2075,8 @@ mDNSlocal int ListenForUpdates(DaemonInfo *d) { if (errno == EINTR) { - if (terminate) { DeleteExpiredRecords(d); return 0; } - else if (dumptable) { PrintLeaseTable(d); PrintLLQTable(d); dumptable = 0; } + if (terminate) { DeleteRecords(d, mDNStrue); return 0; } + else if (dumptable) { PrintLeaseTable(d); PrintLLQTable(d); PrintLLQAnswers(d); dumptable = 0; } else Log("Received unhandled signal - continuing"); } else { LogErr("ListenForUpdates", "select"); return -1; } diff --git a/mDNSPosix/mDNSUNP.c b/mDNSPosix/mDNSUNP.c index 32a016c..a049138 100755 --- a/mDNSPosix/mDNSUNP.c +++ b/mDNSPosix/mDNSUNP.c @@ -24,6 +24,17 @@ Change History (most recent first): $Log: mDNSUNP.c,v $ +Revision 1.26 2005/04/08 21:43:59 ksekar + mDNSPosix (v98) retrieve interface list bug on AMD64 architecture +Submitted by Andrew de Quincey + +Revision 1.25 2005/04/08 21:37:57 ksekar + get_ifi_info doesn't return IPv6 interfaces on Linux + +Revision 1.24 2005/04/08 21:30:16 ksekar + Compiling problems with mDNSResponder-98 on Solaris/Sparc v9 +Patch submitted by Bernd Kuhls + Revision 1.23 2004/12/01 04:25:05 cheshire Darwin patches for Solaris and Suse Provide daemon() for platforms that don't have it @@ -129,10 +140,135 @@ First checkin #include #endif -#if defined(AF_INET6) && HAVE_IPV6 +#if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX #include #endif +#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX +#include +#include + +/* Converts a prefix length to IPv6 network mask */ +void plen_to_mask(int plen, char *addr) { + int i; + int colons=7; /* Number of colons in IPv6 address */ + int bits_in_block=16; /* Bits per IPv6 block */ + for(i=0;i<=colons;i++) { + int block, ones=0xffff, ones_in_block; + if(plen>bits_in_block) ones_in_block=bits_in_block; + else ones_in_block=plen; + block = ones & (ones << (bits_in_block-ones_in_block)); + i==0 ? sprintf(addr, "%x", block) : + sprintf(addr, "%s:%x", addr, block); + plen -= ones_in_block; + } + } + +/* Gets IPv6 interface information from the /proc filesystem in linux*/ +struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) + { + struct ifi_info *ifi, *ifihead, **ifipnext; + FILE *fp; + char addr[8][5]; + int flags, myflags, index, plen, scope; + char ifname[8], lastname[IFNAMSIZ]; + char addr6[33]; + struct addrinfo hints, *res0; + struct sockaddr_in6 *sin6; + struct in6_addr *addrptr; + int err; + + res0=NULL; + ifihead = NULL; + ifipnext = &ifihead; + lastname[0] = 0; + + if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) { + while (fscanf(fp, + "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n", + addr[0],addr[1],addr[2],addr[3], + addr[4],addr[5],addr[6],addr[7], + &index, &plen, &scope, &flags, ifname) != EOF) { + + myflags = 0; + if (strncmp(lastname, ifname, IFNAMSIZ) == 0) { + if (doaliases == 0) + continue; /* already processed this interface */ + myflags = IFI_ALIAS; + } + memcpy(lastname, ifname, IFNAMSIZ); + ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info)); + if (ifi == NULL) { + goto gotError; + } + + *ifipnext = ifi; /* prev points to this new one */ + ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ + + sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", + addr[0],addr[1],addr[2],addr[3], + addr[4],addr[5],addr[6],addr[7]); + + /* Add address of the interface */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_flags = AI_NUMERICHOST; + err = getaddrinfo(addr6, NULL, &hints, &res0); + if (err) { + goto gotError; + } + ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6)); + if (ifi->ifi_addr == NULL) { + goto gotError; + } + memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6)); + + /* Add netmask of the interface */ + char ipv6addr[INET6_ADDRSTRLEN]; + plen_to_mask(plen, ipv6addr); + ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6)); + if (ifi->ifi_addr == NULL) { + goto gotError; + } + sin6=calloc(1, sizeof(struct sockaddr_in6)); + addrptr=calloc(1, sizeof(struct in6_addr)); + inet_pton(family, ipv6addr, addrptr); + sin6->sin6_family=family; + sin6->sin6_addr=*addrptr; + sin6->sin6_scope_id=scope; + memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6)); + free(sin6); + + + /* Add interface name */ + memcpy(ifi->ifi_name, ifname, IFI_NAME); + + /* Add interface index */ + ifi->ifi_index = index; + + /* If interface is in /proc then it is up*/ + ifi->ifi_flags = IFF_UP; + + freeaddrinfo(res0); + res0=NULL; + } + } + goto done; + + gotError: + if (ifihead != NULL) { + free_ifi_info(ifihead); + ifihead = NULL; + } + if (res0 != NULL) { + freeaddrinfo(res0); + res0=NULL; + } + done: + return(ifihead); /* pointer to first structure in linked list */ + } +#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX + struct ifi_info *get_ifi_info(int family, int doaliases) { int junk; @@ -150,7 +286,11 @@ struct ifi_info *get_ifi_info(int family, int doaliases) struct sockaddr_in6 *sinptr6; #endif - sockfd = -1; +#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX + if(family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases); +#endif + + sockfd = -1; sockf6 = -1; buf = NULL; ifihead = NULL; @@ -191,7 +331,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases) ifr = (struct ifreq *) ptr; len = GET_SA_LEN(ifr->ifr_addr); - ptr += sizeof(ifr->ifr_name) + len; /* for next one in buffer */ + ptr += sizeof(struct ifreq); /* for next one in buffer */ // fprintf(stderr, "intf %d name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family); @@ -534,6 +674,8 @@ struct in_pktinfo #ifdef NOT_HAVE_DAEMON #include #include +#include + int daemon(int nochdir, int noclose) { switch (fork()) diff --git a/mDNSPosix/mDNSUNP.h b/mDNSPosix/mDNSUNP.h index 786fef7..912c9d8 100755 --- a/mDNSPosix/mDNSUNP.h +++ b/mDNSPosix/mDNSUNP.h @@ -24,6 +24,9 @@ Change History (most recent first): $Log: mDNSUNP.h,v $ +Revision 1.18 2005/04/08 21:37:57 ksekar + get_ifi_info doesn't return IPv6 interfaces on Linux + Revision 1.17 2004/12/17 19:32:43 cheshire Add missing semicolon @@ -90,6 +93,10 @@ First checkin #include #include +#ifdef HAVE_LINUX +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -99,8 +106,12 @@ First checkin #endif #if !defined(_SS_MAXSIZE) - #define sockaddr_storage sockaddr -#endif +#if HAVE_IPV6 +#define sockaddr_storage sockaddr_in6 +#else +#define sockaddr_storage sockaddr +#endif // HAVE_IPV6 +#endif // !defined(_SS_MAXSIZE) #ifndef NOT_HAVE_SA_LEN #define GET_SA_LEN(X) (sizeof(struct sockaddr) > ((struct sockaddr*)&(X))->sa_len ? \ @@ -146,6 +157,17 @@ struct ifi_info { struct ifi_info *ifi_next; /* next of these structures */ }; +#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX +#define PROC_IFINET6_PATH "/proc/net/if_inet6" +extern struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases); +#endif + +#if defined(AF_INET6) && HAVE_IPV6 +#define INET6_ADDRSTRLEN 46 /*Maximum length of IPv6 address */ +#endif + + + #define IFI_ALIAS 1 /* ifi_addr is an alias */ /* From the text (Stevens, section 16.6): */ diff --git a/mDNSResponder.sln b/mDNSResponder.sln index 423805f..a034e3e 100755 --- a/mDNSResponder.sln +++ b/mDNSResponder.sln @@ -34,6 +34,7 @@ Global {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} + {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.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} diff --git a/mDNSShared/PlatformCommon.c b/mDNSShared/PlatformCommon.c index 3baee26..6ec40da 100644 --- a/mDNSShared/PlatformCommon.c +++ b/mDNSShared/PlatformCommon.c @@ -24,6 +24,10 @@ Change History (most recent first): $Log: PlatformCommon.c,v $ +Revision 1.6 2005/04/08 21:30:16 ksekar + Compiling problems with mDNSResponder-98 on Solaris/Sparc v9 +Patch submitted by Bernd Kuhls + Revision 1.5 2005/02/01 19:33:30 ksekar Keychain format too restrictive @@ -44,7 +48,7 @@ Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c #include // Needed for fopen() etc. #include // Needed for close() #include // Needed for strlen() etc. -#include // Needed for errno etc. +#include // Needed for errno etc. #include // Needed for socket() etc. #include // Needed for sockaddr_in diff --git a/mDNSShared/dns_sd.h b/mDNSShared/dns_sd.h index 81e0856..fa18cce 100755 --- a/mDNSShared/dns_sd.h +++ b/mDNSShared/dns_sd.h @@ -48,12 +48,14 @@ #include #define _UNUSED #define bzero(a, b) memset(a, 0, b) +#ifndef _MSL_STDINT_H typedef UINT8 uint8_t; typedef INT8 int8_t; typedef UINT16 uint16_t; typedef INT16 int16_t; typedef UINT32 uint32_t; typedef INT32 int32_t; +#endif #else #include #endif diff --git a/mDNSShared/dnssd_clientlib.c b/mDNSShared/dnssd_clientlib.c index 40ab0d0..6284b1e 100755 --- a/mDNSShared/dnssd_clientlib.c +++ b/mDNSShared/dnssd_clientlib.c @@ -27,6 +27,9 @@ Change History (most recent first): $Log: dnssd_clientlib.c,v $ +Revision 1.10 2005/04/06 02:06:56 shersche +Add DNSSD_API macro to TXTRecord API calls + Revision 1.9 2004/10/06 02:22:19 cheshire Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)" @@ -196,7 +199,7 @@ struct dnssd_clientlib_CompileTimeAssertionCheck char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1]; }; -void TXTRecordCreate +void DNSSD_API TXTRecordCreate ( TXTRecordRef *txtRecord, uint16_t bufferLen, @@ -209,12 +212,12 @@ void TXTRecordCreate txtRec->malloced = 0; } -void TXTRecordDeallocate(TXTRecordRef *txtRecord) +void DNSSD_API TXTRecordDeallocate(TXTRecordRef *txtRecord) { if (txtRec->malloced) free(txtRec->buffer); } -DNSServiceErrorType TXTRecordSetValue +DNSServiceErrorType DNSSD_API TXTRecordSetValue ( TXTRecordRef *txtRecord, const char *key, @@ -259,7 +262,7 @@ DNSServiceErrorType TXTRecordSetValue return(kDNSServiceErr_NoError); } -DNSServiceErrorType TXTRecordRemoveValue +DNSServiceErrorType DNSSD_API TXTRecordRemoveValue ( TXTRecordRef *txtRecord, const char *key @@ -276,8 +279,8 @@ DNSServiceErrorType TXTRecordRemoveValue return(kDNSServiceErr_NoError); } -uint16_t TXTRecordGetLength (const TXTRecordRef *txtRecord) { return(txtRec->datalen); } -const void * TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtRec->buffer); } +uint16_t DNSSD_API TXTRecordGetLength (const TXTRecordRef *txtRecord) { return(txtRec->datalen); } +const void * DNSSD_API TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtRec->buffer); } /********************************************************************************************* * @@ -285,7 +288,7 @@ const void * TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtR * *********************************************************************************************/ -int TXTRecordContainsKey +int DNSSD_API TXTRecordContainsKey ( uint16_t txtLen, const void *txtRecord, @@ -296,7 +299,7 @@ int TXTRecordContainsKey return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0); } -const void * TXTRecordGetValuePtr +const void * DNSSD_API TXTRecordGetValuePtr ( uint16_t txtLen, const void *txtRecord, @@ -311,7 +314,7 @@ const void * TXTRecordGetValuePtr return (item + 1 + keylen + 1); } -uint16_t TXTRecordGetCount +uint16_t DNSSD_API TXTRecordGetCount ( uint16_t txtLen, const void *txtRecord @@ -324,7 +327,7 @@ uint16_t TXTRecordGetCount return((p>e) ? (uint16_t)0 : count); } -DNSServiceErrorType TXTRecordGetItemAtIndex +DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex ( uint16_t txtLen, const void *txtRecord, diff --git a/mDNSShared/dnssd_clientstub.c b/mDNSShared/dnssd_clientstub.c index 8cf98d3..ffc7111 100755 --- a/mDNSShared/dnssd_clientstub.c +++ b/mDNSShared/dnssd_clientstub.c @@ -28,6 +28,13 @@ Change History (most recent first): $Log: dnssd_clientstub.c,v $ +Revision 1.47 2005/03/31 02:19:56 cheshire + Fix build warnings +Reviewed by: Scott Herscher + +Revision 1.46 2005/03/21 00:39:31 shersche + Fix build warnings on Win32 platform + Revision 1.45 2005/02/01 01:25:06 shersche Define sleep() to be Sleep() for Windows compatibility @@ -266,7 +273,9 @@ static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int char *msg = NULL; ipc_msg_hdr *hdr; int datalen; +#if !defined(USE_TCP_LOOPBACK) char ctrl_path[256]; +#endif if (!reuse_socket) { @@ -369,7 +378,7 @@ static DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reu char *data = (char *)msg + sizeof(ipc_msg_hdr); dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket; int ret; - unsigned int len = sizeof(caddr); + dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr); DNSServiceErrorType err = kDNSServiceErr_Unknown; if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown; diff --git a/mDNSShared/dnssd_ipc.h b/mDNSShared/dnssd_ipc.h index 58c0ec3..a04eacc 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.20 2005/03/21 00:39:31 shersche + Fix build warnings on Win32 platform + Revision 1.19 2005/02/02 02:25:22 cheshire /var/run/mDNSResponder should be /var/run/mdnsd on Linux @@ -89,7 +92,8 @@ Update to APSL 2.0 # define dnssd_EINTR WSAEINTR # define MSG_WAITALL 0 # define dnssd_sock_t SOCKET -# define dnssd_sockbuf_t +# define dnssd_socklen_t int +# define dnssd_sockbuf_t const char* # define dnssd_close(sock) closesocket(sock) # define dnssd_errno() WSAGetLastError() # define ssize_t int @@ -109,6 +113,8 @@ Update to APSL 2.0 # define dnssd_EINTR EINTR # define dnssd_EPIPE EPIPE # define dnssd_sock_t int +# define dnssd_socklen_t unsigned int +# define dnssd_sockbuf_t const char* # define dnssd_close(sock) close(sock) # define dnssd_errno() errno #endif diff --git a/mDNSShared/uds_daemon.c b/mDNSShared/uds_daemon.c index 964d2fc..9dc98e4 100644 --- a/mDNSShared/uds_daemon.c +++ b/mDNSShared/uds_daemon.c @@ -24,6 +24,14 @@ Change History (most recent first): $Log: uds_daemon.c,v $ +Revision 1.182 2005/03/21 00:39:31 shersche + Fix build warnings on Win32 platform + +Revision 1.181 2005/03/20 20:21:32 shersche + mDNSResponder crashes when incorrect interface index is passed to DNSServiceRegister() +Text record length and data parameters must be initialized to 0 and NULL to ensure that the service request +object is cleaned up correctly when encountering an interface index error. + 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, @@ -645,7 +653,7 @@ typedef struct service_instance domainname domain; mDNSBool default_local; // is this the "local." from an empty-string registration? struct request_state *request; - int sd; + dnssd_sock_t sd; AuthRecord *subtypes; ServiceRecordSet srs; // note - must be last field in struct } service_instance; @@ -834,7 +842,7 @@ static void handle_query_request(request_state *rstate); static reply_state *format_enumeration_reply(request_state *rstate, const char *domain, DNSServiceFlags flags, uint32_t ifi, DNSServiceErrorType err); static void handle_enum_request(request_state *rstate); static mStatus handle_regrecord_request(request_state *rstate); -static void regrecord_callback(mDNS *const m, AuthRecord *const rr, mStatus result); +static void regrecord_callback(mDNS *const m, AuthRecord * rr, mStatus result); static void connected_registration_termination(void *context); static void handle_reconfirm_request(request_state *rstate); static AuthRecord *read_rr_from_ipc_msg(char *msgbuf, int ttl, int validate_flags); @@ -1164,13 +1172,13 @@ void udsserver_handle_configchange(void) static void connect_callback(void *info) { dnssd_sock_t sd; - unsigned int len; + dnssd_socklen_t len; unsigned long optval; dnssd_sockaddr_t cliaddr; request_state *rstate; (void)info; // Unused - len = (int) sizeof(cliaddr); + len = (dnssd_socklen_t) sizeof(cliaddr); sd = accept(listenfd, (struct sockaddr*) &cliaddr, &len); @@ -1279,7 +1287,7 @@ static void request_callback(void *info) { mStatus err = 0; int nwritten; - int errfd = socket(AF_DNSSD, SOCK_STREAM, 0); + dnssd_sock_t errfd = socket(AF_DNSSD, SOCK_STREAM, 0); if (errfd == dnssd_InvalidSocket) { my_perror("ERROR: socket"); @@ -1336,7 +1344,7 @@ static void request_callback(void *info) } err = dnssd_htonl(err); - nwritten = send(errfd, &err, sizeof(err), 0); + nwritten = send(errfd, (dnssd_sockbuf_t) &err, sizeof(err), 0); // On a freshly-created Unix Domain Socket, the kernel should *never* fail to buffer a four-byte write for us. // If not, we don't attempt to handle this failure, but we do log it. if (nwritten < (int)sizeof(err)) @@ -2206,6 +2214,8 @@ static void handle_regservice_request(request_state *request) service->instances = NULL; service->request = request; + service->txtlen = 0; + service->txtdata = NULL; request->service_registration = service; request->termination_context = request->service_registration; request->terminate = regservice_termination_callback; @@ -3053,7 +3063,7 @@ static AuthRecord *read_rr_from_ipc_msg(char *msgbuf, int GetTTL, int validate_f bzero(rr, sizeof(AuthRecord)); // ok if oversized rdata not zero'd mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSPlatformInterfaceIDfromInterfaceIndex(gmDNS, interfaceIndex), - type, 0, (flags & kDNSServiceFlagsShared) ? kDNSRecordTypeShared : kDNSRecordTypeUnique, mDNSNULL, mDNSNULL); + type, 0, (mDNSu8) ((flags & kDNSServiceFlagsShared) ? kDNSRecordTypeShared : kDNSRecordTypeUnique), mDNSNULL, mDNSNULL); if (!MakeDomainNameFromDNSNameString(rr->resrec.name, name)) { @@ -3342,7 +3352,7 @@ static int deliver_error(request_state *rstate, mStatus err) undelivered_error_t *undeliv; err = dnssd_htonl(err); - nwritten = send(rstate->sd, &err, sizeof(mStatus), 0); + nwritten = send(rstate->sd, (dnssd_sockbuf_t) &err, sizeof(mStatus), 0); if (nwritten < (int)sizeof(mStatus)) { if (dnssd_errno() == dnssd_EINTR || dnssd_errno() == dnssd_EWOULDBLOCK) diff --git a/mDNSWindows/ControlPanel/ControlPanel.rc b/mDNSWindows/ControlPanel/ControlPanel.rc index db16d91..51dbb77 100755 --- a/mDNSWindows/ControlPanel/ControlPanel.rc +++ b/mDNSWindows/ControlPanel/ControlPanel.rc @@ -60,7 +60,6 @@ BEGIN END END - #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // @@ -120,13 +119,13 @@ CAPTION "Hostname" FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN LTEXT "Enter a hostname for this computer. Other computers on the Internet will be able to reach your computer using this hostname.", - IDC_STATIC,7,19,248,28 - LTEXT "Hostname:",IDC_STATIC,15,55,35,8 - EDITTEXT IDC_EDIT1,52,53,187,14,ES_AUTOHSCROLL - PUSHBUTTON "Password...",IDC_BUTTON1,52,72,67,14 - ICON IDI_FAILURE,IDC_FAILURE,240,50,21,20,SS_CENTERIMAGE | + IDC_STATIC,10,19,245,28 + LTEXT "Hostname:",IDC_STATIC,13,55,35,8 + EDITTEXT IDC_EDIT1,55,53,184,14,ES_AUTOHSCROLL + PUSHBUTTON "Password...",IDC_BUTTON1,55,72,65,14 + ICON IDI_FAILURE,IDC_FAILURE,240,50,20,20,SS_CENTERIMAGE | SS_REALSIZEIMAGE - ICON IDI_SUCCESS,IDC_SUCCESS,240,50,21,20,SS_CENTERIMAGE | + ICON IDI_SUCCESS,IDC_SUCCESS,240,50,20,20,SS_CENTERIMAGE | SS_REALSIZEIMAGE | NOT WS_VISIBLE END @@ -136,12 +135,12 @@ CAPTION "Registration" FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN CONTROL "Domain:",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,13,54,42,10 - COMBOBOX IDC_COMBO2,59,53,189,46,CBS_DROPDOWN | CBS_SORT | + WS_TABSTOP,13,54,41,10 + COMBOBOX IDC_COMBO2,55,53,193,46,CBS_DROPDOWN | CBS_SORT | WS_DISABLED | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Password...",IDC_BUTTON1,59,72,65,14 + PUSHBUTTON "Password...",IDC_BUTTON1,55,72,65,14 LTEXT "Check the box and enter a registration domain to enable Bonjour advertising beyond the local subnet. ", - IDC_STATIC,14,20,233,23 + IDC_STATIC,10,19,233,23 END IDR_SECRET DIALOGEX 0, 0, 251, 90 @@ -153,7 +152,7 @@ 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 + EDITTEXT IDC_KEY,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.", @@ -182,7 +181,7 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,117,74,50,14 PUSHBUTTON "Cancel",IDCANCEL,173,74,50,14 - COMBOBOX IDC_COMBO1,35,42,188,30,CBS_DROPDOWN | CBS_SORT | + COMBOBOX IDC_COMBO1,35,42,188,100,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP LTEXT "Domain:",IDC_STATIC,7,43,27,8 LTEXT "The following domain will be added to your list of Bonjour browse domains.", diff --git a/mDNSWindows/ControlPanel/FirstPage.cpp b/mDNSWindows/ControlPanel/FirstPage.cpp index 9dfe401..48cf1ff 100755 --- a/mDNSWindows/ControlPanel/FirstPage.cpp +++ b/mDNSWindows/ControlPanel/FirstPage.cpp @@ -23,6 +23,9 @@ Change History (most recent first): $Log: FirstPage.cpp,v $ +Revision 1.4 2005/04/05 03:52:14 shersche + Registering with shared secret key doesn't work. Additionally, mDNSResponder wasn't dynamically re-reading it's DynDNS setup after setting a shared secret key. + Revision 1.3 2005/03/07 18:27:42 shersche Fix problem when ControlPanel commits changes to the browse domain list @@ -51,7 +54,8 @@ CFirstPage::CFirstPage() : CPropertyPage(CFirstPage::IDD), m_ignoreHostnameChange( false ), - m_statusKey( NULL ) + m_statusKey( NULL ), + m_setupKey( NULL ) { //{{AFX_DATA_INIT(CFirstPage) //}}AFX_DATA_INIT @@ -128,12 +132,33 @@ void CFirstPage::OnBnClickedSharedSecret() CSharedSecret dlg; - dlg.m_secretName = name; + dlg.m_key = name; if ( dlg.DoModal() == IDOK ) { - dlg.Commit(); + DWORD wakeup = 0; + DWORD dwSize = sizeof( DWORD ); + OSStatus err; + + dlg.Commit( name ); + + // We have now updated the secret, however the system service + // doesn't know about it yet. So we're going to update the + // registry with a dummy value which will cause the system + // service to re-initialize it's DynDNS setup + // + + RegQueryValueEx( m_setupKey, L"Wakeup", NULL, NULL, (LPBYTE) &wakeup, &dwSize ); + + wakeup++; + + err = RegSetValueEx( m_setupKey, L"Wakeup", 0, REG_DWORD, (LPBYTE) &wakeup, sizeof( DWORD ) ); + require_noerr( err, exit ); } + +exit: + + return; } diff --git a/mDNSWindows/ControlPanel/SecondPage.cpp b/mDNSWindows/ControlPanel/SecondPage.cpp index a330e84..b14c769 100755 --- a/mDNSWindows/ControlPanel/SecondPage.cpp +++ b/mDNSWindows/ControlPanel/SecondPage.cpp @@ -23,6 +23,12 @@ Change History (most recent first): $Log: SecondPage.cpp,v $ +Revision 1.5 2005/04/05 04:15:46 shersche +RegQueryString was returning uninitialized strings if the registry key couldn't be found, so always initialize strings before checking the registry key. + +Revision 1.4 2005/04/05 03:52:14 shersche + Registering with shared secret key doesn't work. Additionally, mDNSResponder wasn't dynamically re-reading it's DynDNS setup after setting a shared secret key. + Revision 1.3 2005/03/03 19:55:22 shersche ControlPanel source code isn't saving CVS log info @@ -46,10 +52,16 @@ IMPLEMENT_DYNCREATE(CSecondPage, CPropertyPage) CSecondPage::CSecondPage() : - CPropertyPage(CSecondPage::IDD) + CPropertyPage(CSecondPage::IDD), + m_setupKey( NULL ) { //{{AFX_DATA_INIT(CSecondPage) //}}AFX_DATA_INIT + + OSStatus err; + + err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &m_setupKey ); + check_noerr( err ); } @@ -59,6 +71,11 @@ CSecondPage::CSecondPage() CSecondPage::~CSecondPage() { + if ( m_setupKey ) + { + RegCloseKey( m_setupKey ); + m_setupKey = NULL; + } } @@ -109,7 +126,6 @@ BOOL CSecondPage::OnSetActive() { CConfigPropertySheet * psheet; - HKEY key = NULL; DWORD dwSize; DWORD enabled; DWORD err; @@ -126,20 +142,15 @@ CSecondPage::OnSetActive() // Now populate the registration domain box - err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key ); - require_noerr( err, exit ); - - err = Populate( m_regDomainsBox, key, psheet->m_regDomains ); + err = Populate( m_regDomainsBox, m_setupKey, psheet->m_regDomains ); check_noerr( err ); dwSize = sizeof( DWORD ); - err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize ); + err = RegQueryValueEx( m_setupKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize ); m_advertiseServicesButton.SetCheck( ( !err && enabled ) ? BST_CHECKED : BST_UNCHECKED ); m_regDomainsBox.EnableWindow( ( !err && enabled ) ); m_sharedSecretButton.EnableWindow( (!err && enabled ) ); - RegCloseKey( key ); - exit: return b; @@ -168,20 +179,12 @@ CSecondPage::OnOK() void CSecondPage::Commit() { - HKEY key = NULL; - DWORD err; + 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 ) + if ( m_setupKey != NULL ) { - RegCloseKey( key ); + err = Commit( m_regDomainsBox, m_setupKey, m_advertiseServicesButton.GetCheck() == BST_CHECKED ); + check_noerr( err ); } } @@ -244,15 +247,39 @@ CSecondPage::Commit( CComboBox & box, HKEY key, DWORD enabled ) void CSecondPage::OnBnClickedSharedSecret() { - CString string; + CString name; - m_regDomainsBox.GetWindowText( string ); + m_regDomainsBox.GetWindowText( name ); CSharedSecret dlg; - dlg.m_secretName = string; + dlg.m_key = name; + + if ( dlg.DoModal() == IDOK ) + { + DWORD wakeup = 0; + DWORD dwSize = sizeof( DWORD ); + OSStatus err; + + dlg.Commit( name ); + + // We have now updated the secret, however the system service + // doesn't know about it yet. So we're going to update the + // registry with a dummy value which will cause the system + // service to re-initialize it's DynDNS setup + // + + RegQueryValueEx( m_setupKey, L"Wakeup", NULL, NULL, (LPBYTE) &wakeup, &dwSize ); + + wakeup++; + + err = RegSetValueEx( m_setupKey, L"Wakeup", 0, REG_DWORD, (LPBYTE) &wakeup, sizeof( DWORD ) ); + require_noerr( err, exit ); + } + +exit: - dlg.DoModal(); + return; } @@ -470,6 +497,7 @@ CSecondPage::RegQueryString( HKEY key, CString valueName, CString & value ) string = (TCHAR*) malloc( stringLen ); require_action( string, exit, err = kUnknownErr ); + *string = '\0'; err = RegQueryValueEx( key, valueName, 0, NULL, (LPBYTE) string, &stringLen ); diff --git a/mDNSWindows/ControlPanel/SecondPage.h b/mDNSWindows/ControlPanel/SecondPage.h index a8d1f09..917608e 100755 --- a/mDNSWindows/ControlPanel/SecondPage.h +++ b/mDNSWindows/ControlPanel/SecondPage.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: SecondPage.h,v $ +Revision 1.4 2005/04/05 03:52:14 shersche + Registering with shared secret key doesn't work. Additionally, mDNSResponder wasn't dynamically re-reading it's DynDNS setup after setting a shared secret key. + Revision 1.3 2005/03/03 19:55:21 shersche ControlPanel source code isn't saving CVS log info @@ -113,6 +116,7 @@ private: CButton m_advertiseServicesButton; CButton m_sharedSecretButton; BOOL m_modified; + HKEY m_setupKey; public: afx_msg void OnCbnSelChange(); diff --git a/mDNSWindows/ControlPanel/SharedSecret.cpp b/mDNSWindows/ControlPanel/SharedSecret.cpp index 6c42aca..29636df 100755 --- a/mDNSWindows/ControlPanel/SharedSecret.cpp +++ b/mDNSWindows/ControlPanel/SharedSecret.cpp @@ -23,6 +23,9 @@ Change History (most recent first): $Log: SharedSecret.cpp,v $ +Revision 1.3 2005/04/06 02:04:49 shersche + Registering with shared secret doesn't work + Revision 1.2 2005/03/03 19:55:22 shersche ControlPanel source code isn't saving CVS log info @@ -61,8 +64,8 @@ IMPLEMENT_DYNAMIC(CSharedSecret, CDialog) CSharedSecret::CSharedSecret(CWnd* pParent /*=NULL*/) : CDialog(CSharedSecret::IDD, pParent) + , m_key(_T("")) , m_secret(_T("")) - , m_secretName(_T("")) { } @@ -83,8 +86,8 @@ CSharedSecret::~CSharedSecret() void CSharedSecret::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_SECRET, m_secret); - DDX_Text(pDX, IDC_SECRET_NAME, m_secretName); + DDX_Text(pDX, IDC_KEY, m_key ); + DDX_Text(pDX, IDC_SECRET, m_secret ); } @@ -98,27 +101,33 @@ END_MESSAGE_MAP() //--------------------------------------------------------------------------------------------------------------------------- void -CSharedSecret::Commit() +CSharedSecret::Commit( CString zone ) { LSA_OBJECT_ATTRIBUTES attrs; LSA_HANDLE handle = NULL; NTSTATUS res; + LSA_UNICODE_STRING lucZoneName; LSA_UNICODE_STRING lucKeyName; - LSA_UNICODE_STRING lucPrivateData; + LSA_UNICODE_STRING lucSecretName; BOOL ok; OSStatus err; // If there isn't a trailing dot, add one because the mDNSResponder // presents names with the trailing dot. - if ( m_secretName.ReverseFind( '.' ) != m_secretName.GetLength() ) + if ( zone.ReverseFind( '.' ) != zone.GetLength() ) { - m_secretName += '.'; + zone += '.'; + } + + if ( m_key.ReverseFind( '.' ) != m_key.GetLength() ) + { + m_key += '.'; } // attrs are reserved, so initialize to zeroes. - ZeroMemory(&attrs, sizeof( attrs ) ); + ZeroMemory( &attrs, sizeof( attrs ) ); // Get a handle to the Policy object on the local system @@ -128,17 +137,25 @@ CSharedSecret::Commit() // Intializing PLSA_UNICODE_STRING structures - ok = InitLsaString( &lucKeyName, m_secretName ); + ok = InitLsaString( &lucZoneName, zone ); + err = translate_errno( ok, errno_compat(), kUnknownErr ); + require_noerr( err, exit ); + + ok = InitLsaString( &lucKeyName, m_key ); err = translate_errno( ok, errno_compat(), kUnknownErr ); require_noerr( err, exit ); - ok = InitLsaString( &lucPrivateData, m_secret ); + ok = InitLsaString( &lucSecretName, m_secret ); err = translate_errno( ok, errno_compat(), kUnknownErr ); require_noerr( err, exit ); // Store the private data. - res = LsaStorePrivateData( handle, &lucKeyName, &lucPrivateData ); + res = LsaStorePrivateData( handle, &lucZoneName, &lucKeyName ); + err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr ); + require_noerr( err, exit ); + + res = LsaStorePrivateData( handle, &lucKeyName, &lucSecretName ); err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr ); require_noerr( err, exit ); diff --git a/mDNSWindows/ControlPanel/SharedSecret.h b/mDNSWindows/ControlPanel/SharedSecret.h index 07e79e1..804f6b4 100755 --- a/mDNSWindows/ControlPanel/SharedSecret.h +++ b/mDNSWindows/ControlPanel/SharedSecret.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: SharedSecret.h,v $ +Revision 1.3 2005/04/06 02:04:49 shersche + Registering with shared secret doesn't work + Revision 1.2 2005/03/03 19:55:21 shersche ControlPanel source code isn't saving CVS log info @@ -51,7 +54,7 @@ public: enum { IDD = IDR_SECRET }; void - Commit(); + Commit( CString zone ); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support @@ -59,6 +62,7 @@ protected: DECLARE_MESSAGE_MAP() public: + + CString m_key; CString m_secret; - CString m_secretName; }; diff --git a/mDNSWindows/ControlPanel/resource.h b/mDNSWindows/ControlPanel/resource.h index 1fbf6a5..a4e4014 100755 --- a/mDNSWindows/ControlPanel/resource.h +++ b/mDNSWindows/ControlPanel/resource.h @@ -23,6 +23,8 @@ #define IDC_FAILURE 1008 #define IDC_SUCCESS 1009 #define IDC_SECRET_NAME 1010 +#define IDC_NAME 1010 +#define IDC_KEY 1010 #define IDC_LIST1 1011 #define IDC_BROWSE_LIST 1011 #define IDC_BUTTON2 1012 diff --git a/mDNSWindows/DLL/dnssd.vcproj b/mDNSWindows/DLL/dnssd.vcproj index 3975048..e048c02 100644 --- a/mDNSWindows/DLL/dnssd.vcproj +++ b/mDNSWindows/DLL/dnssd.vcproj @@ -33,7 +33,8 @@ Detect64BitPortabilityProblems="TRUE" DebugInformationFormat="4" CallingConvention="2" - CompileAs="0"/> + CompileAs="0" + DisableSpecificWarnings="4127;4204"/> + CompileAs="0" + DisableSpecificWarnings="4127;4204"/> hR@lDcPFsXDq_E%oTA%F0&fsIIB3mPR9KYO^Y{ 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

n}hsO~0UTS`Wc8qaD z8SXB&xMsR3ln$;5*-5ax*;h9>BGW$M#JP&!7}#tNYwDapt9>&^zjTmNr0IGlj*kyA zpUHaD8)8e@IO$5d=m{Pf$=g%9@GZ7BszqVLX-dR5(wvhluN~}!jME8CpMMqSbo8b@S07l%5g-Az5ih0ix7x%Zjn@ZOmP59N@gdw^x3 z2AGb_Grdh5{kW0iuGQJ~r{F0V(tv+8xLbY|>|zL`e%l!ygw)(b!fBZDxzV-@PxnbW zlp-7Bg#wIGl(FKKjGT!6QCs!SjH5LnupLv(X2Wi-e$=cQZAUBu1+fC`z8slM2dT|R&L5`}Y;5yam5Eb0R- zgq)HP6RWC_NP$WjIefLv+LCqWYIExb(}6npM8yNm0(ChP2ICjf%o!CE-JcG|XJ>-g z{o#|?XJ}4?-bE@1G3%jdqnAW`GU(I3mw@CrgpydX;)ODs=o$4Ad56hZ$4YOt>#ek> zB#hj&ihDOy9+9bYF*OSzODyb}^mY+%7Tm*rW^Z=f!F?e5e}*+DFN&;ok`QXTjD?>X()0$qjMH*$(St_6%tJ+a(J$dGhnRn1^m*o~9KQ2mSj;L1DB1C&!IgfekqSSeNp3+ zm+MPqXV~W?&M*dY*$qv>A=^O<>K4?#72M2*e4rG@nDKw*<=Q&JrtX144b4zl$VYJ} zX|0Kq0uQk_>||4et&6?SasF>c<)W(ojrOJp77uXCUnGU1F)O`xRi||FDcTo5uZ{M) z`X->LO4qKkTxF84>7?;?q%>R``220?!u3Iy*X4D8<)H9FsQ69BF@0ZEM1tdupEME& z-=glfE|It{T)|Xnnn!F#{ET+3K^TXlSjg0kBKT*Zeu37JZXEFLqOazGR)AYKIEq{Z z@#^hh&y$CcZ*cswR;&Akk76kfqnBzFO{TZnn?9E^XPpL3CATIs8Cq$ff2$YlusDc- zN{BruC#|ohjI0u3KaGp4V)-`WcbaX-}afRJDB~cm=7+jh8#MUGpX}TE9nJT^XuBjXQ)9t#k z8z&#z_8|tWXXZVw6bIqydd()Dq0XvBu>)mOLDj{D+bsxtpce=XMa}5}78Ww*q{?WO ziOQx#5{cZTSG{{wpN!uvT#6AR58FC$T(c&ND0TKRq=SAt2c0_hd+mt-sWHPyP#aG5 zFP)w%&vJlsdG3tHU&#gv>(dzC^S7v>DA_EiZeoJ;V6PC^hm!aQVOhjX&p5zzaQR_j zl&!|wv@j2$3)Iq{Srt!de*}%c@)YO{HG%ZViYuM9&QnqxowFw0a6B*I zv%Jp}Uv>r00V?kWKyI^u>5m^vudjx?q)CZqnyUm-`rR zDue6<92=ddr;z+M9n*cpOMo8&(Rd(TDAp45X6I*rAe*Grjr+9up zu~ml$uuxEbIx|vj9vIy>9bWz$D(|KURW7Nm%sj~r8Kb2X!X0?ybJWv^B zE1>cVKe9nkJIS6vI1ql+U!Da{hIipqc$A;Q3FnF{h`R90ygvXakC(|yI9EHXZ62qV z(x0o(scf;G)#fT!><22Z-qlX3xA3U*PlXf35nj|Egj;aVK5!U#tZUgTZpi?w+AnV_;A(V48WE72*LUO)B0 zH9&SSYTK^?!kPNL#1Ym( zA~;yz{ERSBKRNg;<9ujIQ#=guE}C=LO~l+``w_=$xuTIK~HLd&loC0PBoFfe3_xx(Zw5+hpdy;92U53W0v`H*aCJk?i8^1tkly5G* z99rt)d#(OffMCDqD>JJ*Hw*M#GJnMdsUFRbCc`MysJy$yvV`NIGRp3OsJJ{9(!)4Vn z1QMh zQJHCq$Sb7S42UtoOcGq_X?a;=_Z_yjniwg)?mcacSf#ipI4aZr-MH_}3mnlX}L!i%>{t251+qziV^D?DJyM?P2>@o!*lcBqXM7Ah{ z#s0Qy=Fu^ef_GZJtXfvWv_j^9dQ3@W>4UL4rZgcry}H`X2ENi=r*}pEUfn5#WZxs3 zpyf$-{keqKqed|mBMzXiF9*Tnt3KlzX?C2 zE^QOLP>4_qf^$kjR#M)n5{nSqSOKTI=>e=dX*RY>RxOH-?Je7Bm^vyEzj~d8yIZ-} zoW48N(ROb$BWr6YYCu6w*VnGsG*)bc*q}7ADN8*(kti{+x7uu6&+BcrEqKD)%l_Vp z@m9={zS3c1m81eOAg%00 z*TeqP%=socT1Qu=arm*8gf^S)PQV?Q$ac8OH_l3?@k=yeqITUr8>3rnjDlgn%s{va zGn#2r)I>K{QTmBkAe+&rkIDrkY@MFEdhVUh;6~itgq`^Zsx0E?q-`ynb7(!KiR|BY zv|I02#j=(7WktCh)9?(P0Eo&nW6O}K&%}+0F&5CIi<{C5iUO2Nrw@j1EtQ`*c}9h{ zKAFaI3|gG2k@8xyML}DrV0O&l%IwJ*8g^UFi>3LCm(HKNaQ?!@(&<-g%eA$7b%R@; z*!07W+FAddF;Sro=TJ0FaZEkgfZRw7*vcgfad#(ccd@unyna2)#nA zF*@V>aiBp-(CT8NzEECbkH7Hl%jsp>BkbKtibXfUgbOJxHlrA#1qC1*_e^mkGs6Q^ zx}}&@&E&xCP9`k;!ee7}r#X0Vx)kz=#G#>CTKcv}8Xzx*^qE9@LG%bk!y z;mlJkIguHHT;)<~ZcAv*mU3!4nGr~_t3};J4l{tby~-oUiiY$xuc@(E(W^ z-YB9z3Jo$XpMtX6=w6$aAOL-}IrX?CcKS zkaHq6 zR65<~irtcHc#w0_Nf^wT4(m+Xml!=sxN)Cp$O#=Tno-0)H(4{aDSVUGMkQ`U<2(q% zL!7sxoK_J{ObaH|5mi9}J32>m@nt@~oQp5#69PZQsxj}<5aj%v;%$wXz-@q&UGkCb zgp@;lJIuA{N2q%>HT+3PZZ zu?(krTUzu%pX$^b!uf*bkLKkYqIFB=Q zHXW|3Ys1x;p~@hb9`R+vSajg9#O$c{%a!XMfRr-f0$)(2cz$s)c# z$lu;uXG1&`Q+T(oln0%_Z0=>V-Qn0x0%jOynZ5;~;g1w_*X&&J!zHL6R=;IxwIjl)Yab1v}_EI_f-aK1UtV_w3bK$Q&?ClmVLaJ*l& z3pKQ33gwKNj{~6K+nLTK22I-67!yC2Kvs(rLA7JW_7k(LcYfOQiDmcwUs|Lv%V;@E zyZY_LWG6$c9SIjT%i2;%TqVnZmBkv;2e&X~^OZW4q!MCFol*8oqA&x34RhiG5>Ayp;mXb1I5q-YQthKY)Gm3;Ymu`&26fj*R|7Tg^QfJi}*#0 z@8OeA))%+~d3B?*wpv|TTB&sVHDpyvndlspK$NiDHA6nDd4Bxs5TZ3+R zmjAQo*PFYDKrRJbUa#vQs-i|-ZI6`*W&}ew1MG50jBk9bHjO!YYwjJDrLnQWD3jQ0 z84i8J&sBKx$;2%>O@uYe;%2uHICGl_9h#vKI=G#iU3lYqqrSXeTYJ5-XotLbQ7dbq zR@L1;M~WcCi1$g?Uau`;>atw9vRG5(tDJY#xVBKQEUvuj)k30QU8}FIZ@gYxYjE{6 zCz3YEL%xUmfQ|{@mBocAad4FwbY*3IV|8V1ePem$$tUSftCi(9HXWU9~l0*3&f z3m;KA6F${?Z?0Tl+n{eRT(43f3K9Geql)AN=_QUkQjtmWGn;(p+S4MlBnRNuZ*J72ka<+<833l}Q$&z!H#&OcMRGQaT5r7H{1U%XmJJBjd6h`PRID0@?^lqL8O23jEKax*^(!`2n7k*OFI?`BjeLkER7FRB27)utc1KM0 zvhy}c8h&`+5tvb%mfiNO{fn%vZ0CSzQ&ysU&Ve#Phhqs_c@QQFO`T4>6gh_RH6+-( z3BAozglx;mCo4hMlECV+hKMd&&1~DxZN4Osnm6veu(F;j(M0cb4#Lwa%7yNpbrI4mXA$w*`Ctm z#%^M2Ih}35oY+IW%NDw*Q}fv(6Ew&2sW!GqCpTXKHoM^ln2q{y37IhxPZ?=1baytg z_V^8y(XZSn8tuX%D>-|MY8arO|ducYtJksQR z`P3e04zs+@XUWxv6P}!ey+YRxhrB3GSbp6Rj?j?D0WgprNb8lzEDUV%huGYjD-&@I z1~(+(qWNUA@HQY@3Y{IGd*x*FAX^IATgc8qwj-B#>Rw^l9muXhb{F!~9e%Q*kbQ(~ z6J*<=^B!amB0Gb4&Vy`66i)URvY`;jO>txgp|l>sRsM>jn?T(*!_T3341e8qeT}DJ z0GuGikY^82XxVzGe7Xlt@2Z1rXH<_b1G2wZ1nwgroe81zWltpA3E4=fPO_6wT;ZX@ z_Z{G?z^?}00XFfg@zk9cs)KAul;$@9x5=3~_9fn51aynKaH;yJ9Oo>I+vUinMCFtn zi1J+mWXqvcg|`$`U)eyZb!5YFmUrPzX+8oLRbJV)2%oBp&NWdO*@LLgy1UtJVRV0o z+Xo5fYAcLHtzXnUhF z3upIZF(X_lp3-jvN_!6YF+lxKet!On-@J`0@w|@w!BD4a_Mf-efoTr zO`AbJ8KoUmAC~!=#ZXS zaurQYCcV|72gadrrC-9{G^0@37Fn4*)z!~1Bi*5|{E7=Vn|vEl`06>?>7FCy8>~w( zEY)XL5u@-jq(`Kxm1(97VLLj??u|S>=2I!l3Y*mL`ZUmDep>5&?+yc9lYY*0hGC%~ zru1sErcHZJ(yJ!Ubv10W{DjXkogar#h@+0(=m_r*r0_ENYFNwr0eMH{7^)bQleUP< z=I2gl&*o=GNI0xey(~YF*YZM|lpO=yveOu?Pb8XoMRJzV(cz(t*^M4Fq4;bVTD1Mz zc3bho@^J5Tw#nQ}vEH=n46XYy98sCMnncnMPkY*#y=8VArY)E;u}SmUKuVkTD578$ zP@aJ#`*})EDJ48Jbvp(-YG|0(rpA)(R`GK zxkXjSV~bd9v%QqNZdK@PBRf$iWtTaXFaf5wh{VDflVFKpbQH)zC}Kc;KvVeA+RhNA z7n4hcrdi~i<`r3BzN+)Pvh!2Xk6Um}9rdV@OXrc0E|N;u)=lwKRug4IXv{`GIk)XD zRfb3?cd$+aMOLpBW_ay}w0bS<9F~My}2jAH--^kn9R!B9}t6Am|SvO3%2Q$e2dDF9FS7 zne)f5^+)h?eBHv3{0)v18%(7dxFa~Rb0Tc&Dv*wh?b0}4@TzQ_J~|kYz8ihehGrKV zh=?^q?7cA{$b@%^!KRiX9~x5#SWar)uFdVDG;QuMYMs3mry*(stO~gACTGNv@oMG+HqVbu(|Noo;6(F8K3tOH;0}nT1HL zhHjZc!SF=egu6V#Dk3QTHAc!@x^VfqNZK+vpoyF`;l+toBUiiX?h4u z&t^ZPTcTr)*pk`81i4#~ZF5w8eCzb2K*hlx&SQA7>2c_Xa3FGc6!U9{vrM_ z*^@dEdBW4ypE2t=kR@@>W}b;OjtKWC3mvfTj z0+UkQ!y!jsA@Aol9zG?|39Quus;vb?Ksed3B?1x#pJc#<)b!#9eu!&QvZXE42x7Dy z#N8o4WWx$gN*kJ-xy-IlU+j3PLezMCDJ(R*&PSzlb4uNAZ(%j9Eicwf3b@acG(m*< zQGU0ur1097Lxra+Cf_fS zjL}QX)pQJjaRkB{RbuE$`wXHKJr4zb()*So8Y7la$BQQjo3dQ1A27f6DpzpXX-B2g zYtn?js$D*3OIKtJWfvUHJ~Mye!r77nzF1l-eX%ru;o=uw_2<{;zrcYD*xmK_bVihI zEg~ClI_-ohR|XsoYkw};-{F>KUYEKyv&Rv)ViJJNF2vaz)@jj--btMm%GTUakXF`i1p-j6 zY-+}o@Yj`GWLEp?x^!D+y;N{Sul4Gcf(yE_*NQG&cDqz`LE*L3?j3kWh1h7j%%??{ z8gV5?!Be;0n{T&UT`2mX0t`Njl9LoYxsWz^h9h$d-obY)#gNrxY9Xg-DP_vWfH7$p zkwADgr&Lx-#@v5um31L+7G$i5x|=uin=Ghq>dm~T6<0U+DnQJ*vZ;12;6``(7J|gE z#ZVwC4K-d)P?ma6DJqytLrg2}yd$%^P}!U)=DZ^kzp3S$cO+I9#tNppt;x2!Fj*qq zaxJf2wrNOQw%pz+RC(TUm-(;uhedx!oT9F>5@)_GdOOA}-)Z%6jJfypDmlh1#8|D) zIik$V{uFXP=cqD|X=py@xC&lV%686?76VKz-8siz2s5P+j=kU?9>roh{(SWw8eqH) z&N&hbVaD6xoMSQ%Lx72N9G8VK1>d;423*m>O-CQI2$OS(Yme_urxD1EZ@ zjndIRjK)xU$0a~I;|~G5fOPaP@$3SMDSd3zcb2hIZ0AHR;qB=U_<0crJcoeFp>RJAdP(iSM6 z6ja7n2&1wnu0T3joeLpduRwTx0Bp$~KxI%I;a~^&{lE_cs-w;#xu2&X>WhUJy$hso z7U)C>ed|1qhjGI(t|6!p7$K`jNxKFDy#BSS)y)S@l_r@<*%p8si(q7kFBTl_Ik=M#?>>1i~h0| zNd5ILkltI*@%X}x+*MXRV}9`|9LhaD^`3^0b&KI+d18LiJ;safhdpC@(O-54iW}<} z%b|SKX0abedm7na{78Tw{7< z(pE>=auzE$Q{K;6+^`Dq+=H;?pMLJP<}KVgtli$KcU+?R;dgCh>MW76D%rZr@u#Y1 z?p}Xi?1LJsUA_Up@kz80Uf6RcKV%vfH6}wDn2yx-yvQbeU8A-%#kblcYSKbGdV?VC zv*QAAJjEvDQ7=zG-ZmP=Ry>hUjZ9nl-aC*G1(jt}!*xLrY4^k!aeIUXc-nN%M!Dy?vHQti!^VPm_eivMVJkcNB_Bu#_!KgO)rl>|&Tq z0?lC$`4w}Qr(RaJI~wi3@a(gOu8plT0RJ`HRJ@6!tT?7_aIg)$q+!$$-7 zxo0k1xL|Pp!t8~j|9Wk)wt8)4xi&Rbt<&@HsWp6kVWY9WhWYkf!Jo@rE9*5G(Noub zjID#O-TS)!=4x%jP*z$%LSuPU-XE5}zj9|HEY}$ox4*BJ_ErLoy{THDy`qt%za&m^tZez4ZAHl)&6u ztAqYGkFOp7%(35a{M-yY+02ERi!=WiM&bDV_uT)X`~TF3UY>bn=Bvkl?B1^(ug(1U zy?^|^wR^74eC_yWj<3wD&OCAaYsWcz>iAb@-X!ijGhd(Cm{~l2b*4SDJ+m{jJJX%{ z^nGi`ze)H} z_pf`8sl=80-n#GjiTh9J`8J`}j+c&o?f63{Jj~aQKX&44#~(lO#EB1|SUmn$@Bh>Z z=Fbm(`ow2&eUkS-aNiG{cF%oP>gwt+-95dtMn|KYkwD4EiLZgbhS1$0J$o2O8ry}z z$Zd!*)EH(AH%1u88Y7JpjR{5*=_F&KQDO8|$BBK^8bSgV+^$Vf8wwxjUm0HmUq{?5 ze`9=W#5Tq@Dl3)M%Ie+gr8TkjyWs|G?71PaVZcUm6r;PeX7_q!bpcH3K#Z8+NbH-3Yf*s$@=Cox34-W6sK4NCkbJm*e^zXhQOKZ^$7Xd~I@85|4CM z&y_u)ksrGQq4fhGkN8M)a)R#$Ag_9%yaucnHsr3)-N4E?0NPWIVX36uZsg7U-J6L< zPO9t)nWSByd16B@^v?A(B#E#GS!(_6Rb(H8Hv8#U4p<2a*=iO1l}vi>O3G*V`kw1^ zR_34#JvZ#$04r6Zv?vR?94}|2U8z(ISYHo%5``pF%7iD6a!ah*jWUwl-78OCnShl@ z>!4l);zVjnOSXS%CGz%cMZQ$&VS(Sh(knGlk)!V@1<}^$0=FAEkQ3mfN}>P<8l-vr zEImuj!<25oMrAd$SefhDb2l_a9CD~6q!(#}wt~84ccP=*Xe(YxJPBTItEp^W`H&`e zbM9vFp#&&B(t_J>Rj3J)RtcM~kHN8c&Sokrk6OW5dcq}s|w?F?8S+sN!fwx>Fiu0jYU#@*{rWJj_d zS&qu8Aw;$U4ziIJxWIWB#3?$L=79rZS96=>0@Lny>YwbyB$95haqcR#=~d7UJ=V7$c&W5rFGU`(!{*)4 zS-L8ykDjmudM#NC645irhUn12C@^59unzJn{q~5q)EpM|(!zq2j%<$B z&+_sqEG}K8R7jQ7$1z$}Lh5>qC&*7)!`d6w1#XXU}Enw9(G!9dnz$lH8gtSGOHrCr*52KHA8PY-h6qD@@N6CLGQ9=?(4#9E;(nrKZy%GyLB0 zH2kYE`{5tX*3c(;*OwG4lZYFH* zyd1o-3%#V9pHhxYN!okg?Zz8Ad?o>lg?#_*4uanMRCZDYhjH;W5KP5p#Mm!SBdm17 zn*L%3lWeSQ=xj@yOnG(i)Z;H8=kp@rOo;af+8K)3u}3VYH@*>=Nm{2IPwAsF(K_ca zJ@GN-Oyn-(F}d#5yVt0GeFu)5kcp!!Lk3?CO0DlSe3mLt)^vITzp~Q_etoAC{3=f) zWW%@5Qif?!RnT2$yCLOD#%;{K7Wu&o2l#x`8CLMBy;8S-PHL59cM`m>zGH7=L2i1bFafQZ; zj9GU|9WngD$Nzx}tum9MLSslqNvttuBz5V7PoLs|P$5n!O!YLXre0VhO_ejE2!{YN zwkk$xhmp$rZ<6Ezu}tRjc{8;#pOmR_GE%16W0Xvl$0(T^5uEkp2eI_-si^+!EOeX5okB$y|>C*&fc*3x+>{G+ZOInUTBj-Jc_%jw%?*tdN z2)xs>VWm=^zx*%}|C&X5;Q}4#x3mS6Grsl1&LGY9<^b8t);YDQ@*1bNeRSL>Lyu*~ z?vmq|Br8YOCO0--fNeGW%r;w6&XBd?aE7eyhcmRFm%|SFuoFJ>eLU~fei8gXO<>a{ zuc@Tez@F6XKwF_HqMDCv;ZMHUud(;OrqLL()-#Tj(DzdDHIzd7bT6CO&}1TO?Q%0@ z8eF|<S0=zDbH_*C_!KoohX_8Y zNfe({I!efzf}U%`@mw1cey*{RpAF64PrH-FipouvE=ouiGD^r+)}$>X39@CKE$3_* zXUmsAV4`K_PZv4^$1K60E>TY2&+(Z|3_h&hf`3?y(IID^G+^Ns5@2$B;m{U+qPdh# zZ-u|rjL$82qZ)cyKAY!zL(|cIzYIjQ-;;=xZoLO#k?AJO1;-BYw^nHxcgz`vZFkHv z2bKofbPDxWo)^8QNl}7#WBh^($K<^po*cTvh2?zxFs}3N9%R)y2VVk7Q-Doa!zv}K z3V)teG!rLd=<5+h-lr0H*I^s#DWrD%z+Gssp3ej_u~#Q5DT@xja*flqX_uQr|KnQ? zL;IohVR!E*2AG;9Ke6PWfeQ}Xm3oDwqsTalTaCO9846hqJMU(h%HOF+GE;sSkomt-;p;2EYVZ02|-{TmbRZ zgkK9#+mF|UUk^|pu%C}>0RI3#d=UJD0S*25A-+$t8YA2U&=kCbXb8Kxd7rJ zINcAQ0e^uXR&na56|C7&_)Pd*_(AwX*ewWn)8dK;i%rC1#j#?sI7^%-E)dTbw~8~R zNo25>JRGgs-xA>8fY!G)>>Pwqt;D3P8+A? zX;ZagZI(7qo3GuWeWrb(?bLqKe$`~%)@$kY^(K0b-cmn8&()9AkJ9_w%g2V^8>`=4klT7YpFK@aMp<0e>-klDz_c9r)+LuM7Wn_|%W@hfn!^icA{8 zr+%ttaEG8xP^+MJ!CJ;=XdUD}_uLO?C(QkU_QKq5v>WD7w2(8=mZ&vF-N9&I(z!dx@-73Nx^&!oE}y?)daeJRxq_xcv~u2eS-y^Xs< z^gHHed;RZh^g(j#GP*0!JIP&>!QF&j%iS&Lzk$08eL2wBS+wV$0!nZjuyB&7+sia zfKev1Yw3+XtuX@87(}BGjYHYpaTud$lwvLqqZN%;%oStYqLGWac^JWH4Eww84vc<( z-O+f-+)j*}-2LQ@pub`iWlq)uXJcHYk(Ign7-7?06O6jt?ggFlIA18e=z&-ZXwQHwEK3cQY`e)0ocPT#W9_B{0e-FwS$g93wt= z=XqoQI*k9^eTXLkbD!afkm`QG6C!Yb;Az1ehFsriczT4LgJ%hIHStVgu7US#IS9`e z=9=I+li9V$^M{^5+1y|}n^N70cvdloS4AmqsrLliiKkfL=zB|e;9=yaGrkU<6gA*t z!l8mGTH+9KDDE+g=U)ihg&pu4isyvl0VN0tq9{tDEGnWZYT|at87V4wiZm2lu?Eg% z(5Z|%kZ~~1H#EWtiKb#RjQt~VZlVq_$BQT6l*V}RL~(*hCnio7^KgcP=%+%8CC&!* zbn$afn>vUs5EEjBxKLaqE*2}rC1RDImzm6|8OHgw;sxS5@j~$;@nS#6u{c-3q>|=q z#j*0|LL=lwp)=%hkgC86+l5!<*W~TqNs>B9zeD~~-YI`2e=UC_e=C0{@521%d}W8w zMd_+^Q@Se_?6pu?qzr+UBc(HyvRYws4^|t3(oD@!55ozM?I>{q_WVk2skTyE zt8LUHJo*=~bRAe_oY+(CrS?|)sD0HT;t0TKHRhdS>4ou~omU~7^zu%wOb3nE6O}B8 z)et6%7pfPj7pv>lOVkbOrRrtsci?I z7}uXrn~6`Vif7Ab)g3q!^OE|q`ilB0O50a`8~69r_mlJw)sNIu#jWZ#bw7c(mS(7z zi%~P*s;u>_6~9AxKhz-OI92>seO3NL{ZrkYJeNdPY$y`O)kK8*LbE!Wg4SIJ)_G8+ zJP*(g)DF@P)*5P!w7zO9jqKJ+YooQ(aKzmSoNPAd&M0-?wOnY2=LVHqsN_$#+MtfF!PJ13R;Zvd0c5R0?6fLB$x>Nf~ z`x^Q-Lm9tSf7O1|e%Jm${8X_s%BAS4j_;G{j=n=^qt@2z=${Mw>HF&q^aJz*^@H?- z^@e&Q{SdvGx}V-uZ-x>5F#QW5Pt3vDuU~M!2_u8wpDxBcx4q6ziBX;Kb7IGfbWV)- zi}rfj~(TI49Ou-L6#_4TTBb>9D>kJ1a(~#A;*JT^r+W zsv``iq|!N-@dqh0g#sQXgQey2IF7h@YR-|WO{y-Om!;y;f)pIXWHISMnjkMOHJm38 zbDvA4IG04BKpw|)ZCDD%&pElYzz^i6rsFyVQqptgQW!5!!SmuNnOvSvm@Ar&%L{x; z6~t0Q)zMNp1Iwi5$YW7Sgy%FSDbPNk5ryMZ^J8fPI?tcWV$ylqC^yfU(V3J~`8++x z2ApATt|?JDCrcT`f>4x)r4DrDA(jJ=?VZo{<=hnK@&kEHm#`jO+W^NUu=HW=8Bh2g zPR;pw`qY$^il=0LK<5;WNvAUk&waFmCzJYNw|Do+Sq*sSq(i3o*og8aXF{l0tmf(&UA9G8i{w>U1t z_emx}^h!h!6c0m~O!&WjiHVG5<+e*i1V`f$@*bn%^b`&QqG?wm4Fg0}=W6OXV|tRg zhcuLqfL{p&2(n#?Y=j7YZ}}q0_9_~c9gXuc6F!ZW1qbwAU5N}_NnEDB!TGDBah`qt zf87EJXh0CX5HjJ}&x_K9(`E~& zJ=>8k)0GGzDa?UC<3i*hSWUm7^#9V8MRo#03Fu0AcXrDb4zaMH-$oL=t)wwzK}6?B zK3gISJE4gd21L_zCVKQr0Kp+lBivqHu$^}ib1XH_y-H6^7!eau<}fZC=6rjL)hV@g$&hVg4xZ-qJWXwa{%i5D4PEX+^M9ReFP(|`^*bmDgd^FB^ zv!(aa9FlH#F3Zy^l=l?W5doJQ^|R&wcln~}_9h8}!$xHoRUro%@`R(Y z{#Bp%>F5~B@g$#zxzF>&NvZ^eqtA~hoyY&T`q4VeR*r0Z+_pr|#*&wGo9xj{XxX*dRK5v&{9EG#tqkPrHGs&QG(naaQdfgZ5 z+k3JprKkSRUJ`1*xHyjdXgo~YQ+Tk^ z6NfJc(?QGR)sl{5{_X2vm^rx8WiiYGyve3cwKavC(vdC;BG@kU_j-G{cF5=ZshUJm zvxEVig%*gA>R*4Rl%FBlsY=d4KI7-M>Zyjcq%hB+rAJwZ^It4A&xhNB(HV`)pjzmu zw)bj-C>+nYc%Cfw&$*{+8P+RGX^Ar{b?A6+HP;Tg3C=iu=(oNd=;jpu%(voaI-?Zh zWMNoHOO-IcXKb_C@@xqSbe^`GX8Y2^5>vz7yxce+_rpBJ;4o4Dik!q14o=F_OSAlrM!c)1z3%TYdiYWu5G$TQ3{nT)tZ^o5D!mDJ_q9E zl)y$z0<#)V#c=$dEl(zwrR2QXd?uO8=YE)*Nn_gbdzk+34QJ9QJ;%M{N>9fy(bUm6 zPe=G@{V)v21}PaYPZ{JB<_LILh)W^vfG>!#8cn4z$>DpL&cb0#X31gfp3{VL<6)+I zYEGP%*=ME6Oe3tAsOA0Mkixa-hEty8YT-OPQECYzM7q=O3kg0)m^gVnQ%DyLoIoc> z7s(=EA(jW>nRN1-fV-AJX(*=q`RN{(QW=m(be4+fqz9AExG9Ig5uH--i=^{1uzV>; zrVo=!rK$y)EFI-VapG+#yd^Wum^3Dp(HV~bOEIaWK`o(5VJV5q^a{8cF3^@_c2-j@ z!=-X8X-cP7DHQ?Jk(G%o!?a}9W_02SxGDDExtKQ0Vx%u=o~kFqGCPrujNTU(VI?4+ zU97yda3-C_DGi00bi(yjX=cpiHxwj|m78>+v@Awp&cS?2&#{3|a#_k$>rsqz1tE?h zpRk-F`@B33LNYazODU)nJQk)$rKZYeoGc~d42J_vxb+D`J?#gLY0($I=Aaak&Md%E zvodo%nIDd&V_1#Roq8m*Gue(yqB`;NL48n<=Jm*VnWZ^D`AyLGn65$Hk_485aZ;Q@ zEEZ5G&hjI_iHJk#;AE|YB(Twf>A_@p>}YosqdWE0pE28I;|&ipjfj`%lpi0H0uG)x z)kH$h%!4@5Hm^d8wFNK}LSHjoAH^Lh6T=Be6JfH-j)Uuu> z&Qa&8^~L?ggT#7bU2#9Lfp~y;pm?Zwh!_(ai#g(9VsmknI9i-47Kw%8ByqAhMU0En z#OY$bc#1efoGF%zC1ROaDxN0J5$B5Y#WTd^;#uNK@l3>)ip#_m;wtfMakcMQUK^4* zT`687t`{#AFB2~puMn>ik5?(j6V!6Cjb0}Hq>htMl#iEBkQd5}o=OkpNaZNyXl1do zM5$DkDreyn;b$u=lvT>P%6ZBf6)u8)Wg;GYIn7Z+DYxG=BjPg zc4`N;o7zJ?Nb%t7?26aF-4`Qh`@}G(=#SG$6^)YXhep-DBzcGDYeL;OreG}yxs=lVa zuD*fNzN@~2`#bPC{bThL^$Ybg^>cOqP#vyE&3&itQdv!W58Llje^Gx_e^!50e^Y+~ z#nu!})ih1V55P^$(rRh7wVEELhE`wOU#q9>r`6S(Xw9`8?NIG7?GRvMT4SxL)=X=m z9UdB0kI>p{9kec5S8aecP#dHT)`n<9wPD(DZG?8LHc}g9!$7?5mK0%wPour+t z#kDEgWNn6)uT9rZ(Mq*4tz0`zo2$;z=E6T+o1IpiuS7Zn)bT( zhW4iRmiD&xj`ps$MSD+sU;9A&Q2R*xSo=i#RNJa;(>_OuzVu4c6t}Rv))bbuJ_QXPI!Iv(R=B=^#S@2{TO|aK3E^957kHM z)ZUNPN9tqr)i2OD=$Gl2>Zgbo>+AJP^lkdf@+bPI z`d0lH^$VT1p3n84)b08&`tSO$`fvJA`j7fa>M#0k{ZB6}87maoPz=>D4a2Yv-C#YB zcxo6w>8^2-THmN=4AJ*9_BReN4m27Wjg3QqjTwg;ha0(wwKUoq?SN@zv@%-b9}C(T zM;M)qE=E`5XrqrY$mnVGGx{4x8NH0&;Oc7}V+=G#8>5Ud#&O12<9Oo)W1KPGm}H!6 zsu&;J8YhX2$!u`i$ME#QAT zjQt5I|2Q?0(D#A%2lU227R`v^lisJ`Yj3g9as0s!J{!yEO+fe4`yas^RW!A1b{@XK z*QcnYxTwUF8p!f_<0Y+zjvCl1$c*wLS$*h#wkMZ$i^aVEyD7j|L)5(WyAEAjcj(=rck5nlyR>WF zKDTYV{$1Mj?bJKB*L*PU#r3GT+*oO>GFBVs8f%QT#yaC7W4*D#xXif1xZ1eZxZb$Y zxXHN1*ks&p+-clx+-ux#JYYOzJYqa%JYhU#JYzg(ykNX!ykfj&ykWd$ykl%J-Zwrp zJ~lozwi%xr+l?=cE74z97-t!08|N738Rr`p7#A8B8ljcLYoBj1=|6c~j@u~A}_8f8YgG0T{3%rWK~^NiDt`NkQ>0;9-? z`|cFu6k{ghr+TgkA?8jqxTDXb(AV@W&o{l#rLeo@;Thcly;dT%nsy^jkoijB!s(K% zbe3v&0>@F3Jcb_5-TNzel2RMdOOY;K*-WfxoY*sFA1vo|?FG_np2= z|3?2--=Tl0@6^B2zfL~M_qGJbiKPD}Qcq}pu`Fs=>(}bn>l^i(_1pA2^t<(Y_51Y) z^au5a^+)x`^e6PE^r!V__2=~$^_TTm_1E+_^tbf4^>_4l^)32)`UmewTiaexJTs|5JKMe+1aa^(XZu@-zB#`uqAz`YXC#<5vAm z{Vw@#`5yT*@izGr`n=k|^%|m#S7s?^C^NM}tw{UKm1rOfU4P=!I-#f^#AxK5kI&@O zdC2IQ$aD!DvqRmfeywg-zf`|cF&=s;Nh+uB$!~=(2X@9+7LUPK5+~wIhSv!{2|o+J z2)_!y3BL;qq^qSnq|Wlk@~854xkR0%o`)HG5g@qAQevysbJTOy3)J(~wQ8|PS)-m^ z@qNYTi(-owFS@DX!irlKAHT3(N53Ab-B7i zJxi@qV-;-i3R<)v%va~D3B(qu6r*d5_ySt7AgomP&(KyFPqupt|Lc!bhduCB%-;9{ zCe`IAe97{7e65n|G>$J(o`Nq=7USPx%kfpodHAQv3SqHOC7g-BAvzo1$~+%`o^r9U zLAXq~Qn&_fV3Tl%aF=keuvvIictUtqctLnscujayct?0o_)z#n*d}}{d?)M@{uDk# zt0+ag_{#m-{l@*)UE|eC&_Y-nIMr(jES#+*+3~!E75gnJ8z+5lvE0ik;Ha_W?26~k zX6>)+tn*gCR8?~J;zd_hT)L{knrqLWQ%UXdt+Rez)pJRg3ogDuSoiblzUQBK&h6(l zJ@>V>51n)Rn&PzsR(`r-Vdaf0Yn^rQij$W$KQpo7_=O*?xnSv##m?G-swC@}}DfJat z=>PA~uNdim&){r{+#!N1<6D|?)HRY~QWKv#3jJ#x`prXLzi6U1Rb%R*YGb_jBG*od zI)+bL9Zzy8p(Ip%29N)Lkdtt|Cv~kv?L?hK-9)`a{ltEFzQ+=WCWbDqU%6l9{*?_X z52!q_@}SCtD;riesyw7JR(WV;8erD_d2zu543zL}lB` zxs|6?&Z|7Va(?9*l?y5pl@*l>E4Ng>SNVSB2bH~+^j^|uN#7;?mh@k8%#s01u3B>S zl53V+yX3kh*DtwY$&E`kF1cyR%}Z`sa_f>!OUx>(%C2&%+^QN?HLGS;6;>5h6<3{F zRZ>-2RaRAAHLGfN)tsuiRi{mOOv9eydMA@KRs$8aAu3Vv9sa&O8tz4sAt6ZmCuiT*AsBBbj zQf^jmQEpW>DYq%ND|aY&Dt9S&EB7e(D)%Y(E1Q)Eln0fEl!ui^lt-1vl*g4PlqZ#^ zl&6(vlxLOal;@Qfloyqkl$VuPlvkD4l-HFvlsA>Pl(&_4ly{Xa%6rQD$_L7a%16q_ z$|uUF%2s8Y@|p6v@`bWp*`a)?>{Px|zE-|bzE!?cb}8R0KPW#cKPf*ezbL;dzbU^f ze<*({IBuZ+lds-@bhqq=GhwWeB2t*zEk>#FtC`s#k_{%QmD0QJDg zsFiFTdkowmUL?OKe&zGD?}Cj8 la)!z6lJQCugp+pDn-hv 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 VT60_CF#bQ+@weTaGriDv{y*Lex~%{J diff --git a/mDNSWindows/SystemService/Service.c b/mDNSWindows/SystemService/Service.c index 451c239..0ab2dbf 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.34 2005/04/22 07:34:23 shersche +Check an interface's address and make sure it's valid before using it to set link-local routes. + +Revision 1.33 2005/04/13 17:48:23 shersche + Make sure there is only one default route for link-local addresses. + +Revision 1.32 2005/04/06 01:32:05 shersche +Remove default route for link-local addressing when another interface comes up with a routable IPv4 address + +Revision 1.31 2005/04/06 01:00:11 shersche + GetFullPathName() should be passed the number of TCHARs in the path buffer, not the size in bytes of the path buffer. + +Revision 1.30 2005/04/06 00:52:43 shersche + Only add default route if there are no other routable IPv4 addresses on any of the other interfaces. More work needs to be done to correctly configure the routing table when multiple interfaces are extant and none of them have routable IPv4 addresses. + Revision 1.29 2005/03/06 05:21:56 shersche Fix corrupt UTF-8 name when non-ASCII system name used, enabled unicode support @@ -257,8 +272,9 @@ static mDNSs32 udsIdle(mDNS * const inMDNS, mDNSs32 interval); static void CoreCallback(mDNS * const inMDNS, mStatus result); static void HostDescriptionChanged(mDNS * const inMDNS); static OSStatus GetRouteDestination(DWORD * ifIndex, DWORD * address); -static bool HaveLLRoute(PMIB_IPFORWARDROW rowExtant); -static OSStatus SetLLRoute(); +static OSStatus SetLLRoute( mDNS * const inMDNS ); +static bool HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr ); +static bool IsValidAddress( const char * addr ); #if defined(UNICODE) # define StrLen(X) wcslen(X) @@ -478,7 +494,7 @@ static OSStatus InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR i // Get a full path to the executable since a relative path may have been specified. - size = GetFullPathName( inPath, sizeof( fullPath ), fullPath, &namePtr ); + size = GetFullPathName( inPath, MAX_PATH, fullPath, &namePtr ); err = translate_errno( size > 0, (OSStatus) GetLastError(), kPathErr ); require_noerr( err, exit ); @@ -1162,7 +1178,7 @@ static OSStatus ServiceSpecificInitialize( int argc, LPTSTR argv[] ) // if (gServiceManageLLRouting == true) { - SetLLRoute(); + SetLLRoute( &gMDNSRecord ); } exit: @@ -1246,13 +1262,11 @@ static void ServiceSpecificFinalize( int argc, LPTSTR argv[] ) static void CoreCallback(mDNS * const inMDNS, mStatus status) { - DEBUG_UNUSED( inMDNS ); - if (status == mStatus_ConfigChanged) { if (gServiceManageLLRouting == true) { - SetLLRoute(); + SetLLRoute( inMDNS ); } } } @@ -1658,11 +1672,11 @@ EventSourceUnlock() //=========================================================================================================================== -// HaveLLRoute +// HaveRoute //=========================================================================================================================== static bool -HaveLLRoute(PMIB_IPFORWARDROW rowExtant) +HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr ) { PMIB_IPFORWARDTABLE pIpForwardTable = NULL; DWORD dwSize = 0; @@ -1694,7 +1708,7 @@ HaveLLRoute(PMIB_IPFORWARDROW rowExtant) // for ( i = 0; i < pIpForwardTable->dwNumEntries; i++) { - if (pIpForwardTable->table[i].dwForwardDest == inet_addr(kLLNetworkAddr)) + if ( pIpForwardTable->table[i].dwForwardDest == addr ) { memcpy( rowExtant, &(pIpForwardTable->table[i]), sizeof(*rowExtant) ); found = true; @@ -1713,12 +1727,23 @@ exit: } +//=========================================================================================================================== +// IsValidAddress +//=========================================================================================================================== + +static bool +IsValidAddress( const char * addr ) +{ + return ( addr && ( strcmp( addr, "0.0.0.0" ) != 0 ) ) ? true : false; +} + + //=========================================================================================================================== // SetLLRoute //=========================================================================================================================== static OSStatus -SetLLRoute() +SetLLRoute( mDNS * const inMDNS ) { DWORD ifIndex; MIB_IPFORWARDROW rowExtant; @@ -1748,7 +1773,7 @@ SetLLRoute() // // check to make sure we don't already have a route // - if (HaveLLRoute(&rowExtant)) + if ( HaveRoute( &rowExtant, inet_addr( kLLNetworkAddr ) ) ) { // // set the age to 0 so that we can do a memcmp. @@ -1782,13 +1807,32 @@ SetLLRoute() } // - // see if this address is a link local address + // Now we want to see if we should install a default route for this interface. + // We want to do this if the following are true: // - if ((row.dwForwardNextHop & 0xFFFF) == row.dwForwardDest) + // 1. This interface has a link-local address + // 2. This is the only IPv4 interface + // + + if ( ( row.dwForwardNextHop & 0xFFFF ) == row.dwForwardDest ) { - // - // if so, set up a route to ARP everything - // + mDNSInterfaceData * ifd; + int numLinkLocalInterfaces = 0; + int numInterfaces = 0; + + for ( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next ) + { + if ( ifd->defaultAddr.type == mDNSAddrType_IPv4 ) + { + numInterfaces++; + + if ( ( ifd->interfaceInfo.ip.ip.v4.b[0] == 169 ) && ( ifd->interfaceInfo.ip.ip.v4.b[1] == 254 ) ) + { + numLinkLocalInterfaces++; + } + } + } + row.dwForwardDest = 0; row.dwForwardIfIndex = ifIndex; row.dwForwardMask = 0; @@ -1796,16 +1840,26 @@ SetLLRoute() row.dwForwardProto = MIB_IPPROTO_NETMGMT; row.dwForwardAge = 0; row.dwForwardPolicy = 0; - row.dwForwardMetric1 = 1; + row.dwForwardMetric1 = 20; row.dwForwardMetric2 = (DWORD) - 1; row.dwForwardMetric3 = (DWORD) - 1; row.dwForwardMetric4 = (DWORD) - 1; row.dwForwardMetric5 = (DWORD) - 1; - - err = CreateIpForwardEntry(&row); - - require_noerr( err, exit ); + + if ( numInterfaces == numLinkLocalInterfaces ) + { + if ( !HaveRoute( &row, 0 ) ) + { + err = CreateIpForwardEntry(&row); + require_noerr( err, exit ); + } + } + else + { + DeleteIpForwardEntry( &row ); + } } + exit: return ( err ); @@ -1823,6 +1877,7 @@ GetRouteDestination(DWORD * ifIndex, DWORD * address) IP_ADAPTER_INFO * pAdapterInfo = NULL; IP_ADAPTER_INFO * pAdapter = NULL; ULONG bufLen; + mDNSBool done = mDNSfalse; OSStatus err; // @@ -1882,24 +1937,41 @@ GetRouteDestination(DWORD * ifIndex, DWORD * address) pAdapter = pAdapter->Next; } - pAdapter = pAdapterInfo; - err = kUnknownErr; - - while (pAdapter) + while ( !done ) { - // - // if we don't have an interface selected, choose the first one - // - if ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) && (!(*ifIndex) || (pAdapter->Index == (*ifIndex)))) + pAdapter = pAdapterInfo; + err = kUnknownErr; + + while (pAdapter) { - *address = inet_addr( pAdapter->IpAddressList.IpAddress.String ); - *ifIndex = pAdapter->Index; - err = kNoErr; - break; + // If we don't have an interface selected, choose the first one that is of type ethernet and + // has a valid IP Address + + if ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) && ( IsValidAddress( pAdapter->IpAddressList.IpAddress.String ) ) && (!(*ifIndex) || (pAdapter->Index == (*ifIndex)))) + { + *address = inet_addr( pAdapter->IpAddressList.IpAddress.String ); + *ifIndex = pAdapter->Index; + err = kNoErr; + break; + } + + pAdapter = pAdapter->Next; } - - pAdapter = pAdapter->Next; - } + + // If we found the right interface, or we weren't trying to find a specific interface then we're done + + if ( !err || !( *ifIndex) ) + { + done = mDNStrue; + } + + // Otherwise, try again by wildcarding the interface + + else + { + *ifIndex = 0; + } + } exit: @@ -1910,4 +1982,3 @@ exit: return( err ); } - diff --git a/mDNSWindows/SystemServiceTest/Prefix.h b/mDNSWindows/SystemServiceTest/Prefix.h deleted file mode 100644 index 53fb893..0000000 --- a/mDNSWindows/SystemServiceTest/Prefix.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: Prefix.h,v $ -Revision 1.1 2004/06/18 04:17:43 rpantos -Move up one level. - -Revision 1.1 2004/01/30 02:58:57 bradley -Test tool for the mDNSResponder Windows service. - -*/ - -#ifndef __PREFIX__ -#define __PREFIX__ - -#if( defined( _DEBUG ) ) - #define DEBUG 1 - #define MDNS_DEBUGMSGS 1 -#else - #define DEBUG 0 -#endif - -#define DNS_SD_DIRECT_ENABLED 0 -#define DNS_SD_CLIENT_ENABLED 1 - -#endif // __PREFIX__ diff --git a/mDNSWindows/SystemServiceTest/Tool.c b/mDNSWindows/SystemServiceTest/Tool.c deleted file mode 100644 index f4d675a..0000000 --- a/mDNSWindows/SystemServiceTest/Tool.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: Tool.c,v $ -Revision 1.2 2004/07/13 21:24:28 rpantos -Fix for . - -Revision 1.1 2004/06/18 04:17:43 rpantos -Move up one level. - -Revision 1.3 2004/04/09 21:03:15 bradley -Changed port numbers to use network byte order for consistency with other platforms. - -Revision 1.2 2004/04/08 09:43:43 bradley -Changed callback calling conventions to __stdcall so they can be used with C# delegates. - -Revision 1.1 2004/01/30 02:58:57 bradley -Test tool for the mDNSResponder Windows service. - -*/ - -#include -#include - -#include "CommonServices.h" -#include "DebugServices.h" -#include "DNSSD.h" - -//=========================================================================================================================== -// Structures -//=========================================================================================================================== - -#define MAX_DOMAIN_LABEL 63 -#define MAX_DOMAIN_NAME 255 - -typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16; - -typedef struct { u_char c[ 64]; } domainlabel; -typedef struct { u_char c[256]; } domainname; - -typedef struct - { - uint16_t priority; - uint16_t weight; - uint16_t port; - domainname target; - } srv_rdata; - -//=========================================================================================================================== -// Prototypes -//=========================================================================================================================== - -int main( int argc, char* argv[] ); -static void Usage( void ); -static int ProcessArgs( int argc, char* argv[] ); - -#if( defined( WINVER ) ) - static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ); -#endif - -static void CALLBACK_COMPAT - EnumerateDomainsCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - uint32_t inInterfaceIndex, - DNSServiceErrorType inErrorCode, - const char * inDomain, - void * inContext ); - -static void CALLBACK_COMPAT - BrowseCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - uint32_t inInterfaceIndex, - DNSServiceErrorType inErrorCode, - const char * inName, - const char * inType, - const char * inDomain, - void * inContext ); - -static void CALLBACK_COMPAT - ResolveCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - uint32_t inInterfaceIndex, - DNSServiceErrorType inErrorCode, - const char * inFullName, - const char * inHostName, - uint16_t inPort, - uint16_t inTXTSize, - const char * inTXT, - void * inContext ); - -static void CALLBACK_COMPAT - RegisterCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - DNSServiceErrorType inErrorCode, - const char * inName, - const char * inType, - const char * inDomain, - void * inContext ); - -static void CALLBACK_COMPAT - RecordCallBack( - DNSServiceRef inRef, - DNSRecordRef inRecordRef, - DNSServiceFlags inFlags, - DNSServiceErrorType inErrorCode, - void * inContext ); - -static void CALLBACK_COMPAT - QueryCallBack( - const DNSServiceRef inRef, - const DNSServiceFlags inFlags, - const uint32_t inInterfaceIndex, - const DNSServiceErrorType inErrorCode, - const char * inName, - const uint16_t inRRType, - const uint16_t inRRClass, - const uint16_t inRDataSize, - const void * inRData, - const uint32_t inTTL, - void * inContext ); - -static void PrintRData( uint16_t inRRType, size_t inRDataSize, const uint8_t *inRData ); - -static char *ConvertDomainLabelToCString_withescape(const domainlabel *const label, char *ptr, char esc); -static char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc); - -//=========================================================================================================================== -// Globals -//=========================================================================================================================== - -#if( defined( WINVER ) ) - static volatile int gQuit = 0; -#endif - -//=========================================================================================================================== -// main -//=========================================================================================================================== - -int main( int argc, char *argv[] ) -{ - OSStatus err; - - debug_initialize( kDebugOutputTypeMetaConsole ); - debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace ); - - SetConsoleCtrlHandler( ConsoleControlHandler, TRUE ); - err = ProcessArgs( argc, argv ); - return( (int) err ); -} - -//=========================================================================================================================== -// Usage -//=========================================================================================================================== - -static void Usage( void ) -{ - fprintf( stderr, "\n" ); - fprintf( stderr, "DNSServiceTest 1.0d1\n" ); - fprintf( stderr, "\n" ); - fprintf( stderr, " -server Set Remote Server\n" ); - fprintf( stderr, " -cv Check Version\n" ); - fprintf( stderr, " -bd Browse for Browse Domains\n" ); - fprintf( stderr, " -bs Browse for Services\n" ); - fprintf( stderr, " -rsi Resolve Service Instance\n" ); - fprintf( stderr, " -rs Register Service\n" ); - fprintf( stderr, " -rr Register Records\n" ); - fprintf( stderr, " -qr Query Record\n" ); - fprintf( stderr, " -cr Reconfirm Record\n" ); - fprintf( stderr, " -cp Copy Property\n" ); - fprintf( stderr, " -h[elp] Help\n" ); - fprintf( stderr, "\n" ); -} - -DEBUG_LOCAL DNSServiceRef gRef = NULL; -DEBUG_LOCAL DNSRecordRef gRecordRef = NULL; -DEBUG_LOCAL const char * gServer = NULL; - -//=========================================================================================================================== -// ProcessArgs -//=========================================================================================================================== - -static int ProcessArgs( int argc, char* argv[] ) -{ - OSStatus err; - int i; - const char * name; - const char * type; - const char * domain; - uint16_t port; - const char * host; - const char * txt; - uint16_t txtSize; - uint8_t txtStorage[ 256 ]; - uint32_t ipv4; - char s[ 256 ]; - DNSRecordRef records[ 10 ]; - char fullName[ kDNSServiceMaxDomainName ]; - uint16_t rrType; - - err = DNSServiceInitialize( kDNSServiceInitializeFlagsNoServerCheck, 0 ); - require_noerr( err, exit ); - - // Parse the command line arguments (ignore first argument since it's just the program name). - - if( argc <= 1 ) - { - Usage(); - err = 0; - goto exit; - } - for( i = 1; i < argc; ++i ) - { - if( strcmp( argv[ i ], "-server" ) == 0 ) - { - require_action( argc > ( i + 1 ), exit, err = kParamErr ); - gServer = argv[ ++i ]; - - printf( "Server set to \"%s\"\n", gServer ); - } - else if( strcmp( argv[ i ], "-cv" ) == 0 ) - { - // Check Version - - err = DNSServiceCheckVersion(); - printf( "CheckVersion: %ld\n", err ); - err = kNoErr; - goto exit; - } - else if( strcmp( argv[ i ], "-bd" ) == 0 ) - { - err = DNSServiceEnumerateDomains( &gRef, kDNSServiceFlagsBrowseDomains, 0, - EnumerateDomainsCallBack, NULL ); - require_noerr( err, exit ); - } - else if( strcmp( argv[ i ], "-bs" ) == 0 ) - { - // Browse service - - if( argc > ( i + 2 ) ) - { - type = argv[ ++i ]; - domain = argv[ ++i ]; - } - else - { - type = "_http._tcp"; - domain = ""; - } - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - - err = DNSServiceBrowse( &gRef, 0, 0, type, domain, BrowseCallBack, NULL ); - require_noerr( err, exit ); - } - else if( strcmp( argv[ i ], "-rsi" ) == 0 ) - { - // Resolve Service Instance - - if( argc > ( i + 3 ) ) - { - name = argv[ ++i ]; - type = argv[ ++i ]; - domain = argv[ ++i ]; - } - else - { - name = "test service"; - type = "_http._tcp"; - domain = ""; - } - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - - err = DNSServiceResolve( &gRef, 0, 0, name, type, domain, ResolveCallBack, NULL ); - require_noerr( err, exit ); - } - else if( strcmp( argv[ i ], "-rs" ) == 0 ) - { - // Register Service - - if( argc > ( i + 6 ) ) - { - name = argv[ ++i ]; - type = argv[ ++i ]; - domain = argv[ ++i ]; - host = argv[ ++i ]; - port = (uint16_t) atoi( argv[ ++i ] ); - txt = argv[ ++i ]; - } - else - { - name = "test service"; - type = "_http._tcp"; - domain = ""; - host = ""; - port = 80; - txt = "My TXT Record"; - } - if( *txt != '\0' ) - { - txtStorage[ 0 ] = (uint8_t) strlen( txt ); - memcpy( &txtStorage[ 1 ], txt, txtStorage[ 0 ] ); - txtSize = (uint16_t)( 1 + txtStorage[ 0 ] ); - txt = (const char *) txtStorage; - } - else - { - txt = NULL; - txtSize = 0; - } - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - - err = DNSServiceRegister( &gRef, 0, 0, name, type, domain, host, htons( port ), txtSize, txt, - RegisterCallBack, NULL ); - require_noerr( err, exit ); - - #if( TEST_SERVICE_RECORDS ) - ipv4 = 0x11223344; - err = DNSServiceAddRecord( gRef, &gRecordRef, 0, kDNSServiceDNSType_A, kDNSServiceDNSClass_IN, &ipv4, 60 ); - require_noerr( err, exit ); - - Sleep( 10000 ); - - ipv4 = 0x22334455; - err = DNSServiceUpdateRecord( gRef, gRecordRef, 0, 4, &ipv4, 60 ); - require_noerr( err, exit ); - - Sleep( 10000 ); - - err = DNSServiceRemoveRecord( gRef, gRecordRef, 0 ); - require_noerr( err, exit ); - gRecordRef = NULL; - - Sleep( 10000 ); - #endif - } - else if( strcmp( argv[ i ], "-rr" ) == 0 ) - { - // Register Records - - err = DNSServiceCreateConnection( &gRef ); - require_noerr( err, exit ); - - printf( "registering 10 address records...\n" ); - ipv4 = 0x11223310; - for( i = 0; i < 10; ++i ) - { - sprintf( s, "testhost-%d.local.", i ); - ++ipv4; - err = DNSServiceRegisterRecord( gRef, &records[ i ], kDNSServiceFlagsUnique, 0, s, - kDNSServiceDNSType_A, kDNSServiceDNSClass_IN, 4, &ipv4, 60, RecordCallBack, NULL ); - check_noerr( err ); - } - Sleep( 10000 ); - - printf( "deregistering half of the records\n" ); - for( i = 0; i < 10; ++i ) - { - if( i % 2 ) - { - err = DNSServiceRemoveRecord( gRef, records[ i ], 0 ); - check_noerr( err ); - records[ i ] = NULL; - } - } - Sleep( 10000 ); - - printf( "updating the remaining records\n" ); - for( i = 0; i < 10; ++i ) - { - if( records[ i ] ) - { - ++ipv4; - err = DNSServiceUpdateRecord( gRef, records[ i ], 0, 4, &ipv4, 60 ); - check_noerr( err ); - } - } - Sleep( 10000 ); - - printf( "deregistering all remaining records\n" ); - DNSServiceRefDeallocate( gRef ); - - Sleep( 5000 ); - } - else if( strcmp( argv[ i ], "-qr" ) == 0 ) - { - // Query Record - - if( argc > ( i + 4 ) ) - { - name = argv[ ++i ]; - type = argv[ ++i ]; - domain = argv[ ++i ]; - rrType = (uint16_t) atoi( argv[ ++i ] ); - } - else - { - name = "test"; - type = ""; - domain = ""; - rrType = 1; // Address - } - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - err = DNSServiceConstructFullName( fullName, name, type, domain ); - require_noerr( err, exit ); - - printf( "resolving fullname %s type %d\n", fullName, rrType ); - err = DNSServiceQueryRecord( &gRef, 0, 0, fullName, rrType, kDNSServiceDNSClass_IN, QueryCallBack, NULL ); - require_noerr( err, exit ); - } - else if( strcmp( argv[ i ], "-cr" ) == 0 ) - { - // Reconfirm Record - - if( argc > ( i + 4 ) ) - { - name = argv[ ++i ]; - type = argv[ ++i ]; - domain = argv[ ++i ]; - rrType = (uint16_t) atoi( argv[ ++i ] ); - } - else - { - name = "test"; - type = ""; - domain = ""; - rrType = 1; // Address - } - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - err = DNSServiceConstructFullName( fullName, name, type, domain ); - require_noerr( err, exit ); - - printf( "reconfirming record fullname %s type %d\n", fullName, rrType ); - ipv4 = 0x11223310; - DNSServiceReconfirmRecord( 0, 0, fullName, rrType, kDNSServiceDNSClass_IN, 4, &ipv4 ); - } - else if( strcmp( argv[ i ], "-cp" ) == 0 ) - { - DNSPropertyCode code; - DNSPropertyData data; - - // Copy Property - - if( argc > ( i + 1 ) ) - { - name = argv[ ++i ]; - require_action( strlen( name ) == 4, exit, err = kParamErr ); - - code = (DNSPropertyCode)( name[ 0 ] << 24 ); - code |= (DNSPropertyCode)( name[ 1 ] << 16 ); - code |= (DNSPropertyCode)( name[ 2 ] << 8 ); - code |= (DNSPropertyCode) name[ 3 ]; - } - else - { - code = kDNSPropertyCodeVersion; - name = "vers"; - } - - err = DNSServiceCopyProperty( code, &data ); - require_noerr( err, exit ); - - printf( "'%s' property:\n", name ); - if( code == kDNSPropertyCodeVersion ) - { - printf( " clientCurrentVersion: 0x%08X\n", data.u.version.clientCurrentVersion ); - printf( " clientOldestServerVersion: 0x%08X\n", data.u.version.clientOldestServerVersion ); - printf( " serverCurrentVersion: 0x%08X\n", data.u.version.serverCurrentVersion ); - printf( " serverOldestClientVersion: 0x%08X\n", data.u.version.serverOldestClientVersion ); - } - } - else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || ( strcmp( argv[ i ], "-h" ) == 0 ) ) - { - // Help - - Usage(); - err = 0; - goto exit; - } - else - { - // Unknown parameter. - - dlog( kDebugLevelError, "unknown parameter (%s)\n", argv[ i ] ); - err = kParamErr; - goto exit; - } - } - - // Run until control-C'd. - - while( !gQuit ) - { - Sleep( 100 ); - } - err = kNoErr; - -exit: - DNSServiceFinalize(); - if( err ) - { - Usage(); - } - return( err ); -} - -//=========================================================================================================================== -// ConsoleControlHandler -//=========================================================================================================================== - -static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ) -{ - BOOL handled; - - handled = 0; - switch( inControlEvent ) - { - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: - case CTRL_CLOSE_EVENT: - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - gQuit = 1; - handled = 1; - break; - - default: - break; - } - return( handled ); -} - -//=========================================================================================================================== -// EnumerateDomainsCallBack -//=========================================================================================================================== - -static void CALLBACK_COMPAT - EnumerateDomainsCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - uint32_t inInterfaceIndex, - DNSServiceErrorType inErrorCode, - const char * inDomain, - void * inContext ) -{ - printf( "inRef: 0x%08X\n", (uintptr_t) inRef ); - printf( "inFlags: 0x%08X\n", (int) inFlags ); - printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex ); - printf( "inErrorCode: %ld\n", inErrorCode ); - printf( "inDomain: \"%s\"\n", inDomain ? inDomain : "" ); - printf( "inContext: 0x%08X\n", (uintptr_t) inContext ); - printf( "\n" ); -} - -//=========================================================================================================================== -// BrowseCallBack -//=========================================================================================================================== - -static void CALLBACK_COMPAT - BrowseCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - uint32_t inInterfaceIndex, - DNSServiceErrorType inErrorCode, - const char * inName, - const char * inType, - const char * inDomain, - void * inContext ) -{ - printf( "inRef: 0x%08X\n", (uintptr_t) inRef ); - printf( "inFlags: 0x%08X\n", (int) inFlags ); - printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex ); - printf( "inErrorCode: %ld\n", inErrorCode ); - printf( "inName: \"%s\"\n", inName ? inName : "" ); - printf( "inType: \"%s\"\n", inType ? inType : "" ); - printf( "inDomain: \"%s\"\n", inDomain ? inDomain : "" ); - printf( "inContext: 0x%08X\n", (uintptr_t) inContext ); - printf( "\n" ); -} - -//=========================================================================================================================== -// ResolveCallBack -//=========================================================================================================================== - -static void CALLBACK_COMPAT - ResolveCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - uint32_t inInterfaceIndex, - DNSServiceErrorType inErrorCode, - const char * inFullName, - const char * inHostName, - uint16_t inPort, - uint16_t inTXTSize, - const char * inTXT, - void * inContext ) -{ - printf( "inRef: 0x%08X\n", (uintptr_t) inRef ); - printf( "inFlags: 0x%08X\n", (int) inFlags ); - printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex ); - printf( "inErrorCode: %ld\n", inErrorCode ); - printf( "inFullName: \"%s\"\n", inFullName ? inFullName : "" ); - printf( "inHostName: \"%s\"\n", inHostName ? inHostName : "" ); - printf( "inPort: %d\n", ntohs( inPort ) ); - printf( "inTXTSize: %ld\n", inTXTSize ); - printf( "inTXT: 0x%08X\n", (uintptr_t) inTXT ); - printf( "inContext: 0x%08X\n", (uintptr_t) inContext ); - printf( "\n" ); -} - -//=========================================================================================================================== -// RegisterCallBack -//=========================================================================================================================== - -static void CALLBACK_COMPAT - RegisterCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - DNSServiceErrorType inErrorCode, - const char * inName, - const char * inType, - const char * inDomain, - void * inContext ) -{ - printf( "inRef: 0x%08X\n", (uintptr_t) inRef ); - printf( "inFlags: 0x%08X\n", (int) inFlags ); - printf( "inErrorCode: %ld\n", inErrorCode ); - printf( "inName: \"%s\"\n", inName ? inName : "" ); - printf( "inType: \"%s\"\n", inType ? inType : "" ); - printf( "inDomain: \"%s\"\n", inDomain ? inDomain : "" ); - printf( "inContext: 0x%08X\n", (uintptr_t) inContext ); - printf( "\n" ); -} - -//=========================================================================================================================== -// RecordCallBack -//=========================================================================================================================== - -static void CALLBACK_COMPAT - RecordCallBack( - DNSServiceRef inRef, - DNSRecordRef inRecordRef, - DNSServiceFlags inFlags, - DNSServiceErrorType inErrorCode, - void * inContext ) -{ - DEBUG_UNUSED( inRef ); - DEBUG_UNUSED( inRecordRef ); - DEBUG_UNUSED( inFlags ); - DEBUG_UNUSED( inContext ); - - if( inErrorCode == kDNSServiceErr_NoError ) - { - printf( "RecordCallBack: no errors\n" ); - } - else - { - printf( "RecordCallBack: %ld error\n", inErrorCode ); - } -} - -//=========================================================================================================================== -// QueryCallBack -//=========================================================================================================================== - -static void CALLBACK_COMPAT - QueryCallBack( - const DNSServiceRef inRef, - const DNSServiceFlags inFlags, - const uint32_t inInterfaceIndex, - const DNSServiceErrorType inErrorCode, - const char * inName, - const uint16_t inRRType, - const uint16_t inRRClass, - const uint16_t inRDataSize, - const void * inRData, - const uint32_t inTTL, - void * inContext ) -{ - DEBUG_UNUSED( inRef ); - DEBUG_UNUSED( inRRClass ); - DEBUG_UNUSED( inTTL ); - DEBUG_UNUSED( inContext ); - - if( inErrorCode == kDNSServiceErr_NoError ) - { - if( inFlags & kDNSServiceFlagsAdd ) - { - printf( "Add" ); - } - else - { - printf( "Rmv" ); - } - if( inFlags & kDNSServiceFlagsMoreComing ) - { - printf( "+" ); - } - else - { - printf( " " ); - } - printf(" 0x%04X %d %s rdata ", inFlags, inInterfaceIndex, inName ); - PrintRData( inRRType, (size_t) inRDataSize, (const uint8_t *) inRData ); - } - else - { - printf( "QueryCallback: %ld error\n", inErrorCode ); - } -} - -//=========================================================================================================================== -// PrintRData -//=========================================================================================================================== - -static void PrintRData( uint16_t inRRType, size_t inRDataSize, const uint8_t *inRData ) -{ - size_t i; - srv_rdata * srv; - char s[ 1005 ]; - struct in_addr in; - - switch( inRRType ) - { - case kDNSServiceDNSType_TXT: - - // Print all the alphanumeric and punctuation characters - - for( i = 0; i < inRDataSize; ++i ) - { - if( ( inRData[ i ] >= 32 ) && ( inRData[ i ] <= 127 ) ) - { - printf( "%c", inRData[ i ] ); - } - } - printf( "\n" ); - break; - - case kDNSServiceDNSType_SRV: - srv = (srv_rdata *)inRData; - ConvertDomainNameToCString_withescape(&srv->target, s, 0); - printf("pri=%d, w=%d, port=%d, target=%s\n", srv->priority, srv->weight, srv->port, s); - break; - - case kDNSServiceDNSType_A: - check( inRDataSize == 4 ); - memcpy( &in, inRData, sizeof( in ) ); - printf( "%s\n", inet_ntoa( in ) ); - break; - - case kDNSServiceDNSType_PTR: - ConvertDomainNameToCString_withescape( (domainname *) inRData, s, 0 ); - break; - - case kDNSServiceDNSType_AAAA: - check( inRDataSize == 16 ); - printf( "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\n", - inRData[0], inRData[1], inRData[2], inRData[3], inRData[4], inRData[5], inRData[6], inRData[7], inRData[8], - inRData[9], inRData[10], inRData[11], inRData[12], inRData[13], inRData[14], inRData[15] ); - break; - - default: - printf( "ERROR: I dont know how to print inRData of type %d\n", inRRType ); - return; - } -} - -static char *ConvertDomainLabelToCString_withescape(const domainlabel *const label, char *ptr, char esc) - { - const unsigned char * src = label->c; // Domain label we're reading - const unsigned char len = *src++; // Read length of this (non-null) label - const unsigned char *const end = src + len; // Work out where the label ends - if (len > 63) return(NULL); // If illegal label, abort - while (src < end) // While we have characters in the label - { - unsigned char c = *src++; - if (esc) - { - if (c == '.') // If character is a dot, - *ptr++ = esc; // Output escape character - else if (c <= ' ') // If non-printing ascii, - { // Output decimal escape sequence - *ptr++ = esc; - *ptr++ = (char) ('0' + (c / 100) ); - *ptr++ = (char) ('0' + (c / 10) % 10); - c = (unsigned char)('0' + (c ) % 10); - } - } - *ptr++ = (char)c; // Copy the character - } - *ptr = 0; // Null-terminate the string - return(ptr); // and return - } - -static char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc) - { - const unsigned char *src = name->c; // Domain name we're reading - const unsigned char *const max = name->c + MAX_DOMAIN_NAME; // Maximum that's valid - - if (*src == 0) *ptr++ = '.'; // Special case: For root, just write a dot - - while (*src) // While more characters in the domain name - { - if (src + 1 + *src >= max) return(NULL); - ptr = ConvertDomainLabelToCString_withescape((const domainlabel *)src, ptr, esc); - if (!ptr) return(NULL); - src += 1 + *src; - *ptr++ = '.'; // Write the dot after the label - } - - *ptr++ = 0; // Null-terminate the string - return(ptr); // and return - } diff --git a/mDNSWindows/SystemServiceTest/Tool.mcp b/mDNSWindows/SystemServiceTest/Tool.mcp deleted file mode 100644 index 2f38283556de75bcc00a25ccd1fbb8f14bd0392a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 210145 zcmeHw3t${o)&H5@yqmTu6f6&A6CMq;-SmN2V#S0cZBr7uHldB!&vvufHk)pC*WFDC zNG0-BKt-&8QV=xlzw%W@EC`5zw7jIeN=4o;%hRf$RS{7O{r}FrcV=g^n@!rJ&}Q#V z&YW}4J@@sSd(X_y+?nx(!$Bf)5*g*>JTgGeqrO9Qga`34hQmOT3^n04{~~WR8VE;S zo@ltk?~9vBS;3ouQ?0+XYk6f;xGU=OyPBhZe~c39YM;*^i@7}Bc)MLK@+|j9T?@KG z@j$2FmZRAlUG9&&n*8y2Ahg_`X?7s!cQtw=kv{sb09&b;uHJRV?s# zhU0#hFtDksyW-&~aZ$ZZThkSbhdW(o_|H8j9Bs2#P*YJeX_BiZ+!;Z`qV_Bz0plXn zr=_!-J%A$Q58909c~^S5kWO!?&D9VH*|G3&qU;As>YJ&-8(QAwU2e}H3TyO+0?Yid z_>_6owI+_P`p~j)-vSyJ%&U$>1bj*D7p2VaibuNQeY2Q@Jh6vG6T?1h_$N{ty}tQP zu0}uhXG*VS>8{y9Z_+OIczr9-BTS|~D0w_J0IAJC#~-pa$)?4?@U>5w-zTv)5c9@j z{?69q9mM(O1jDV~plf~v<1cVtQvW#_dtyb35_P!HrIrCwQ$gYqWdr-oipINAMk?p? z)XnbGtF+};$2wC{i-sfqX#8AM8nf@p1^)BWjoU?m&;o`zWk7e&JS7eKLOXx9y>+bW z2XjuU>-PD9cR0izA$b~ba)w>P$tk;pm3Ayrols?p|EaXxg5C90rt>E%5OyfSJX_DuVs?1J9*`)XjskgZb zsYu!>=^R95df!l);ub2?c!Wxx6?SJ}SJ?f4(5DPXp-nr~M2c;ciFmp>pPZ1?+w?Qt z%+P0&3$;1FWkj7suoq=T@~o~zRedHjhFYJwT$yGXSMpRzf=npP$t#jmfnuAqQ&!lg zhmiBwA>_CTkT)1io}#QsnxU*nnV_ufJ3m>MJUv;HG&_^ZQj?Q)Npq7G_NmG7zB5zk zl8^NXl{GI}m6(62$@vf7%ZraCcGO-<@- zHBHcOhlNlCUtDx)Ln>bpbx&SbNI)Y)vNB+Y13*=JT;YTL|C zqcdl>Jt=7%+Y?fTtUb|owBW9)$(wqf-8Zc-9I3P3UJF36&3t=`dHgjiPg8Ef3s@PG zJb|fA@&=}|k4G@ocCV16GY`t#9yUsgYFZCrFQ#9}ZJxqz->27Nnx=IbG9{hgkSW## zx1V35FEX_s4p(vE`qP$qq#(rt>N?C5>y53H|sNm6+Da*wgxY8kv^j zZltzWGF!jCNhYUrP%sISkz=oV~`fbe!W>z0jVx6k!q}_+-$9w2U?P9!U6|?)6FJQtqqs}>Cvhny zD=zNpPHF@Ohk$uQ*s4Q-9+&>Ya9@`ux`@nOR{AKVwC0`DnujCuR3zU2xc%hP? z120nYKfp&x*(e5QLNJcUX0#B=I2C-1lFtGktK<-PiIOh@AE)G>gCC;gN5KzO@~hzE zmHcn;!=&us^uv{00nYtLaLmSLf)L5E1pEjkcYzbVk*~vPWk}JVWmAnwVOv&xw$13?N;KwQXyWorwf|Kh#L5SqMAAF*cUji>zGUI%r zlyi7roup*0bCQy)z$Yu2`#VL+d^3#40Yc6z9{z)n4GXAG1nfvr9C9`g(lFtC=ae$D^ZDYI;a%0$hT8NZ;A^0pMUk&~l zB{M#!DR~R{XO;Xqc$JcOgI7yAZ#4MnO6Gl4qhxM-t&+JtbxQspa2_iNd0)b2ju0u2 z+cQ_m*MRf(a; zJ|{%V|2+5tC9eQ)QZkR9W+kryKTF9Qzxib{~;9kv02IzAI8QAbRKp3+en;#32#_&G;iITZpKUMPW;5R6FEBMcp{37^`O8y%-k9CBx z`PlHBL>PNCHjEv@*csT|EJPYR2mBXGZUMhV$zKA$Rmr?>Z&Nb2<(Epn8=TvOF!l*- zczhs?eG8jAgh(ZM;CCwdIB>=ep`;p{Uki~+7K3wH2qiqvHVctTcwB5zGWYc!CI1He zUM0T<&f@@~gvZ|fLZoqw`2$Lx4$gTH#(fT(2Zc!EI>8x7gmF9%9ugvrV+M#+uf&nh_x{+yD(3C_L);m}@eUSJ6_?;jp32#0c=JZBIN{R=iP z3z5bbfd5{}+^-!<{tWmlN^SywRmnU~cpo5)=l%7%5NSM*oi~)sIK8Q4=6{f~-tGkg zJeJx(UeGeoa*!YNMNlhfDX1O9$IulZ9uJ+M5GV|afOua;K`~GVC=OzO$8+u+P&bIj z>3N_pgU$!70(}K^0jLM$1AP_5b9M>nLeT$$R)f9L!#(*Y(jsP7AItp|&=;NSIfQ|vVK&7BE(6ON7K>48K zK^&Z*6F?I|<)9NmCxIq`CWEGcz6rV<^li|UpzngN09^`N1G)_KJEbO=dPOl9_v1${sPDB-x*43VRce_xFnv^U$EHldrA$Q5F2`s#A zE4>l3i%6^uEXRU8SYo|hFyQlwHBgIj0d{fJAM|@;{>7p#qRZk!F|Vl$AL%klR(?83{+@ z1o)LGtme0N*rNTK8}SQdl>m7Q}Ir%|$dq=IhlgBweCrMarrfR;FBt zW~I7)z@mA%dB4xvVXfd;l*YcEj~{$YVLv|=G!4YZs0t7t2i%~1&^Qnue+ogxpvfQ? zXf$XHXe@}2F?Qzx2Es~YPT8PrQQTNns#EkLuZr$Bb=lV$p}9;iisq67K^ zu|6PuDTC9>di)v30aub(s4=*5(^;nt2! z7Jb&RWHQZ|=8k>{`=`J#)E)GUZPAGu0gZr0KqHV{2#DWg>Xx@VlKFgY1R^84zXWgF zT!ObMM8h#G#m%O0&+pdVBvEZc3T{x4%v;sF;(1uug}MeYCl#~HES2R zq2h-Z)%32h#ScR~Vv9Rqzr_|e5bxzU=%Wdhw{0ph3`Zs!g}WH4e}~bmF*`n*hU!{B zQUnUm`m%B55Ms$HE>R%S<&U8ZA_reUOf-#6}A1N67 zz4Bbc3P94i-|N#AXaq7LaF{wkeRRjEOs&&t8i5ZF0X+vkJgjw18Uc;Kfr&u!St)x( zCi%2AU->aZ*858f0ON{pGD?lOmN=y*h%YCZ5M>t^?*_-0ruO*mUqi-B z*yxWg_q*`v-~+mU;^o)-qlKSEsP=do2#*2fdEL?20Pii>A8i<*%>CB)lzQPJQ*>FT z;13e$ki`h(w9IL!Z40dMb%djy8c)+A^{hhzl7eHF@~1cOO^x-G+gNudzFk4nJs$By z+-VB}ZT#}wd0u~yO0SN4Evy!6nP0VO(nnwdL1^ zmIni|_A%Ci9G7Z|_~ul?`=#_!Ric?jAWIPF`>0ZubX#{*BVZxm5MPknwHAMpq{ z+#~U#(%^TSQ9XEDZK)9$aR~4iJ2Ql#o=YShV)Joc;gw&W%}`~=r2TnbVO2cTYp_Y3 zwo1(^L0`kns@U#KtVQjb}#yhZ#Lz6-Qi64x~)4RqFAE`m%2cF z9i?Rpc;=wbJ@hq=%p*jn4iy1|XQ(V>pt(HMs&syhzyXZ_--qBYIiLE|1GsztRANRFabk?5Pgs*W$!l5?kIfidjw1v-!RWzL& zi~BoO#m#<{F{?tAj#dt;amICreVKQ=ah;199~nJroq~1KS|()QcKpPe`L%TuT@!1o zo2$V*^)<~Cvk3-A3C3NxE9&$2_sZ%5eh+iqTnDc2!2^bDV zYB{x731gO>Tm@$^gMG;jz9ed@_nFI8D*K$>o-xrCp;cdtuv-j9J~C<5yWy3Fr_|A*dKs1j2_T zC=WCq=&>&=ry1Yhg%T~VX`%`n{G%SY$|_!mZlrfrFk)xw9E2SgkTVE7ZcA=IcHAZr zAml>G8-yKu!hE(vKtHS^IBrECkG)e|xhXXIh z>cIUS2fIW1DbH#wghOC==pgJ4h240zt4bZu_VRdc95zsSu+d@UBf#T=N2>5$;KJvC z3ts^)<~X>Ro8V$jfs45SF2*o8kG;JOJPuvl0MK}Dg&3q`B}0q2O?g$^CVU+TvJM&n zF*x=h016!I$l-P`mj8TSUxWAAXpFKF0rnkgT=3Hia$IC361vlN1Z?9X7e^6?_z>-s z?wO~!nz|y9a5TPHeUx{xJ(re8Is)dnsN(aVwBw>7&>Hnd1OAvE86$l#*!pK17fv1* zjZOS0y$;!qfNfmlh+igI4#<>gSq^~izD7VJAQ8Y7UU6RS;`8c;KxoBYzg1QvsS!A+ z5oivFg9mj7hT3?2jdrLAj+p#>uFO~M2XRa|q`9u8+3m~R^~Oc6nu?l9llbtG&Qc_% zOR(u=J(DKcR4L-{)swkH!&eV4vg5zq)|1hNeQ@taKD@^(iu zpU;gzY()2$;J4(GMz1d#j=3|Q(2hU=&?WKYg!+vxd#G2}jm$m0*S+FJ(w*KwXs~fAK)?yh0ar3u;;|%gihG~=Y^a-cmAmGA+`{YhDkwhH3I!3a7-1a@se;}=FO9V z$Kdgx6G4AdoOSj%r?ZajIUncG104q9Jja4Q0Xj~_nWu}h9out0&d+o>h|4_^#E(TV zA55I{nPqT!oQHM1oc&`e&OBWl>Z}jxFz$;f?<=-5X)tkf-g8N!;PMjzF=J5K5?Mx`lq;T578@Yx9C;noJvyimI84pa%y{|4-lV@%_MdHhbdfX^EbgwtGDwua1rWoZMAfJQ(gpb^jrXaqC@ z8Uc-fMnEH=5zq)|1U`HOa8G>fJnu@cxW40$xjVekzKw8s>d*F^y{J*>7z#!=Ylk1qGS=8JFh-atR28|mk?iEg5s z=@)bh-AcF7FX?vr72QF1(p~gxx|=rB7P^P-rTgf9dVqd|2Q;?QL-a5`LXXm8w2dC8 z?etrEf__I&(o^&_JwwmZbM!pDKrhlu^fLXPcF-&ID!oRp(;M_A{egDUAL&o@XL^g? zroYf%v7GvE^mqCPy+i+`cj;gB9{rpCL;t1S^gew+VofrA(U@RNpq0ifV;1!otBuvP z+Sq7pq|1!m#%{XY;c~d>TIWpXO!|ql$Js-@&JE5DbhC3OzU+5*PH|2#ZO`%Kc&zUZ z<1wH-uR9ux`hIlMB^ULGrPO5n=%k)Y#f~>7ljmDR9u-?l?TEF@n4^Sx5bG%xmd-0_ z?S(|O$lE=d60%C&O`B|~mMl|q+GwjS)sjm}s0x22)JEO>0D!EQ7Sl}BJJUtfYi#0g zP9X10<402?SpR)L&`M~Q!sdS9USh5s-xLaT3CbUEVZ9d$9bDmXTahi}-99Gm(5{^fV7q@(cc2S5CQ z^+c?n!7GbkB;>V177rE8xR>SP`cN|%WLY$fYYm~c{JPL`e3rC* zjI|)g#VzSA53J$m4ierkrI)G_%`^g8f`ER9OqT3u-OYXxaEPxU;b72bGB|8Ga`3Yu z#emZ-BXJ%n-pOP?pUjtMmv)t{)WM5Omc-)TA-&9N@O7oPly`MRN0NGjRnbFk8h^>9 zuG{bHihEmw;?y908!~A5sNPuDQU{YNX@(R2VG34%6Kxbfn)bSQ{aZtSF?_EF&B)5& zaF4``N`v1=M)lxrwWUU2#38_6Va*VRdM=T4h|R}&g?G@O{7&1d{drztRVc5)TG720 zk~+QDxkp3>eGPL&?8bfWM7Ez->@#pWqefsPAi%G7(jgTA+z-w5y2IjLcWSE8Sa(E3 z%;>?TE)ZWwY1smvIp}i_eN7|t2+^rSMZn-0DhnBCE)TUTonIqxKqJ8SA^1zqQ_mm1 z3;YLkhch-#-F_;X8`~o7I%DyqCoGDlz3nmhRh`yN3|Iv1Wx`^qF{h73(hEFb5iwkS zEKmzpm8noP?X69sf zYVnz`L6<8n-ddBcmi(KM%C8ee8E^Hbv-mvc&sP>(j5{DD_qOc9|A9`N%c6|!Y04$@fpcY37(cOQer?@E*TmZD=4voceND4~E?Yowl;A6H z;jXC9@4;a*(4G1Xlmc>E!$+ZFQyAiSD2|DoC<5iuR+t->$20+j4NqeSS5U>jLyYup3d#6K2?N`40Xc)P|tN5zr4_{ZKLpJAQk{xIwfJ2VFX(pYp86 zqF(;^#i4_+!PVMFKm_KZw@?fKbM!-aX#}7u9xDF%y5@g{|z}XM*9OwDV zbCc&C&nccSJQsMJ^BCswxi5jotBWfK9m*Rqn7L#Q;#`$-s>GNlhh9q}P|5lYkC8nH zU`~t~Jub3-L`VS4aZ$zYB>kzJMoJ@~5zq)^9|AaoJ2M>eXJ5y4k2L}k0dFwr27C6w zV(>349W(+80bBtb#4*8WZ1hC;H)d5_L4mwGwZH4qY=sPyEuCfosg=*ExiW3 z+Y{G|F61|ON}KcPTDu1C^lU>(HXCS~X|-J=O5Tvr6!b!KCEbwF96G_nZxQXG4!lJ4 z(&2iGD(RpRpkt~SgmN;*8@+18ZIol#m~5Cc;C9xuka&CVROmNSxpBL3J54oq8at`V z*zH(KGaV5}giso8G_GZP%!;|p@p>{bJ1(T0ogBxl@+$n<<^(hm{6TYZ4;{npQFfDQ zGAvIPe{4~XIj|A$@T7cUH@bxFq@1%pAv+eZtjcnzvdWRWPYsyCCsQqJvp$&Ly*(S3 zzVqk!Xuh; z3@(TjR$Q139-BD0LPnewug*&ZXF}AHM&Khr;IQO{kRL${bd?%`0|NnlbUHBhgKmXJ zKqK(cA&`7lYM#O$p&FDpgUxz>X#rrI`d^@9G~!y~6!C4j(#lusqPj!5h zE%}J*c8qCUFt0j-S6KMG@jy7ug=K5Vd_*nO)oKJZ0vZ90fJQ(gpb^jrXaqC@8Uc-f zMnEHw2?5*_A3G1<+7{P${4sZjH{}V3v+F&s#zkj)L^1N0zWH8)OeO2I5skp2>IG+y z=nm@6X#_qD1lXf?#yVC8{O5ca)#*Ak0tYSvonBu!)_vf%?*M9+vsuHPQRrm=y&uaJw;E`GxRJyN6*s>^dh}P zFVpX72faeC(rffOy+Lo%A8052k^V$~rnl&A`V0M)cG2JH@AMCPhyF?L(!c0E`ZxWD z{!6>*efogJn&jbn>Vv<;(%|t_^SdDP*cENE6>Lh26*1VeA%-sJuA2RU4dD-+Y_D6ZJEj+0ZHJ+wLv6a3~`{N73 zwBVSf#q%H?P3tMQvF^;XAW!#r!mZ$^EeNzVfY0;#7Wd3T8NgBm`P?KmQB8V(kM}=m9lrjk|jg^ zu>9WDmufB7M~jXm^#&`Whuk#0nV#yp{l2caw>2nE4N~hLK*LA%#=4d|m{m#B!9TP) zK+$NN3W+wlqp_&ZR1cbKZ>zoSpa;vyG|cwz+#A&+bHD0dX#@s^0Dlo9Lm2A0MA9KP zABS%5-hHpEZ`1bYd4*M%ybfzc_gYBm^j_y45gGKAj1jRL_qh|E82E=4#NTptaD=1-}J!7YKFVi*oNPs1Gd*yYcdoSe%f~HiEbeQyzfdyHVMe zgU=K|=1`wMBhSc@e|=NZ#f{UkCNRTaPD|=vvVGp?5`T`*W%|>r*hrs&eK_9cfUPAS z3r5hmU*7(!JMO&e*LQE;a?ic@-T%OE9^CrS!;d`r*tW;F|MrRBJ^9qr&pi9w^Dn&k z(#yZ!@ye^Oz5d3Vf7toQKmGZwxBv3jU4Q%gKi>K0yZ?Ic-~ajV?)N{~Q=@unTy<89 zaa9Xw5$J6Aw=aSggPN}eU1{2xz?gCPvFFp#1v0=VKK8sR+wweX=CSEsfbNyt;%%d3 z+P0<4xjxgztXpsgdDJ=u>!x*5dKN{-Ppp|=TQ|`)v9`Lo8q8B)(>yVY`kz>u(r>2= zGJgHnz>y6rU(DP>z{ccCU&WkHL$Kb$fr|m=f*1Q@n*PV4Jq2G`m#9SP!oPtxR z^Qv%p6&m$Bj16_jW(0VQ>_Gr?^0;uj7t8<7+B2JK!qI(O-I&dYj*PzB#s#l-mE&S$ zbWQhS2ng85MJ|pa4)O8ADcv(qaW!>CBH?I!vHFnX;vrO`vmSH^nB$^KUhPgZE*b)@ zQExQhkLi(d(CyuQZ?J7#IN4t`HmTe8`(C8ZIRX%{jfV`_RjOUGGDbH z#4+KJ=DL<75s;Q`%G>H!{sj0YA&xz?0Y&uy_X0zd|Cv%5}uO42M(SI1m zdNNitZ1uGHm-XM9;YktWpgnV0L+ual)RU+uBWieOG0L#%ZS`iaqB@RWPg0^nP%$n)f4I3pSW558Q@hG=nq`wf|^Wi87NKQ7WHQw2V99i z=Bn@H>)rzum?7PbcUWdf9&(aLmEaBrS~C@fE3~RJLzqCQz#VSw$W+h#){fz+=fl`P z1>zk!nYyFXGy)m{jetfV3lR{%$)q+z5n6bbkqcE-q>G`l8{OJL3uMhy!3N zjruH!mA2|Py6mA|T{q(P^uBe7*JO9%d*l0-dxYdtE76OpAMD{CxtgPX{H_ugc>S$i z%PXsWK7TBRpYHK?ySkPWm;0lx1zn+dpwn;5(d@-L@#C&0e>@%tEw^Wy9SHhejowJ4 zkN)(oK(NhK*By`Ir+uPos}5PBEoFhfGaTpFHKP$WwfJ~?TvTt<)^x?<;ZD~X{&UX> zN89Wb$m?uF`XxF-MuF}I9aF_1xaK#xT3nuJxWn&@+Xj)xQ-hJ~Yo9XTyyce|r?#|| zk;-YFy4ih7N?U$)tP|5L^W)L;0-PB@-A0qB6p)V6j#{}^ zV#c7dSvf|akSm^PlMl8TdS%rJ+`|V~mkv{NGs`#wYnpfJP&(B~B6Fwzn|KDna~0wmy@VRb7{zb&Qce zu!8}gHy#M5xv*>vnJh#{cUdE#5zq)|1T+E~0gZr0KqH_L&pT9KyThCE)VIr1f41lBMUA2}@+z8n)$G9UpKjrPLZEhbL-V-$P~0C4VO3mRcO;1S z_N9!S0V>zmjcBM44uG&uJ{S<_jCHIG_|G{QnyTBV5!inSbb5W^Soi)be*~56l*{eR z9yK-A)tj>B*@-}VJRYg6sOZ4?ygSwva{I!a6_IGTt;-jWRdlqisF>!SR)OcfV-?;= zpkf4Kgg2BIHu~|Lh6_u7(Z3t$XLKX|oHo%-bTj>eZlPQ0Hu@#qPQRi%=uWzeeoc4N zX4*pc(7kjY-A@nDZ|FhVN)OS)^awplkI^=I9A6#!Ej>ZMqbKPpdYYc0XX!b5o?f6A z=_PuZeos5-6?&Ckqu1#TdXxS@JL!+~C;BtJMQ_tz=&!Vk{ziYNf6zPhPkNXBMeotS z=|A*e+D-4%2PD=c(-(~i#spev%ra(CkFnZVO{`Ifbk3xo zID4Eu)a%^f+(0)wcRF{{-8scM#k4)gljE_zQ;Elb^5i$OuZmuBQ4bx?``frG+HO@ud+A@5A%s_w`H!oJyU(=3I}{lLA%h#PVK ztOi>Wi4_a7f4xSp{_2zd>XR4@*}TbVnbT0)7Fgly2uD3No~A|WS%(BB1;;Ec4kLOr zt*6|^x--v$Jl*37w}PLxAkfwTKF{lq^K1DRuJlJ^D52H2EV>-=^NzY0TNNCe2@Zn9 z>-!y>`ThRocdDeLh)z6F$Oh|Yd_l+#A+J?7$3lNE%fmHvp|NPAjicm;qUnIa|a3Um(ojBiDnvsEI~kgT`EiZs=KKXNQZ!f z@>$JOA?aeX!)Ba=pA9JnoNgJ354MSSGT95s=O^ts>kz||B{4kRJ(QPu4Y2|0iM`a` zU{&;xo5o*qsq6Opy5io}pg1+y>(=s7y|J#P4jHRtW_~;0@C0k`CEDnY#s+xVTe_;n z7)h6qJ-W*5>8kE&8U!5fk$6!lO-K7t8P)wHXthQl8xRiwzK+te1w3=m=N_cbJu(jwojODW44$E~jDhCz5Np!e zH3A1V0{nCdzSm3jSM55m8~UNN&bs}iY8(AbIgQ@7g+@O+mqu@A^3dpKK-+pj8$p|p z=2^F}V$HgRC%xBO9)54#!V}M5zp8o5`c;kFd&@g|ddpWl+IvLDanMIVi`TE3br*QU z`c-GW1AR;H5rLiSSIsY2w{ZIFy+^E=j52m0y$$(yAU}b2uV3|P$boVY>R9pYx`mS$ zL+*uq9QX~eX$Li|TR5p5Z9(}{OQ7G`TOLDuD&9hwCnNo6q}Q%nSdOwHi@~2o{dd7; zH{>8>lo77w7k#=TSnv_20+hc7?RXYt^{iiY>PDom1--L=)n^vNek$bV-tz8CA#;7J zL6@vwRd@cnh10lANQ?BK{+)=wi2S|lSJjpvetvIx2>lEkjr_Ziej5@sUq=h-cn@v8fBmXYUfNsUi9U92 zHNJYvF5|1ydLTcEw%h=DEp$7Ljjzu&Ha@uqd;+K(G!wMj*!V_`UcshUuze`L<^ZlF z9t%dec||jSSY>Q{0{jO%6z@^oCHZw*6kn=1Nq%jw;#HD=e~aQ%CBH_cU%gAluU7iC z%5JSk>erIwS8Y;!sp2J)e{YTC-&Og(8&PqWcDOfkH58&OlUz;|5V$J;8x{0odwbjklV4nJ#=85~Y#sjQyM+v?H7w(Gs{QbSM zx`3R0hlx#L5Ei`%5*_0R$4oAi;wph$1%ve#4qOb73tn(g;zcj2^uCp-tYAh?A`M>> zO(g82#Ak=Y6wnyi9=TOti`d)3Cv?`H*@XQN35VMJ(Pq4*9A6LKi(67dhh%SCtnD=d zBOd{Hv0P9-$N=Smc#WSE#J{Q7dzI6yPj82Zgeo~e!PC-Vz_JQ?$Vl&YR9X3KhXA{z z*=$8%#|0EBJNQ8>Nn|uPu){wcp0G=**UAK=T-fFI(>}W$d$qhl*zpQU=RkI_(Lp1i z5y%b%*mtl$Vqe2Pg}q#oLqdFi1@=cSt{jxlH4CRURx-4L+mTnrZ8Jo>5Y-{u5#TYh z2LTMnVsg0Mi{(F`qu1cwG}#VNmiFH^F8E0VIWDpk3*GGm0=99Hi=&7`d{lM{e>$$I zD-sDuY53 z$aVy5<09un`-OA>gFdCT?Er3_Zkk3wBk-Xifc44ZyxPU*)%gDJioJeA?1$D=U6Dp$ ze;^<}Zr;!!zIMGo%0J-C)YoVa_+9j2HIUDh`KtXOjtPe}*R?deeVJRBQ*S5M{+4PQNC!CXo|OvNzPld+;xpK%;;CH|PJzLT$e4^&`=bT{5DoFRG0Ngh># zI~ZuqR2Z(%s?H2y0-*wTxV0lwJ@Z>ThNqqnWB(M$Rhyamqti438Uc-fMj-nT5WmUP zEpK-u^ZDEeL`QUgNzJ55OB%htXgKE1ctShk00@VJl_Z{mP`}Y-59QkC5!YMYp}j?b z7p-@C1EIamH=^vt{7Ceu(&MRd)r8ypcon@1UZZ`=eDVf^LR}k(d1EnuC*F7)wUl#$ z;a2>npC5?_Is@m~64ad$Gc(F^&2MtGn0HK4^qy$A!|#h*1nlCbsE z&9?IODW^KtiR%s_e^44k!x4WpelCi|)7RXF1^)9Az1LFqB5+I<_r0N#KOBmY9||nP zqi<8@RoA+j{PB1owA{td?UTCoq0AP{tByoY?+OI*s9bUqzSR@KD~yuN&7o;m)`oqq zzIqIOOcnXfA31i-9I{l`?4Wmf%qrXC^{wzO_ea$@H*IY*IboVQyY1$+*}MDAo}UNr z*BJ@0i!+fCm#b3MeEU~+;28 z6&-CWDyF%oRp7brScNwds2G75;U(mSa(y{gl%sz)(9h^b`Z;Z)o9Jfx1>Hio(rxrh zx}APSchH@57yX*g4?xB0>KDwVCpx@Agw3QyBhv^Y|lpdpP^f+y&-_jHGJ9?6y zqNnK@dX}D}=jjD{kzS&g>G!mQUZGd%HF}-ipf~9cw3Gfwf1*FrTl6;lh5kyr=x_9Q z`Uky3|D<>6U-TaRoBl)prQP&CeL!MOGJVmQU`(Ku#w=qN^%$#-)wJ5!h;K<&aBiTRojaX7>F%83oMPIZB;eEmMbv9-BD|3dd1o3MwnZio z_RVgaW+`m$2ks?C+=!zbX?a!6m$}KtRV&HpHG1_I`Sch0csyiv$Z46=P}>$*;p+%T zJvE-DMe13H1Skc^EG@ng(W7ZS>` zt-fW^<%pkm)Wz7U;Mh!X5F}pT@7T=m_bU} zt`7wRA-}5@kCC*GZVSYNOO{2$xYiJA%dZP9$0tVH$5;z;T-*}=wkJP#knnyfy;PNG zrV+>z1jLvBvZSxNn;L<12srRnA_SfaNf($YT#5mwTSnqzn&O>I_CoUcNqf#Z z#IR&ZEbblB%e;oz0QJOPYHzSAddN-VFS*op`+Z$;FP^a9rOSDn^Xxi)2#TeP^Tq7z&<%sHy?#$jI;Bb$`i%Nq>!Kfa*t+vz%j5q|wWbV;W z&n1!$vH3W!@b1M2ywfyof1X!Z)yZqHR&=k0q)zX3?h%nepI3~C-MG)4$oBJ!eFjcv z)Ci0O1PVq%C-y@haECP4>kf;1-Tf4A-4PM#Mh~u6f%rN~%NFp=L7#h&KKIBxM0Dy9 z5iod$$}$F;%R{V5XV(ZE*a+~`CHy649T)+HL(!b>T>_BN&y>^XZChycvvX_WE);rL*^d1q|xqj9Bf^`e0zutSqipeNr2h!V+e+TjtX!rV6pN1SL z2ceD?&#qfIc`@W($j5=-0GoDD!@7l&+R+x2KeYtsNhdG3=*8 zZtgAbz7#Uow;FWG`c-x3uUj~c+k~`859;5E_>0KjyM9$|3F7DXmWR;Kz|qLR3;8#q zy)DRxvO9u^Uy1%Be*k%A-2!ZKU^f}~z61Rl=s{uhtz&6#`MDlogZ6c_ppN&@*8A75 z`sAg(<(=qb=T_sZr|dGmI;{utlW5Bgkk>-D)42ZmxyJPmuK}L`DhJI3?KZA|p+>J@ z(<|7r-5JJX!3bkeH1mg5#`Rmlf3QRG9>rafU$;f^rHYf}*Y+x2CHeQaC_Yv4YgGEx zyJY-orC+P;)_SCVElGaWCdHR3ULyJT)=2(cmG8R|6?aK~<#xq;6rU>j6+0AH`L9s= z%a#6e=mCI(JZhbSb<;Xq$Hw@HHS=rhCb}lpRyS9JdFpGLCuS2EjuLzYPP_%XzgJcl z@T!jFfr51|W-y2&mO=>Fm|U4vG3V0|thaFBVt`!mf`bwltjbQVf-{)GzT^g95;fKP z%=zqam_ni}qCh+ay)WV8owa8+VLwE|A-pKR886naRbLMt+XjSdXYk z%V!}j!mp3`*>QXJ-1d+e*F5VGn1F$qc3cpBD8=5LwDFj;3%AAq#YMTO|7Pp=2?dTpL-JCLV+_--r$uLM0lp1=m;@f zoD1g9Z|0~OoO2eOl^BDwvwaxA&NT{cPMTsp35B7=h{ki zPVqv;i){5f^W+y8(LuAB z`~!i181SnhnHS@vyd3N#$U0~Q`XZ2nDS#k-t^6e^<`^q^V!4oZzWR+RCR$N_J?=sv zoP65%1t+{{N8}&>o|>A7<2IqRGi-LOHk~?GE31}Mna3&zH^}@!dpcyZF4nr2$L&mwI3<4o&V4{|aC=V>A~`+@K2gcD!Qo#xIL^T4L?M!+1zh8U)la>4*aBeGtlgHO7 zLL?{epHC^7+dEUqr-7fUwsn5R|x;&|0 zcsYu6N&V;9mgg11=V6nl>b>xPpePV(T5>OVj<7GiVKL-FrT-21ky8K62FS_}EZKoB zR>|^%Jbsi<@VX$6k@mej=ahf&Vm#(vCiQ>040?X44#Kj#pqIFnef@SQ#t1d7xF7rz zvi#4V2U+=$6|bURh0mBbpf8d3!FK_zD(CC~bmOExgn2jiMOn`0cn%#R^&9^~Vd@+GX_!W&m7)(?T(^)7Y^o$*K? z{R7Zb5A@t8oBad5h?hXmbH%RbdeuD2<2j*@9S>k`DnC}b_8ZVo1tC1K81*WDavI~T zjw#Qe9mHS*hmH)qt_rWZoHyjP%YP|jN-;h6}^c|>I`ICvu zpgT?KonNv1Sm{mdV?HbOxfdn;*ytZXS0(j_wSr4OR{B&fJNt zV~$Svv6C5Ro_o-jVSg$=R{BpaAN^td#D&;OKUTW)4#;(^CZinVRQa*8IX{JFw$!^h zpPF~EPRMhVp8Kfu$MT$;tMr$ED?fH5j=5B?^gMsnyngRt$h==subbPZ{Ma%FJkhxse^S+RNtSm4Y@)uZ5#sc84{8-uP|A1z()Gy?D z)}Z_t?=KmQg{vW$e$1{%dn`X@(|>{6Y5Fmne(`b8n|{o$XaAw*X-JQUggK8bHCUZz}~+G`%BH!*1tisl+|Rc;P$MM<<#)8#mj0kf~eO# zA3N$nY&L{QfU`(3lW0!1(u1)G!VZJLrRyN~x$bO~gv90`A3zyIH z3iYl+drUv}!BfyIm-?@8UggKG_#tGTCouiW-_hU8Wc$bSI1fnu>K^Eo|F32L(;@X= zzXV*3x051}S1A4UC`{qw;bVAE>c4S^<;TiCUke@k0+?QUZ^Dm#i^q6K>aXQ_t6q&r!eW$0mOTnz+>8x*A;itJ41#L+(;~^w-pHYlDpahhW^g6 z#^bBma{b3Ej)u^ReEu~mL-3FC7StD)z6-f76eBiuVQ2H!CPV=Cl;XOT0f#KbFud19d)@PS4{n zp*LPyi@52>?0Rm4nvaVjkiQ8+J73y_Zfy|by!7!OL363p|EbyXW2JX&f$m#U|JOF` zFF8+3-{rb5llp(6{pRn=X7&N!mipbh5`Jth_9?9qdPnXd2|xCA-tXU$`hw}!cqn~@ z$Ij(aKZdcD=VN8w`ygMT^s~X${<@j)#Mo4i>*4I9=ioH z&u7-(nDAqt;<~Pq`om@={8%B+U&a^qN7iDi{MZD>>}pm+-->#bAG?Id5|2OVkHY*m ze^*Xk2+jAU{^OW8>UU-7<&4|4Qa^>qxjG;F$8RBDr}V(j{9SqT^U(c3>OVC;;m6#$ z(6Nt3m6hdazxrMIrLEBPvYH&9<$WRjSm{eV{@1aZ991U(fBCzzEare_J*&wv8#t(W zSJwUiATzQ4i`c69c+(!p8(0l}54OsW#eWW&#}?~(9;kV=kp0{BtcITVgYskF>xKM( zAn4~T#a5kB^6FJ_z|IQttsirXOoyZ24G)a$2x4 z{n*>hh}^(xa(sRQS$@pRbNXjezho!u)%cn7Ip{EM5FAV2g}plNmpl#)_Zj--dDy7_ zevvW2d}Dn8KnjJKW5hlF%C)jF`Hie{xr|W?E1G*j_Jqj`rXhgKNjHe%*Ozj`t1he{hjC9!js{c5Y!cIW~L`TlKqgn*;JatcLy?Y}NVL z_%|W*{$M@!r+Izsm@;VC$3g$2cd%9C@Te7#?`JhRu1A^X`Pk@7pm{**e+s{0o{t^F zb^b=`H?0MizwU4?oD~!VgLPFP^acSlNj@ zR$+(WxR2+DIv;D|c5)r8f8Fw9Wuv&Az@7DvwI}@8#FfxICiUCTNBgB8D}9c!+9vf+ ztp`_r?5UR_^PE9BPoD?;r5`K3V=^?`rT#_WV9vWXu9JN$>|f-0rhZpCiy@;w2#yz@ z#8&yS)t5p39jl?|y5u}6-OclY?O6XOY^5J7i+&sOQ>-S(OW2R5AM?+L{4}e{@p4JR zFP&Ea%`;N}29I;;$4a+<1M;&{|0eJ;{a7B4+2^GGFU^)8D?5BObk9ruUxUCwosXU2 zg6;*We|MJU$4Z}JU-F{V|7%`i+&;rty(IPTpN+<<{=Sc~jZZspaO_!zt@8hWL|^d1 z2M&%syie7*x(#in9U#_UkFD}!A2=bu!fNQbf6|YYKE!kSRaQg43tQ#Kgz7b+cZ%!B zsy+8{8!(;_oZ`Bv^kZc;KZoWGr3e1z`Pk~Wp?g#6a~P}Rlpo6#I^H;QHeze~F}r>% z#-ZuQZ2Cgzt>2Y4ebHR#O+RMWw_sSE-x*(y{bRfS?;OwL=;NK?cmO;Roa6t7{Z-&; zz{9>}Q^zCW4!E{9MKeP4U7Pw7ot=57x* X#hu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mDNSWindows/WinVersRes.h b/mDNSWindows/WinVersRes.h index 884d661..a115258 100644 --- a/mDNSWindows/WinVersRes.h +++ b/mDNSWindows/WinVersRes.h @@ -23,6 +23,30 @@ Change History (most recent first): $Log: WinVersRes.h,v $ +Revision 1.38 2005/04/25 21:59:42 shersche +Bump to 1.0.0.66 + +Revision 1.37 2005/04/22 07:39:48 shersche +Bump to 1.0.0.65 + +Revision 1.36 2005/04/19 07:25:56 shersche +Bump version to 1.0.0.64 + +Revision 1.35 2005/04/13 17:48:58 shersche +Bump to 1.0.0.63 + +Revision 1.34 2005/04/06 01:00:55 shersche +Bump to 1.0.0.62 + +Revision 1.33 2005/03/30 07:37:41 shersche +Bump to 1.0.0.61 + +Revision 1.32 2005/03/23 00:39:46 shersche +Bump to version 1.0.0.60 + +Revision 1.31 2005/03/16 03:52:06 shersche +Bump to 1.0.0.59 + Revision 1.30 2005/03/07 19:18:18 shersche Update Windows build to 1.0.0.58 @@ -121,10 +145,10 @@ First checked in. #define MASTER_PROD_NAME "Bonjour" // Define the product version for mDNSResponder on Windows -#define MASTER_PROD_VERS 1,0,0,58 -#define MASTER_PROD_VERS_STR "1,0,0,58" -#define MASTER_PROD_VERS_STR2 "1.0.0.58" -#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.0.58" +#define MASTER_PROD_VERS 1,0,0,66 +#define MASTER_PROD_VERS_STR "1,0,0,66" +#define MASTER_PROD_VERS_STR2 "1.0.0.66" +#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.0.66" // 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 08cbc88..850a2d4 100755 --- a/mDNSWindows/dDNS.c +++ b/mDNSWindows/dDNS.c @@ -22,10 +22,16 @@ Change History (most recent first): +$Log: dDNS.c,v $ +Revision 1.6 2005/03/23 05:54:48 cheshire + Fix build warnings +Fix %s where it should be %##s in debugf & LogMsg calls + */ #include "dDNS.h" #include "DNSCommon.h" +#include "uds_daemon.h" #include #include #include @@ -166,7 +172,7 @@ mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceR { if (SameDomainName(&ptr->ar.resrec.rdata->u.name, &answer->rdata->u.name)) { - debugf("Deregistering PTR %s -> %s", ptr->ar.resrec.name->c, ptr->ar.resrec.rdata->u.name.c); + debugf("Deregistering PTR %##s -> %##s", ptr->ar.resrec.name->c, ptr->ar.resrec.rdata->u.name.c); dereg = &ptr->ar; if (prev) prev->next = ptr->next; else slElem->AuthRecs = ptr->next; @@ -271,7 +277,7 @@ mDNSlocal void FoundDefBrowseDomain(mDNS *const m, DNSQuestion *question, const prev = ptr; ptr = ptr->next; } - LogMsg("FoundDefBrowseDomain: Got remove event for domain %s not in list", answer->rdata->u.name.c); + LogMsg("FoundDefBrowseDomain: Got remove event for domain %##s not in list", answer->rdata->u.name.c); } } @@ -359,7 +365,7 @@ mDNSlocal mStatus RegisterSearchDomains( mDNS *const m ) { AuthRecord *dereg = &arList->ar; arList = arList->next; - debugf("Deregistering PTR %s -> %s", dereg->resrec.name->c, dereg->resrec.rdata->u.name.c); + debugf("Deregistering PTR %##s -> %##s", dereg->resrec.name->c, dereg->resrec.rdata->u.name.c); err = mDNS_Deregister(m, dereg); if (err) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err); } @@ -471,7 +477,7 @@ mDNSlocal void SetSCPrefsBrowseDomains(mDNS *m, DNameListElem * browseDomains, m { if ( !browseDomain->name.c[0] ) { - LogMsg("SetSCPrefsBrowseDomains bad DDNS browse domain: %s", browseDomain->name.c[0] ? browseDomain->name.c : "(unknown)"); + LogMsg("SetSCPrefsBrowseDomains bad DDNS browse domain: %##s", browseDomain->name.c[0] ? (char*) browseDomain->name.c : "(unknown)"); } else { @@ -608,14 +614,28 @@ mStatus dDNS_Setup( mDNS *const m ) mStatus dDNS_InitDNSConfig(mDNS *const m) { mStatus err; + static AuthRecord LocalRegPTR; // start query for domains to be used in default (empty string domain) browses err = mDNS_GetDomains(m, &LegacyBrowseDomainQ, mDNS_DomainTypeBrowseLegacy, NULL, mDNSInterface_LocalOnly, FoundDefBrowseDomain, NULL); // provide .local automatically SetSCPrefsBrowseDomain(m, &localdomain, mDNStrue); + + // dns-sd -E does not return "local." + // register registration domain "local" + mDNS_SetupResourceRecord(&LocalRegPTR, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, NULL, NULL); + MakeDomainNameFromDNSNameString(LocalRegPTR.resrec.name, mDNS_DomainTypeNames[mDNS_DomainTypeRegistration]); + AppendDNSNameString (LocalRegPTR.resrec.name, "local"); + AssignDomainName(&LocalRegPTR.resrec.rdata->u.name, &localdomain); + err = mDNS_Register(m, &LocalRegPTR); + if (err) + { + LogMsg("ERROR: dDNS_InitDNSConfig - mDNS_Register returned error %d", err); + } + return mStatus_NoError; -} + } void dDNS_FreeIPAddrList(IPAddrListElem * list) diff --git a/mDNSWindows/dDNS.h b/mDNSWindows/dDNS.h index e1b148e..12c56da 100755 --- a/mDNSWindows/dDNS.h +++ b/mDNSWindows/dDNS.h @@ -35,6 +35,11 @@ #pragma mark - DynDNS structures #endif +#if WIN32 +// named type definition in parentheses +# pragma warning( disable: 4115 ) +#endif + typedef struct IPAddrListElem { mDNSAddr addr; diff --git a/mDNSWindows/loclibrary.c b/mDNSWindows/loclibrary.c index 7a90e66..7084d16 100755 --- a/mDNSWindows/loclibrary.c +++ b/mDNSWindows/loclibrary.c @@ -72,7 +72,7 @@ static int _getISOCode(LANGID wLangID, char *isoLangCode, int codeLen) { int startIndex = i * MODULO_ISOCODES; langCode = (ISOCODES[startIndex] << 8); - langCode += ( (unsigned short) (ISOCODES[startIndex + 1]) ); + langCode = langCode + ( (unsigned short) (ISOCODES[startIndex + 1]) ); if (langCode == wLangID) { char *langStr = (char *)&(ISOCODES[startIndex+2]); @@ -118,6 +118,7 @@ int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locF if ( !strcmp( appPathNameA, "" ) ) { char folder[MAX_PATH]; + char * ext; char * app; GetModuleFileNameA( module, folder, MAX_PATH ); @@ -126,10 +127,16 @@ int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locF app = strrchr( folder, '\\' ); require_action( app, exit, ret = 0 ); - *app++ = '\0'; - snprintf( appPathNameA, MAX_PATH, "%s\\Resources\\%s", folder, app ); + // Strip the extension + + if ( ( ( ext = strstr( app, ".exe" ) ) != NULL ) || ( ( ext = strstr( app, ".dll" ) ) != NULL ) ) + { + *ext = '\0'; + } + + snprintf( appPathNameA, MAX_PATH, "%s\\%s", folder, app ); } ret = PathForResourceWithPathA (appPathNameA, name, locFile, locFileLen); @@ -149,6 +156,7 @@ int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, in { wchar_t folder[MAX_PATH]; wchar_t * app; + wchar_t * ext; GetModuleFileNameW( module, folder, MAX_PATH); @@ -156,10 +164,16 @@ int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, in app = wcsrchr( folder, '\\' ); require_action( app, exit, ret = 0 ); - *app++ = '\0'; - swprintf( appPathNameW, MAX_PATH, L"%ls\\Resources\\%ls", folder, app ); + // Strip the extension + + if ( ( ( ext = wcsstr( app, L".exe" ) ) != NULL ) || ( ( ext = wcsstr( app, L".dll" ) ) != NULL ) ) + { + *ext = '\0'; + } + + swprintf( appPathNameW, MAX_PATH, L"%ls\\%ls", folder, app ); } ret = PathForResourceWithPathW (appPathNameW, name, locFile, locFileLen); diff --git a/mDNSWindows/mDNSWin32.c b/mDNSWindows/mDNSWin32.c index 6e7bb36..656b6e5 100755 --- a/mDNSWindows/mDNSWin32.c +++ b/mDNSWindows/mDNSWin32.c @@ -23,6 +23,31 @@ Change History (most recent first): $Log: mDNSWin32.c,v $ +Revision 1.91 2005/04/25 21:34:28 shersche + Wide-Area services don't disappear when interface goes away + +Revision 1.90 2005/04/25 21:18:08 shersche + mDNSResponder crash when interface goes away. This error seems to be caused by the Windows platform code not returning mStatus_TransientErr when there is a problem with a udp unicast send. + +Revision 1.89 2005/04/22 07:32:24 shersche + PPP connection disables Bonjour .local lookups + mDNSResponder ignores Point-to-Point interfaces + +Revision 1.88 2005/04/05 03:53:03 shersche + Registering with shared secret key doesn't work. + +Revision 1.87 2005/04/03 08:03:12 shersche + mDNSResponder won't start on Windows 2000. + +Revision 1.86 2005/03/30 07:37:14 shersche +Use prefix to compute IPv4 subnet mask, falling back to calling AddressToIndexAndMask only if prefix is zero. + +Revision 1.85 2005/03/30 07:34:52 shersche + Interface index being returned is 512 + +Revision 1.84 2005/03/29 19:19:47 shersche + Windows is not accepting unicast responses. This bug was a result of an error in obtaining the subnet mask for IPv4 interfaces. + Revision 1.83 2005/03/07 18:27:42 shersche Fix problem when ControlPanel commits changes to the browse domain list @@ -381,6 +406,8 @@ Multicast DNS platform plugin for Win32 static GUID kWSARecvMsgGUID = WSAID_WSARECVMSG; #endif +#define kIPv6IfIndexBase (10000000L) + #if 0 #pragma mark == Prototypes == @@ -446,6 +473,16 @@ mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInter // Utilities +typedef struct PolyString PolyString; + +struct PolyString +{ + domainname m_dname; + char m_utf8[256]; + PLSA_UNICODE_STRING m_lsa; +}; + + #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS ) mDNSlocal int getifaddrs_ipv6( struct ifaddrs **outAddrs ); #endif @@ -458,15 +495,18 @@ mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInter mDNSlocal int getifaddrs_ce( struct ifaddrs **outAddrs ); #endif -mDNSlocal mDNSBool CanReceiveUnicast( void ); +mDNSlocal DWORD GetPrimaryInterface(); +mDNSlocal mStatus AddressToIndexAndMask( struct sockaddr * address, uint32_t * index, struct sockaddr * mask ); +mDNSlocal mDNSBool CanReceiveUnicast( void ); +mDNSlocal mDNSBool IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr ); mDNSlocal mStatus StringToAddress( mDNSAddr * ip, LPSTR string ); mDNSlocal mStatus RegQueryString( HKEY key, LPCSTR param, LPSTR * string, DWORD * stringLen, DWORD * enabled ); mDNSlocal struct ifaddrs* myGetIfAddrs(int refresh); mDNSlocal OSStatus TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize ); mDNSlocal OSStatus WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize ); -mDNSlocal OSStatus ConvertUTF8ToLsaString( const char * input, PLSA_UNICODE_STRING output ); -mDNSlocal OSStatus ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char ** output ); +mDNSlocal OSStatus MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input ); +mDNSlocal OSStatus MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input ); mDNSlocal void FreeTCPConnectionData( mDNSTCPConnectionData * data ); #ifdef __cplusplus @@ -793,7 +833,20 @@ mStatus { n = sendto( sendingsocket, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) ); err = translate_errno( n > 0, errno_compat(), kWriteErr ); - require_noerr( err, exit ); + + if ( err ) + { + // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations + + if ( !mDNSAddressIsAllDNSLinkGroup( inDstIP ) && ( WSAGetLastError() == WSAEHOSTDOWN || WSAGetLastError() == WSAENETDOWN || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAENETUNREACH ) ) + { + err = mStatus_TransientErr; + } + else + { + require_noerr( err, exit ); + } + } } exit: @@ -960,7 +1013,7 @@ mDNSs32 mDNSPlatformRawTime( void ) mDNSexport mDNSs32 mDNSPlatformUTC( void ) { - return( -1 ); + return ( mDNSs32 ) time( NULL ); } //=========================================================================================================================== @@ -1462,36 +1515,38 @@ exit: //=========================================================================================================================== void -dDNSPlatformSetSecretForDomain( mDNS *m, const domainname * domain ) +dDNSPlatformSetSecretForDomain( mDNS *m, const domainname * inDomain ) { - char dstring[MAX_ESCAPED_DOMAIN_NAME]; - domainname * d; - domainname canon; + PolyString domain; + PolyString key; + PolyString secret; size_t i; size_t dlen; LSA_OBJECT_ATTRIBUTES attrs; LSA_HANDLE handle = NULL; - LSA_UNICODE_STRING keyName = { 0, 0, NULL }; - LSA_UNICODE_STRING * secret = NULL; - char * converted = NULL; NTSTATUS res; OSStatus err; + // Initialize PolyStrings + + domain.m_lsa = NULL; + key.m_lsa = NULL; + secret.m_lsa = NULL; + // canonicalize name by converting to lower case (keychain and some name servers are case sensitive) - ConvertDomainNameToCString(domain, dstring); - dlen = strlen(dstring); - for (i = 0; i < dlen; i++) + ConvertDomainNameToCString( inDomain, domain.m_utf8 ); + dlen = strlen( domain.m_utf8 ); + for ( i = 0; i < dlen; i++ ) { - dstring[i] = (char) tolower(dstring[i]); // canonicalize -> lower case + domain.m_utf8[i] = (char) tolower( domain.m_utf8[i] ); // canonicalize -> lower case } - MakeDomainNameFromDNSNameString(&canon, dstring); - d = &canon; + MakeDomainNameFromDNSNameString( &domain.m_dname, domain.m_utf8 ); // attrs are reserved, so initialize to zeroes. - ZeroMemory(&attrs, sizeof( attrs ) ); + ZeroMemory( &attrs, sizeof( attrs ) ); // Get a handle to the Policy object on the local system @@ -1501,38 +1556,59 @@ dDNSPlatformSetSecretForDomain( mDNS *m, const domainname * domain ) // Get the encrypted data - err = ConvertUTF8ToLsaString( dstring, &keyName ); + domain.m_lsa = ( PLSA_UNICODE_STRING) malloc( sizeof( LSA_UNICODE_STRING ) ); + require_action( domain.m_lsa != NULL, exit, err = mStatus_NoMemoryErr ); + err = MakeLsaStringFromUTF8String( domain.m_lsa, domain.m_utf8 ); require_noerr( err, exit ); - res = LsaRetrievePrivateData( handle, &keyName, &secret ); + // Retrieve the key + + res = LsaRetrievePrivateData( handle, domain.m_lsa, &key.m_lsa ); err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr ); require_noerr_quiet( err, exit ); - // Convert the unicode to string to 8 bit + // Convert the key to a domainname - err = ConvertLsaStringToUTF8( secret, &converted ); + err = MakeUTF8StringFromLsaString( key.m_utf8, sizeof( key.m_utf8 ), key.m_lsa ); require_noerr( err, exit ); + MakeDomainNameFromDNSNameString( &key.m_dname, key.m_utf8 ); - mDNS_SetSecretForZone( m, d, d, converted ); + // Retrieve the secret + + res = LsaRetrievePrivateData( handle, key.m_lsa, &secret.m_lsa ); + err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr ); + require_noerr_quiet( err, exit ); + + // Convert the secret to UTF8 string + + err = MakeUTF8StringFromLsaString( secret.m_utf8, sizeof( secret.m_utf8 ), secret.m_lsa ); + require_noerr( err, exit ); + + // And finally, tell the core about this secret + + debugf("Setting shared secret for zone %s with key %##s", domain.m_utf8, key.m_dname.c); + mDNS_SetSecretForZone( m, &domain.m_dname, &key.m_dname, secret.m_utf8 ); exit: - if ( converted ) + if ( domain.m_lsa != NULL ) { - free( converted ); - converted = NULL; + if ( domain.m_lsa->Buffer != NULL ) + { + free( domain.m_lsa->Buffer ); + } + + free( domain.m_lsa ); } - if ( secret ) + if ( key.m_lsa != NULL ) { - LsaFreeMemory( secret ); - secret = NULL; + LsaFreeMemory( key.m_lsa ); } - if ( keyName.Buffer ) + if ( secret.m_lsa != NULL ) { - free( keyName.Buffer ); - keyName.Buffer = NULL; + LsaFreeMemory( secret.m_lsa ); } if ( handle ) @@ -1680,35 +1756,64 @@ exit: IPAddrListElem* dDNSPlatformGetDNSServers( void ) { - FIXED_INFO * fixedInfo = NULL; - ULONG bufLen = sizeof( FIXED_INFO ); - IP_ADDR_STRING * ipAddr; - IPAddrListElem * head = NULL; - IPAddrListElem * current = NULL; + PIP_PER_ADAPTER_INFO pAdapterInfo = NULL; + FIXED_INFO * fixedInfo = NULL; + ULONG bufLen = 0; + IP_ADDR_STRING * dnsServerList; + IP_ADDR_STRING * ipAddr; + IPAddrListElem * head = NULL; + IPAddrListElem * current = NULL; + DWORD index; int i = 0; mStatus err; - while ( 1 ) + // Get the primary interface. + + index = GetPrimaryInterface(); + + // This should have the interface index of the primary index. Fall back in cases where + // it can't be determined. + + if ( index ) { - if ( fixedInfo ) + bufLen = 0; + + while ( GetPerAdapterInfo( index, pAdapterInfo, &bufLen ) == ERROR_BUFFER_OVERFLOW ) { - GlobalFree( fixedInfo ); - fixedInfo = NULL; + pAdapterInfo = (PIP_PER_ADAPTER_INFO) realloc( pAdapterInfo, bufLen ); + require_action( pAdapterInfo, exit, err = mStatus_NoMemoryErr ); } - fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen ); - - err = GetNetworkParams( fixedInfo, &bufLen ); + dnsServerList = &pAdapterInfo->DnsServerList; + } + else + { + bufLen = sizeof( FIXED_INFO ); - if ( ( err != ERROR_BUFFER_OVERFLOW ) || ( i++ == 100 ) ) + while ( 1 ) { - break; + if ( fixedInfo ) + { + GlobalFree( fixedInfo ); + fixedInfo = NULL; + } + + fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen ); + + err = GetNetworkParams( fixedInfo, &bufLen ); + + if ( ( err != ERROR_BUFFER_OVERFLOW ) || ( i++ == 100 ) ) + { + break; + } } - } - require_noerr( err, exit ); + require_noerr( err, exit ); + + dnsServerList = &fixedInfo->DnsServerList; + } - for ( ipAddr = &fixedInfo->DnsServerList; ipAddr; ipAddr = ipAddr->Next ) + for ( ipAddr = dnsServerList; ipAddr; ipAddr = ipAddr->Next ) { mDNSAddr addr; IPAddrListElem * last = current; @@ -1739,6 +1844,11 @@ dDNSPlatformGetDNSServers( void ) exit: + if ( pAdapterInfo ) + { + free( pAdapterInfo ); + } + if ( fixedInfo ) { GlobalFree( fixedInfo ); @@ -1835,6 +1945,7 @@ dDNSPlatformGetPrimaryInterface( mDNS * m, mDNSAddr * primary, mDNSAddr * router DWORD bufLen = sizeof( IP_ADAPTER_INFO ); int i; BOOL found; + DWORD index; mStatus err = mStatus_NoError; DEBUG_UNUSED( m ); @@ -1861,10 +1972,7 @@ dDNSPlatformGetPrimaryInterface( mDNS * m, mDNSAddr * primary, mDNSAddr * router } } - // Windows doesn't really have a concept of a primary adapter, - // so we're just going to iterate through all the adapters and - // pick the first one that has an IP address assigned and - // a gateway assigned + index = GetPrimaryInterface(); for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next ) { @@ -1873,7 +1981,8 @@ dDNSPlatformGetPrimaryInterface( mDNS * m, mDNSAddr * primary, mDNSAddr * router pAdapter->GatewayList.IpAddress.String && pAdapter->GatewayList.IpAddress.String[0] && ( StringToAddress( primary, pAdapter->IpAddressList.IpAddress.String ) == mStatus_NoError ) && - ( StringToAddress( router, pAdapter->GatewayList.IpAddress.String ) == mStatus_NoError ) ) + ( StringToAddress( router, pAdapter->GatewayList.IpAddress.String ) == mStatus_NoError ) && + ( !index || ( pAdapter->Index == index ) ) ) { // Found one that will work @@ -1882,16 +1991,6 @@ dDNSPlatformGetPrimaryInterface( mDNS * m, mDNSAddr * primary, mDNSAddr * router } } - if ( !found ) - { - // If we couldn't find one, then let's try the first one in the list - - err = StringToAddress( primary, pAdapter->IpAddressList.IpAddress.String ); - require_noerr( err, exit ); - - found = TRUE; - } - exit: if ( pAdapterInfo ) @@ -2232,19 +2331,24 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) mDNSInterfaceData * ifd; struct ifaddrs * addrs; struct ifaddrs * p; - struct ifaddrs * loopback; + struct ifaddrs * loopbackv4; + struct ifaddrs * loopbackv6; u_int flagMask; u_int flagTest; - BOOL foundUnicastSock4DestAddr; - BOOL foundUnicastSock6DestAddr; + mDNSBool foundv4; + mDNSBool foundv6; + mDNSBool foundUnicastSock4DestAddr; + mDNSBool foundUnicastSock6DestAddr; dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list\n" ); check( inMDNS ); check( inMDNS->p ); addrs = NULL; - foundUnicastSock4DestAddr = FALSE; - foundUnicastSock6DestAddr = FALSE; + foundv4 = mDNSfalse; + foundv6 = mDNSfalse; + foundUnicastSock4DestAddr = mDNSfalse; + foundUnicastSock6DestAddr = mDNSfalse; // Tear down any existing interfaces that may be set up. @@ -2266,10 +2370,11 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) err = getifaddrs( &addrs ); require_noerr( err, exit ); - loopback = NULL; + loopbackv4 = NULL; + loopbackv6 = NULL; next = &inMDNS->p->interfaceList; - - flagMask = IFF_UP | IFF_MULTICAST | IFF_POINTTOPOINT; + + flagMask = IFF_UP | IFF_MULTICAST; flagTest = IFF_UP | IFF_MULTICAST; #if( MDNS_WINDOWS_ENABLE_IPV4 ) @@ -2281,9 +2386,9 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) } if( p->ifa_flags & IFF_LOOPBACK ) { - if( !loopback ) + if( !loopbackv4 ) { - loopback = p; + loopbackv4 = p; } continue; } @@ -2292,7 +2397,16 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) err = SetupInterface( inMDNS, p, &ifd ); require_noerr( err, exit ); - + + // If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to + // register him, but we also want to note that we haven't found a v4 interface + // so that we register loopback so same host operations work + + if ( ifd->interfaceInfo.McastTxRx == mDNStrue ) + { + foundv4 = mDNStrue; + } + // If we're on a platform that doesn't have WSARecvMsg(), there's no way // of determing the destination address of a packet that is sent to us. // For multicast packets, that's easy to determine. But for the unicast @@ -2308,8 +2422,6 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) *next = ifd; next = &ifd->next; ++inMDNS->p->interfaceCount; - - } #endif @@ -2324,9 +2436,9 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) } if( p->ifa_flags & IFF_LOOPBACK ) { - if( !loopback ) + if( !loopbackv6 ) { - loopback = p; + loopbackv6 = p; } continue; } @@ -2336,6 +2448,15 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) err = SetupInterface( inMDNS, p, &ifd ); require_noerr( err, exit ); + // If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to + // register him, but we also want to note that we haven't found a v4 interface + // so that we register loopback so same host operations work + + if ( ifd->interfaceInfo.McastTxRx == mDNStrue ) + { + foundv6 = mDNStrue; + } + // If we're on a platform that doesn't have WSARecvMsg(), there's no way // of determing the destination address of a packet that is sent to us. // For multicast packets, that's easy to determine. But for the unicast @@ -2371,18 +2492,19 @@ mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) { continue; } - loopback = p; + + v4loopback = p; break; } #endif - if( !inMDNS->p->interfaceList && loopback ) + if ( !foundv4 && loopbackv4 ) { dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", - loopback->ifa_name ? loopback->ifa_name : "", loopback->ifa_extra.index, loopback->ifa_addr ); + loopbackv4->ifa_name ? loopbackv4->ifa_name : "", loopbackv4->ifa_extra.index, loopbackv4->ifa_addr ); - err = SetupInterface( inMDNS, loopback, &ifd ); + err = SetupInterface( inMDNS, loopbackv4, &ifd ); require_noerr( err, exit ); #if( MDNS_WINDOWS_ENABLE_IPV4 ) @@ -2497,7 +2619,6 @@ mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI ifd->sock = kInvalidSocketRef; ifd->index = inIFA->ifa_extra.index; ifd->scopeID = inIFA->ifa_extra.index; - check( strlen( inIFA->ifa_name ) < sizeof( ifd->name ) ); strncpy( ifd->name, inIFA->ifa_name, sizeof( ifd->name ) - 1 ); ifd->name[ sizeof( ifd->name ) - 1 ] = '\0'; @@ -2512,7 +2633,7 @@ mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI // but we cut the packet rate in half. At this time, reducing the packet rate is more important than v6-only // devices on a large configured network, so we are willing to make that sacrifice. - ifd->interfaceInfo.McastTxRx = mDNStrue; + ifd->interfaceInfo.McastTxRx = ( ( inIFA->ifa_flags & IFF_MULTICAST ) && !( inIFA->ifa_flags & IFF_POINTTOPOINT ) ) ? mDNStrue : mDNSfalse; ifd->interfaceInfo.InterfaceID = NULL; for( p = inMDNS->p->interfaceList; p; p = p->next ) @@ -2521,7 +2642,6 @@ mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI { if (!ifd->interfaceInfo.InterfaceID) { - p->scopeID = ifd->scopeID; ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) p; } @@ -3496,7 +3616,7 @@ mDNSlocal void ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *i if ( inIFD ) { - require_action( ipv4PacketInfo->ipi_ifindex == ( inIFD->index >> 8 ), exit, err = kMismatchErr ); + require_action( ipv4PacketInfo->ipi_ifindex == inIFD->index, exit, err = kMismatchErr ); } dstAddr.type = mDNSAddrType_IPv4; @@ -3510,7 +3630,7 @@ mDNSlocal void ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *i if ( inIFD ) { - require_action( ipv6PacketInfo->ipi6_ifindex == inIFD->index, exit, err = kMismatchErr ); + require_action( ipv6PacketInfo->ipi6_ifindex == ( inIFD->index - kIPv6IfIndexBase), exit, err = kMismatchErr ); } dstAddr.type = mDNSAddrType_IPv6; @@ -3577,6 +3697,13 @@ mDNSlocal void ProcessingThreadInterfaceListChanged( mDNS *inMDNS ) err = SetupInterfaceList( inMDNS ); check_noerr( err ); + err = dDNS_Setup( inMDNS ); + check_noerr( err ); + + // so that LLQs are restarted against the up to date name servers + + mDNS_UpdateLLQs( inMDNS ); + mDNSPlatformUnlock( inMDNS ); // Inform clients of the change. @@ -3638,6 +3765,10 @@ mDNSlocal void ProcessingThreadTCPIPConfigChanged( mDNS * inMDNS ) err = dDNS_Setup( inMDNS ); check_noerr( err ); + // so that LLQs are restarted against the up to date name servers + + mDNS_UpdateLLQs( inMDNS ); + // and reset the event handler if ( ( inMDNS->p->tcpipKey != NULL ) && ( inMDNS->p->tcpipChangedEvent ) ) @@ -3665,6 +3796,10 @@ mDNSlocal void ProcessingThreadDynDNSConfigChanged( mDNS *inMDNS ) err = dDNS_Setup( inMDNS ); check_noerr( err ); + // so that LLQs are restarted against the up to date name servers + + mDNS_UpdateLLQs( inMDNS ); + // and reset the event handler if ((inMDNS->p->ddnsKey != NULL) && (inMDNS->p->ddnsChangedEvent)) @@ -3770,7 +3905,7 @@ mDNSlocal int getifaddrs_ipv6( struct ifaddrs **outAddrs ) // This loops to handle the case where the interface changes in the window after getting the size, but before the // second call completes. A limit of 100 retries is enforced to prevent infinite loops if something else is wrong. - flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME; + flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME; i = 0; for( ;; ) { @@ -3868,16 +4003,27 @@ mDNSlocal int getifaddrs_ipv6( struct ifaddrs **outAddrs ) ifa->ifa_flags = 0; if( iaa->OperStatus == IfOperStatusUp ) ifa->ifa_flags |= IFF_UP; if( iaa->IfType == IF_TYPE_SOFTWARE_LOOPBACK ) ifa->ifa_flags |= IFF_LOOPBACK; + else if ( IsPointToPoint( addr ) ) ifa->ifa_flags |= IFF_POINTTOPOINT; if( !( iaa->Flags & IP_ADAPTER_NO_MULTICAST ) ) ifa->ifa_flags |= IFF_MULTICAST; + - // Get the interface index. Windows does not have a uniform scheme for IPv4 and IPv6 interface indexes - // so the following is a hack to put IPv4 interface indexes in the upper 24-bits and IPv6 interface indexes - // in the lower 8-bits. This allows the IPv6 interface index to be usable as an IPv6 scope ID directly. + // Interface index being returned is 512 + // + // Windows does not have a uniform scheme for IPv4 and IPv6 interface indexes. + // This code used to shift the IPv4 index up to ensure uniqueness between + // it and IPv6 indexes. Although this worked, it was somewhat confusing to developers, who + // then see interface indexes passed back that don't correspond to anything + // that is seen in Win32 APIs or command line tools like "route". As a relatively + // small percentage of developers are actively using IPv6, it seems to + // make sense to make our use of IPv4 as confusion free as possible. + // So now, IPv6 interface indexes will be shifted up by a + // constant value which will serve to uniquely identify them, and we will + // leave IPv4 interface indexes unmodified. switch( family ) { - case AF_INET: ifa->ifa_extra.index = iaa->IfIndex << 8; break; - case AF_INET6: ifa->ifa_extra.index = ipv6IfIndex; break; + case AF_INET: ifa->ifa_extra.index = iaa->IfIndex; break; + case AF_INET6: ifa->ifa_extra.index = ipv6IfIndex + kIPv6IfIndexBase; break; default: break; } @@ -3913,7 +4059,7 @@ mDNSlocal int getifaddrs_ipv6( struct ifaddrs **outAddrs ) { case AF_INET: { - struct sockaddr_in * sa4; + struct sockaddr_in * sa4; require_action( prefixLength <= 32, exit, err = ERROR_INVALID_DATA ); @@ -3921,12 +4067,21 @@ mDNSlocal int getifaddrs_ipv6( struct ifaddrs **outAddrs ) require_action( sa4, exit, err = WSAENOBUFS ); sa4->sin_family = AF_INET; - if( prefixLength == 0 ) + + if ( prefixLength != 0 ) + { + sa4->sin_addr.s_addr = htonl( 0xFFFFFFFFU << ( 32 - prefixLength ) ); + } + else { - dlog( kDebugLevelWarning, DEBUG_NAME "%s: IPv4 netmask 0, defaulting to 255.255.255.255\n", __ROUTINE__ ); - prefixLength = 32; + uint32_t index; + + dlog( kDebugLevelWarning, DEBUG_NAME "%s: IPv4 prefixLength is 0\n", __ROUTINE__ ); + err = AddressToIndexAndMask( ifa->ifa_addr, &index, (struct sockaddr*) sa4 ); + require_noerr( err, exit ); } - sa4->sin_addr.s_addr = htonl( 0xFFFFFFFFU << ( 32 - prefixLength ) ); + + dlog( kDebugLevelInfo, DEBUG_NAME "%s: IPv4 mask = %s\n", __ROUTINE__, inet_ntoa( sa4->sin_addr ) ); ifa->ifa_netmask = (struct sockaddr *) sa4; break; } @@ -4073,32 +4228,31 @@ mDNSlocal int getifaddrs_ipv4( struct ifaddrs **outAddrs ) // Get addresses. - switch( ifInfo->iiAddress.Address.sa_family ) + if ( ifInfo->iiAddress.Address.sa_family == AF_INET ) { - case AF_INET: - { - struct sockaddr_in * sa4; - - sa4 = &ifInfo->iiAddress.AddressIn; - ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( *sa4 ) ); - require_action( ifa->ifa_addr, exit, err = WSAENOBUFS ); - memcpy( ifa->ifa_addr, sa4, sizeof( *sa4 ) ); + struct sockaddr_in * sa4; + + sa4 = &ifInfo->iiAddress.AddressIn; + ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( *sa4 ) ); + require_action( ifa->ifa_addr, exit, err = WSAENOBUFS ); + memcpy( ifa->ifa_addr, sa4, sizeof( *sa4 ) ); - sa4 = &ifInfo->iiNetmask.AddressIn; - ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) ); - require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS ); - memcpy( ifa->ifa_netmask, sa4, sizeof( *sa4 ) ); + ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) ); - break; - } - - default: - break; + // Service won't start on Win2K. The address + // family field was not being initialized. + + ifa->ifa_netmask->sa_family = AF_INET; + require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS ); + err = AddressToIndexAndMask( ifa->ifa_addr, &ifa->ifa_extra.index, ifa->ifa_netmask ); + require_noerr( err, exit ); } + else + { + // Emulate an interface index. - // Emulate an interface index. - - ifa->ifa_extra.index = (uint32_t)( i + 1 ); + ifa->ifa_extra.index = (uint32_t)( i + 1 ); + } } // Success! @@ -4297,6 +4451,118 @@ void freeifaddrs( struct ifaddrs *inIFAs ) } } + +//=========================================================================================================================== +// GetPrimaryInterface +//=========================================================================================================================== + +mDNSlocal DWORD +GetPrimaryInterface() +{ + PMIB_IPFORWARDTABLE pIpForwardTable = NULL; + DWORD dwSize = 0; + BOOL bOrder = FALSE; + OSStatus err; + DWORD index = 0; + DWORD metric = 0; + unsigned long int i; + + // Find out how big our buffer needs to be. + + err = GetIpForwardTable(NULL, &dwSize, bOrder); + require_action( err == ERROR_INSUFFICIENT_BUFFER, exit, err = kUnknownErr ); + + // Allocate the memory for the table + + pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc( dwSize ); + require_action( pIpForwardTable, exit, err = kNoMemoryErr ); + + // Now get the table. + + err = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder); + require_noerr( err, exit ); + + + // Search for the row in the table we want. + + for ( i = 0; i < pIpForwardTable->dwNumEntries; i++) + { + // Look for a default route + + if ( pIpForwardTable->table[i].dwForwardDest == 0 ) + { + if ( index && ( pIpForwardTable->table[i].dwForwardMetric1 >= metric ) ) + { + continue; + } + + index = pIpForwardTable->table[i].dwForwardIfIndex; + metric = pIpForwardTable->table[i].dwForwardMetric1; + } + } + +exit: + + if ( pIpForwardTable != NULL ) + { + free( pIpForwardTable ); + } + + return index; +} + + +//=========================================================================================================================== +// AddressToIndexAndMask +//=========================================================================================================================== + +mDNSlocal mStatus +AddressToIndexAndMask( struct sockaddr * addr, uint32_t * ifIndex, struct sockaddr * mask ) +{ + // Before calling AddIPAddress we use GetIpAddrTable to get + // an adapter to which we can add the IP. + + PMIB_IPADDRTABLE pIPAddrTable = NULL; + DWORD dwSize = 0; + mStatus err = mStatus_UnknownErr; + DWORD i; + + // For now, this is only for IPv4 addresses. That is why we can safely cast + // addr's to sockaddr_in. + + require_action( addr->sa_family == AF_INET, exit, err = mStatus_UnknownErr ); + + // Make an initial call to GetIpAddrTable to get the + // necessary size into the dwSize variable + + while ( GetIpAddrTable( pIPAddrTable, &dwSize, 0 ) == ERROR_INSUFFICIENT_BUFFER ) + { + pIPAddrTable = (MIB_IPADDRTABLE *) realloc( pIPAddrTable, dwSize ); + require_action( pIPAddrTable, exit, err = WSAENOBUFS ); + } + + for ( i = 0; i < pIPAddrTable->dwNumEntries; i++ ) + { + if ( ( ( struct sockaddr_in* ) addr )->sin_addr.s_addr == pIPAddrTable->table[i].dwAddr ) + { + *ifIndex = pIPAddrTable->table[i].dwIndex; + ( ( struct sockaddr_in*) mask )->sin_addr.s_addr = pIPAddrTable->table[i].dwMask; + err = mStatus_NoError; + break; + } + } + +exit: + + if ( pIPAddrTable ) + { + free( pIPAddrTable ); + } + + return err; +} + + //=========================================================================================================================== // CanReceiveUnicast //=========================================================================================================================== @@ -4327,6 +4593,49 @@ mDNSlocal mDNSBool CanReceiveUnicast( void ) return( ok ); } + +//=========================================================================================================================== +// IsPointToPoint +//=========================================================================================================================== + +mDNSlocal mDNSBool IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr ) +{ + struct ifaddrs * addrs = NULL; + struct ifaddrs * p = NULL; + OSStatus err; + mDNSBool ret = mDNSfalse; + + // For now, only works for IPv4 interfaces + + if ( addr->Address.lpSockaddr->sa_family == AF_INET ) + { + // The getifaddrs_ipv4 call will give us correct information regarding IFF_POINTTOPOINT flags. + + err = getifaddrs_ipv4( &addrs ); + require_noerr( err, exit ); + + for ( p = addrs; p; p = p->ifa_next ) + { + if ( ( addr->Address.lpSockaddr->sa_family == p->ifa_addr->sa_family ) && + ( ( ( struct sockaddr_in* ) addr->Address.lpSockaddr )->sin_addr.s_addr == ( ( struct sockaddr_in* ) p->ifa_addr )->sin_addr.s_addr ) ) + { + ret = ( p->ifa_flags & IFF_POINTTOPOINT ) ? mDNStrue : mDNSfalse; + break; + } + } + } + +exit: + + if ( addrs ) + { + freeifaddrs( addrs ); + } + + return ret; +} + + //=========================================================================================================================== // GetWindowsVersionString //=========================================================================================================================== @@ -4504,6 +4813,7 @@ static mStatus StringToAddress( mDNSAddr * ip, LPSTR string ) dwSize = sizeof( sa4 ); err = WSAStringToAddressA( string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize ); + err = translate_errno( err == 0, WSAGetLastError(), kUnknownErr ); require_noerr( err, exit ); err = dDNS_SetupAddr( ip, (struct sockaddr*) &sa4 ); @@ -4606,7 +4916,7 @@ exit: //=========================================================================================================================== mDNSlocal OSStatus -ConvertUTF8ToLsaString( const char * input, PLSA_UNICODE_STRING output ) +MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input ) { int size; OSStatus err; @@ -4650,41 +4960,36 @@ exit: //=========================================================================================================================== static OSStatus -ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char ** output ) +MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input ) { - int size; + size_t size; OSStatus err = kNoErr; // The Length field of this structure holds the number of bytes, // but WideCharToMultiByte expects the number of wchar_t's. So // we divide by sizeof(wchar_t) to get the correct number. - size = WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), NULL, 0, NULL, NULL); + size = (size_t) WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), NULL, 0, NULL, NULL); err = translate_errno( size != 0, GetLastError(), kUnknownErr ); require_noerr( err, exit ); - // Add one for trailing '\0' + // Ensure that we have enough space (Add one for trailing '\0') + + require_action( ( size + 1 ) <= len, exit, err = mStatus_NoMemoryErr ); - *output = (char*) malloc( size + 1 ); - require_action( *output, exit, err = mStatus_NoMemoryErr ); + // Convert the string - size = WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), *output, size, NULL, NULL); + size = (size_t) WideCharToMultiByte( CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), output, (int) size, NULL, NULL); err = translate_errno( size != 0, GetLastError(), kUnknownErr ); require_noerr( err, exit ); // have to add the trailing 0 because WideCharToMultiByte doesn't do it, // although it does return the correct size - (*output)[size] = '\0'; + output[size] = '\0'; exit: - if ( err && *output ) - { - free( *output ); - *output = NULL; - } - return err; } diff --git a/mDNSWindows/mdnsNSP/mdnsNSP.c b/mDNSWindows/mdnsNSP/mdnsNSP.c index c690459..d192543 100644 --- a/mDNSWindows/mdnsNSP/mdnsNSP.c +++ b/mDNSWindows/mdnsNSP/mdnsNSP.c @@ -23,6 +23,18 @@ Change History (most recent first): $Log: mdnsNSP.c,v $ +Revision 1.14 2005/03/29 20:35:28 shersche + Remove reverse lookup implementation due to NSP framework limitation + +Revision 1.13 2005/03/29 19:42:47 shersche +Do label check before checking etc/hosts file + +Revision 1.12 2005/03/21 00:42:45 shersche + Fix build warnings on Win32 platform + +Revision 1.11 2005/03/16 03:04:51 shersche + Don't issue multicast query multilabel dot-local names + Revision 1.10 2005/02/23 22:16:07 shersche Unregister the NSP before registering to workaround an installer problem during upgrade installs @@ -227,6 +239,11 @@ DEBUG_LOCAL OSStatus HostsFileOpen( HostsFile ** self, const char * fname ); DEBUG_LOCAL OSStatus HostsFileClose( HostsFile * self ); DEBUG_LOCAL void HostsFileInfoFree( HostsFileInfo * info ); DEBUG_LOCAL OSStatus HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo ); +DEBUG_LOCAL const char * GetNextLabel( const char *cstr, char label[64] ); + +#ifdef ENABLE_REVERSE_LOOKUP +DEBUG_LOCAL OSStatus IsReverseLookup( LPCWSTR name, size_t size ); +#endif #if 0 @@ -545,70 +562,49 @@ DEBUG_LOCAL int WSPAPI ( ( p[ 4 ] != 'A' ) && ( p[ 4 ] != 'a' ) ) || ( ( p[ 5 ] != 'L' ) && ( p[ 5 ] != 'l' ) ) ) ) { - require_action_quiet( size > sizeof_string( ".0.8.e.f.ip6.arpa" ), exit, err = WSASERVICE_NOT_FOUND ); - - p = name + ( size - 1 ); - p = ( *p == '.' ) ? ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) : ( ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) + 1 ); - - if ( ( ( p[ 0 ] != '.' ) || - ( ( p[ 1 ] != '0' ) ) || - ( ( p[ 2 ] != '.' ) ) || - ( ( p[ 3 ] != '8' ) ) || - ( ( p[ 4 ] != '.' ) ) || - ( ( p[ 5 ] != 'E' ) && ( p[ 5 ] != 'e' ) ) || - ( ( p[ 6 ] != '.' ) ) || - ( ( p[ 7 ] != 'F' ) && ( p[ 7 ] != 'f' ) ) || - ( ( p[ 8 ] != '.' ) ) || - ( ( p[ 9 ] != 'I' ) && ( p[ 9 ] != 'i' ) ) || - ( ( p[ 10 ] != 'P' ) && ( p[ 10 ] != 'p' ) ) || - ( ( p[ 11 ] != '6' ) ) || - ( ( p[ 12 ] != '.' ) ) || - ( ( p[ 13 ] != 'A' ) && ( p[ 13 ] != 'a' ) ) || - ( ( p[ 14 ] != 'R' ) && ( p[ 14 ] != 'r' ) ) || - ( ( p[ 15 ] != 'P' ) && ( p[ 15 ] != 'p' ) ) || - ( ( p[ 16 ] != 'A' ) && ( p[ 16 ] != 'a' ) ) ) ) - { - require_action_quiet( size > sizeof_string( ".254.169.in-addr.arpa" ), exit, err = WSASERVICE_NOT_FOUND ); - - p = name + ( size - 1 ); - p = ( *p == '.' ) ? ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) : ( ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) + 1 ); - - require_action_quiet( ( ( p[ 0 ] == '.' ) && - ( ( p[ 1 ] == '2' ) ) && - ( ( p[ 2 ] == '5' ) ) && - ( ( p[ 3 ] == '4' ) ) && - ( ( p[ 4 ] == '.' ) ) && - ( ( p[ 5 ] == '1' ) ) && - ( ( p[ 6 ] == '6' ) ) && - ( ( p[ 7 ] == '9' ) ) && - ( ( p[ 8 ] == '.' ) ) && - ( ( p[ 9 ] == 'I' ) || ( p[ 9 ] == 'i' ) ) && - ( ( p[ 10 ] == 'N' ) || ( p[ 10 ] == 'n' ) ) && - ( ( p[ 11 ] == '-' ) ) && - ( ( p[ 12 ] == 'A' ) || ( p[ 12 ] == 'a' ) ) && - ( ( p[ 13 ] == 'D' ) || ( p[ 13 ] == 'd' ) ) && - ( ( p[ 14 ] == 'D' ) || ( p[ 14 ] == 'd' ) ) && - ( ( p[ 15 ] == 'R' ) || ( p[ 15 ] == 'r' ) ) && - ( ( p[ 16 ] == '.' ) ) && - ( ( p[ 17 ] == 'A' ) || ( p[ 17 ] == 'a' ) ) && - ( ( p[ 18 ] == 'R' ) || ( p[ 18 ] == 'r' ) ) && - ( ( p[ 19 ] == 'P' ) || ( p[ 19 ] == 'p' ) ) && - ( ( p[ 20 ] == 'A' ) || ( p[ 20 ] == 'a' ) ) ), - exit, err = WSASERVICE_NOT_FOUND ); - } +#ifdef ENABLE_REVERSE_LOOKUP + + err = IsReverseLookup( name, size ); + +#else + + err = WSASERVICE_NOT_FOUND; + +#endif + + require_noerr( err, exit ); } else { + const char * replyDomain; + char translated[ kDNSServiceMaxDomainName ]; + int n; + int labels = 0; + const char * label[128]; + char text[64]; + + n = WideCharToMultiByte( CP_UTF8, 0, name, -1, translated, sizeof( translated ), NULL, NULL ); + require_action( n > 0, exit, err = WSASERVICE_NOT_FOUND ); + + // + + // Don't resolve multi-label name + + replyDomain = translated; + + while ( *replyDomain ) + { + label[labels++] = replyDomain; + replyDomain = GetNextLabel(replyDomain, text); + } + + require_action( labels == 2, exit, err = WSASERVICE_NOT_FOUND ); + // // // 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 ); } @@ -1984,3 +1980,108 @@ exit: return err; } + + +//=========================================================================================================================== +// GetNextLabel +//=========================================================================================================================== +DEBUG_LOCAL const char* +GetNextLabel(const char *cstr, char label[64]) +{ + char *ptr = label; + while (*cstr && *cstr != '.') // While we have characters in the label... + { + char c = *cstr++; + if (c == '\\') + { + c = *cstr++; + if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1])) + { + int v0 = cstr[-1] - '0'; // then interpret as three-digit decimal + int v1 = cstr[ 0] - '0'; + int v2 = cstr[ 1] - '0'; + int val = v0 * 100 + v1 * 10 + v2; + if (val <= 255) { c = (char)val; cstr += 2; } // If valid three-digit decimal value, use it + } + } + *ptr++ = c; + if (ptr >= label+64) return(NULL); + } + if (*cstr) cstr++; // Skip over the trailing dot (if present) + *ptr++ = 0; + return(cstr); +} + + +#ifdef ENABLE_REVERSE_LOOKUP +//=========================================================================================================================== +// IsReverseLookup +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus +IsReverseLookup( LPCWSTR name, size_t size ) +{ + LPCWSTR p; + OSStatus err = kNoErr; + + require_action_quiet( size > sizeof_string( ".0.8.e.f.ip6.arpa" ), exit, err = WSASERVICE_NOT_FOUND ); + + p = name + ( size - 1 ); + p = ( *p == '.' ) ? ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) : ( ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) + 1 ); + + if ( ( ( p[ 0 ] != '.' ) || + ( ( p[ 1 ] != '0' ) ) || + ( ( p[ 2 ] != '.' ) ) || + ( ( p[ 3 ] != '8' ) ) || + ( ( p[ 4 ] != '.' ) ) || + ( ( p[ 5 ] != 'E' ) && ( p[ 5 ] != 'e' ) ) || + ( ( p[ 6 ] != '.' ) ) || + ( ( p[ 7 ] != 'F' ) && ( p[ 7 ] != 'f' ) ) || + ( ( p[ 8 ] != '.' ) ) || + ( ( p[ 9 ] != 'I' ) && ( p[ 9 ] != 'i' ) ) || + ( ( p[ 10 ] != 'P' ) && ( p[ 10 ] != 'p' ) ) || + ( ( p[ 11 ] != '6' ) ) || + ( ( p[ 12 ] != '.' ) ) || + ( ( p[ 13 ] != 'A' ) && ( p[ 13 ] != 'a' ) ) || + ( ( p[ 14 ] != 'R' ) && ( p[ 14 ] != 'r' ) ) || + ( ( p[ 15 ] != 'P' ) && ( p[ 15 ] != 'p' ) ) || + ( ( p[ 16 ] != 'A' ) && ( p[ 16 ] != 'a' ) ) ) ) + { + require_action_quiet( size > sizeof_string( ".254.169.in-addr.arpa" ), exit, err = WSASERVICE_NOT_FOUND ); + + p = name + ( size - 1 ); + p = ( *p == '.' ) ? ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) : ( ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) + 1 ); + + require_action_quiet( ( ( p[ 0 ] == '.' ) && + ( ( p[ 1 ] == '2' ) ) && + ( ( p[ 2 ] == '5' ) ) && + ( ( p[ 3 ] == '4' ) ) && + ( ( p[ 4 ] == '.' ) ) && + ( ( p[ 5 ] == '1' ) ) && + ( ( p[ 6 ] == '6' ) ) && + ( ( p[ 7 ] == '9' ) ) && + ( ( p[ 8 ] == '.' ) ) && + ( ( p[ 9 ] == 'I' ) || ( p[ 9 ] == 'i' ) ) && + ( ( p[ 10 ] == 'N' ) || ( p[ 10 ] == 'n' ) ) && + ( ( p[ 11 ] == '-' ) ) && + ( ( p[ 12 ] == 'A' ) || ( p[ 12 ] == 'a' ) ) && + ( ( p[ 13 ] == 'D' ) || ( p[ 13 ] == 'd' ) ) && + ( ( p[ 14 ] == 'D' ) || ( p[ 14 ] == 'd' ) ) && + ( ( p[ 15 ] == 'R' ) || ( p[ 15 ] == 'r' ) ) && + ( ( p[ 16 ] == '.' ) ) && + ( ( p[ 17 ] == 'A' ) || ( p[ 17 ] == 'a' ) ) && + ( ( p[ 18 ] == 'R' ) || ( p[ 18 ] == 'r' ) ) && + ( ( p[ 19 ] == 'P' ) || ( p[ 19 ] == 'p' ) ) && + ( ( p[ 20 ] == 'A' ) || ( p[ 20 ] == 'a' ) ) ), + exit, err = WSASERVICE_NOT_FOUND ); + } + + // It's a reverse lookup + + check( err == kNoErr ); + +exit: + + return err; +} +#endif -- 2.45.2