2 * Copyright (c) 2002 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@
26 #include "DNSServiceDiscovery.h"
27 #include "DNSServiceDiscoveryDefines.h"
31 #include <servers/bootstrap.h>
32 #include <mach/mach.h>
33 #include <mach/mach_error.h>
36 #include <netinet/in.h>
38 extern struct rpc_subsystem internal_DNSServiceDiscoveryReply_subsystem
;
40 extern boolean_t
DNSServiceDiscoveryReply_server(
41 mach_msg_header_t
*InHeadP
,
42 mach_msg_header_t
*OutHeadP
);
45 kern_return_t DNSServiceBrowserCreate_rpc
54 kern_return_t DNSServiceDomainEnumerationCreate_rpc
58 int registrationDomains
62 kern_return_t DNSServiceRegistrationCreate_rpc
74 kern_return_t DNSServiceResolverResolve_rpc
84 kern_return_t DNSServiceRegistrationAddRecord_rpc
90 mach_msg_type_number_t record_dataCnt
,
96 int DNSServiceRegistrationUpdateRecord_rpc
102 mach_msg_type_number_t record_dataCnt
,
107 kern_return_t DNSServiceRegistrationRemoveRecord_rpc
115 struct a_requests
*next
;
116 mach_port_t client_port
;
118 DNSServiceBrowserReply browserCallback
;
119 DNSServiceDomainEnumerationReply enumCallback
;
120 DNSServiceRegistrationReply regCallback
;
121 DNSServiceResolverReply resolveCallback
;
126 static struct a_requests
*a_requests
= NULL
;
127 static pthread_mutex_t a_requests_lock
= PTHREAD_MUTEX_INITIALIZER
;
129 typedef struct _dns_service_discovery_t
{
131 } dns_service_discovery_t
;
133 mach_port_t
DNSServiceDiscoveryLookupServer(void)
135 static mach_port_t sndPort
= MACH_PORT_NULL
;
136 kern_return_t result
;
138 if (sndPort
!= MACH_PORT_NULL
) {
142 result
= bootstrap_look_up(bootstrap_port
, DNS_SERVICE_DISCOVERY_SERVER
, &sndPort
);
143 if (result
!= KERN_SUCCESS
) {
144 printf("%s(): {%s:%d} bootstrap_look_up() failed: $%x\n", __FUNCTION__
, __FILE__
, __LINE__
, (int) result
);
145 sndPort
= MACH_PORT_NULL
;
152 void _increaseQueueLengthOnPort(mach_port_t port
)
154 mach_port_limits_t qlimits
;
155 kern_return_t result
;
157 qlimits
.mpl_qlimit
= 16;
158 result
= mach_port_set_attributes(mach_task_self(), port
, MACH_PORT_LIMITS_INFO
, (mach_port_info_t
)&qlimits
, MACH_PORT_LIMITS_INFO_COUNT
);
160 if (result
!= KERN_SUCCESS
) {
161 printf("%s(): {%s:%d} mach_port_set_attributes() failed: $%x %s\n", __FUNCTION__
, __FILE__
, __LINE__
, (int) result
, mach_error_string(result
));
165 dns_service_discovery_ref
DNSServiceBrowserCreate (const char *regtype
, const char *domain
, DNSServiceBrowserReply callBack
,void *context
)
167 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
168 mach_port_t clientPort
;
169 kern_return_t result
;
170 dns_service_discovery_ref return_t
;
171 struct a_requests
*request
;
177 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
178 if (result
!= KERN_SUCCESS
) {
179 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
182 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
183 if (result
!= KERN_SUCCESS
) {
184 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
185 mach_port_destroy(mach_task_self(), clientPort
);
188 _increaseQueueLengthOnPort(clientPort
);
190 return_t
= malloc(sizeof(dns_service_discovery_t
));
191 return_t
->port
= clientPort
;
193 request
= malloc(sizeof(struct a_requests
));
194 request
->client_port
= clientPort
;
195 request
->context
= context
;
196 request
->callout
.browserCallback
= callBack
;
198 result
= DNSServiceBrowserCreate_rpc(serverPort
, clientPort
, (char *)regtype
, (char *)domain
);
200 if (result
!= KERN_SUCCESS
) {
201 printf("There was an error creating a browser, %s\n", mach_error_string(result
));
206 pthread_mutex_lock(&a_requests_lock
);
207 request
->next
= a_requests
;
208 a_requests
= request
;
209 pthread_mutex_unlock(&a_requests_lock
);
214 /* Service Enumeration */
216 dns_service_discovery_ref
DNSServiceDomainEnumerationCreate (int registrationDomains
, DNSServiceDomainEnumerationReply callBack
, void *context
)
218 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
219 mach_port_t clientPort
;
220 kern_return_t result
;
221 dns_service_discovery_ref return_t
;
222 struct a_requests
*request
;
228 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
229 if (result
!= KERN_SUCCESS
) {
230 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
233 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
234 if (result
!= KERN_SUCCESS
) {
235 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
236 mach_port_destroy(mach_task_self(), clientPort
);
239 _increaseQueueLengthOnPort(clientPort
);
241 return_t
= malloc(sizeof(dns_service_discovery_t
));
242 return_t
->port
= clientPort
;
244 request
= malloc(sizeof(struct a_requests
));
245 request
->client_port
= clientPort
;
246 request
->context
= context
;
247 request
->callout
.enumCallback
= callBack
;
249 result
= DNSServiceDomainEnumerationCreate_rpc(serverPort
, clientPort
, registrationDomains
);
251 if (result
!= KERN_SUCCESS
) {
252 printf("There was an error creating an enumerator, %s\n", mach_error_string(result
));
257 pthread_mutex_lock(&a_requests_lock
);
258 request
->next
= a_requests
;
259 a_requests
= request
;
260 pthread_mutex_unlock(&a_requests_lock
);
266 /* Service Registration */
268 dns_service_discovery_ref DNSServiceRegistrationCreate
269 (const char *name
, const char *regtype
, const char *domain
, uint16_t port
, const char *txtRecord
, DNSServiceRegistrationReply callBack
, void *context
)
271 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
272 mach_port_t clientPort
;
273 kern_return_t result
;
274 dns_service_discovery_ref return_t
;
275 struct a_requests
*request
;
285 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
286 if (result
!= KERN_SUCCESS
) {
287 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
290 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
291 if (result
!= KERN_SUCCESS
) {
292 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
293 mach_port_destroy(mach_task_self(), clientPort
);
296 _increaseQueueLengthOnPort(clientPort
);
298 return_t
= malloc(sizeof(dns_service_discovery_t
));
299 return_t
->port
= clientPort
;
301 request
= malloc(sizeof(struct a_requests
));
302 request
->client_port
= clientPort
;
303 request
->context
= context
;
304 request
->callout
.regCallback
= callBack
;
306 result
= DNSServiceRegistrationCreate_rpc(serverPort
, clientPort
, (char *)name
, (char *)regtype
, (char *)domain
, port
, (char *)txtRecord
);
308 if (result
!= KERN_SUCCESS
) {
309 printf("There was an error creating a resolve, %s\n", mach_error_string(result
));
314 pthread_mutex_lock(&a_requests_lock
);
315 request
->next
= a_requests
;
316 a_requests
= request
;
317 pthread_mutex_unlock(&a_requests_lock
);
322 /* Resolver requests */
324 dns_service_discovery_ref
DNSServiceResolverResolve(const char *name
, const char *regtype
, const char *domain
, DNSServiceResolverReply callBack
, void *context
)
326 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
327 mach_port_t clientPort
;
328 kern_return_t result
;
329 dns_service_discovery_ref return_t
;
330 struct a_requests
*request
;
336 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
337 if (result
!= KERN_SUCCESS
) {
338 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
341 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
342 if (result
!= KERN_SUCCESS
) {
343 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
344 mach_port_destroy(mach_task_self(), clientPort
);
347 _increaseQueueLengthOnPort(clientPort
);
349 return_t
= malloc(sizeof(dns_service_discovery_t
));
350 return_t
->port
= clientPort
;
352 request
= malloc(sizeof(struct a_requests
));
353 request
->client_port
= clientPort
;
354 request
->context
= context
;
355 request
->callout
.resolveCallback
= callBack
;
357 DNSServiceResolverResolve_rpc(serverPort
, clientPort
, (char *)name
, (char *)regtype
, (char *)domain
);
359 pthread_mutex_lock(&a_requests_lock
);
360 request
->next
= a_requests
;
361 a_requests
= request
;
362 pthread_mutex_unlock(&a_requests_lock
);
367 DNSRecordReference
DNSServiceRegistrationAddRecord(dns_service_discovery_ref ref
, uint16_t rrtype
, uint16_t rdlen
, const char *rdata
, uint32_t ttl
)
369 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
370 mach_port_t clientPort
;
371 natural_t reference
= 0;
372 kern_return_t result
= KERN_SUCCESS
;
375 return kDNSServiceDiscoveryUnknownErr
;
378 clientPort
= DNSServiceDiscoveryMachPort(ref
);
381 return kDNSServiceDiscoveryUnknownErr
;
384 result
= DNSServiceRegistrationAddRecord_rpc(serverPort
, clientPort
, rrtype
, (record_data_t
)rdata
, rdlen
, ttl
, &reference
);
386 if (result
!= KERN_SUCCESS
) {
387 printf("The result of the registration was not successful. Error %d, result %s\n", result
, mach_error_string(result
));
393 DNSServiceRegistrationReplyErrorType
DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref
, DNSRecordReference reference
, uint16_t rdlen
, const char *rdata
, uint32_t ttl
)
395 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
396 mach_port_t clientPort
;
397 kern_return_t result
= KERN_SUCCESS
;
400 return kDNSServiceDiscoveryUnknownErr
;
403 clientPort
= DNSServiceDiscoveryMachPort(ref
);
406 return kDNSServiceDiscoveryUnknownErr
;
409 result
= DNSServiceRegistrationUpdateRecord_rpc(serverPort
, clientPort
, (natural_t
)reference
, (record_data_t
)rdata
, rdlen
, ttl
);
410 if (result
!= KERN_SUCCESS
) {
411 printf("The result of the registration was not successful. Error %d, result %s\n", result
, mach_error_string(result
));
415 return kDNSServiceDiscoveryNoError
;
419 DNSServiceRegistrationReplyErrorType
DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref
, DNSRecordReference reference
)
421 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
422 mach_port_t clientPort
;
423 kern_return_t result
= KERN_SUCCESS
;
426 return kDNSServiceDiscoveryUnknownErr
;
429 clientPort
= DNSServiceDiscoveryMachPort(ref
);
432 return kDNSServiceDiscoveryUnknownErr
;
435 result
= DNSServiceRegistrationRemoveRecord_rpc(serverPort
, clientPort
, (natural_t
)reference
);
437 if (result
!= KERN_SUCCESS
) {
438 printf("The result of the registration was not successful. Error %d, result %s\n", result
, mach_error_string(result
));
442 return kDNSServiceDiscoveryNoError
;
445 void DNSServiceDiscovery_handleReply(void *replyMsg
)
447 unsigned long result
= 0xFFFFFFFF;
448 mach_msg_header_t
* msgSendBufPtr
;
449 mach_msg_header_t
* receivedMessage
;
450 unsigned msgSendBufLength
;
452 msgSendBufLength
= internal_DNSServiceDiscoveryReply_subsystem
.maxsize
;
453 msgSendBufPtr
= (mach_msg_header_t
*) malloc(msgSendBufLength
);
456 receivedMessage
= ( mach_msg_header_t
* ) replyMsg
;
458 // Call DNSServiceDiscoveryReply_server to change mig-generated message into a
459 // genuine mach message. It will then cause the callback to get called.
460 result
= DNSServiceDiscoveryReply_server ( receivedMessage
, msgSendBufPtr
);
461 ( void ) mach_msg_send ( msgSendBufPtr
);
465 mach_port_t
DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery
)
467 return dnsServiceDiscovery
->port
;
470 void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery
)
472 struct a_requests
*request0
, *request
;
473 mach_port_t reply
= dnsServiceDiscovery
->port
;
475 if (dnsServiceDiscovery
->port
) {
476 pthread_mutex_lock(&a_requests_lock
);
478 request
= a_requests
;
480 if (request
->client_port
== reply
) {
481 /* request info found, remove from list */
483 request0
->next
= request
->next
;
485 a_requests
= request
->next
;
489 /* not info for this request, skip to next */
491 request
= request
->next
;
495 pthread_mutex_unlock(&a_requests_lock
);
499 mach_port_destroy(mach_task_self(), dnsServiceDiscovery
->port
);
501 free(dnsServiceDiscovery
);
506 // reply functions, calls the users setup callbacks with function pointers
508 kern_return_t internal_DNSServiceDomainEnumerationReply_rpc
512 DNSCString replyDomain
,
513 DNSServiceDiscoveryReplyFlags flags
516 struct a_requests
*request
;
517 void *requestContext
= NULL
;
518 DNSServiceDomainEnumerationReply callback
= NULL
;
520 pthread_mutex_lock(&a_requests_lock
);
521 request
= a_requests
;
523 if (request
->client_port
== reply
) {
526 request
= request
->next
;
529 if (request
!= NULL
) {
530 callback
= (*request
->callout
.enumCallback
);
531 requestContext
= request
->context
;
533 pthread_mutex_unlock(&a_requests_lock
);
535 if (request
!= NULL
) {
536 (callback
)(resultType
, replyDomain
, flags
, requestContext
);
543 kern_return_t internal_DNSServiceBrowserReply_rpc
547 DNSCString replyName
,
548 DNSCString replyType
,
549 DNSCString replyDomain
,
550 DNSServiceDiscoveryReplyFlags flags
553 struct a_requests
*request
;
554 void *requestContext
= NULL
;
555 DNSServiceBrowserReply callback
= NULL
;
557 pthread_mutex_lock(&a_requests_lock
);
558 request
= a_requests
;
560 if (request
->client_port
== reply
) {
563 request
= request
->next
;
565 if (request
!= NULL
) {
566 callback
= (*request
->callout
.browserCallback
);
567 requestContext
= request
->context
;
570 pthread_mutex_unlock(&a_requests_lock
);
572 if (request
!= NULL
) {
573 (callback
)(resultType
, replyName
, replyType
, replyDomain
, flags
, requestContext
);
580 kern_return_t internal_DNSServiceRegistrationReply_rpc
586 struct a_requests
*request
;
587 void *requestContext
= NULL
;
588 DNSServiceRegistrationReply callback
= NULL
;
590 pthread_mutex_lock(&a_requests_lock
);
591 request
= a_requests
;
593 if (request
->client_port
== reply
) {
596 request
= request
->next
;
598 if (request
!= NULL
) {
599 callback
= (*request
->callout
.regCallback
);
600 requestContext
= request
->context
;
603 pthread_mutex_unlock(&a_requests_lock
);
604 if (request
!= NULL
) {
605 (callback
)(resultType
, requestContext
);
611 kern_return_t internal_DNSServiceResolverReply_rpc
614 sockaddr_t interface
,
616 DNSCString txtRecord
,
617 DNSServiceDiscoveryReplyFlags flags
620 struct sockaddr
*interface_storage
= NULL
;
621 struct sockaddr
*address_storage
= NULL
;
622 struct a_requests
*request
;
623 void *requestContext
= NULL
;
624 DNSServiceResolverReply callback
= NULL
;
627 int len
= ((struct sockaddr
*)interface
)->sa_len
;
628 interface_storage
= (struct sockaddr
*)malloc(len
);
629 bcopy(interface
, interface_storage
,len
);
633 int len
= ((struct sockaddr
*)address
)->sa_len
;
634 address_storage
= (struct sockaddr
*)malloc(len
);
635 bcopy(address
, address_storage
, len
);
638 pthread_mutex_lock(&a_requests_lock
);
639 request
= a_requests
;
641 if (request
->client_port
== reply
) {
644 request
= request
->next
;
647 if (request
!= NULL
) {
648 callback
= (*request
->callout
.resolveCallback
);
649 requestContext
= request
->context
;
651 pthread_mutex_unlock(&a_requests_lock
);
653 if (request
!= NULL
) {
654 (callback
)(interface_storage
, address_storage
, txtRecord
, flags
, requestContext
);
658 free(interface_storage
);
661 free(address_storage
);