]> git.saurik.com Git - apple/mdnsresponder.git/blobdiff - mDNSWindows/SystemServiceTest/Tool.c
mDNSResponder-87.tar.gz
[apple/mdnsresponder.git] / mDNSWindows / SystemServiceTest / Tool.c
diff --git a/mDNSWindows/SystemServiceTest/Tool.c b/mDNSWindows/SystemServiceTest/Tool.c
new file mode 100644 (file)
index 0000000..f4d675a
--- /dev/null
@@ -0,0 +1,851 @@
+/*
+ * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+
+    Change History (most recent first):
+       
+$Log: Tool.c,v $
+Revision 1.2  2004/07/13 21:24:28  rpantos
+Fix for <rdar://problem/3701120>.
+
+Revision 1.1  2004/06/18 04:17:43  rpantos
+Move up one level.
+
+Revision 1.3  2004/04/09 21:03:15  bradley
+Changed port numbers to use network byte order for consistency with other platforms.
+
+Revision 1.2  2004/04/08 09:43:43  bradley
+Changed callback calling conventions to __stdcall so they can be used with C# delegates.
+
+Revision 1.1  2004/01/30 02:58:57  bradley
+Test tool for the mDNSResponder Windows service.
+
+*/
+
+#include       <stdio.h>
+#include       <stdlib.h>
+
+#include       "CommonServices.h"
+#include       "DebugServices.h"
+#include       "DNSSD.h"
+
+//===========================================================================================================================
+//     Structures
+//===========================================================================================================================
+
+#define MAX_DOMAIN_LABEL 63
+#define MAX_DOMAIN_NAME 255
+
+typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
+
+typedef struct { u_char c[ 64]; } domainlabel;
+typedef struct { u_char c[256]; } domainname;
+
+typedef struct 
+    { 
+    uint16_t priority; 
+    uint16_t weight; 
+    uint16_t port; 
+    domainname target;
+    } srv_rdata;
+
+//===========================================================================================================================
+//     Prototypes
+//===========================================================================================================================
+
+int                            main( int argc, char* argv[] );
+static void                    Usage( void );
+static int                     ProcessArgs( int argc, char* argv[] );
+
+#if( defined( WINVER ) )
+       static BOOL WINAPI      ConsoleControlHandler( DWORD inControlEvent );
+#endif
+
+static void CALLBACK_COMPAT
+       EnumerateDomainsCallBack(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               uint32_t                        inInterfaceIndex,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inDomain,  
+               void *                          inContext );
+
+static void CALLBACK_COMPAT
+       BrowseCallBack(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               uint32_t                        inInterfaceIndex,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inName,  
+               const char *            inType,  
+               const char *            inDomain,  
+               void *                          inContext );
+
+static void CALLBACK_COMPAT
+       ResolveCallBack(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               uint32_t                        inInterfaceIndex,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inFullName,  
+               const char *            inHostName,  
+               uint16_t                        inPort, 
+               uint16_t                        inTXTSize, 
+               const char *            inTXT, 
+               void *                          inContext );
+
+static void CALLBACK_COMPAT
+       RegisterCallBack(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inName,  
+               const char *            inType,  
+               const char *            inDomain,  
+               void *                          inContext );
+
+static void CALLBACK_COMPAT
+       RecordCallBack( 
+               DNSServiceRef                   inRef, 
+               DNSRecordRef                    inRecordRef, 
+               DNSServiceFlags                 inFlags, 
+               DNSServiceErrorType     inErrorCode, 
+               void *                                  inContext );
+
+static void CALLBACK_COMPAT
+       QueryCallBack( 
+               const DNSServiceRef             inRef, 
+               const DNSServiceFlags           inFlags, 
+               const uint32_t                          inInterfaceIndex, 
+               const DNSServiceErrorType       inErrorCode, 
+               const char *                            inName, 
+               const uint16_t                          inRRType, 
+               const uint16_t                          inRRClass, 
+               const uint16_t                          inRDataSize, 
+               const void *                            inRData, 
+               const uint32_t                          inTTL, 
+               void *                                          inContext );
+
+static void    PrintRData( uint16_t inRRType, size_t inRDataSize, const uint8_t *inRData );
+
+static char *ConvertDomainLabelToCString_withescape(const domainlabel *const label, char *ptr, char esc);
+static char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc);
+
+//===========================================================================================================================
+//     Globals
+//===========================================================================================================================
+
+#if( defined( WINVER ) )
+       static volatile int             gQuit = 0;
+#endif
+
+//===========================================================================================================================
+//     main
+//===========================================================================================================================
+
+int main( int argc, char *argv[] )
+{
+       OSStatus                err;
+       
+       debug_initialize( kDebugOutputTypeMetaConsole );
+       debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
+
+       SetConsoleCtrlHandler( ConsoleControlHandler, TRUE );
+       err = ProcessArgs( argc, argv );
+       return( (int) err );
+}
+
+//===========================================================================================================================
+//     Usage
+//===========================================================================================================================
+
+static void    Usage( void )
+{
+       fprintf( stderr, "\n" );
+       fprintf( stderr, "DNSServiceTest 1.0d1\n" );
+       fprintf( stderr, "\n" );
+       fprintf( stderr, "  -server <IP>                                      Set Remote Server\n" );
+       fprintf( stderr, "  -cv                                               Check Version\n" );
+       fprintf( stderr, "  -bd                                               Browse for Browse Domains\n" );
+       fprintf( stderr, "  -bs <type> <domain>                               Browse for Services\n" );
+       fprintf( stderr, "  -rsi <name> <type> <domain>                       Resolve Service Instance\n" );
+       fprintf( stderr, "  -rs <name> <type> <domain> <host> <port> <txt>    Register Service\n" );
+       fprintf( stderr, "  -rr                                               Register Records\n" );
+       fprintf( stderr, "  -qr <name> <type> <domain> <rrType>               Query Record\n" );
+       fprintf( stderr, "  -cr <name> <type> <domain> <rrType>               Reconfirm Record\n" );
+       fprintf( stderr, "  -cp <code>                                        Copy Property\n" );
+       fprintf( stderr, "  -h[elp]                                           Help\n" );
+       fprintf( stderr, "\n" );
+}
+
+DEBUG_LOCAL DNSServiceRef              gRef            = NULL;
+DEBUG_LOCAL DNSRecordRef               gRecordRef      = NULL;
+DEBUG_LOCAL const char *               gServer         = NULL;
+
+//===========================================================================================================================
+//     ProcessArgs
+//===========================================================================================================================
+
+static int ProcessArgs( int argc, char* argv[] )
+{      
+       OSStatus                        err;
+       int                                     i;
+       const char *            name;
+       const char *            type;
+       const char *            domain;
+       uint16_t                        port;
+       const char *            host;
+       const char *            txt;
+       uint16_t                        txtSize;
+       uint8_t                         txtStorage[ 256 ];
+       uint32_t                        ipv4;
+       char                            s[ 256 ];
+       DNSRecordRef            records[ 10 ];
+       char                            fullName[ kDNSServiceMaxDomainName ];
+       uint16_t                        rrType;
+       
+       err = DNSServiceInitialize( kDNSServiceInitializeFlagsNoServerCheck, 0 );
+       require_noerr( err, exit );
+       
+       // Parse the command line arguments (ignore first argument since it's just the program name).
+       
+       if( argc <= 1 )
+       {
+               Usage();
+               err = 0;
+               goto exit;
+       }
+       for( i = 1; i < argc; ++i )
+       {
+               if( strcmp( argv[ i ], "-server" ) == 0 )
+               {
+                       require_action( argc > ( i + 1 ), exit, err = kParamErr );
+                       gServer = argv[ ++i ];
+                       
+                       printf( "Server set to \"%s\"\n", gServer );
+               }
+               else if( strcmp( argv[ i ], "-cv" ) == 0 )
+               {
+                       // Check Version
+                                               
+                       err = DNSServiceCheckVersion();
+                       printf( "CheckVersion: %ld\n", err );
+                       err = kNoErr;
+                       goto exit;
+               }
+               else if( strcmp( argv[ i ], "-bd" ) == 0 )
+               {
+                       err = DNSServiceEnumerateDomains( &gRef, kDNSServiceFlagsBrowseDomains, 0, 
+                               EnumerateDomainsCallBack, NULL );
+                       require_noerr( err, exit );
+               }
+               else if( strcmp( argv[ i ], "-bs" ) == 0 )
+               {
+                       // Browse service <type> <domain>
+                                               
+                       if( argc > ( i + 2 ) )
+                       {
+                               type    = argv[ ++i ];
+                               domain  = argv[ ++i ];
+                       }
+                       else
+                       {
+                               type    = "_http._tcp";
+                               domain  = "";
+                       }
+                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
+                       {
+                               domain = "local.";
+                       }
+                       
+                       err = DNSServiceBrowse( &gRef, 0, 0, type, domain, BrowseCallBack, NULL );
+                       require_noerr( err, exit );
+               }
+               else if( strcmp( argv[ i ], "-rsi" ) == 0 )
+               {
+                       // Resolve Service Instance <name> <type> <domain>
+                                               
+                       if( argc > ( i + 3 ) )
+                       {
+                               name    = argv[ ++i ];
+                               type    = argv[ ++i ];
+                               domain  = argv[ ++i ];
+                       }
+                       else
+                       {
+                               name    = "test service";
+                               type    = "_http._tcp";
+                               domain  = "";
+                       }
+                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
+                       {
+                               domain = "local.";
+                       }
+                       
+                       err = DNSServiceResolve( &gRef, 0, 0, name, type, domain, ResolveCallBack, NULL );
+                       require_noerr( err, exit );
+               }
+               else if( strcmp( argv[ i ], "-rs" ) == 0 )
+               {
+                       // Register Service <name> <type> <domain> <host> <port> <txt>
+                       
+                       if( argc > ( i + 6 ) )
+                       {
+                               name    = argv[ ++i ];
+                               type    = argv[ ++i ];
+                               domain  = argv[ ++i ];
+                               host    = argv[ ++i ];
+                               port    = (uint16_t) atoi( argv[ ++i ] );
+                               txt     = argv[ ++i ];
+                       }
+                       else
+                       {
+                               name    = "test service";
+                               type    = "_http._tcp";
+                               domain  = "";
+                               host    = "";
+                               port    = 80;
+                               txt             = "My TXT Record";
+                       }
+                       if( *txt != '\0' )
+                       {
+                               txtStorage[ 0 ] = (uint8_t) strlen( txt );
+                               memcpy( &txtStorage[ 1 ], txt, txtStorage[ 0 ] );
+                               txtSize = (uint16_t)( 1 + txtStorage[ 0 ] );
+                               txt = (const char *) txtStorage;
+                       }
+                       else
+                       {
+                               txt = NULL;
+                               txtSize = 0;
+                       }
+                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
+                       {
+                               domain = "local.";
+                       }
+                       
+                       err = DNSServiceRegister( &gRef, 0, 0, name, type, domain, host, htons( port ), txtSize, txt, 
+                               RegisterCallBack, NULL );
+                       require_noerr( err, exit );
+                       
+                       #if( TEST_SERVICE_RECORDS )
+                               ipv4 = 0x11223344;
+                               err = DNSServiceAddRecord( gRef, &gRecordRef, 0, kDNSServiceDNSType_A, kDNSServiceDNSClass_IN, &ipv4, 60 );
+                               require_noerr( err, exit );
+                               
+                               Sleep( 10000 );
+                               
+                               ipv4 = 0x22334455;
+                               err = DNSServiceUpdateRecord( gRef, gRecordRef, 0, 4, &ipv4, 60 );
+                               require_noerr( err, exit );
+                               
+                               Sleep( 10000 );
+                               
+                               err = DNSServiceRemoveRecord( gRef, gRecordRef, 0 );
+                               require_noerr( err, exit );
+                               gRecordRef = NULL;
+                               
+                               Sleep( 10000 );
+                       #endif
+               }
+               else if( strcmp( argv[ i ], "-rr" ) == 0 )
+               {
+                       // Register Records
+                       
+                       err = DNSServiceCreateConnection( &gRef );
+                       require_noerr( err, exit );
+                                               
+                       printf( "registering 10 address records...\n" );
+                       ipv4 = 0x11223310;
+                       for( i = 0; i < 10; ++i )
+                       {
+                               sprintf( s, "testhost-%d.local.", i );
+                               ++ipv4;
+                               err = DNSServiceRegisterRecord( gRef, &records[ i ], kDNSServiceFlagsUnique, 0, s, 
+                                       kDNSServiceDNSType_A, kDNSServiceDNSClass_IN, 4, &ipv4, 60, RecordCallBack, NULL );
+                               check_noerr( err );
+                       }
+                       Sleep( 10000 );
+                       
+                       printf( "deregistering half of the records\n" );
+                       for( i = 0; i < 10; ++i )
+                       {
+                               if( i % 2 )
+                               {
+                                       err = DNSServiceRemoveRecord( gRef, records[ i ], 0 );
+                                       check_noerr( err );
+                                       records[ i ] = NULL;
+                               }
+                       }
+                       Sleep( 10000 );
+                       
+                       printf( "updating the remaining records\n" );
+                       for( i = 0; i < 10; ++i )
+                       {
+                               if( records[ i ] )
+                               {
+                                       ++ipv4;
+                                       err = DNSServiceUpdateRecord( gRef, records[ i ], 0, 4, &ipv4, 60 );
+                                       check_noerr( err );
+                               }
+                       }
+                       Sleep( 10000 );
+                       
+                       printf( "deregistering all remaining records\n" );
+               DNSServiceRefDeallocate( gRef );
+               
+               Sleep( 5000 );
+               }
+               else if( strcmp( argv[ i ], "-qr" ) == 0 )
+               {
+                       // Query Record <name> <type> <domain> <rrType>
+                                               
+                       if( argc > ( i + 4 ) )
+                       {
+                               name    = argv[ ++i ];
+                               type    = argv[ ++i ];
+                               domain  = argv[ ++i ];
+                               rrType  = (uint16_t) atoi( argv[ ++i ] );
+                       }
+                       else
+                       {
+                               name    = "test";
+                               type    = "";
+                               domain  = "";
+                               rrType  = 1;    // Address
+                       }
+                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
+                       {
+                               domain = "local.";
+                       }
+                       err = DNSServiceConstructFullName( fullName, name, type, domain );
+                       require_noerr( err, exit );
+                       
+                       printf( "resolving fullname %s type %d\n", fullName, rrType );
+                       err = DNSServiceQueryRecord( &gRef, 0, 0, fullName, rrType, kDNSServiceDNSClass_IN, QueryCallBack, NULL );
+                       require_noerr( err, exit );
+               }
+               else if( strcmp( argv[ i ], "-cr" ) == 0 )
+               {
+                       // Reconfirm Record <name> <type> <domain> <rrType>
+                       
+                       if( argc > ( i + 4 ) )
+                       {
+                               name    = argv[ ++i ];
+                               type    = argv[ ++i ];
+                               domain  = argv[ ++i ];
+                               rrType  = (uint16_t) atoi( argv[ ++i ] );
+                       }
+                       else
+                       {
+                               name    = "test";
+                               type    = "";
+                               domain  = "";
+                               rrType  = 1;    // Address
+                       }
+                       if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
+                       {
+                               domain = "local.";
+                       }
+                       err = DNSServiceConstructFullName( fullName, name, type, domain );
+                       require_noerr( err, exit );
+                       
+                       printf( "reconfirming record fullname %s type %d\n", fullName, rrType );
+                       ipv4 = 0x11223310;
+                       DNSServiceReconfirmRecord( 0, 0, fullName, rrType, kDNSServiceDNSClass_IN, 4, &ipv4 );
+               }
+               else if( strcmp( argv[ i ], "-cp" ) == 0 )
+               {
+                       DNSPropertyCode         code;
+                       DNSPropertyData         data;
+                       
+                       // Copy Property <code>
+                                               
+                       if( argc > ( i + 1 ) )
+                       {
+                               name = argv[ ++i ];
+                               require_action( strlen( name ) == 4, exit, err = kParamErr );
+                               
+                               code  = (DNSPropertyCode)( name[ 0 ] << 24 );
+                               code |= (DNSPropertyCode)( name[ 1 ] << 16 );
+                               code |= (DNSPropertyCode)( name[ 2 ] <<  8 );
+                               code |= (DNSPropertyCode)  name[ 3 ];
+                       }
+                       else
+                       {
+                               code = kDNSPropertyCodeVersion;
+                               name = "vers";
+                       }
+                       
+                       err = DNSServiceCopyProperty( code, &data );
+                       require_noerr( err, exit );
+                       
+                       printf( "'%s' property:\n", name );
+                       if( code == kDNSPropertyCodeVersion )
+                       {
+                               printf( "    clientCurrentVersion:      0x%08X\n", data.u.version.clientCurrentVersion );
+                               printf( "    clientOldestServerVersion: 0x%08X\n", data.u.version.clientOldestServerVersion );
+                               printf( "    serverCurrentVersion:      0x%08X\n", data.u.version.serverCurrentVersion );
+                               printf( "    serverOldestClientVersion: 0x%08X\n", data.u.version.serverOldestClientVersion );
+                       }
+               }
+               else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || ( strcmp( argv[ i ], "-h" ) == 0 ) )
+               {
+                       // Help
+                       
+                       Usage();
+                       err = 0;
+                       goto exit;
+               }
+               else
+               {
+                       // Unknown parameter.
+                       
+                       dlog( kDebugLevelError, "unknown parameter (%s)\n", argv[ i ] );
+                       err = kParamErr;
+                       goto exit;
+               }
+       }
+       
+       // Run until control-C'd.
+       
+       while( !gQuit )
+       {
+               Sleep( 100 );
+       }
+       err = kNoErr;
+       
+exit:
+       DNSServiceFinalize();
+       if( err )
+       {
+               Usage();
+       }
+       return( err );
+}
+
+//===========================================================================================================================
+//     ConsoleControlHandler
+//===========================================================================================================================
+
+static BOOL WINAPI     ConsoleControlHandler( DWORD inControlEvent )
+{
+       BOOL            handled;
+       
+       handled = 0;
+       switch( inControlEvent )
+       {
+               case CTRL_C_EVENT:
+               case CTRL_BREAK_EVENT:
+               case CTRL_CLOSE_EVENT:
+               case CTRL_LOGOFF_EVENT:
+               case CTRL_SHUTDOWN_EVENT:
+                       gQuit = 1;
+                       handled = 1;
+                       break;
+               
+               default:
+                       break;
+       }
+       return( handled );
+}
+
+//===========================================================================================================================
+//     EnumerateDomainsCallBack
+//===========================================================================================================================
+
+static void CALLBACK_COMPAT
+       EnumerateDomainsCallBack(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               uint32_t                        inInterfaceIndex,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inDomain,  
+               void *                          inContext )
+{
+       printf( "inRef:            0x%08X\n", (uintptr_t) inRef );
+       printf( "inFlags:          0x%08X\n", (int) inFlags );
+       printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex );
+       printf( "inErrorCode:      %ld\n", inErrorCode );
+       printf( "inDomain:         \"%s\"\n", inDomain ? inDomain : "<null>" );
+       printf( "inContext:        0x%08X\n", (uintptr_t) inContext );
+       printf( "\n" );
+}
+
+//===========================================================================================================================
+//     BrowseCallBack
+//===========================================================================================================================
+
+static void CALLBACK_COMPAT
+       BrowseCallBack(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               uint32_t                        inInterfaceIndex,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inName,  
+               const char *            inType,  
+               const char *            inDomain,  
+               void *                          inContext )
+{
+       printf( "inRef:            0x%08X\n", (uintptr_t) inRef );
+       printf( "inFlags:          0x%08X\n", (int) inFlags );
+       printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex );
+       printf( "inErrorCode:      %ld\n", inErrorCode );
+       printf( "inName:           \"%s\"\n", inName ? inName : "<null>" );
+       printf( "inType:           \"%s\"\n", inType ? inType : "<null>" );
+       printf( "inDomain:         \"%s\"\n", inDomain ? inDomain : "<null>" );
+       printf( "inContext:        0x%08X\n", (uintptr_t) inContext );
+       printf( "\n" );
+}
+
+//===========================================================================================================================
+//     ResolveCallBack
+//===========================================================================================================================
+
+static void CALLBACK_COMPAT
+       ResolveCallBack(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               uint32_t                        inInterfaceIndex,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inFullName,  
+               const char *            inHostName,  
+               uint16_t                        inPort, 
+               uint16_t                        inTXTSize, 
+               const char *            inTXT, 
+               void *                          inContext )
+{
+       printf( "inRef:            0x%08X\n", (uintptr_t) inRef );
+       printf( "inFlags:          0x%08X\n", (int) inFlags );
+       printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex );
+       printf( "inErrorCode:      %ld\n", inErrorCode );
+       printf( "inFullName:       \"%s\"\n", inFullName ? inFullName : "<null>" );
+       printf( "inHostName:       \"%s\"\n", inHostName ? inHostName : "<null>" );
+       printf( "inPort:           %d\n", ntohs( inPort ) );
+       printf( "inTXTSize:        %ld\n", inTXTSize );
+       printf( "inTXT:            0x%08X\n", (uintptr_t) inTXT );
+       printf( "inContext:        0x%08X\n", (uintptr_t) inContext );
+       printf( "\n" );
+}
+
+//===========================================================================================================================
+//     RegisterCallBack
+//===========================================================================================================================
+
+static void CALLBACK_COMPAT
+       RegisterCallBack(
+               DNSServiceRef           inRef,
+               DNSServiceFlags         inFlags,
+               DNSServiceErrorType     inErrorCode,
+               const char *            inName,  
+               const char *            inType,  
+               const char *            inDomain,  
+               void *                          inContext )
+{
+       printf( "inRef:            0x%08X\n", (uintptr_t) inRef );
+       printf( "inFlags:          0x%08X\n", (int) inFlags );
+       printf( "inErrorCode:      %ld\n", inErrorCode );
+       printf( "inName:           \"%s\"\n", inName ? inName : "<null>" );
+       printf( "inType:           \"%s\"\n", inType ? inType : "<null>" );
+       printf( "inDomain:         \"%s\"\n", inDomain ? inDomain : "<null>" );
+       printf( "inContext:        0x%08X\n", (uintptr_t) inContext );
+       printf( "\n" );
+}
+
+//===========================================================================================================================
+//     RecordCallBack
+//===========================================================================================================================
+
+static void CALLBACK_COMPAT
+       RecordCallBack( 
+               DNSServiceRef                   inRef, 
+               DNSRecordRef                    inRecordRef, 
+               DNSServiceFlags                 inFlags, 
+               DNSServiceErrorType     inErrorCode, 
+               void *                                  inContext )
+{
+       DEBUG_UNUSED( inRef );
+       DEBUG_UNUSED( inRecordRef );
+       DEBUG_UNUSED( inFlags );
+       DEBUG_UNUSED( inContext );
+       
+       if( inErrorCode == kDNSServiceErr_NoError )
+       {
+               printf( "RecordCallBack: no errors\n" );
+       }
+       else
+       {
+               printf( "RecordCallBack: %ld error\n", inErrorCode );
+       }
+}
+
+//===========================================================================================================================
+//     QueryCallBack
+//===========================================================================================================================
+
+static void CALLBACK_COMPAT
+       QueryCallBack( 
+               const DNSServiceRef             inRef, 
+               const DNSServiceFlags           inFlags, 
+               const uint32_t                          inInterfaceIndex, 
+               const DNSServiceErrorType       inErrorCode, 
+               const char *                            inName, 
+               const uint16_t                          inRRType, 
+               const uint16_t                          inRRClass, 
+               const uint16_t                          inRDataSize, 
+               const void *                            inRData, 
+               const uint32_t                          inTTL, 
+               void *                                          inContext )
+{
+       DEBUG_UNUSED( inRef );
+       DEBUG_UNUSED( inRRClass );
+       DEBUG_UNUSED( inTTL );
+       DEBUG_UNUSED( inContext );
+       
+       if( inErrorCode == kDNSServiceErr_NoError )
+       {
+               if( inFlags & kDNSServiceFlagsAdd )
+               {
+                       printf( "Add" );
+               }
+               else
+               {
+                       printf( "Rmv" );
+               }
+               if( inFlags & kDNSServiceFlagsMoreComing )
+               {
+                       printf( "+" );
+               }
+               else
+               {
+                       printf( " " );
+               }
+               printf(" 0x%04X %d %s rdata ", inFlags, inInterfaceIndex, inName );
+               PrintRData( inRRType, (size_t) inRDataSize, (const uint8_t *) inRData );
+       }
+       else
+       {
+               printf( "QueryCallback: %ld error\n", inErrorCode );
+       }
+}
+
+//===========================================================================================================================
+//     PrintRData
+//===========================================================================================================================
+
+static void    PrintRData( uint16_t inRRType, size_t inRDataSize, const uint8_t *inRData )
+{
+       size_t                          i;
+       srv_rdata *                     srv;
+       char                            s[ 1005 ];
+       struct in_addr          in;
+       
+       switch( inRRType )
+       {
+               case kDNSServiceDNSType_TXT:
+                       
+                       // Print all the alphanumeric and punctuation characters
+                       
+                       for( i = 0; i < inRDataSize; ++i )
+                       {
+                               if( ( inRData[ i ] >= 32 ) && ( inRData[ i ] <= 127 ) )
+                               {
+                                       printf( "%c", inRData[ i ] );
+                               }
+                       }
+                       printf( "\n" );
+                       break;
+                       
+               case kDNSServiceDNSType_SRV:
+                       srv = (srv_rdata *)inRData;
+                       ConvertDomainNameToCString_withescape(&srv->target, s, 0);
+                       printf("pri=%d, w=%d, port=%d, target=%s\n", srv->priority, srv->weight, srv->port, s);
+                       break;
+                       
+               case kDNSServiceDNSType_A:
+                       check( inRDataSize == 4 );
+                       memcpy( &in, inRData, sizeof( in ) );
+                       printf( "%s\n", inet_ntoa( in ) );
+                       break;
+                       
+               case kDNSServiceDNSType_PTR:
+                       ConvertDomainNameToCString_withescape( (domainname *) inRData, s, 0 );
+                       break;
+               
+               case kDNSServiceDNSType_AAAA:
+                       check( inRDataSize == 16 );
+                       printf( "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\n",
+                                       inRData[0], inRData[1], inRData[2], inRData[3], inRData[4], inRData[5], inRData[6], inRData[7], inRData[8], 
+                                       inRData[9], inRData[10], inRData[11], inRData[12], inRData[13], inRData[14], inRData[15] );
+                       break;
+               
+               default:
+                       printf( "ERROR: I dont know how to print inRData of type %d\n", inRRType );
+                       return;
+       }
+}
+
+static char *ConvertDomainLabelToCString_withescape(const domainlabel *const label, char *ptr, char esc)
+    {
+    const unsigned char *      src = label->c;                         // Domain label we're reading
+    const unsigned char        len = *src++;                           // Read length of this (non-null) label
+    const unsigned char *const end = src + len;                        // Work out where the label ends
+    if (len > 63) return(NULL);           // If illegal label, abort
+    while (src < end)                                           // While we have characters in the label
+        {
+        unsigned char c = *src++;
+        if (esc)
+            {
+            if (c == '.')                                       // If character is a dot,
+                *ptr++ = esc;                                   // Output escape character
+            else if (c <= ' ')                                  // If non-printing ascii,
+                {                                                   // Output decimal escape sequence
+                *ptr++ = esc;
+                *ptr++ = (char)  ('0' + (c / 100)     );
+                *ptr++ = (char)  ('0' + (c /  10) % 10);
+                c      = (unsigned char)('0' + (c      ) % 10);
+                }
+            }
+        *ptr++ = (char)c;                                       // Copy the character
+        }
+    *ptr = 0;                                                   // Null-terminate the string
+    return(ptr);                                                // and return
+    }
+
+static char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc)
+    {
+    const unsigned char *src         = name->c;                        // Domain name we're reading
+    const unsigned char *const max   = name->c + MAX_DOMAIN_NAME;      // Maximum that's valid
+
+    if (*src == 0) *ptr++ = '.';                                // Special case: For root, just write a dot
+
+    while (*src)                                                                                                        // While more characters in the domain name
+        {
+        if (src + 1 + *src >= max) return(NULL);
+        ptr = ConvertDomainLabelToCString_withescape((const domainlabel *)src, ptr, esc);
+        if (!ptr) return(NULL);
+        src += 1 + *src;
+        *ptr++ = '.';                                           // Write the dot after the label
+        }
+
+    *ptr++ = 0;                                                 // Null-terminate the string
+    return(ptr);                                                // and return
+    }