]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSWindows/SystemServiceTest/Tool.c
mDNSResponder-107.tar.gz
[apple/mdnsresponder.git] / mDNSWindows / SystemServiceTest / Tool.c
1 /*
2 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22
23 Change History (most recent first):
24
25 $Log: Tool.c,v $
26 Revision 1.2 2004/07/13 21:24:28 rpantos
27 Fix for <rdar://problem/3701120>.
28
29 Revision 1.1 2004/06/18 04:17:43 rpantos
30 Move up one level.
31
32 Revision 1.3 2004/04/09 21:03:15 bradley
33 Changed port numbers to use network byte order for consistency with other platforms.
34
35 Revision 1.2 2004/04/08 09:43:43 bradley
36 Changed callback calling conventions to __stdcall so they can be used with C# delegates.
37
38 Revision 1.1 2004/01/30 02:58:57 bradley
39 Test tool for the mDNSResponder Windows service.
40
41 */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45
46 #include "CommonServices.h"
47 #include "DebugServices.h"
48 #include "DNSSD.h"
49
50 //===========================================================================================================================
51 // Structures
52 //===========================================================================================================================
53
54 #define MAX_DOMAIN_LABEL 63
55 #define MAX_DOMAIN_NAME 255
56
57 typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
58
59 typedef struct { u_char c[ 64]; } domainlabel;
60 typedef struct { u_char c[256]; } domainname;
61
62 typedef struct
63 {
64 uint16_t priority;
65 uint16_t weight;
66 uint16_t port;
67 domainname target;
68 } srv_rdata;
69
70 //===========================================================================================================================
71 // Prototypes
72 //===========================================================================================================================
73
74 int main( int argc, char* argv[] );
75 static void Usage( void );
76 static int ProcessArgs( int argc, char* argv[] );
77
78 #if( defined( WINVER ) )
79 static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent );
80 #endif
81
82 static void CALLBACK_COMPAT
83 EnumerateDomainsCallBack(
84 DNSServiceRef inRef,
85 DNSServiceFlags inFlags,
86 uint32_t inInterfaceIndex,
87 DNSServiceErrorType inErrorCode,
88 const char * inDomain,
89 void * inContext );
90
91 static void CALLBACK_COMPAT
92 BrowseCallBack(
93 DNSServiceRef inRef,
94 DNSServiceFlags inFlags,
95 uint32_t inInterfaceIndex,
96 DNSServiceErrorType inErrorCode,
97 const char * inName,
98 const char * inType,
99 const char * inDomain,
100 void * inContext );
101
102 static void CALLBACK_COMPAT
103 ResolveCallBack(
104 DNSServiceRef inRef,
105 DNSServiceFlags inFlags,
106 uint32_t inInterfaceIndex,
107 DNSServiceErrorType inErrorCode,
108 const char * inFullName,
109 const char * inHostName,
110 uint16_t inPort,
111 uint16_t inTXTSize,
112 const char * inTXT,
113 void * inContext );
114
115 static void CALLBACK_COMPAT
116 RegisterCallBack(
117 DNSServiceRef inRef,
118 DNSServiceFlags inFlags,
119 DNSServiceErrorType inErrorCode,
120 const char * inName,
121 const char * inType,
122 const char * inDomain,
123 void * inContext );
124
125 static void CALLBACK_COMPAT
126 RecordCallBack(
127 DNSServiceRef inRef,
128 DNSRecordRef inRecordRef,
129 DNSServiceFlags inFlags,
130 DNSServiceErrorType inErrorCode,
131 void * inContext );
132
133 static void CALLBACK_COMPAT
134 QueryCallBack(
135 const DNSServiceRef inRef,
136 const DNSServiceFlags inFlags,
137 const uint32_t inInterfaceIndex,
138 const DNSServiceErrorType inErrorCode,
139 const char * inName,
140 const uint16_t inRRType,
141 const uint16_t inRRClass,
142 const uint16_t inRDataSize,
143 const void * inRData,
144 const uint32_t inTTL,
145 void * inContext );
146
147 static void PrintRData( uint16_t inRRType, size_t inRDataSize, const uint8_t *inRData );
148
149 static char *ConvertDomainLabelToCString_withescape(const domainlabel *const label, char *ptr, char esc);
150 static char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc);
151
152 //===========================================================================================================================
153 // Globals
154 //===========================================================================================================================
155
156 #if( defined( WINVER ) )
157 static volatile int gQuit = 0;
158 #endif
159
160 //===========================================================================================================================
161 // main
162 //===========================================================================================================================
163
164 int main( int argc, char *argv[] )
165 {
166 OSStatus err;
167
168 debug_initialize( kDebugOutputTypeMetaConsole );
169 debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
170
171 SetConsoleCtrlHandler( ConsoleControlHandler, TRUE );
172 err = ProcessArgs( argc, argv );
173 return( (int) err );
174 }
175
176 //===========================================================================================================================
177 // Usage
178 //===========================================================================================================================
179
180 static void Usage( void )
181 {
182 fprintf( stderr, "\n" );
183 fprintf( stderr, "DNSServiceTest 1.0d1\n" );
184 fprintf( stderr, "\n" );
185 fprintf( stderr, " -server <IP> Set Remote Server\n" );
186 fprintf( stderr, " -cv Check Version\n" );
187 fprintf( stderr, " -bd Browse for Browse Domains\n" );
188 fprintf( stderr, " -bs <type> <domain> Browse for Services\n" );
189 fprintf( stderr, " -rsi <name> <type> <domain> Resolve Service Instance\n" );
190 fprintf( stderr, " -rs <name> <type> <domain> <host> <port> <txt> Register Service\n" );
191 fprintf( stderr, " -rr Register Records\n" );
192 fprintf( stderr, " -qr <name> <type> <domain> <rrType> Query Record\n" );
193 fprintf( stderr, " -cr <name> <type> <domain> <rrType> Reconfirm Record\n" );
194 fprintf( stderr, " -cp <code> Copy Property\n" );
195 fprintf( stderr, " -h[elp] Help\n" );
196 fprintf( stderr, "\n" );
197 }
198
199 DEBUG_LOCAL DNSServiceRef gRef = NULL;
200 DEBUG_LOCAL DNSRecordRef gRecordRef = NULL;
201 DEBUG_LOCAL const char * gServer = NULL;
202
203 //===========================================================================================================================
204 // ProcessArgs
205 //===========================================================================================================================
206
207 static int ProcessArgs( int argc, char* argv[] )
208 {
209 OSStatus err;
210 int i;
211 const char * name;
212 const char * type;
213 const char * domain;
214 uint16_t port;
215 const char * host;
216 const char * txt;
217 uint16_t txtSize;
218 uint8_t txtStorage[ 256 ];
219 uint32_t ipv4;
220 char s[ 256 ];
221 DNSRecordRef records[ 10 ];
222 char fullName[ kDNSServiceMaxDomainName ];
223 uint16_t rrType;
224
225 err = DNSServiceInitialize( kDNSServiceInitializeFlagsNoServerCheck, 0 );
226 require_noerr( err, exit );
227
228 // Parse the command line arguments (ignore first argument since it's just the program name).
229
230 if( argc <= 1 )
231 {
232 Usage();
233 err = 0;
234 goto exit;
235 }
236 for( i = 1; i < argc; ++i )
237 {
238 if( strcmp( argv[ i ], "-server" ) == 0 )
239 {
240 require_action( argc > ( i + 1 ), exit, err = kParamErr );
241 gServer = argv[ ++i ];
242
243 printf( "Server set to \"%s\"\n", gServer );
244 }
245 else if( strcmp( argv[ i ], "-cv" ) == 0 )
246 {
247 // Check Version
248
249 err = DNSServiceCheckVersion();
250 printf( "CheckVersion: %ld\n", err );
251 err = kNoErr;
252 goto exit;
253 }
254 else if( strcmp( argv[ i ], "-bd" ) == 0 )
255 {
256 err = DNSServiceEnumerateDomains( &gRef, kDNSServiceFlagsBrowseDomains, 0,
257 EnumerateDomainsCallBack, NULL );
258 require_noerr( err, exit );
259 }
260 else if( strcmp( argv[ i ], "-bs" ) == 0 )
261 {
262 // Browse service <type> <domain>
263
264 if( argc > ( i + 2 ) )
265 {
266 type = argv[ ++i ];
267 domain = argv[ ++i ];
268 }
269 else
270 {
271 type = "_http._tcp";
272 domain = "";
273 }
274 if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
275 {
276 domain = "local.";
277 }
278
279 err = DNSServiceBrowse( &gRef, 0, 0, type, domain, BrowseCallBack, NULL );
280 require_noerr( err, exit );
281 }
282 else if( strcmp( argv[ i ], "-rsi" ) == 0 )
283 {
284 // Resolve Service Instance <name> <type> <domain>
285
286 if( argc > ( i + 3 ) )
287 {
288 name = argv[ ++i ];
289 type = argv[ ++i ];
290 domain = argv[ ++i ];
291 }
292 else
293 {
294 name = "test service";
295 type = "_http._tcp";
296 domain = "";
297 }
298 if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
299 {
300 domain = "local.";
301 }
302
303 err = DNSServiceResolve( &gRef, 0, 0, name, type, domain, ResolveCallBack, NULL );
304 require_noerr( err, exit );
305 }
306 else if( strcmp( argv[ i ], "-rs" ) == 0 )
307 {
308 // Register Service <name> <type> <domain> <host> <port> <txt>
309
310 if( argc > ( i + 6 ) )
311 {
312 name = argv[ ++i ];
313 type = argv[ ++i ];
314 domain = argv[ ++i ];
315 host = argv[ ++i ];
316 port = (uint16_t) atoi( argv[ ++i ] );
317 txt = argv[ ++i ];
318 }
319 else
320 {
321 name = "test service";
322 type = "_http._tcp";
323 domain = "";
324 host = "";
325 port = 80;
326 txt = "My TXT Record";
327 }
328 if( *txt != '\0' )
329 {
330 txtStorage[ 0 ] = (uint8_t) strlen( txt );
331 memcpy( &txtStorage[ 1 ], txt, txtStorage[ 0 ] );
332 txtSize = (uint16_t)( 1 + txtStorage[ 0 ] );
333 txt = (const char *) txtStorage;
334 }
335 else
336 {
337 txt = NULL;
338 txtSize = 0;
339 }
340 if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
341 {
342 domain = "local.";
343 }
344
345 err = DNSServiceRegister( &gRef, 0, 0, name, type, domain, host, htons( port ), txtSize, txt,
346 RegisterCallBack, NULL );
347 require_noerr( err, exit );
348
349 #if( TEST_SERVICE_RECORDS )
350 ipv4 = 0x11223344;
351 err = DNSServiceAddRecord( gRef, &gRecordRef, 0, kDNSServiceDNSType_A, kDNSServiceDNSClass_IN, &ipv4, 60 );
352 require_noerr( err, exit );
353
354 Sleep( 10000 );
355
356 ipv4 = 0x22334455;
357 err = DNSServiceUpdateRecord( gRef, gRecordRef, 0, 4, &ipv4, 60 );
358 require_noerr( err, exit );
359
360 Sleep( 10000 );
361
362 err = DNSServiceRemoveRecord( gRef, gRecordRef, 0 );
363 require_noerr( err, exit );
364 gRecordRef = NULL;
365
366 Sleep( 10000 );
367 #endif
368 }
369 else if( strcmp( argv[ i ], "-rr" ) == 0 )
370 {
371 // Register Records
372
373 err = DNSServiceCreateConnection( &gRef );
374 require_noerr( err, exit );
375
376 printf( "registering 10 address records...\n" );
377 ipv4 = 0x11223310;
378 for( i = 0; i < 10; ++i )
379 {
380 sprintf( s, "testhost-%d.local.", i );
381 ++ipv4;
382 err = DNSServiceRegisterRecord( gRef, &records[ i ], kDNSServiceFlagsUnique, 0, s,
383 kDNSServiceDNSType_A, kDNSServiceDNSClass_IN, 4, &ipv4, 60, RecordCallBack, NULL );
384 check_noerr( err );
385 }
386 Sleep( 10000 );
387
388 printf( "deregistering half of the records\n" );
389 for( i = 0; i < 10; ++i )
390 {
391 if( i % 2 )
392 {
393 err = DNSServiceRemoveRecord( gRef, records[ i ], 0 );
394 check_noerr( err );
395 records[ i ] = NULL;
396 }
397 }
398 Sleep( 10000 );
399
400 printf( "updating the remaining records\n" );
401 for( i = 0; i < 10; ++i )
402 {
403 if( records[ i ] )
404 {
405 ++ipv4;
406 err = DNSServiceUpdateRecord( gRef, records[ i ], 0, 4, &ipv4, 60 );
407 check_noerr( err );
408 }
409 }
410 Sleep( 10000 );
411
412 printf( "deregistering all remaining records\n" );
413 DNSServiceRefDeallocate( gRef );
414
415 Sleep( 5000 );
416 }
417 else if( strcmp( argv[ i ], "-qr" ) == 0 )
418 {
419 // Query Record <name> <type> <domain> <rrType>
420
421 if( argc > ( i + 4 ) )
422 {
423 name = argv[ ++i ];
424 type = argv[ ++i ];
425 domain = argv[ ++i ];
426 rrType = (uint16_t) atoi( argv[ ++i ] );
427 }
428 else
429 {
430 name = "test";
431 type = "";
432 domain = "";
433 rrType = 1; // Address
434 }
435 if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
436 {
437 domain = "local.";
438 }
439 err = DNSServiceConstructFullName( fullName, name, type, domain );
440 require_noerr( err, exit );
441
442 printf( "resolving fullname %s type %d\n", fullName, rrType );
443 err = DNSServiceQueryRecord( &gRef, 0, 0, fullName, rrType, kDNSServiceDNSClass_IN, QueryCallBack, NULL );
444 require_noerr( err, exit );
445 }
446 else if( strcmp( argv[ i ], "-cr" ) == 0 )
447 {
448 // Reconfirm Record <name> <type> <domain> <rrType>
449
450 if( argc > ( i + 4 ) )
451 {
452 name = argv[ ++i ];
453 type = argv[ ++i ];
454 domain = argv[ ++i ];
455 rrType = (uint16_t) atoi( argv[ ++i ] );
456 }
457 else
458 {
459 name = "test";
460 type = "";
461 domain = "";
462 rrType = 1; // Address
463 }
464 if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
465 {
466 domain = "local.";
467 }
468 err = DNSServiceConstructFullName( fullName, name, type, domain );
469 require_noerr( err, exit );
470
471 printf( "reconfirming record fullname %s type %d\n", fullName, rrType );
472 ipv4 = 0x11223310;
473 DNSServiceReconfirmRecord( 0, 0, fullName, rrType, kDNSServiceDNSClass_IN, 4, &ipv4 );
474 }
475 else if( strcmp( argv[ i ], "-cp" ) == 0 )
476 {
477 DNSPropertyCode code;
478 DNSPropertyData data;
479
480 // Copy Property <code>
481
482 if( argc > ( i + 1 ) )
483 {
484 name = argv[ ++i ];
485 require_action( strlen( name ) == 4, exit, err = kParamErr );
486
487 code = (DNSPropertyCode)( name[ 0 ] << 24 );
488 code |= (DNSPropertyCode)( name[ 1 ] << 16 );
489 code |= (DNSPropertyCode)( name[ 2 ] << 8 );
490 code |= (DNSPropertyCode) name[ 3 ];
491 }
492 else
493 {
494 code = kDNSPropertyCodeVersion;
495 name = "vers";
496 }
497
498 err = DNSServiceCopyProperty( code, &data );
499 require_noerr( err, exit );
500
501 printf( "'%s' property:\n", name );
502 if( code == kDNSPropertyCodeVersion )
503 {
504 printf( " clientCurrentVersion: 0x%08X\n", data.u.version.clientCurrentVersion );
505 printf( " clientOldestServerVersion: 0x%08X\n", data.u.version.clientOldestServerVersion );
506 printf( " serverCurrentVersion: 0x%08X\n", data.u.version.serverCurrentVersion );
507 printf( " serverOldestClientVersion: 0x%08X\n", data.u.version.serverOldestClientVersion );
508 }
509 }
510 else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || ( strcmp( argv[ i ], "-h" ) == 0 ) )
511 {
512 // Help
513
514 Usage();
515 err = 0;
516 goto exit;
517 }
518 else
519 {
520 // Unknown parameter.
521
522 dlog( kDebugLevelError, "unknown parameter (%s)\n", argv[ i ] );
523 err = kParamErr;
524 goto exit;
525 }
526 }
527
528 // Run until control-C'd.
529
530 while( !gQuit )
531 {
532 Sleep( 100 );
533 }
534 err = kNoErr;
535
536 exit:
537 DNSServiceFinalize();
538 if( err )
539 {
540 Usage();
541 }
542 return( err );
543 }
544
545 //===========================================================================================================================
546 // ConsoleControlHandler
547 //===========================================================================================================================
548
549 static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent )
550 {
551 BOOL handled;
552
553 handled = 0;
554 switch( inControlEvent )
555 {
556 case CTRL_C_EVENT:
557 case CTRL_BREAK_EVENT:
558 case CTRL_CLOSE_EVENT:
559 case CTRL_LOGOFF_EVENT:
560 case CTRL_SHUTDOWN_EVENT:
561 gQuit = 1;
562 handled = 1;
563 break;
564
565 default:
566 break;
567 }
568 return( handled );
569 }
570
571 //===========================================================================================================================
572 // EnumerateDomainsCallBack
573 //===========================================================================================================================
574
575 static void CALLBACK_COMPAT
576 EnumerateDomainsCallBack(
577 DNSServiceRef inRef,
578 DNSServiceFlags inFlags,
579 uint32_t inInterfaceIndex,
580 DNSServiceErrorType inErrorCode,
581 const char * inDomain,
582 void * inContext )
583 {
584 printf( "inRef: 0x%08X\n", (uintptr_t) inRef );
585 printf( "inFlags: 0x%08X\n", (int) inFlags );
586 printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex );
587 printf( "inErrorCode: %ld\n", inErrorCode );
588 printf( "inDomain: \"%s\"\n", inDomain ? inDomain : "<null>" );
589 printf( "inContext: 0x%08X\n", (uintptr_t) inContext );
590 printf( "\n" );
591 }
592
593 //===========================================================================================================================
594 // BrowseCallBack
595 //===========================================================================================================================
596
597 static void CALLBACK_COMPAT
598 BrowseCallBack(
599 DNSServiceRef inRef,
600 DNSServiceFlags inFlags,
601 uint32_t inInterfaceIndex,
602 DNSServiceErrorType inErrorCode,
603 const char * inName,
604 const char * inType,
605 const char * inDomain,
606 void * inContext )
607 {
608 printf( "inRef: 0x%08X\n", (uintptr_t) inRef );
609 printf( "inFlags: 0x%08X\n", (int) inFlags );
610 printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex );
611 printf( "inErrorCode: %ld\n", inErrorCode );
612 printf( "inName: \"%s\"\n", inName ? inName : "<null>" );
613 printf( "inType: \"%s\"\n", inType ? inType : "<null>" );
614 printf( "inDomain: \"%s\"\n", inDomain ? inDomain : "<null>" );
615 printf( "inContext: 0x%08X\n", (uintptr_t) inContext );
616 printf( "\n" );
617 }
618
619 //===========================================================================================================================
620 // ResolveCallBack
621 //===========================================================================================================================
622
623 static void CALLBACK_COMPAT
624 ResolveCallBack(
625 DNSServiceRef inRef,
626 DNSServiceFlags inFlags,
627 uint32_t inInterfaceIndex,
628 DNSServiceErrorType inErrorCode,
629 const char * inFullName,
630 const char * inHostName,
631 uint16_t inPort,
632 uint16_t inTXTSize,
633 const char * inTXT,
634 void * inContext )
635 {
636 printf( "inRef: 0x%08X\n", (uintptr_t) inRef );
637 printf( "inFlags: 0x%08X\n", (int) inFlags );
638 printf( "inInterfaceIndex: 0x%08X\n", (int) inInterfaceIndex );
639 printf( "inErrorCode: %ld\n", inErrorCode );
640 printf( "inFullName: \"%s\"\n", inFullName ? inFullName : "<null>" );
641 printf( "inHostName: \"%s\"\n", inHostName ? inHostName : "<null>" );
642 printf( "inPort: %d\n", ntohs( inPort ) );
643 printf( "inTXTSize: %ld\n", inTXTSize );
644 printf( "inTXT: 0x%08X\n", (uintptr_t) inTXT );
645 printf( "inContext: 0x%08X\n", (uintptr_t) inContext );
646 printf( "\n" );
647 }
648
649 //===========================================================================================================================
650 // RegisterCallBack
651 //===========================================================================================================================
652
653 static void CALLBACK_COMPAT
654 RegisterCallBack(
655 DNSServiceRef inRef,
656 DNSServiceFlags inFlags,
657 DNSServiceErrorType inErrorCode,
658 const char * inName,
659 const char * inType,
660 const char * inDomain,
661 void * inContext )
662 {
663 printf( "inRef: 0x%08X\n", (uintptr_t) inRef );
664 printf( "inFlags: 0x%08X\n", (int) inFlags );
665 printf( "inErrorCode: %ld\n", inErrorCode );
666 printf( "inName: \"%s\"\n", inName ? inName : "<null>" );
667 printf( "inType: \"%s\"\n", inType ? inType : "<null>" );
668 printf( "inDomain: \"%s\"\n", inDomain ? inDomain : "<null>" );
669 printf( "inContext: 0x%08X\n", (uintptr_t) inContext );
670 printf( "\n" );
671 }
672
673 //===========================================================================================================================
674 // RecordCallBack
675 //===========================================================================================================================
676
677 static void CALLBACK_COMPAT
678 RecordCallBack(
679 DNSServiceRef inRef,
680 DNSRecordRef inRecordRef,
681 DNSServiceFlags inFlags,
682 DNSServiceErrorType inErrorCode,
683 void * inContext )
684 {
685 DEBUG_UNUSED( inRef );
686 DEBUG_UNUSED( inRecordRef );
687 DEBUG_UNUSED( inFlags );
688 DEBUG_UNUSED( inContext );
689
690 if( inErrorCode == kDNSServiceErr_NoError )
691 {
692 printf( "RecordCallBack: no errors\n" );
693 }
694 else
695 {
696 printf( "RecordCallBack: %ld error\n", inErrorCode );
697 }
698 }
699
700 //===========================================================================================================================
701 // QueryCallBack
702 //===========================================================================================================================
703
704 static void CALLBACK_COMPAT
705 QueryCallBack(
706 const DNSServiceRef inRef,
707 const DNSServiceFlags inFlags,
708 const uint32_t inInterfaceIndex,
709 const DNSServiceErrorType inErrorCode,
710 const char * inName,
711 const uint16_t inRRType,
712 const uint16_t inRRClass,
713 const uint16_t inRDataSize,
714 const void * inRData,
715 const uint32_t inTTL,
716 void * inContext )
717 {
718 DEBUG_UNUSED( inRef );
719 DEBUG_UNUSED( inRRClass );
720 DEBUG_UNUSED( inTTL );
721 DEBUG_UNUSED( inContext );
722
723 if( inErrorCode == kDNSServiceErr_NoError )
724 {
725 if( inFlags & kDNSServiceFlagsAdd )
726 {
727 printf( "Add" );
728 }
729 else
730 {
731 printf( "Rmv" );
732 }
733 if( inFlags & kDNSServiceFlagsMoreComing )
734 {
735 printf( "+" );
736 }
737 else
738 {
739 printf( " " );
740 }
741 printf(" 0x%04X %d %s rdata ", inFlags, inInterfaceIndex, inName );
742 PrintRData( inRRType, (size_t) inRDataSize, (const uint8_t *) inRData );
743 }
744 else
745 {
746 printf( "QueryCallback: %ld error\n", inErrorCode );
747 }
748 }
749
750 //===========================================================================================================================
751 // PrintRData
752 //===========================================================================================================================
753
754 static void PrintRData( uint16_t inRRType, size_t inRDataSize, const uint8_t *inRData )
755 {
756 size_t i;
757 srv_rdata * srv;
758 char s[ 1005 ];
759 struct in_addr in;
760
761 switch( inRRType )
762 {
763 case kDNSServiceDNSType_TXT:
764
765 // Print all the alphanumeric and punctuation characters
766
767 for( i = 0; i < inRDataSize; ++i )
768 {
769 if( ( inRData[ i ] >= 32 ) && ( inRData[ i ] <= 127 ) )
770 {
771 printf( "%c", inRData[ i ] );
772 }
773 }
774 printf( "\n" );
775 break;
776
777 case kDNSServiceDNSType_SRV:
778 srv = (srv_rdata *)inRData;
779 ConvertDomainNameToCString_withescape(&srv->target, s, 0);
780 printf("pri=%d, w=%d, port=%d, target=%s\n", srv->priority, srv->weight, srv->port, s);
781 break;
782
783 case kDNSServiceDNSType_A:
784 check( inRDataSize == 4 );
785 memcpy( &in, inRData, sizeof( in ) );
786 printf( "%s\n", inet_ntoa( in ) );
787 break;
788
789 case kDNSServiceDNSType_PTR:
790 ConvertDomainNameToCString_withescape( (domainname *) inRData, s, 0 );
791 break;
792
793 case kDNSServiceDNSType_AAAA:
794 check( inRDataSize == 16 );
795 printf( "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\n",
796 inRData[0], inRData[1], inRData[2], inRData[3], inRData[4], inRData[5], inRData[6], inRData[7], inRData[8],
797 inRData[9], inRData[10], inRData[11], inRData[12], inRData[13], inRData[14], inRData[15] );
798 break;
799
800 default:
801 printf( "ERROR: I dont know how to print inRData of type %d\n", inRRType );
802 return;
803 }
804 }
805
806 static char *ConvertDomainLabelToCString_withescape(const domainlabel *const label, char *ptr, char esc)
807 {
808 const unsigned char * src = label->c; // Domain label we're reading
809 const unsigned char len = *src++; // Read length of this (non-null) label
810 const unsigned char *const end = src + len; // Work out where the label ends
811 if (len > 63) return(NULL); // If illegal label, abort
812 while (src < end) // While we have characters in the label
813 {
814 unsigned char c = *src++;
815 if (esc)
816 {
817 if (c == '.') // If character is a dot,
818 *ptr++ = esc; // Output escape character
819 else if (c <= ' ') // If non-printing ascii,
820 { // Output decimal escape sequence
821 *ptr++ = esc;
822 *ptr++ = (char) ('0' + (c / 100) );
823 *ptr++ = (char) ('0' + (c / 10) % 10);
824 c = (unsigned char)('0' + (c ) % 10);
825 }
826 }
827 *ptr++ = (char)c; // Copy the character
828 }
829 *ptr = 0; // Null-terminate the string
830 return(ptr); // and return
831 }
832
833 static char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc)
834 {
835 const unsigned char *src = name->c; // Domain name we're reading
836 const unsigned char *const max = name->c + MAX_DOMAIN_NAME; // Maximum that's valid
837
838 if (*src == 0) *ptr++ = '.'; // Special case: For root, just write a dot
839
840 while (*src) // While more characters in the domain name
841 {
842 if (src + 1 + *src >= max) return(NULL);
843 ptr = ConvertDomainLabelToCString_withescape((const domainlabel *)src, ptr, esc);
844 if (!ptr) return(NULL);
845 src += 1 + *src;
846 *ptr++ = '.'; // Write the dot after the label
847 }
848
849 *ptr++ = 0; // Null-terminate the string
850 return(ptr); // and return
851 }