2 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
25 Change History (most recent first):
28 Revision 1.12 2004/04/09 21:03:15 bradley
29 Changed port numbers to use network byte order for consistency with other platforms.
31 Revision 1.11 2004/01/30 03:04:32 bradley
32 Updated for latest changes to mDNSWindows.
34 Revision 1.10 2003/10/31 12:18:31 bradley
35 Added display of the resolved host name. Show separate TXT record entries on separate lines.
37 Revision 1.9 2003/10/22 02:00:20 bradley
38 Fixed proxy IP setup to be in network byte order so it works on Mac and Windows.
40 Revision 1.8 2003/10/04 04:47:08 bradley
41 Changed DNSServiceRegistrationCreate to treat the port in network byte order for end-to-end consistency.
43 Revision 1.7 2003/08/20 07:06:34 bradley
44 Update to APSL 2.0. Updated change history to match other mDNSResponder files.
46 Revision 1.6 2003/08/20 06:50:55 bradley
47 Updated to latest internal version of the Rendezvous for Windows code: Re-did everything to support
48 the latest DNSServices APIs (proxies, record updates, etc.); Added support for testing the platform
49 neutral DNSServices-based emulation layer for the Mac OS X DNSServiceDiscovery API.
53 #if( defined( _MSC_VER ) )
54 #pragma warning( disable:4068 ) // Disable "unknown pragma" warning for "pragma unused".
55 #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros.
56 #pragma warning( disable:4311 ) // Disable "type cast : pointer truncation from void *const to int".
58 // No stdint.h with Visual C++ so emulate it here.
60 typedef signed char int8_t; // C99 stdint.h not supported in VC++/VS.NET yet.
61 typedef unsigned char uint8_t; // C99 stdint.h not supported in VC++/VS.NET yet.
62 typedef signed short int16_t; // C99 stdint.h not supported in VC++/VS.NET yet.
63 typedef unsigned short uint16_t; // C99 stdint.h not supported in VC++/VS.NET yet.
64 typedef signed long int32_t; // C99 stdint.h not supported in VC++/VS.NET yet.
65 typedef unsigned long uint32_t; // C99 stdint.h not supported in VC++/VS.NET yet.
74 #include <sys/types.h>
75 #include <sys/socket.h>
76 #include <netinet/in.h>
81 #include <CoreServices/CoreServices.h>
83 #define WIN32_LEAN_AND_MEAN
89 #include "DNSServices.h"
90 #include "DNSServiceDiscovery.h"
92 //===========================================================================================================================
94 //===========================================================================================================================
97 #define require_action_string( X, LABEL, ACTION, STR ) \
102 fprintf( stderr, "%s\n", ( STR ) ); \
108 #define require_string( X, LABEL, STR ) \
113 fprintf( stderr, "%s\n", ( STR ) ); \
119 #define require_noerr_string( ERR, LABEL, STR ) \
124 fprintf( stderr, "%s (%ld)\n", ( STR ), ( ERR ) ); \
130 //===========================================================================================================================
132 //===========================================================================================================================
134 int main( int argc
, char* argv
[] );
135 static void Usage( void );
136 static int ProcessArgs( int argc
, char* argv
[] );
137 static DNSStatus
ProcessPreset( int inPreset
);
140 static void SigIntHandler( int inSignalNumber
);
143 #if( defined( WINVER ) )
144 static BOOL WINAPI
ConsoleControlHandler( DWORD inControlEvent
);
147 static void BrowserCallBack( void *inContext
, DNSBrowserRef inRef
, DNSStatus inStatusCode
, const DNSBrowserEvent
*inEvent
);
148 static void ResolverCallBack( void *inContext
, DNSResolverRef inRef
, DNSStatus inStatusCode
, const DNSResolverEvent
*inEvent
);
151 RegistrationCallBack(
153 DNSRegistrationRef inRef
,
154 DNSStatus inStatusCode
,
155 const DNSRegistrationEvent
* inEvent
);
158 HostRegistrationCallBack(
160 DNSHostRegistrationRef inRef
,
161 DNSStatus inStatusCode
,
165 EmulatedBrowserCallBack(
166 DNSServiceBrowserReplyResultType inResult
,
169 const char * inDomain
,
170 DNSServiceDiscoveryReplyFlags inFlags
,
174 EmulatedDomainEnumerationCallBack(
175 DNSServiceDomainEnumerationReplyResultType inResult
,
176 const char * inDomain
,
177 DNSServiceDiscoveryReplyFlags inFlags
,
181 EmulatedResolverCallBack(
182 struct sockaddr
* inInterfaceAddr
,
183 struct sockaddr
* inAddr
,
184 const char * inTextRecord
,
185 DNSServiceDiscoveryReplyFlags inFlags
,
188 static void EmulatedRegistrationCallBack( DNSServiceRegistrationReplyErrorType inResult
, void *inContext
);
190 static char * IPv4ToString( DNSOpaque32 inIP
, char *outString
);
192 //===========================================================================================================================
194 //===========================================================================================================================
196 #if( defined( WINVER ) )
197 static volatile int gQuit
= 0;
200 static int gPrintTXTRecords
= 1;
204 typedef struct PresetData PresetData
;
212 #pragma mark == Presets ==
215 static const PresetData gPresets
[] =
217 /* 01 */ { 2, { "rendezvous", "-bbd" } },
218 /* 02 */ { 4, { "rendezvous", "-bs", "_airport._tcp", "local." } },
219 /* 03 */ { 4, { "rendezvous", "-bs", "_xserveraid._tcp", "local." } },
220 /* 04 */ { 3, { "rendezvous", "-rdb", "apple.com" } },
221 /* 05 */ { 7, { "rendezvous", "-rs", "My Fake AirPort", "_airport._tcp", "local.", "1234", "My Fake Info" } },
222 /* 06 */ { 7, { "rendezvous", "-rs", "My Fake Xserve RAID", "_xserveraid._tcp", "local.", "1234", "My Fake Info" } },
223 /* 07 */ { 7, { "rendezvous", "-rs", "My Fake Web Server", "_http._tcp", "local.", "8080", "index.html" } },
224 /* 08 */ { 9, { "rendezvous", "-rps", "www.apple.com", "17.254.0.91", "Apple Web Server", "_http._tcp", "local.", "80", "index.html" } },
227 const int gPresetsCount
= sizeof( gPresets
) / sizeof( gPresets
[ 0 ] );
233 //===========================================================================================================================
235 //===========================================================================================================================
237 int main( int argc
, char* argv
[] )
241 // Set up DNS Services and install a Console Control Handler to handle things like control-c signals.
243 err
= DNSServicesInitialize( kDNSFlagAdvertise
, 0 );
244 require_noerr_string( err
, exit
, "could not initialize Rendezvous" );
247 signal( SIGINT
, SigIntHandler
);
250 #if( defined( WINVER ) )
251 SetConsoleCtrlHandler( ConsoleControlHandler
, TRUE
);
254 ProcessArgs( argc
, argv
);
257 DNSServicesFinalize();
261 //===========================================================================================================================
263 //===========================================================================================================================
265 static void Usage( void )
267 fprintf( stderr
, "\n" );
268 fprintf( stderr
, "rendezvous - Rendezvous Tool 1.0d1\n" );
269 fprintf( stderr
, "\n" );
270 fprintf( stderr
, " -bbd 'b'rowse for 'b'rowsing 'd'omains\n" );
271 fprintf( stderr
, " -brd 'b'rowse for 'r'egistration 'd'omains\n" );
272 fprintf( stderr
, " -bs <type> <domain> 'b'rowse for 's'ervices\n" );
273 fprintf( stderr
, " -lsi <name> <type> <domain> 'l'ookup 's'ervice 'i'nstance\n" );
274 fprintf( stderr
, " -rdb[d] <domain> 'r'egister 'd'omain for 'b'rowsing ['d'efault]\n" );
275 fprintf( stderr
, " -rdr[d] <domain> 'r'egister 'd'omain for 'r'egistration ['d'efault]\n" );
276 fprintf( stderr
, " -rs <name> <type> <domain> <port> <txt> 'r'egister 's'ervice\n" );
277 fprintf( stderr
, " -rps <host> <ip> <name> <type> <domain> <port> <txt> 'r'egister 'p'roxy 's'ervice\n" );
278 fprintf( stderr
, " -rnss <name> <type> <domain> 'r'egister 'n'o 's'uch 's'ervice\n" );
280 fprintf( stderr
, " -ebs <type> <domain> 'e'mulated 'b'rowse for 's'ervices\n" );
281 fprintf( stderr
, " -ebd <registration/browse> 'e'mulated 'b'rowse for 'd'omains\n" );
282 fprintf( stderr
, " -elsi <name> <type> <domain> 'e'mulated 'l'ookup 's'ervice 'i'nstance\n" );
283 fprintf( stderr
, " -ers <name> <type> <domain> <port> <txt> 'e'mulated 'r'egister 's'ervice\n" );
285 fprintf( stderr
, " -h[elp] 'h'elp\n" );
286 fprintf( stderr
, "\n" );
288 fprintf( stderr
, " -1 Preset 1 (browse for browsing domains) rendezvous -bbd\n" );
289 fprintf( stderr
, " -2 Preset 2 (browse for AirPort) rendezvous -bs \"_airport._tcp\" \"local.\"\n" );
290 fprintf( stderr
, " -3 Preset 3 (browse for Xserve RAID) rendezvous -bs \"_xserveraid._tcp\" \"local.\"\n" );
291 fprintf( stderr
, " -4 Preset 4 (register apple.com domain) rendezvous -rdb \"apple.com\"\n" );
292 fprintf( stderr
, " -5 Preset 5 (register fake AirPort) rendezvous -rs \"My Fake AirPort\" \"_airport._tcp\" \"local.\" 1234 \"My Fake Info\"\n" );
293 fprintf( stderr
, " -6 Preset 6 (register fake Xserve RAID) rendezvous -rs \"My Fake Xserve RAID\" \"_xserveraid._tcp\" \"local.\" 1234 \"My Fake Info\"\n" );
294 fprintf( stderr
, " -7 Preset 7 (register fake web server) rendezvous -rs \"My Fake Web Server\" \"_http._tcp\" \"local.\" 8080 \"index.html\"\n" );
295 fprintf( stderr
, "\n" );
298 //===========================================================================================================================
300 //===========================================================================================================================
302 static int ProcessArgs( int argc
, char* argv
[] )
312 DNSBrowserRef browser
;
313 DNSResolverFlags resolverFlags
;
314 DNSDomainRegistrationType domainType
;
319 DNSNetworkAddress addr
;
320 dns_service_discovery_ref emulatedRef
;
322 // Parse the command line arguments (ignore first argument since it's just the program name).
324 require_action_string( argc
>= 2, exit
, err
= kDNSBadParamErr
, "no arguments specified" );
326 for( i
= 1; i
< argc
; ++i
)
328 if( strcmp( argv
[ i
], "-bbd" ) == 0 )
330 // 'b'rowse for 'b'rowsing 'd'omains
332 fprintf( stdout
, "browsing for browsing domains\n" );
334 err
= DNSBrowserCreate( 0, BrowserCallBack
, NULL
, &browser
);
335 require_noerr_string( err
, exit
, "create browser failed" );
337 err
= DNSBrowserStartDomainSearch( browser
, 0 );
338 require_noerr_string( err
, exit
, "start domain search failed" );
340 else if( strcmp( argv
[ i
], "-brd" ) == 0 )
342 // 'b'rowse for 'r'egistration 'd'omains
344 fprintf( stdout
, "browsing for registration domains\n" );
346 err
= DNSBrowserCreate( 0, BrowserCallBack
, NULL
, &browser
);
347 require_noerr_string( err
, exit
, "create browser failed" );
349 err
= DNSBrowserStartDomainSearch( browser
, kDNSBrowserFlagRegistrationDomainsOnly
);
350 require_noerr_string( err
, exit
, "start domain search failed" );
352 else if( strcmp( argv
[ i
], "-bs" ) == 0 )
354 // 'b'rowse for 's'ervices <type> <domain>
356 require_action_string( argc
> ( i
+ 2 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
360 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
364 fprintf( stdout
, "browsing for \"%s.%s\"\n", type
, domain
);
366 err
= DNSBrowserCreate( 0, BrowserCallBack
, NULL
, &browser
);
367 require_noerr_string( err
, exit
, "create browser failed" );
369 err
= DNSBrowserStartServiceSearch( browser
, kDNSBrowserFlagAutoResolve
, type
, domain
);
370 require_noerr_string( err
, exit
, "start service search failed" );
372 else if( strcmp( argv
[ i
], "-lsi" ) == 0 )
374 // 'l'ookup 's'ervice 'i'nstance <name> <type> <domain>
376 require_action_string( argc
> ( i
+ 3 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
381 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
385 fprintf( stdout
, "resolving \"%s.%s.%s\"\n", name
, type
, domain
);
387 resolverFlags
= kDNSResolverFlagOnlyIfUnique
|
388 kDNSResolverFlagAutoReleaseByName
;
389 err
= DNSResolverCreate( resolverFlags
, name
, type
, domain
, ResolverCallBack
, 0, NULL
, NULL
);
390 require_noerr_string( err
, exit
, "create resolver failed" );
392 else if( ( strcmp( argv
[ i
], "-rdb" ) == 0 ) || ( strcmp( argv
[ i
], "-rdbd" ) == 0 ) )
394 // 'r'egister 'd'omain for 'b'rowsing ['d'efault] <domain>
396 require_action_string( argc
> ( i
+ 1 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
397 if( strcmp( argv
[ i
], "-rdb" ) == 0 )
399 domainType
= kDNSDomainRegistrationTypeBrowse
;
404 domainType
= kDNSDomainRegistrationTypeBrowseDefault
;
409 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
413 fprintf( stdout
, "registering \"%s\" as %sbrowse domain\n", domain
, label
);
415 err
= DNSDomainRegistrationCreate( 0, domain
, domainType
, NULL
);
416 require_noerr_string( err
, exit
, "create domain registration failed" );
418 else if( ( strcmp( argv
[ i
], "-rdr" ) == 0 ) || ( strcmp( argv
[ i
], "-rdrd" ) == 0 ) )
420 // 'r'egister 'd'omain for 'r'egistration ['d'efault] <domain>
422 require_action_string( argc
> ( i
+ 1 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
423 if( strcmp( argv
[ i
], "-rdr" ) == 0 )
425 domainType
= kDNSDomainRegistrationTypeRegistration
;
430 domainType
= kDNSDomainRegistrationTypeRegistrationDefault
;
435 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
439 fprintf( stdout
, "registering \"%s\" as %sregistration domain\n", domain
, label
);
441 err
= DNSDomainRegistrationCreate( 0, domain
, domainType
, NULL
);
442 require_noerr_string( err
, exit
, "create domain registration failed" );
444 else if( strcmp( argv
[ i
], "-rs" ) == 0 )
446 // 'r'egister 's'ervice <name> <type> <domain> <port> <txt>
448 require_action_string( argc
> ( i
+ 5 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
452 domain
= argv
[ i
++ ];
453 port
= (uint16_t) atoi( argv
[ i
++ ] );
455 textSize
= strlen( text
);
456 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
460 fprintf( stdout
, "registering service \"%s.%s.%s\" port %d text \"%s\"\n", name
, type
, domain
, port
, text
);
462 err
= DNSRegistrationCreate( 0, name
, type
, domain
, (DNSPort
) port
, text
, (DNSCount
) textSize
, NULL
, NULL
,
463 RegistrationCallBack
, NULL
, NULL
);
464 require_noerr_string( err
, exit
, "create registration failed" );
466 else if( strcmp( argv
[ i
], "-rps" ) == 0 )
468 DNSHostRegistrationFlags hostFlags
;
470 // 'r'egister 'p'roxy 's'ervice <host> <ip> <name> <type> <domain> <port> <txt>
472 require_action_string( argc
> ( i
+ 7 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
478 domain
= argv
[ i
++ ];
479 port
= (uint16_t) atoi( argv
[ i
++ ] );
481 textSize
= strlen( text
);
482 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
487 sscanf( ip
, "%u.%u.%u.%u", &b
[ 0 ], &b
[ 1 ], &b
[ 2 ], &b
[ 3 ] );
488 addr
.addressType
= kDNSNetworkAddressTypeIPv4
;
489 addr
.u
.ipv4
.addr
.v8
[ 0 ] = (DNSUInt8
) b
[ 0 ];
490 addr
.u
.ipv4
.addr
.v8
[ 1 ] = (DNSUInt8
) b
[ 1 ];
491 addr
.u
.ipv4
.addr
.v8
[ 2 ] = (DNSUInt8
) b
[ 2 ];
492 addr
.u
.ipv4
.addr
.v8
[ 3 ] = (DNSUInt8
) b
[ 3 ];
494 fprintf( stdout
, "registering proxy service \"%s.%s.%s\" port %d text \"%s\"\n", name
, type
, domain
, port
, text
);
496 hostFlags
= kDNSHostRegistrationFlagOnlyIfNotFound
| kDNSHostRegistrationFlagAutoRenameOnConflict
;
497 err
= DNSHostRegistrationCreate( hostFlags
, host
, domain
, &addr
, NULL
,
498 HostRegistrationCallBack
, NULL
, NULL
);
499 require_noerr_string( err
, exit
, "create host registration failed" );
501 err
= DNSRegistrationCreate( 0, name
, type
, domain
, (DNSPort
) port
, text
, (DNSCount
) textSize
, host
, NULL
,
502 RegistrationCallBack
, NULL
, NULL
);
503 require_noerr_string( err
, exit
, "create registration failed" );
505 else if( strcmp( argv
[ i
], "-rnss" ) == 0 )
507 // 'r'egister 'n'o 's'uch 's'ervice <name> <type> <domain>
509 require_action_string( argc
> ( i
+ 3 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
513 domain
= argv
[ i
++ ];
514 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
518 fprintf( stdout
, "registering no-such-service \"%s.%s.%s\"\n", name
, type
, domain
);
520 err
= DNSNoSuchServiceRegistrationCreate( 0, name
, type
, domain
, NULL
, RegistrationCallBack
, NULL
, NULL
);
521 require_noerr_string( err
, exit
, "create no-such-service registration failed" );
523 else if( strcmp( argv
[ i
], "-ebs" ) == 0 )
525 // 'e'mulated 'b'rowse for 's'ervices <type> <domain>
527 require_action_string( argc
> ( i
+ 2 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
531 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
535 fprintf( stdout
, "emulated browsing for \"%s.%s\"\n", type
, domain
);
537 emulatedRef
= DNSServiceBrowserCreate( type
, domain
, EmulatedBrowserCallBack
, NULL
);
538 require_action_string( emulatedRef
, exit
, err
= kDNSUnknownErr
, "create emulated browser failed" );
540 else if( strcmp( argv
[ i
], "-ebd" ) == 0 )
542 int registrationOnly
;
544 // 'e'mulated 'b'rowse for 'd'omains <registration/browse>
546 require_action_string( argc
> ( i
+ 1 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
549 if( strcmp( type
, "registration" ) == 0 )
551 registrationOnly
= 1;
553 else if( strcmp( type
, "browse" ) == 0 )
555 registrationOnly
= 0;
559 require_action_string( 0, exit
, err
= kDNSBadParamErr
, "invalid browse type" );
561 fprintf( stdout
, "emulated browsing for %s domains\n", type
);
563 emulatedRef
= DNSServiceDomainEnumerationCreate( registrationOnly
, EmulatedDomainEnumerationCallBack
, NULL
);
564 require_action_string( emulatedRef
, exit
, err
= kDNSUnknownErr
, "create emulated domain browser failed" );
566 else if( strcmp( argv
[ i
], "-elsi" ) == 0 )
568 // 'e'mulated 'l'ookup 's'ervice 'i'nstance <name> <type> <domain>
570 require_action_string( argc
> ( i
+ 3 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
575 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
579 fprintf( stdout
, "emulated resolving \"%s.%s.%s\"\n", name
, type
, domain
);
581 emulatedRef
= DNSServiceResolverResolve( name
, type
, domain
, EmulatedResolverCallBack
, NULL
);
582 require_action_string( emulatedRef
, exit
, err
= kDNSUnknownErr
, "create emulated resolver failed" );
584 else if( strcmp( argv
[ i
], "-ers" ) == 0 )
586 // 'e'mulated 'r'egister 's'ervice <name> <type> <domain> <port> <txt>
588 require_action_string( argc
> ( i
+ 5 ), exit
, err
= kDNSBadParamErr
, "missing arguments" );
592 domain
= argv
[ i
++ ];
593 port
= (uint16_t) atoi( argv
[ i
++ ] );
595 textSize
= strlen( text
);
596 if( ( domain
[ 0 ] == '\0' ) || ( ( domain
[ 0 ] == '.' ) && ( domain
[ 1 ] == '\0' ) ) )
600 fprintf( stdout
, "registering service \"%s.%s.%s\" port %d text \"%s\"\n", name
, type
, domain
, port
, text
);
602 emulatedRef
= DNSServiceRegistrationCreate( name
, type
, domain
, htons( port
), text
,
603 EmulatedRegistrationCallBack
, NULL
);
604 require_action_string( emulatedRef
, exit
, err
= kDNSUnknownErr
, "create emulated registration failed" );
606 else if( ( argv
[ i
][ 0 ] == '-' ) && isdigit( argv
[ i
][ 1 ] ) )
610 ProcessPreset( atoi( &argv
[ i
][ 1 ] ) );
614 else if( strcmp( argv
[ i
], "-q" ) == 0 )
616 // Quiet (no text records)
618 gPrintTXTRecords
= 0;
620 else if( ( strcmp( argv
[ i
], "-help" ) == 0 ) || ( strcmp( argv
[ i
], "-h" ) == 0 ) )
630 // Unknown parameter.
632 require_action_string( 0, exit
, err
= kDNSBadParamErr
, "unknown parameter" );
637 // Run until control-C'd.
643 #if( defined( WINVER ) )
660 //===========================================================================================================================
662 //===========================================================================================================================
664 static DNSStatus
ProcessPreset( int inPreset
)
668 require_action_string( ( inPreset
> 0 ) && ( inPreset
<= gPresetsCount
), exit
, err
= kDNSBadParamErr
, "invalid preset" );
670 err
= ProcessArgs( gPresets
[ inPreset
- 1 ].argc
, (char **) gPresets
[ inPreset
- 1 ].argv
);
677 //===========================================================================================================================
679 //===========================================================================================================================
681 static void SigIntHandler( int inSignalNumber
)
683 DNS_UNUSED( inSignalNumber
);
685 signal( SIGINT
, SIG_DFL
);
686 CFRunLoopStop( CFRunLoopGetCurrent() );
690 #if( defined( WINVER ) )
691 //===========================================================================================================================
692 // ConsoleControlHandler
693 //===========================================================================================================================
695 static BOOL WINAPI
ConsoleControlHandler( DWORD inControlEvent
)
700 switch( inControlEvent
)
703 case CTRL_BREAK_EVENT
:
704 case CTRL_CLOSE_EVENT
:
705 case CTRL_LOGOFF_EVENT
:
706 case CTRL_SHUTDOWN_EVENT
:
718 //===========================================================================================================================
720 //===========================================================================================================================
722 static void BrowserCallBack( void *inContext
, DNSBrowserRef inRef
, DNSStatus inStatusCode
, const DNSBrowserEvent
*inEvent
)
727 DNS_UNUSED( inContext
);
729 DNS_UNUSED( inStatusCode
);
731 switch( inEvent
->type
)
733 case kDNSBrowserEventTypeRelease
:
736 case kDNSBrowserEventTypeAddDomain
:
737 fprintf( stdout
, "domain \"%s\" added on interface 0x%08X (%s)\n",
738 inEvent
->data
.addDomain
.domain
,
739 (int) inEvent
->data
.addDomain
.interfaceID
,
740 IPv4ToString( inEvent
->data
.addDomain
.interfaceIP
.u
.ipv4
.addr
, ifIP
) );
743 case kDNSBrowserEventTypeAddDefaultDomain
:
744 fprintf( stdout
, "default domain \"%s\" added on interface 0x%08X (%s)\n",
745 inEvent
->data
.addDefaultDomain
.domain
,
746 (int) inEvent
->data
.addDefaultDomain
.interfaceID
,
747 IPv4ToString( inEvent
->data
.addDefaultDomain
.interfaceIP
.u
.ipv4
.addr
, ifIP
) );
750 case kDNSBrowserEventTypeRemoveDomain
:
751 fprintf( stdout
, "domain \"%s\" removed on interface 0x%08X (%s)\n",
752 inEvent
->data
.removeDomain
.domain
,
753 (int) inEvent
->data
.removeDomain
.interfaceID
,
754 IPv4ToString( inEvent
->data
.removeDomain
.interfaceIP
.u
.ipv4
.addr
, ifIP
) );
757 case kDNSBrowserEventTypeAddService
:
758 fprintf( stdout
, "service \"%s.%s%s\" added on interface 0x%08X (%s)\n",
759 inEvent
->data
.addService
.name
,
760 inEvent
->data
.addService
.type
,
761 inEvent
->data
.addService
.domain
,
762 (int) inEvent
->data
.addService
.interfaceID
,
763 IPv4ToString( inEvent
->data
.addService
.interfaceIP
.u
.ipv4
.addr
, ifIP
) );
766 case kDNSBrowserEventTypeRemoveService
:
767 fprintf( stdout
, "service \"%s.%s%s\" removed on interface 0x%08X (%s)\n",
768 inEvent
->data
.removeService
.name
,
769 inEvent
->data
.removeService
.type
,
770 inEvent
->data
.removeService
.domain
,
771 (int) inEvent
->data
.removeService
.interfaceID
,
772 IPv4ToString( inEvent
->data
.removeService
.interfaceIP
.u
.ipv4
.addr
, ifIP
) );
775 case kDNSBrowserEventTypeResolved
:
781 fprintf( stdout
, "resolved \"%s.%s%s\" to \"%s\" (%s:%u) on interface 0x%08X (%s)%s\n",
782 inEvent
->data
.resolved
->name
,
783 inEvent
->data
.resolved
->type
,
784 inEvent
->data
.resolved
->domain
,
785 inEvent
->data
.resolved
->hostName
,
786 IPv4ToString( inEvent
->data
.resolved
->address
.u
.ipv4
.addr
, ip
),
787 ( inEvent
->data
.resolved
->address
.u
.ipv4
.port
.v8
[ 0 ] << 8 ) |
788 inEvent
->data
.resolved
->address
.u
.ipv4
.port
.v8
[ 1 ],
789 (int) inEvent
->data
.resolved
->interfaceID
,
790 IPv4ToString( inEvent
->data
.resolved
->interfaceIP
.u
.ipv4
.addr
, ifIP
),
791 ( inEvent
->data
.resolved
->textRecordRawSize
> 0 ) ? " with text:" : "" );
793 p
= (const uint8_t *) inEvent
->data
.resolved
->textRecordRaw
;
794 end
= p
+ inEvent
->data
.resolved
->textRecordRawSize
;
797 if( gPrintTXTRecords
)
804 if( ( p
+ size
) > end
)
806 fprintf( stdout
, "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" );
809 fprintf( stdout
, "%5d (%3d bytes): \"%.*s\"\n", i
, size
, size
, p
);
813 fprintf( stdout
, "\n" );
823 //===========================================================================================================================
825 //===========================================================================================================================
827 static void ResolverCallBack( void *inContext
, DNSResolverRef inRef
, DNSStatus inStatusCode
, const DNSResolverEvent
*inEvent
)
832 DNS_UNUSED( inContext
);
834 DNS_UNUSED( inStatusCode
);
836 switch( inEvent
->type
)
838 case kDNSResolverEventTypeResolved
:
844 fprintf( stdout
, "resolved \"%s.%s%s\" to \"%s\" (%s:%u) on interface 0x%08X (%s)%s\n",
845 inEvent
->data
.resolved
.name
,
846 inEvent
->data
.resolved
.type
,
847 inEvent
->data
.resolved
.domain
,
848 inEvent
->data
.resolved
.hostName
,
849 IPv4ToString( inEvent
->data
.resolved
.address
.u
.ipv4
.addr
, ip
),
850 ( inEvent
->data
.resolved
.address
.u
.ipv4
.port
.v8
[ 0 ] << 8 ) |
851 inEvent
->data
.resolved
.address
.u
.ipv4
.port
.v8
[ 1 ],
852 (int) inEvent
->data
.resolved
.interfaceID
,
853 IPv4ToString( inEvent
->data
.resolved
.interfaceIP
.u
.ipv4
.addr
, ifIP
),
854 ( inEvent
->data
.resolved
.textRecordRawSize
> 0 ) ? " with text:" : "" );
856 p
= (const uint8_t *) inEvent
->data
.resolved
.textRecordRaw
;
857 end
= p
+ inEvent
->data
.resolved
.textRecordRawSize
;
860 if( gPrintTXTRecords
)
867 if( ( p
+ size
) > end
)
869 fprintf( stdout
, "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" );
872 fprintf( stdout
, "%5d (%3d bytes): \"%.*s\"\n", i
, size
, size
, p
);
876 fprintf( stdout
, "\n" );
881 case kDNSResolverEventTypeRelease
:
889 //===========================================================================================================================
890 // RegistrationCallBack
891 //===========================================================================================================================
894 RegistrationCallBack(
896 DNSRegistrationRef inRef
,
897 DNSStatus inStatusCode
,
898 const DNSRegistrationEvent
* inEvent
)
900 DNS_UNUSED( inContext
);
902 DNS_UNUSED( inStatusCode
);
904 switch( inEvent
->type
)
906 case kDNSRegistrationEventTypeRelease
:
909 case kDNSRegistrationEventTypeRegistered
:
910 fprintf( stdout
, "name registered and active\n" );
913 case kDNSRegistrationEventTypeNameCollision
:
914 fprintf( stdout
, "name in use, please choose another name\n" );
922 //===========================================================================================================================
923 // HostRegistrationCallBack
924 //===========================================================================================================================
927 HostRegistrationCallBack(
929 DNSHostRegistrationRef inRef
,
930 DNSStatus inStatusCode
,
933 DNS_UNUSED( inContext
);
935 DNS_UNUSED( inData
);
937 if( inStatusCode
== kDNSNoErr
)
939 fprintf( stdout
, "host name registered and active\n" );
941 else if( inStatusCode
== kDNSNameConflictErr
)
943 fprintf( stdout
, "host name in use, please choose another name\n" );
947 fprintf( stdout
, "unknown host registration status (%ld)\n", inStatusCode
);
951 //===========================================================================================================================
952 // EmulatedBrowserCallBack
953 //===========================================================================================================================
956 EmulatedBrowserCallBack(
957 DNSServiceBrowserReplyResultType inResult
,
960 const char * inDomain
,
961 DNSServiceDiscoveryReplyFlags inFlags
,
964 DNS_UNUSED( inFlags
);
965 DNS_UNUSED( inContext
);
967 if( inResult
== DNSServiceBrowserReplyAddInstance
)
969 fprintf( stdout
, "\"%s.%s%s\" service added emulated\n", inName
, inType
, inDomain
);
971 else if( inResult
== DNSServiceBrowserReplyRemoveInstance
)
973 fprintf( stdout
, "\"%s.%s%s\" service removed emulated\n", inName
, inType
, inDomain
);
977 fprintf( stdout
, "### unknown emulated browser callback result (%d)\n", inResult
);
981 //===========================================================================================================================
982 // EmulatedDomainEnumerationCallBack
983 //===========================================================================================================================
986 EmulatedDomainEnumerationCallBack(
987 DNSServiceDomainEnumerationReplyResultType inResult
,
988 const char * inDomain
,
989 DNSServiceDiscoveryReplyFlags inFlags
,
992 DNS_UNUSED( inFlags
);
993 DNS_UNUSED( inContext
);
995 if( inResult
== DNSServiceDomainEnumerationReplyAddDomain
)
997 fprintf( stdout
, "\"%s\" domain added emulated\n", inDomain
);
999 else if( inResult
== DNSServiceDomainEnumerationReplyAddDomainDefault
)
1001 fprintf( stdout
, "\"%s\" default domain added emulated\n", inDomain
);
1003 else if( inResult
== DNSServiceDomainEnumerationReplyRemoveDomain
)
1005 fprintf( stdout
, "\"%s\" domain removed emulated\n", inDomain
);
1009 fprintf( stdout
, "### unknown emulated domain enumeration callback result (%d)\n", inResult
);
1013 //===========================================================================================================================
1014 // EmulatedResolverCallBack
1015 //===========================================================================================================================
1018 EmulatedResolverCallBack(
1019 struct sockaddr
* inInterfaceAddr
,
1020 struct sockaddr
* inAddr
,
1021 const char * inTextRecord
,
1022 DNSServiceDiscoveryReplyFlags inFlags
,
1025 struct sockaddr_in
* ifSin4
;
1026 struct sockaddr_in
* sin4
;
1030 DNS_UNUSED( inFlags
);
1031 DNS_UNUSED( inContext
);
1033 ifSin4
= (struct sockaddr_in
*) inInterfaceAddr
;
1034 sin4
= (struct sockaddr_in
*) inAddr
;
1036 fprintf( stdout
, "service resolved to %s:%d on interface %s with text \"%s\"\n",
1037 IPv4ToString( *( (DNSOpaque32
*) &sin4
->sin_addr
.s_addr
), ip
),
1038 ntohs( sin4
->sin_port
),
1039 IPv4ToString( *( (DNSOpaque32
*) &ifSin4
->sin_addr
.s_addr
), ifIP
),
1040 inTextRecord
? inTextRecord
: "" );
1043 //===========================================================================================================================
1044 // EmulatedResolverCallBack
1045 //===========================================================================================================================
1047 static void EmulatedRegistrationCallBack( DNSServiceRegistrationReplyErrorType inResult
, void *inContext
)
1049 DNS_UNUSED( inContext
);
1051 if( inResult
== kDNSServiceDiscoveryNoError
)
1053 fprintf( stdout
, "service name registered successfully\n" );
1057 fprintf( stdout
, "service registration failed( %d)\n", inResult
);
1061 //===========================================================================================================================
1063 //===========================================================================================================================
1065 static char * IPv4ToString( DNSOpaque32 inIP
, char *outString
)
1067 sprintf( outString
, "%u.%u.%u.%u", inIP
.v8
[ 0 ], inIP
.v8
[ 1 ], inIP
.v8
[ 2 ], inIP
.v8
[ 3 ] );
1068 return( outString
);