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):
27 $Log: DNSServiceDiscovery.c,v $
28 Revision 1.7 2004/05/08 12:24:48 bradley
29 Removed trailing character from zero value to fix compile error.
31 Revision 1.6 2004/05/06 18:42:58 ksekar
32 General dns_sd.h API cleanup, including the following radars:
33 <rdar://problem/3592068>: Remove flags with zero value
34 <rdar://problem/3479569>: Passing in NULL causes a crash.
36 Revision 1.5 2004/01/30 02:56:34 bradley
37 Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
39 Revision 1.4 2003/11/14 20:59:10 cheshire
40 Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
41 Best solution is just to combine mDNSClientAPI.h and mDNSPlatformFunctions.h into a single file.
43 Revision 1.3 2003/10/04 04:47:08 bradley
44 Changed DNSServiceRegistrationCreate to treat the port in network byte order for end-to-end consistency.
46 Revision 1.2 2003/08/20 07:06:34 bradley
47 Update to APSL 2.0. Updated change history to match other mDNSResponder files.
49 Revision 1.1 2003/08/20 06:04:45 bradley
50 Platform-neutral DNSServices-based emulation layer for the Mac OS X DNSServiceDiscovery API.
58 #if( macintosh || __MACH__ )
60 #include <sys/types.h>
61 #include <sys/socket.h>
62 #include <netinet/in.h>
64 #elif( defined( _MSC_VER ) || defined( __MWERKS__ ) )
66 #pragma warning( disable:4054 ) // Disable "type cast : from function pointer to data pointer".
67 #pragma warning( disable:4055 ) // Disable "type cast : from data pointer to function pointer".
68 #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros.
69 #pragma warning( disable:4152 ) // Disable "nonstandard extension, function/data pointer conversion in expression".
71 #define WIN32_LEAN_AND_MEAN // Needed to avoid redefinitions by Windows interfaces.
77 #include "mDNSClientAPI.h"
78 #include "DNSServices.h"
80 #include "DNSServiceDiscovery.h"
87 #pragma mark == Constants & Types ==
90 //===========================================================================================================================
92 //===========================================================================================================================
94 #define DEBUG_NAME "[DNSServiceDiscovery] "
98 kDNSServiceDiscoveryObjectTypeRegistration
= 1,
99 kDNSServiceDiscoveryObjectTypeDomainEnumeration
= 2,
100 kDNSServiceDiscoveryObjectTypeBrowser
= 3,
101 kDNSServiceDiscoveryObjectTypeResolver
= 4
103 } DNSServiceDiscoveryObjectType
;
105 typedef struct _dns_service_discovery_t _dns_service_discovery_t
;
106 struct _dns_service_discovery_t
108 DNSServiceDiscoveryObjectType type
;
115 #pragma mark == Macros ==
118 //===========================================================================================================================
120 //===========================================================================================================================
122 // Emulate Mac OS debugging macros for non-Mac platforms.
124 #if( !TARGET_OS_MAC )
125 #define check(assertion)
126 #define check_string( assertion, cstring )
127 #define check_noerr(err)
128 #define check_noerr_string( error, cstring )
129 #define debug_string( cstring )
130 #define require( assertion, label ) do { if( !(assertion) ) goto label; } while(0)
131 #define require_string( assertion, label, string ) require(assertion, label)
132 #define require_quiet( assertion, label ) require( assertion, label )
133 #define require_noerr( error, label ) do { if( (error) != 0 ) goto label; } while(0)
134 #define require_noerr_quiet( assertion, label ) require_noerr( assertion, label )
135 #define require_noerr_action( error, label, action ) do { if( (error) != 0 ) { {action;}; goto label; } } while(0)
136 #define require_noerr_action_quiet( assertion, label, action ) require_noerr_action( assertion, label, action )
137 #define require_action( assertion, label, action ) do { if( !(assertion) ) { {action;}; goto label; } } while(0)
138 #define require_action_quiet( assertion, label, action ) require_action( assertion, label, action )
139 #define require_action_string( assertion, label, action, cstring ) do { if( !(assertion) ) { {action;}; goto label; } } while(0)
143 #pragma mark == Prototypes ==
146 //===========================================================================================================================
148 //===========================================================================================================================
151 DNSServiceRegistrationPrivateCallBack(
153 DNSRegistrationRef inRef
,
154 DNSStatus inStatusCode
,
155 const DNSRegistrationEvent
* inEvent
);
158 DNSServiceDomainEnumerationPrivateCallBack(
161 DNSStatus inStatusCode
,
162 const DNSBrowserEvent
* inEvent
);
165 DNSServiceBrowserPrivateCallBack(
168 DNSStatus inStatusCode
,
169 const DNSBrowserEvent
* inEvent
);
172 DNSServiceResolverPrivateCallBack(
174 DNSResolverRef inRef
,
175 DNSStatus inStatusCode
,
176 const DNSResolverEvent
* inEvent
);
182 //===========================================================================================================================
183 // DNSServiceRegistrationCreate
184 //===========================================================================================================================
186 dns_service_discovery_ref
187 DNSServiceRegistrationCreate(
190 const char * inDomain
,
192 const char * inTextRecord
,
193 DNSServiceRegistrationReply inCallBack
,
197 dns_service_discovery_ref result
;
198 dns_service_discovery_ref obj
;
202 DNSRegistrationRef registration
;
208 // Allocate and initialize the object.
210 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
211 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
213 obj
->type
= kDNSServiceDiscoveryObjectTypeRegistration
;
215 obj
->callback
= inCallBack
;
216 obj
->context
= inContext
;
218 // Create the underlying registration. Build a \001-escaped text record if needed.
222 err
= DNSDynamicTextRecordBuildEscaped( inTextRecord
, &txt
, &txtSize
);
223 require_noerr( err
, exit
);
226 port
.v8
[ 0 ] = (DNSUInt8
)( inPort
>> 8 );
227 port
.v8
[ 1 ] = (DNSUInt8
)( inPort
& 0xFF );
228 err
= DNSRegistrationCreate( kDNSRegistrationFlagPreFormattedTextRecord
, inName
, inType
, inDomain
, port
.v16
, txt
,
229 (DNSCount
) txtSize
, NULL
, NULL
, DNSServiceRegistrationPrivateCallBack
, obj
, ®istration
);
230 require_noerr( err
, exit
);
231 obj
->ref
= registration
;
241 DNSDynamicTextRecordRelease( txt
);
245 DNSServiceDiscoveryDeallocate( obj
);
250 //===========================================================================================================================
251 // DNSServiceRegistrationPrivateCallBack
252 //===========================================================================================================================
255 DNSServiceRegistrationPrivateCallBack(
257 DNSRegistrationRef inRef
,
258 DNSStatus inStatusCode
,
259 const DNSRegistrationEvent
* inEvent
)
261 dns_service_discovery_ref obj
;
262 DNSServiceRegistrationReply callback
;
265 DNS_UNUSED( inStatusCode
);
268 obj
= (dns_service_discovery_ref
) inContext
;
269 check( obj
->callback
);
270 callback
= (DNSServiceRegistrationReply
) obj
->callback
;
272 switch( inEvent
->type
)
274 case kDNSRegistrationEventTypeRegistered
:
275 debugf( DEBUG_NAME
"name registered and active\n" );
279 callback( kDNSServiceDiscoveryNoError
, obj
->context
);
283 case kDNSRegistrationEventTypeNameCollision
:
284 debugf( DEBUG_NAME
"name in use, please choose another name\n" );
288 callback( kDNSServiceDiscoveryNameConflict
, obj
->context
);
297 //===========================================================================================================================
298 // DNSServiceRegistrationAddRecord
299 //===========================================================================================================================
302 DNSServiceRegistrationAddRecord(
303 dns_service_discovery_ref inRef
,
306 const char * inRData
,
310 DNS_UNUSED( inRRType
);
311 DNS_UNUSED( inRDLength
);
312 DNS_UNUSED( inRData
);
315 debugf( DEBUG_NAME
"DNSServiceRegistrationAddRecord is currently not supported\n" );
319 //===========================================================================================================================
320 // DNSServiceRegistrationUpdateRecord
321 //===========================================================================================================================
323 DNSServiceRegistrationReplyErrorType
324 DNSServiceRegistrationUpdateRecord(
325 dns_service_discovery_ref inRef
,
326 DNSRecordReference inRecordRef
,
328 const char * inRData
,
332 DNS_UNUSED( inRecordRef
);
333 DNS_UNUSED( inRDLength
);
334 DNS_UNUSED( inRData
);
337 debugf( DEBUG_NAME
"DNSServiceRegistrationUpdateRecord is currently not supported\n" );
338 return( kDNSServiceDiscoveryUnsupportedErr
);
341 //===========================================================================================================================
342 // DNSServiceRegistrationRemoveRecord
343 //===========================================================================================================================
345 DNSServiceRegistrationReplyErrorType
346 DNSServiceRegistrationRemoveRecord(
347 dns_service_discovery_ref inRef
,
348 DNSRecordReference inRecordRef
)
351 DNS_UNUSED( inRecordRef
);
353 debugf( DEBUG_NAME
"DNSServiceRegistrationRemoveRecord is currently not supported\n" );
354 return( kDNSServiceDiscoveryUnsupportedErr
);
357 //===========================================================================================================================
358 // DNSServiceDomainEnumerationCreate
359 //===========================================================================================================================
361 dns_service_discovery_ref
362 DNSServiceDomainEnumerationCreate(
363 int inRegistrationDomains
,
364 DNSServiceDomainEnumerationReply inCallBack
,
368 dns_service_discovery_ref result
;
369 dns_service_discovery_ref obj
;
370 DNSBrowserRef browser
;
371 DNSBrowserFlags flags
;
376 // Allocate and initialize the object.
378 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
379 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
381 obj
->type
= kDNSServiceDiscoveryObjectTypeDomainEnumeration
;
383 obj
->callback
= inCallBack
;
384 obj
->context
= inContext
;
386 // Create the underlying browser and start searching for domains.
388 err
= DNSBrowserCreate( 0, DNSServiceDomainEnumerationPrivateCallBack
, obj
, &browser
);
389 require_noerr( err
, exit
);
392 if( inRegistrationDomains
)
394 flags
= kDNSBrowserFlagRegistrationDomainsOnly
;
400 err
= DNSBrowserStartDomainSearch( browser
, flags
);
401 require_noerr( err
, exit
);
412 DNSBrowserRelease( browser
, 0 );
416 DNSServiceDiscoveryDeallocate( obj
);
421 //===========================================================================================================================
422 // DNSServiceDomainEnumerationPrivateCallBack
423 //===========================================================================================================================
426 DNSServiceDomainEnumerationPrivateCallBack(
429 DNSStatus inStatusCode
,
430 const DNSBrowserEvent
* inEvent
)
432 dns_service_discovery_ref obj
;
433 DNSServiceDomainEnumerationReply callback
;
436 DNS_UNUSED( inStatusCode
);
439 obj
= (dns_service_discovery_ref
) inContext
;
440 check( obj
->callback
);
441 callback
= (DNSServiceDomainEnumerationReply
) obj
->callback
;
443 switch( inEvent
->type
)
445 case kDNSBrowserEventTypeAddDomain
:
446 debugf( DEBUG_NAME
"add domain \"%s\"\n", inEvent
->data
.addDomain
.domain
);
450 callback( DNSServiceDomainEnumerationReplyAddDomain
, inEvent
->data
.addDomain
.domain
,
455 case kDNSBrowserEventTypeAddDefaultDomain
:
456 debugf( DEBUG_NAME
"add default domain \"%s\"\n", inEvent
->data
.addDefaultDomain
.domain
);
460 callback( DNSServiceDomainEnumerationReplyAddDomainDefault
, inEvent
->data
.addDefaultDomain
.domain
,
465 case kDNSBrowserEventTypeRemoveDomain
:
466 debugf( DEBUG_NAME
"add default domain \"%s\"\n", inEvent
->data
.removeDomain
.domain
);
470 callback( DNSServiceDomainEnumerationReplyRemoveDomain
, inEvent
->data
.removeDomain
.domain
,
480 //===========================================================================================================================
481 // DNSServiceBrowserCreate
482 //===========================================================================================================================
484 dns_service_discovery_ref
485 DNSServiceBrowserCreate(
487 const char * inDomain
,
488 DNSServiceBrowserReply inCallBack
,
492 dns_service_discovery_ref result
;
493 dns_service_discovery_ref obj
;
494 DNSBrowserRef browser
;
499 // Allocate and initialize the object.
501 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
502 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
504 obj
->type
= kDNSServiceDiscoveryObjectTypeBrowser
;
506 obj
->callback
= inCallBack
;
507 obj
->context
= inContext
;
509 // Create the underlying browser and start searching for domains.
511 err
= DNSBrowserCreate( 0, DNSServiceBrowserPrivateCallBack
, obj
, &browser
);
512 require_noerr( err
, exit
);
515 err
= DNSBrowserStartServiceSearch( browser
, 0, inType
, inDomain
);
516 require_noerr( err
, exit
);
527 DNSBrowserRelease( browser
, 0 );
531 DNSServiceDiscoveryDeallocate( obj
);
536 //===========================================================================================================================
537 // DNSServiceBrowserPrivateCallBack
538 //===========================================================================================================================
541 DNSServiceBrowserPrivateCallBack(
544 DNSStatus inStatusCode
,
545 const DNSBrowserEvent
* inEvent
)
547 dns_service_discovery_ref obj
;
548 DNSServiceBrowserReply callback
;
551 DNS_UNUSED( inStatusCode
);
554 obj
= (dns_service_discovery_ref
) inContext
;
555 check( obj
->callback
);
556 callback
= (DNSServiceBrowserReply
) obj
->callback
;
558 switch( inEvent
->type
)
560 case kDNSBrowserEventTypeAddService
:
561 debugf( DEBUG_NAME
"add service \"%s.%s%s\"\n",
562 inEvent
->data
.addService
.name
,
563 inEvent
->data
.addService
.type
,
564 inEvent
->data
.addService
.domain
);
568 callback( DNSServiceBrowserReplyAddInstance
,
569 inEvent
->data
.addService
.name
,
570 inEvent
->data
.addService
.type
,
571 inEvent
->data
.addService
.domain
,
577 case kDNSBrowserEventTypeRemoveService
:
578 debugf( DEBUG_NAME
"remove service \"%s.%s%s\"\n",
579 inEvent
->data
.removeService
.name
,
580 inEvent
->data
.removeService
.type
,
581 inEvent
->data
.removeService
.domain
);
585 callback( DNSServiceBrowserReplyRemoveInstance
,
586 inEvent
->data
.removeService
.name
,
587 inEvent
->data
.removeService
.type
,
588 inEvent
->data
.removeService
.domain
,
599 //===========================================================================================================================
600 // DNSServiceResolverResolve
601 //===========================================================================================================================
603 dns_service_discovery_ref
604 DNSServiceResolverResolve(
607 const char * inDomain
,
608 DNSServiceResolverReply inCallBack
,
612 dns_service_discovery_ref result
;
613 dns_service_discovery_ref obj
;
614 DNSResolverRef resolver
;
618 // Allocate and initialize the object.
620 obj
= (dns_service_discovery_ref
) malloc( sizeof( *obj
) );
621 require_action( obj
, exit
, err
= kDNSNoMemoryErr
);
623 obj
->type
= kDNSServiceDiscoveryObjectTypeResolver
;
625 obj
->callback
= inCallBack
;
626 obj
->context
= inContext
;
628 // Create the underlying resolver and start searching for domains.
630 err
= DNSResolverCreate( 0, inName
, inType
, inDomain
, DNSServiceResolverPrivateCallBack
, obj
, NULL
, &resolver
);
631 require_noerr( err
, exit
);
642 DNSServiceDiscoveryDeallocate( obj
);
647 //===========================================================================================================================
648 // DNSServiceResolverPrivateCallBack
649 //===========================================================================================================================
652 DNSServiceResolverPrivateCallBack(
654 DNSResolverRef inRef
,
655 DNSStatus inStatusCode
,
656 const DNSResolverEvent
* inEvent
)
658 dns_service_discovery_ref obj
;
659 DNSServiceResolverReply callback
;
660 struct sockaddr_in interfaceAddr
;
661 struct sockaddr_in addr
;
664 DNS_UNUSED( inStatusCode
);
667 obj
= (dns_service_discovery_ref
) inContext
;
668 check( obj
->callback
);
669 callback
= (DNSServiceResolverReply
) obj
->callback
;
671 switch( inEvent
->type
)
673 case kDNSResolverEventTypeResolved
:
674 debugf( DEBUG_NAME
"resolved \"%s.%s%s\"\n",
675 inEvent
->data
.resolved
.name
,
676 inEvent
->data
.resolved
.type
,
677 inEvent
->data
.resolved
.domain
);
679 memset( &interfaceAddr
, 0, sizeof( interfaceAddr
) );
680 interfaceAddr
.sin_family
= AF_INET
;
681 interfaceAddr
.sin_port
= 0;
682 interfaceAddr
.sin_addr
.s_addr
= inEvent
->data
.resolved
.interfaceIP
.u
.ipv4
.addr
.v32
;
684 memset( &addr
, 0, sizeof( addr
) );
685 addr
.sin_family
= AF_INET
;
686 addr
.sin_port
= inEvent
->data
.resolved
.address
.u
.ipv4
.port
.v16
;
687 addr
.sin_addr
.s_addr
= inEvent
->data
.resolved
.address
.u
.ipv4
.addr
.v32
;
691 callback( (struct sockaddr
*) &interfaceAddr
, (struct sockaddr
*) &addr
, inEvent
->data
.resolved
.textRecord
,
701 //===========================================================================================================================
702 // DNSServiceDiscoveryMachPort
703 //===========================================================================================================================
705 mach_port_t
DNSServiceDiscoveryMachPort( dns_service_discovery_ref inRef
)
709 debugf( DEBUG_NAME
"DNSServiceDiscoveryMachPort is not supported\n" );
713 //===========================================================================================================================
714 // DNSServiceDiscoveryDeallocate
715 //===========================================================================================================================
717 void DNSServiceDiscoveryDeallocate( dns_service_discovery_ref inRef
)
719 _dns_service_discovery_t
* obj
;
725 obj
= (_dns_service_discovery_t
*) inRef
;
728 case kDNSServiceDiscoveryObjectTypeRegistration
:
731 err
= DNSRegistrationRelease( (DNSRegistrationRef
) inRef
->ref
, 0 );
737 case kDNSServiceDiscoveryObjectTypeDomainEnumeration
:
740 err
= DNSBrowserRelease( (DNSBrowserRef
) inRef
->ref
, 0 );
746 case kDNSServiceDiscoveryObjectTypeBrowser
:
749 err
= DNSBrowserRelease( (DNSBrowserRef
) inRef
->ref
, 0 );
755 case kDNSServiceDiscoveryObjectTypeResolver
:
758 err
= DNSResolverRelease( (DNSResolverRef
) inRef
->ref
, 0 );
765 debugf( DEBUG_NAME
"unknown object type (%d)\n", obj
->type
);
770 //===========================================================================================================================
771 // DNSServiceDiscovery_handleReply
772 //===========================================================================================================================
774 void DNSServiceDiscovery_handleReply( void *inReplyMessage
)
776 DNS_UNUSED( inReplyMessage
);
778 debugf( DEBUG_NAME
"DNSServiceDiscovery_handleReply is not supported\n" );