2 * Copyright (c) 2002-2003 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):
27 $Log: DNSServiceDiscovery.c,v $
28 Revision 1.2 2003/08/20 07:06:34 bradley
29 Update to APSL 2.0. Updated change history to match other mDNSResponder files.
31 Revision 1.1 2003/08/20 06:04:45 bradley
32 Platform-neutral DNSServices-based emulation layer for the Mac OS X DNSServiceDiscovery API.
40 #if( macintosh || __MACH__ )
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <netinet/in.h>
46 #elif( defined( _MSC_VER ) || defined( __MWERKS__ ) )
48 #pragma warning( disable:4054 ) // Disable "type cast : from function pointer to data pointer".
49 #pragma warning( disable:4055 ) // Disable "type cast : from data pointer to function pointer".
50 #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros.
51 #pragma warning( disable:4152 ) // Disable "nonstandard extension, function/data pointer conversion in expression".
53 #define WIN32_LEAN_AND_MEAN // Needed to avoid redefinitions by Windows interfaces.
59 #include "mDNSClientAPI.h"
60 #include "mDNSPlatformFunctions.h"
61 #include "DNSServices.h"
63 #include "DNSServiceDiscovery.h"
70 #pragma mark == Constants & Types ==
73 //===========================================================================================================================
75 //===========================================================================================================================
77 #define DEBUG_NAME "[DNSServiceDiscovery] "
81 kDNSServiceDiscoveryObjectTypeRegistration
= 1,
82 kDNSServiceDiscoveryObjectTypeDomainEnumeration
= 2,
83 kDNSServiceDiscoveryObjectTypeBrowser
= 3,
84 kDNSServiceDiscoveryObjectTypeResolver
= 4
86 } DNSServiceDiscoveryObjectType
;
88 typedef struct _dns_service_discovery_t _dns_service_discovery_t
;
89 struct _dns_service_discovery_t
91 DNSServiceDiscoveryObjectType type
;
98 #pragma mark == Macros ==
101 //===========================================================================================================================
103 //===========================================================================================================================
105 // Emulate Mac OS debugging macros for non-Mac platforms.
107 #if( !TARGET_OS_MAC )
108 #define check(assertion)
109 #define check_string( assertion, cstring )
110 #define check_noerr(err)
111 #define check_noerr_string( error, cstring )
112 #define debug_string( cstring )
113 #define require( assertion, label ) do { if( !(assertion) ) goto label; } while(0)
114 #define require_string( assertion, label, string ) require(assertion, label)
115 #define require_quiet( assertion, label ) require( assertion, label )
116 #define require_noerr( error, label ) do { if( (error) != 0 ) goto label; } while(0)
117 #define require_noerr_quiet( assertion, label ) require_noerr( assertion, label )
118 #define require_noerr_action( error, label, action ) do { if( (error) != 0 ) { {action;}; goto label; } } while(0)
119 #define require_noerr_action_quiet( assertion, label, action ) require_noerr_action( assertion, label, action )
120 #define require_action( assertion, label, action ) do { if( !(assertion) ) { {action;}; goto label; } } while(0)
121 #define require_action_quiet( assertion, label, action ) require_action( assertion, label, action )
122 #define require_action_string( assertion, label, action, cstring ) do { if( !(assertion) ) { {action;}; goto label; } } while(0)
126 #pragma mark == Prototypes ==
129 //===========================================================================================================================
131 //===========================================================================================================================
134 DNSServiceRegistrationPrivateCallBack(
136 DNSRegistrationRef inRef
,
137 DNSStatus inStatusCode
,
138 const DNSRegistrationEvent
* inEvent
);
141 DNSServiceDomainEnumerationPrivateCallBack(
144 DNSStatus inStatusCode
,
145 const DNSBrowserEvent
* inEvent
);
148 DNSServiceBrowserPrivateCallBack(
151 DNSStatus inStatusCode
,
152 const DNSBrowserEvent
* inEvent
);
155 DNSServiceResolverPrivateCallBack(
157 DNSResolverRef inRef
,
158 DNSStatus inStatusCode
,
159 const DNSResolverEvent
* inEvent
);
165 //===========================================================================================================================
166 // DNSServiceRegistrationCreate
167 //===========================================================================================================================
169 dns_service_discovery_ref
170 DNSServiceRegistrationCreate(
173 const char * inDomain
,
175 const char * inTextRecord
,
176 DNSServiceRegistrationReply inCallBack
,
180 dns_service_discovery_ref result
;
181 dns_service_discovery_ref obj
;
184 DNSRegistrationRef registration
;
190 // Allocate and initialize the object.
192 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
193 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
195 obj
->type
= kDNSServiceDiscoveryObjectTypeRegistration
;
197 obj
->callback
= inCallBack
;
198 obj
->context
= inContext
;
200 // Create the underlying registration. Build a \001-escaped text record if needed.
204 err
= DNSDynamicTextRecordBuildEscaped( inTextRecord
, &txt
, &txtSize
);
205 require_noerr( err
, exit
);
208 err
= DNSRegistrationCreate( kDNSRegistrationFlagPreFormattedTextRecord
, inName
, inType
, inDomain
, inPort
, txt
,
209 (DNSCount
) txtSize
, NULL
, NULL
, DNSServiceRegistrationPrivateCallBack
, obj
, ®istration
);
210 require_noerr( err
, exit
);
211 obj
->ref
= registration
;
221 DNSDynamicTextRecordRelease( txt
);
225 DNSServiceDiscoveryDeallocate( obj
);
230 //===========================================================================================================================
231 // DNSServiceRegistrationPrivateCallBack
232 //===========================================================================================================================
235 DNSServiceRegistrationPrivateCallBack(
237 DNSRegistrationRef inRef
,
238 DNSStatus inStatusCode
,
239 const DNSRegistrationEvent
* inEvent
)
241 dns_service_discovery_ref obj
;
242 DNSServiceRegistrationReply callback
;
245 DNS_UNUSED( inStatusCode
);
248 obj
= (dns_service_discovery_ref
) inContext
;
249 check( obj
->callback
);
250 callback
= (DNSServiceRegistrationReply
) obj
->callback
;
252 switch( inEvent
->type
)
254 case kDNSRegistrationEventTypeRegistered
:
255 debugf( DEBUG_NAME
"name registered and active\n" );
259 callback( kDNSServiceDiscoveryNoError
, obj
->context
);
263 case kDNSRegistrationEventTypeNameCollision
:
264 debugf( DEBUG_NAME
"name in use, please choose another name\n" );
268 callback( kDNSServiceDiscoveryNameConflict
, obj
->context
);
277 //===========================================================================================================================
278 // DNSServiceRegistrationAddRecord
279 //===========================================================================================================================
282 DNSServiceRegistrationAddRecord(
283 dns_service_discovery_ref inRef
,
286 const char * inRData
,
290 DNS_UNUSED( inRRType
);
291 DNS_UNUSED( inRDLength
);
292 DNS_UNUSED( inRData
);
295 debugf( DEBUG_NAME
"DNSServiceRegistrationAddRecord is currently not supported\n" );
299 //===========================================================================================================================
300 // DNSServiceRegistrationUpdateRecord
301 //===========================================================================================================================
303 DNSServiceRegistrationReplyErrorType
304 DNSServiceRegistrationUpdateRecord(
305 dns_service_discovery_ref inRef
,
306 DNSRecordReference inRecordRef
,
308 const char * inRData
,
312 DNS_UNUSED( inRecordRef
);
313 DNS_UNUSED( inRDLength
);
314 DNS_UNUSED( inRData
);
317 debugf( DEBUG_NAME
"DNSServiceRegistrationUpdateRecord is currently not supported\n" );
318 return( kDNSServiceDiscoveryUnsupportedErr
);
321 //===========================================================================================================================
322 // DNSServiceRegistrationRemoveRecord
323 //===========================================================================================================================
325 DNSServiceRegistrationReplyErrorType
326 DNSServiceRegistrationRemoveRecord(
327 dns_service_discovery_ref inRef
,
328 DNSRecordReference inRecordRef
)
331 DNS_UNUSED( inRecordRef
);
333 debugf( DEBUG_NAME
"DNSServiceRegistrationRemoveRecord is currently not supported\n" );
334 return( kDNSServiceDiscoveryUnsupportedErr
);
337 //===========================================================================================================================
338 // DNSServiceDomainEnumerationCreate
339 //===========================================================================================================================
341 dns_service_discovery_ref
342 DNSServiceDomainEnumerationCreate(
343 int inRegistrationDomains
,
344 DNSServiceDomainEnumerationReply inCallBack
,
348 dns_service_discovery_ref result
;
349 dns_service_discovery_ref obj
;
350 DNSBrowserRef browser
;
351 DNSBrowserFlags flags
;
356 // Allocate and initialize the object.
358 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
359 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
361 obj
->type
= kDNSServiceDiscoveryObjectTypeDomainEnumeration
;
363 obj
->callback
= inCallBack
;
364 obj
->context
= inContext
;
366 // Create the underlying browser and start searching for domains.
368 err
= DNSBrowserCreate( 0, DNSServiceDomainEnumerationPrivateCallBack
, obj
, &browser
);
369 require_noerr( err
, exit
);
372 if( inRegistrationDomains
)
374 flags
= kDNSBrowserFlagRegistrationDomainsOnly
;
380 err
= DNSBrowserStartDomainSearch( browser
, flags
);
381 require_noerr( err
, exit
);
392 DNSBrowserRelease( browser
, 0 );
396 DNSServiceDiscoveryDeallocate( obj
);
401 //===========================================================================================================================
402 // DNSServiceDomainEnumerationPrivateCallBack
403 //===========================================================================================================================
406 DNSServiceDomainEnumerationPrivateCallBack(
409 DNSStatus inStatusCode
,
410 const DNSBrowserEvent
* inEvent
)
412 dns_service_discovery_ref obj
;
413 DNSServiceDomainEnumerationReply callback
;
416 DNS_UNUSED( inStatusCode
);
419 obj
= (dns_service_discovery_ref
) inContext
;
420 check( obj
->callback
);
421 callback
= (DNSServiceDomainEnumerationReply
) obj
->callback
;
423 switch( inEvent
->type
)
425 case kDNSBrowserEventTypeAddDomain
:
426 debugf( DEBUG_NAME
"add domain \"%s\"\n", inEvent
->data
.addDomain
.domain
);
430 callback( DNSServiceDomainEnumerationReplyAddDomain
, inEvent
->data
.addDomain
.domain
,
431 DNSServiceDiscoverReplyFlagsFinished
, obj
->context
);
435 case kDNSBrowserEventTypeAddDefaultDomain
:
436 debugf( DEBUG_NAME
"add default domain \"%s\"\n", inEvent
->data
.addDefaultDomain
.domain
);
440 callback( DNSServiceDomainEnumerationReplyAddDomainDefault
, inEvent
->data
.addDefaultDomain
.domain
,
441 DNSServiceDiscoverReplyFlagsFinished
, obj
->context
);
445 case kDNSBrowserEventTypeRemoveDomain
:
446 debugf( DEBUG_NAME
"add default domain \"%s\"\n", inEvent
->data
.removeDomain
.domain
);
450 callback( DNSServiceDomainEnumerationReplyRemoveDomain
, inEvent
->data
.removeDomain
.domain
,
451 DNSServiceDiscoverReplyFlagsFinished
, obj
->context
);
460 //===========================================================================================================================
461 // DNSServiceBrowserCreate
462 //===========================================================================================================================
464 dns_service_discovery_ref
465 DNSServiceBrowserCreate(
467 const char * inDomain
,
468 DNSServiceBrowserReply inCallBack
,
472 dns_service_discovery_ref result
;
473 dns_service_discovery_ref obj
;
474 DNSBrowserRef browser
;
479 // Allocate and initialize the object.
481 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
482 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
484 obj
->type
= kDNSServiceDiscoveryObjectTypeBrowser
;
486 obj
->callback
= inCallBack
;
487 obj
->context
= inContext
;
489 // Create the underlying browser and start searching for domains.
491 err
= DNSBrowserCreate( 0, DNSServiceBrowserPrivateCallBack
, obj
, &browser
);
492 require_noerr( err
, exit
);
495 err
= DNSBrowserStartServiceSearch( browser
, 0, inType
, inDomain
);
496 require_noerr( err
, exit
);
507 DNSBrowserRelease( browser
, 0 );
511 DNSServiceDiscoveryDeallocate( obj
);
516 //===========================================================================================================================
517 // DNSServiceBrowserPrivateCallBack
518 //===========================================================================================================================
521 DNSServiceBrowserPrivateCallBack(
524 DNSStatus inStatusCode
,
525 const DNSBrowserEvent
* inEvent
)
527 dns_service_discovery_ref obj
;
528 DNSServiceBrowserReply callback
;
531 DNS_UNUSED( inStatusCode
);
534 obj
= (dns_service_discovery_ref
) inContext
;
535 check( obj
->callback
);
536 callback
= (DNSServiceBrowserReply
) obj
->callback
;
538 switch( inEvent
->type
)
540 case kDNSBrowserEventTypeAddService
:
541 debugf( DEBUG_NAME
"add service \"%s.%s%s\"\n",
542 inEvent
->data
.addService
.name
,
543 inEvent
->data
.addService
.type
,
544 inEvent
->data
.addService
.domain
);
548 callback( DNSServiceBrowserReplyAddInstance
,
549 inEvent
->data
.addService
.name
,
550 inEvent
->data
.addService
.type
,
551 inEvent
->data
.addService
.domain
,
552 DNSServiceDiscoverReplyFlagsFinished
,
557 case kDNSBrowserEventTypeRemoveService
:
558 debugf( DEBUG_NAME
"remove service \"%s.%s%s\"\n",
559 inEvent
->data
.removeService
.name
,
560 inEvent
->data
.removeService
.type
,
561 inEvent
->data
.removeService
.domain
);
565 callback( DNSServiceBrowserReplyRemoveInstance
,
566 inEvent
->data
.removeService
.name
,
567 inEvent
->data
.removeService
.type
,
568 inEvent
->data
.removeService
.domain
,
569 DNSServiceDiscoverReplyFlagsFinished
,
579 //===========================================================================================================================
580 // DNSServiceResolverResolve
581 //===========================================================================================================================
583 dns_service_discovery_ref
584 DNSServiceResolverResolve(
587 const char * inDomain
,
588 DNSServiceResolverReply inCallBack
,
592 dns_service_discovery_ref result
;
593 dns_service_discovery_ref obj
;
594 DNSResolverRef resolver
;
598 // Allocate and initialize the object.
600 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
601 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
603 obj
->type
= kDNSServiceDiscoveryObjectTypeResolver
;
605 obj
->callback
= inCallBack
;
606 obj
->context
= inContext
;
608 // Create the underlying resolver and start searching for domains.
610 err
= DNSResolverCreate( 0, inName
, inType
, inDomain
, DNSServiceResolverPrivateCallBack
, obj
, NULL
, &resolver
);
611 require_noerr( err
, exit
);
622 DNSServiceDiscoveryDeallocate( obj
);
627 //===========================================================================================================================
628 // DNSServiceResolverPrivateCallBack
629 //===========================================================================================================================
632 DNSServiceResolverPrivateCallBack(
634 DNSResolverRef inRef
,
635 DNSStatus inStatusCode
,
636 const DNSResolverEvent
* inEvent
)
638 dns_service_discovery_ref obj
;
639 DNSServiceResolverReply callback
;
640 struct sockaddr_in interfaceAddr
;
641 struct sockaddr_in addr
;
644 DNS_UNUSED( inStatusCode
);
647 obj
= (dns_service_discovery_ref
) inContext
;
648 check( obj
->callback
);
649 callback
= (DNSServiceResolverReply
) obj
->callback
;
651 switch( inEvent
->type
)
653 case kDNSResolverEventTypeResolved
:
654 debugf( DEBUG_NAME
"resolved \"%s.%s%s\"\n",
655 inEvent
->data
.resolved
.name
,
656 inEvent
->data
.resolved
.type
,
657 inEvent
->data
.resolved
.domain
);
659 memset( &interfaceAddr
, 0, sizeof( interfaceAddr
) );
660 interfaceAddr
.sin_family
= AF_INET
;
661 interfaceAddr
.sin_port
= 0;
662 interfaceAddr
.sin_addr
.s_addr
= inEvent
->data
.resolved
.interfaceIP
.u
.ipv4
.addr
.v32
;
664 memset( &addr
, 0, sizeof( addr
) );
665 addr
.sin_family
= AF_INET
;
666 addr
.sin_port
= inEvent
->data
.resolved
.address
.u
.ipv4
.port
.v16
;
667 addr
.sin_addr
.s_addr
= inEvent
->data
.resolved
.address
.u
.ipv4
.addr
.v32
;
671 callback( (struct sockaddr
*) &interfaceAddr
, (struct sockaddr
*) &addr
, inEvent
->data
.resolved
.textRecord
,
672 DNSServiceDiscoverReplyFlagsFinished
, obj
->context
);
681 //===========================================================================================================================
682 // DNSServiceDiscoveryMachPort
683 //===========================================================================================================================
685 mach_port_t
DNSServiceDiscoveryMachPort( dns_service_discovery_ref inRef
)
689 debugf( DEBUG_NAME
"DNSServiceDiscoveryMachPort is not supported\n" );
693 //===========================================================================================================================
694 // DNSServiceDiscoveryDeallocate
695 //===========================================================================================================================
697 void DNSServiceDiscoveryDeallocate( dns_service_discovery_ref inRef
)
699 _dns_service_discovery_t
* obj
;
705 obj
= (_dns_service_discovery_t
*) inRef
;
708 case kDNSServiceDiscoveryObjectTypeRegistration
:
711 err
= DNSRegistrationRelease( (DNSRegistrationRef
) inRef
->ref
, 0 );
717 case kDNSServiceDiscoveryObjectTypeDomainEnumeration
:
720 err
= DNSBrowserRelease( (DNSBrowserRef
) inRef
->ref
, 0 );
726 case kDNSServiceDiscoveryObjectTypeBrowser
:
729 err
= DNSBrowserRelease( (DNSBrowserRef
) inRef
->ref
, 0 );
735 case kDNSServiceDiscoveryObjectTypeResolver
:
738 err
= DNSResolverRelease( (DNSResolverRef
) inRef
->ref
, 0 );
745 debugf( DEBUG_NAME
"unknown object type (%d)\n", obj
->type
);
750 //===========================================================================================================================
751 // DNSServiceDiscovery_handleReply
752 //===========================================================================================================================
754 void DNSServiceDiscovery_handleReply( void *inReplyMessage
)
756 DNS_UNUSED( inReplyMessage
);
758 debugf( DEBUG_NAME
"DNSServiceDiscovery_handleReply is not supported\n" );