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