2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
25 $Log: DNSServiceDiscovery.c,v $
26 Revision 1.2 2003/08/20 07:06:34 bradley
27 Update to APSL 2.0. Updated change history to match other mDNSResponder files.
29 Revision 1.1 2003/08/20 06:04:45 bradley
30 Platform-neutral DNSServices-based emulation layer for the Mac OS X DNSServiceDiscovery API.
38 #if( macintosh || __MACH__ )
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
44 #elif( defined( _MSC_VER ) || defined( __MWERKS__ ) )
46 #pragma warning( disable:4054 ) // Disable "type cast : from function pointer to data pointer".
47 #pragma warning( disable:4055 ) // Disable "type cast : from data pointer to function pointer".
48 #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros.
49 #pragma warning( disable:4152 ) // Disable "nonstandard extension, function/data pointer conversion in expression".
51 #define WIN32_LEAN_AND_MEAN // Needed to avoid redefinitions by Windows interfaces.
57 #include "mDNSClientAPI.h"
58 #include "mDNSPlatformFunctions.h"
59 #include "DNSServices.h"
61 #include "DNSServiceDiscovery.h"
68 #pragma mark == Constants & Types ==
71 //===========================================================================================================================
73 //===========================================================================================================================
75 #define DEBUG_NAME "[DNSServiceDiscovery] "
79 kDNSServiceDiscoveryObjectTypeRegistration
= 1,
80 kDNSServiceDiscoveryObjectTypeDomainEnumeration
= 2,
81 kDNSServiceDiscoveryObjectTypeBrowser
= 3,
82 kDNSServiceDiscoveryObjectTypeResolver
= 4
84 } DNSServiceDiscoveryObjectType
;
86 typedef struct _dns_service_discovery_t _dns_service_discovery_t
;
87 struct _dns_service_discovery_t
89 DNSServiceDiscoveryObjectType type
;
96 #pragma mark == Macros ==
99 //===========================================================================================================================
101 //===========================================================================================================================
103 // Emulate Mac OS debugging macros for non-Mac platforms.
105 #if( !TARGET_OS_MAC )
106 #define check(assertion)
107 #define check_string( assertion, cstring )
108 #define check_noerr(err)
109 #define check_noerr_string( error, cstring )
110 #define debug_string( cstring )
111 #define require( assertion, label ) do { if( !(assertion) ) goto label; } while(0)
112 #define require_string( assertion, label, string ) require(assertion, label)
113 #define require_quiet( assertion, label ) require( assertion, label )
114 #define require_noerr( error, label ) do { if( (error) != 0 ) goto label; } while(0)
115 #define require_noerr_quiet( assertion, label ) require_noerr( assertion, label )
116 #define require_noerr_action( error, label, action ) do { if( (error) != 0 ) { {action;}; goto label; } } while(0)
117 #define require_noerr_action_quiet( assertion, label, action ) require_noerr_action( assertion, label, action )
118 #define require_action( assertion, label, action ) do { if( !(assertion) ) { {action;}; goto label; } } while(0)
119 #define require_action_quiet( assertion, label, action ) require_action( assertion, label, action )
120 #define require_action_string( assertion, label, action, cstring ) do { if( !(assertion) ) { {action;}; goto label; } } while(0)
124 #pragma mark == Prototypes ==
127 //===========================================================================================================================
129 //===========================================================================================================================
132 DNSServiceRegistrationPrivateCallBack(
134 DNSRegistrationRef inRef
,
135 DNSStatus inStatusCode
,
136 const DNSRegistrationEvent
* inEvent
);
139 DNSServiceDomainEnumerationPrivateCallBack(
142 DNSStatus inStatusCode
,
143 const DNSBrowserEvent
* inEvent
);
146 DNSServiceBrowserPrivateCallBack(
149 DNSStatus inStatusCode
,
150 const DNSBrowserEvent
* inEvent
);
153 DNSServiceResolverPrivateCallBack(
155 DNSResolverRef inRef
,
156 DNSStatus inStatusCode
,
157 const DNSResolverEvent
* inEvent
);
163 //===========================================================================================================================
164 // DNSServiceRegistrationCreate
165 //===========================================================================================================================
167 dns_service_discovery_ref
168 DNSServiceRegistrationCreate(
171 const char * inDomain
,
173 const char * inTextRecord
,
174 DNSServiceRegistrationReply inCallBack
,
178 dns_service_discovery_ref result
;
179 dns_service_discovery_ref obj
;
182 DNSRegistrationRef registration
;
188 // Allocate and initialize the object.
190 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
191 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
193 obj
->type
= kDNSServiceDiscoveryObjectTypeRegistration
;
195 obj
->callback
= inCallBack
;
196 obj
->context
= inContext
;
198 // Create the underlying registration. Build a \001-escaped text record if needed.
202 err
= DNSDynamicTextRecordBuildEscaped( inTextRecord
, &txt
, &txtSize
);
203 require_noerr( err
, exit
);
206 err
= DNSRegistrationCreate( kDNSRegistrationFlagPreFormattedTextRecord
, inName
, inType
, inDomain
, inPort
, txt
,
207 (DNSCount
) txtSize
, NULL
, NULL
, DNSServiceRegistrationPrivateCallBack
, obj
, ®istration
);
208 require_noerr( err
, exit
);
209 obj
->ref
= registration
;
219 DNSDynamicTextRecordRelease( txt
);
223 DNSServiceDiscoveryDeallocate( obj
);
228 //===========================================================================================================================
229 // DNSServiceRegistrationPrivateCallBack
230 //===========================================================================================================================
233 DNSServiceRegistrationPrivateCallBack(
235 DNSRegistrationRef inRef
,
236 DNSStatus inStatusCode
,
237 const DNSRegistrationEvent
* inEvent
)
239 dns_service_discovery_ref obj
;
240 DNSServiceRegistrationReply callback
;
243 DNS_UNUSED( inStatusCode
);
246 obj
= (dns_service_discovery_ref
) inContext
;
247 check( obj
->callback
);
248 callback
= (DNSServiceRegistrationReply
) obj
->callback
;
250 switch( inEvent
->type
)
252 case kDNSRegistrationEventTypeRegistered
:
253 debugf( DEBUG_NAME
"name registered and active\n" );
257 callback( kDNSServiceDiscoveryNoError
, obj
->context
);
261 case kDNSRegistrationEventTypeNameCollision
:
262 debugf( DEBUG_NAME
"name in use, please choose another name\n" );
266 callback( kDNSServiceDiscoveryNameConflict
, obj
->context
);
275 //===========================================================================================================================
276 // DNSServiceRegistrationAddRecord
277 //===========================================================================================================================
280 DNSServiceRegistrationAddRecord(
281 dns_service_discovery_ref inRef
,
284 const char * inRData
,
288 DNS_UNUSED( inRRType
);
289 DNS_UNUSED( inRDLength
);
290 DNS_UNUSED( inRData
);
293 debugf( DEBUG_NAME
"DNSServiceRegistrationAddRecord is currently not supported\n" );
297 //===========================================================================================================================
298 // DNSServiceRegistrationUpdateRecord
299 //===========================================================================================================================
301 DNSServiceRegistrationReplyErrorType
302 DNSServiceRegistrationUpdateRecord(
303 dns_service_discovery_ref inRef
,
304 DNSRecordReference inRecordRef
,
306 const char * inRData
,
310 DNS_UNUSED( inRecordRef
);
311 DNS_UNUSED( inRDLength
);
312 DNS_UNUSED( inRData
);
315 debugf( DEBUG_NAME
"DNSServiceRegistrationUpdateRecord is currently not supported\n" );
316 return( kDNSServiceDiscoveryUnsupportedErr
);
319 //===========================================================================================================================
320 // DNSServiceRegistrationRemoveRecord
321 //===========================================================================================================================
323 DNSServiceRegistrationReplyErrorType
324 DNSServiceRegistrationRemoveRecord(
325 dns_service_discovery_ref inRef
,
326 DNSRecordReference inRecordRef
)
329 DNS_UNUSED( inRecordRef
);
331 debugf( DEBUG_NAME
"DNSServiceRegistrationRemoveRecord is currently not supported\n" );
332 return( kDNSServiceDiscoveryUnsupportedErr
);
335 //===========================================================================================================================
336 // DNSServiceDomainEnumerationCreate
337 //===========================================================================================================================
339 dns_service_discovery_ref
340 DNSServiceDomainEnumerationCreate(
341 int inRegistrationDomains
,
342 DNSServiceDomainEnumerationReply inCallBack
,
346 dns_service_discovery_ref result
;
347 dns_service_discovery_ref obj
;
348 DNSBrowserRef browser
;
349 DNSBrowserFlags flags
;
354 // Allocate and initialize the object.
356 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
357 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
359 obj
->type
= kDNSServiceDiscoveryObjectTypeDomainEnumeration
;
361 obj
->callback
= inCallBack
;
362 obj
->context
= inContext
;
364 // Create the underlying browser and start searching for domains.
366 err
= DNSBrowserCreate( 0, DNSServiceDomainEnumerationPrivateCallBack
, obj
, &browser
);
367 require_noerr( err
, exit
);
370 if( inRegistrationDomains
)
372 flags
= kDNSBrowserFlagRegistrationDomainsOnly
;
378 err
= DNSBrowserStartDomainSearch( browser
, flags
);
379 require_noerr( err
, exit
);
390 DNSBrowserRelease( browser
, 0 );
394 DNSServiceDiscoveryDeallocate( obj
);
399 //===========================================================================================================================
400 // DNSServiceDomainEnumerationPrivateCallBack
401 //===========================================================================================================================
404 DNSServiceDomainEnumerationPrivateCallBack(
407 DNSStatus inStatusCode
,
408 const DNSBrowserEvent
* inEvent
)
410 dns_service_discovery_ref obj
;
411 DNSServiceDomainEnumerationReply callback
;
414 DNS_UNUSED( inStatusCode
);
417 obj
= (dns_service_discovery_ref
) inContext
;
418 check( obj
->callback
);
419 callback
= (DNSServiceDomainEnumerationReply
) obj
->callback
;
421 switch( inEvent
->type
)
423 case kDNSBrowserEventTypeAddDomain
:
424 debugf( DEBUG_NAME
"add domain \"%s\"\n", inEvent
->data
.addDomain
.domain
);
428 callback( DNSServiceDomainEnumerationReplyAddDomain
, inEvent
->data
.addDomain
.domain
,
429 DNSServiceDiscoverReplyFlagsFinished
, obj
->context
);
433 case kDNSBrowserEventTypeAddDefaultDomain
:
434 debugf( DEBUG_NAME
"add default domain \"%s\"\n", inEvent
->data
.addDefaultDomain
.domain
);
438 callback( DNSServiceDomainEnumerationReplyAddDomainDefault
, inEvent
->data
.addDefaultDomain
.domain
,
439 DNSServiceDiscoverReplyFlagsFinished
, obj
->context
);
443 case kDNSBrowserEventTypeRemoveDomain
:
444 debugf( DEBUG_NAME
"add default domain \"%s\"\n", inEvent
->data
.removeDomain
.domain
);
448 callback( DNSServiceDomainEnumerationReplyRemoveDomain
, inEvent
->data
.removeDomain
.domain
,
449 DNSServiceDiscoverReplyFlagsFinished
, obj
->context
);
458 //===========================================================================================================================
459 // DNSServiceBrowserCreate
460 //===========================================================================================================================
462 dns_service_discovery_ref
463 DNSServiceBrowserCreate(
465 const char * inDomain
,
466 DNSServiceBrowserReply inCallBack
,
470 dns_service_discovery_ref result
;
471 dns_service_discovery_ref obj
;
472 DNSBrowserRef browser
;
477 // Allocate and initialize the object.
479 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
480 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
482 obj
->type
= kDNSServiceDiscoveryObjectTypeBrowser
;
484 obj
->callback
= inCallBack
;
485 obj
->context
= inContext
;
487 // Create the underlying browser and start searching for domains.
489 err
= DNSBrowserCreate( 0, DNSServiceBrowserPrivateCallBack
, obj
, &browser
);
490 require_noerr( err
, exit
);
493 err
= DNSBrowserStartServiceSearch( browser
, 0, inType
, inDomain
);
494 require_noerr( err
, exit
);
505 DNSBrowserRelease( browser
, 0 );
509 DNSServiceDiscoveryDeallocate( obj
);
514 //===========================================================================================================================
515 // DNSServiceBrowserPrivateCallBack
516 //===========================================================================================================================
519 DNSServiceBrowserPrivateCallBack(
522 DNSStatus inStatusCode
,
523 const DNSBrowserEvent
* inEvent
)
525 dns_service_discovery_ref obj
;
526 DNSServiceBrowserReply callback
;
529 DNS_UNUSED( inStatusCode
);
532 obj
= (dns_service_discovery_ref
) inContext
;
533 check( obj
->callback
);
534 callback
= (DNSServiceBrowserReply
) obj
->callback
;
536 switch( inEvent
->type
)
538 case kDNSBrowserEventTypeAddService
:
539 debugf( DEBUG_NAME
"add service \"%s.%s%s\"\n",
540 inEvent
->data
.addService
.name
,
541 inEvent
->data
.addService
.type
,
542 inEvent
->data
.addService
.domain
);
546 callback( DNSServiceBrowserReplyAddInstance
,
547 inEvent
->data
.addService
.name
,
548 inEvent
->data
.addService
.type
,
549 inEvent
->data
.addService
.domain
,
550 DNSServiceDiscoverReplyFlagsFinished
,
555 case kDNSBrowserEventTypeRemoveService
:
556 debugf( DEBUG_NAME
"remove service \"%s.%s%s\"\n",
557 inEvent
->data
.removeService
.name
,
558 inEvent
->data
.removeService
.type
,
559 inEvent
->data
.removeService
.domain
);
563 callback( DNSServiceBrowserReplyRemoveInstance
,
564 inEvent
->data
.removeService
.name
,
565 inEvent
->data
.removeService
.type
,
566 inEvent
->data
.removeService
.domain
,
567 DNSServiceDiscoverReplyFlagsFinished
,
577 //===========================================================================================================================
578 // DNSServiceResolverResolve
579 //===========================================================================================================================
581 dns_service_discovery_ref
582 DNSServiceResolverResolve(
585 const char * inDomain
,
586 DNSServiceResolverReply inCallBack
,
590 dns_service_discovery_ref result
;
591 dns_service_discovery_ref obj
;
592 DNSResolverRef resolver
;
596 // Allocate and initialize the object.
598 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
599 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
601 obj
->type
= kDNSServiceDiscoveryObjectTypeResolver
;
603 obj
->callback
= inCallBack
;
604 obj
->context
= inContext
;
606 // Create the underlying resolver and start searching for domains.
608 err
= DNSResolverCreate( 0, inName
, inType
, inDomain
, DNSServiceResolverPrivateCallBack
, obj
, NULL
, &resolver
);
609 require_noerr( err
, exit
);
620 DNSServiceDiscoveryDeallocate( obj
);
625 //===========================================================================================================================
626 // DNSServiceResolverPrivateCallBack
627 //===========================================================================================================================
630 DNSServiceResolverPrivateCallBack(
632 DNSResolverRef inRef
,
633 DNSStatus inStatusCode
,
634 const DNSResolverEvent
* inEvent
)
636 dns_service_discovery_ref obj
;
637 DNSServiceResolverReply callback
;
638 struct sockaddr_in interfaceAddr
;
639 struct sockaddr_in addr
;
642 DNS_UNUSED( inStatusCode
);
645 obj
= (dns_service_discovery_ref
) inContext
;
646 check( obj
->callback
);
647 callback
= (DNSServiceResolverReply
) obj
->callback
;
649 switch( inEvent
->type
)
651 case kDNSResolverEventTypeResolved
:
652 debugf( DEBUG_NAME
"resolved \"%s.%s%s\"\n",
653 inEvent
->data
.resolved
.name
,
654 inEvent
->data
.resolved
.type
,
655 inEvent
->data
.resolved
.domain
);
657 memset( &interfaceAddr
, 0, sizeof( interfaceAddr
) );
658 interfaceAddr
.sin_family
= AF_INET
;
659 interfaceAddr
.sin_port
= 0;
660 interfaceAddr
.sin_addr
.s_addr
= inEvent
->data
.resolved
.interfaceIP
.u
.ipv4
.addr
.v32
;
662 memset( &addr
, 0, sizeof( addr
) );
663 addr
.sin_family
= AF_INET
;
664 addr
.sin_port
= inEvent
->data
.resolved
.address
.u
.ipv4
.port
.v16
;
665 addr
.sin_addr
.s_addr
= inEvent
->data
.resolved
.address
.u
.ipv4
.addr
.v32
;
669 callback( (struct sockaddr
*) &interfaceAddr
, (struct sockaddr
*) &addr
, inEvent
->data
.resolved
.textRecord
,
670 DNSServiceDiscoverReplyFlagsFinished
, obj
->context
);
679 //===========================================================================================================================
680 // DNSServiceDiscoveryMachPort
681 //===========================================================================================================================
683 mach_port_t
DNSServiceDiscoveryMachPort( dns_service_discovery_ref inRef
)
687 debugf( DEBUG_NAME
"DNSServiceDiscoveryMachPort is not supported\n" );
691 //===========================================================================================================================
692 // DNSServiceDiscoveryDeallocate
693 //===========================================================================================================================
695 void DNSServiceDiscoveryDeallocate( dns_service_discovery_ref inRef
)
697 _dns_service_discovery_t
* obj
;
703 obj
= (_dns_service_discovery_t
*) inRef
;
706 case kDNSServiceDiscoveryObjectTypeRegistration
:
709 err
= DNSRegistrationRelease( (DNSRegistrationRef
) inRef
->ref
, 0 );
715 case kDNSServiceDiscoveryObjectTypeDomainEnumeration
:
718 err
= DNSBrowserRelease( (DNSBrowserRef
) inRef
->ref
, 0 );
724 case kDNSServiceDiscoveryObjectTypeBrowser
:
727 err
= DNSBrowserRelease( (DNSBrowserRef
) inRef
->ref
, 0 );
733 case kDNSServiceDiscoveryObjectTypeResolver
:
736 err
= DNSResolverRelease( (DNSResolverRef
) inRef
->ref
, 0 );
743 debugf( DEBUG_NAME
"unknown object type (%d)\n", obj
->type
);
748 //===========================================================================================================================
749 // DNSServiceDiscovery_handleReply
750 //===========================================================================================================================
752 void DNSServiceDiscovery_handleReply( void *inReplyMessage
)
754 DNS_UNUSED( inReplyMessage
);
756 debugf( DEBUG_NAME
"DNSServiceDiscovery_handleReply is not supported\n" );