2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include "DNSServiceDiscovery.h"
24 #include "DNSServiceDiscoveryDefines.h"
28 #include <servers/bootstrap.h>
29 #include <mach/mach.h>
30 #include <mach/mach_error.h>
33 #include <netinet/in.h>
35 extern struct rpc_subsystem internal_DNSServiceDiscoveryReply_subsystem
;
37 extern boolean_t
DNSServiceDiscoveryReply_server(
38 mach_msg_header_t
*InHeadP
,
39 mach_msg_header_t
*OutHeadP
);
42 kern_return_t DNSServiceBrowserCreate_rpc
51 kern_return_t DNSServiceDomainEnumerationCreate_rpc
55 int registrationDomains
59 kern_return_t DNSServiceRegistrationCreate_rpc
71 kern_return_t DNSServiceResolverResolve_rpc
81 kern_return_t DNSServiceRegistrationAddRecord_rpc
87 mach_msg_type_number_t record_dataCnt
,
93 int DNSServiceRegistrationUpdateRecord_rpc
99 mach_msg_type_number_t record_dataCnt
,
104 kern_return_t DNSServiceRegistrationRemoveRecord_rpc
112 struct a_requests
*next
;
113 mach_port_t client_port
;
115 DNSServiceBrowserReply browserCallback
;
116 DNSServiceDomainEnumerationReply enumCallback
;
117 DNSServiceRegistrationReply regCallback
;
118 DNSServiceResolverReply resolveCallback
;
123 static struct a_requests
*a_requests
= NULL
;
124 static pthread_mutex_t a_requests_lock
= PTHREAD_MUTEX_INITIALIZER
;
126 typedef struct _dns_service_discovery_t
{
128 } dns_service_discovery_t
;
130 mach_port_t
DNSServiceDiscoveryLookupServer(void)
132 static mach_port_t sndPort
= MACH_PORT_NULL
;
133 kern_return_t result
;
135 if (sndPort
!= MACH_PORT_NULL
) {
139 result
= bootstrap_look_up(bootstrap_port
, DNS_SERVICE_DISCOVERY_SERVER
, &sndPort
);
140 if (result
!= KERN_SUCCESS
) {
141 printf("%s(): {%s:%d} bootstrap_look_up() failed: $%x\n", __FUNCTION__
, __FILE__
, __LINE__
, (int) result
);
142 sndPort
= MACH_PORT_NULL
;
149 void _increaseQueueLengthOnPort(mach_port_t port
)
151 mach_port_limits_t qlimits
;
152 kern_return_t result
;
154 qlimits
.mpl_qlimit
= 16;
155 result
= mach_port_set_attributes(mach_task_self(), port
, MACH_PORT_LIMITS_INFO
, (mach_port_info_t
)&qlimits
, MACH_PORT_LIMITS_INFO_COUNT
);
157 if (result
!= KERN_SUCCESS
) {
158 printf("%s(): {%s:%d} mach_port_set_attributes() failed: $%x %s\n", __FUNCTION__
, __FILE__
, __LINE__
, (int) result
, mach_error_string(result
));
162 dns_service_discovery_ref
DNSServiceBrowserCreate (const char *regtype
, const char *domain
, DNSServiceBrowserReply callBack
,void *context
)
164 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
165 mach_port_t clientPort
;
166 kern_return_t result
;
167 dns_service_discovery_ref return_t
;
168 struct a_requests
*request
;
174 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
175 if (result
!= KERN_SUCCESS
) {
176 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
179 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
180 if (result
!= KERN_SUCCESS
) {
181 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
182 mach_port_destroy(mach_task_self(), clientPort
);
185 _increaseQueueLengthOnPort(clientPort
);
187 return_t
= malloc(sizeof(dns_service_discovery_t
));
188 return_t
->port
= clientPort
;
190 request
= malloc(sizeof(struct a_requests
));
191 request
->client_port
= clientPort
;
192 request
->context
= context
;
193 request
->callout
.browserCallback
= callBack
;
195 result
= DNSServiceBrowserCreate_rpc(serverPort
, clientPort
, (char *)regtype
, (char *)domain
);
197 if (result
!= KERN_SUCCESS
) {
198 printf("There was an error creating a browser, %s\n", mach_error_string(result
));
203 pthread_mutex_lock(&a_requests_lock
);
204 request
->next
= a_requests
;
205 a_requests
= request
;
206 pthread_mutex_unlock(&a_requests_lock
);
211 /* Service Enumeration */
213 dns_service_discovery_ref
DNSServiceDomainEnumerationCreate (int registrationDomains
, DNSServiceDomainEnumerationReply callBack
, void *context
)
215 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
216 mach_port_t clientPort
;
217 kern_return_t result
;
218 dns_service_discovery_ref return_t
;
219 struct a_requests
*request
;
225 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
226 if (result
!= KERN_SUCCESS
) {
227 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
230 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
231 if (result
!= KERN_SUCCESS
) {
232 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
233 mach_port_destroy(mach_task_self(), clientPort
);
236 _increaseQueueLengthOnPort(clientPort
);
238 return_t
= malloc(sizeof(dns_service_discovery_t
));
239 return_t
->port
= clientPort
;
241 request
= malloc(sizeof(struct a_requests
));
242 request
->client_port
= clientPort
;
243 request
->context
= context
;
244 request
->callout
.enumCallback
= callBack
;
246 result
= DNSServiceDomainEnumerationCreate_rpc(serverPort
, clientPort
, registrationDomains
);
248 if (result
!= KERN_SUCCESS
) {
249 printf("There was an error creating an enumerator, %s\n", mach_error_string(result
));
254 pthread_mutex_lock(&a_requests_lock
);
255 request
->next
= a_requests
;
256 a_requests
= request
;
257 pthread_mutex_unlock(&a_requests_lock
);
263 /* Service Registration */
265 dns_service_discovery_ref DNSServiceRegistrationCreate
266 (const char *name
, const char *regtype
, const char *domain
, uint16_t port
, const char *txtRecord
, DNSServiceRegistrationReply callBack
, void *context
)
268 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
269 mach_port_t clientPort
;
270 kern_return_t result
;
271 dns_service_discovery_ref return_t
;
272 struct a_requests
*request
;
278 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
279 if (result
!= KERN_SUCCESS
) {
280 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
283 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
284 if (result
!= KERN_SUCCESS
) {
285 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
286 mach_port_destroy(mach_task_self(), clientPort
);
289 _increaseQueueLengthOnPort(clientPort
);
291 return_t
= malloc(sizeof(dns_service_discovery_t
));
292 return_t
->port
= clientPort
;
294 request
= malloc(sizeof(struct a_requests
));
295 request
->client_port
= clientPort
;
296 request
->context
= context
;
297 request
->callout
.regCallback
= callBack
;
299 result
= DNSServiceRegistrationCreate_rpc(serverPort
, clientPort
, (char *)name
, (char *)regtype
, (char *)domain
, port
, (char *)txtRecord
);
301 if (result
!= KERN_SUCCESS
) {
302 printf("There was an error creating a resolve, %s\n", mach_error_string(result
));
307 pthread_mutex_lock(&a_requests_lock
);
308 request
->next
= a_requests
;
309 a_requests
= request
;
310 pthread_mutex_unlock(&a_requests_lock
);
315 /* Resolver requests */
317 dns_service_discovery_ref
DNSServiceResolverResolve(const char *name
, const char *regtype
, const char *domain
, DNSServiceResolverReply callBack
, void *context
)
319 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
320 mach_port_t clientPort
;
321 kern_return_t result
;
322 dns_service_discovery_ref return_t
;
323 struct a_requests
*request
;
329 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
330 if (result
!= KERN_SUCCESS
) {
331 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
334 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
335 if (result
!= KERN_SUCCESS
) {
336 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
337 mach_port_destroy(mach_task_self(), clientPort
);
340 _increaseQueueLengthOnPort(clientPort
);
342 return_t
= malloc(sizeof(dns_service_discovery_t
));
343 return_t
->port
= clientPort
;
345 request
= malloc(sizeof(struct a_requests
));
346 request
->client_port
= clientPort
;
347 request
->context
= context
;
348 request
->callout
.resolveCallback
= callBack
;
350 DNSServiceResolverResolve_rpc(serverPort
, clientPort
, (char *)name
, (char *)regtype
, (char *)domain
);
352 pthread_mutex_lock(&a_requests_lock
);
353 request
->next
= a_requests
;
354 a_requests
= request
;
355 pthread_mutex_unlock(&a_requests_lock
);
360 DNSRecordReference
DNSServiceRegistrationAddRecord(dns_service_discovery_ref ref
, uint16_t rrtype
, uint16_t rdlen
, const char *rdata
, uint32_t ttl
)
362 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
363 mach_port_t clientPort
;
364 natural_t reference
= 0;
365 kern_return_t result
= KERN_SUCCESS
;
368 return kDNSServiceDiscoveryUnknownErr
;
371 clientPort
= DNSServiceDiscoveryMachPort(ref
);
374 return kDNSServiceDiscoveryUnknownErr
;
377 result
= DNSServiceRegistrationAddRecord_rpc(serverPort
, clientPort
, rrtype
, (record_data_t
)rdata
, rdlen
, ttl
, &reference
);
379 if (result
!= KERN_SUCCESS
) {
380 printf("The result of the registration was not successful. Error %d, result %s\n", result
, mach_error_string(result
));
386 DNSServiceRegistrationReplyErrorType
DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref
, DNSRecordReference reference
, uint16_t rdlen
, const char *rdata
, uint32_t ttl
)
388 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
389 mach_port_t clientPort
;
390 kern_return_t result
= KERN_SUCCESS
;
393 return kDNSServiceDiscoveryUnknownErr
;
396 clientPort
= DNSServiceDiscoveryMachPort(ref
);
399 return kDNSServiceDiscoveryUnknownErr
;
402 result
= DNSServiceRegistrationUpdateRecord_rpc(serverPort
, clientPort
, (natural_t
)reference
, (record_data_t
)rdata
, rdlen
, ttl
);
403 if (result
!= KERN_SUCCESS
) {
404 printf("The result of the registration was not successful. Error %d, result %s\n", result
, mach_error_string(result
));
408 return kDNSServiceDiscoveryNoError
;
412 DNSServiceRegistrationReplyErrorType
DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref
, DNSRecordReference reference
)
414 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
415 mach_port_t clientPort
;
416 kern_return_t result
= KERN_SUCCESS
;
419 return kDNSServiceDiscoveryUnknownErr
;
422 clientPort
= DNSServiceDiscoveryMachPort(ref
);
425 return kDNSServiceDiscoveryUnknownErr
;
428 result
= DNSServiceRegistrationRemoveRecord_rpc(serverPort
, clientPort
, (natural_t
)reference
);
430 if (result
!= KERN_SUCCESS
) {
431 printf("The result of the registration was not successful. Error %d, result %s\n", result
, mach_error_string(result
));
435 return kDNSServiceDiscoveryNoError
;
438 void DNSServiceDiscovery_handleReply(void *replyMsg
)
440 unsigned long result
= 0xFFFFFFFF;
441 mach_msg_header_t
* msgSendBufPtr
;
442 mach_msg_header_t
* receivedMessage
;
443 unsigned msgSendBufLength
;
445 msgSendBufLength
= internal_DNSServiceDiscoveryReply_subsystem
.maxsize
;
446 msgSendBufPtr
= (mach_msg_header_t
*) malloc(msgSendBufLength
);
449 receivedMessage
= ( mach_msg_header_t
* ) replyMsg
;
451 // Call DNSServiceDiscoveryReply_server to change mig-generated message into a
452 // genuine mach message. It will then cause the callback to get called.
453 result
= DNSServiceDiscoveryReply_server ( receivedMessage
, msgSendBufPtr
);
454 ( void ) mach_msg_send ( msgSendBufPtr
);
458 mach_port_t
DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery
)
460 return dnsServiceDiscovery
->port
;
463 void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery
)
465 struct a_requests
*request0
, *request
;
466 mach_port_t reply
= dnsServiceDiscovery
->port
;
468 if (dnsServiceDiscovery
->port
) {
469 pthread_mutex_lock(&a_requests_lock
);
471 request
= a_requests
;
473 if (request
->client_port
== reply
) {
474 /* request info found, remove from list */
476 request0
->next
= request
->next
;
478 a_requests
= request
->next
;
482 /* not info for this request, skip to next */
484 request
= request
->next
;
488 pthread_mutex_unlock(&a_requests_lock
);
492 mach_port_destroy(mach_task_self(), dnsServiceDiscovery
->port
);
494 free(dnsServiceDiscovery
);
499 // reply functions, calls the users setup callbacks with function pointers
501 kern_return_t internal_DNSServiceDomainEnumerationReply_rpc
505 DNSCString replyDomain
,
506 DNSServiceDiscoveryReplyFlags flags
509 struct a_requests
*request
;
510 void *requestContext
= NULL
;
511 DNSServiceDomainEnumerationReply callback
= NULL
;
513 pthread_mutex_lock(&a_requests_lock
);
514 request
= a_requests
;
516 if (request
->client_port
== reply
) {
519 request
= request
->next
;
522 if (request
!= NULL
) {
523 callback
= (*request
->callout
.enumCallback
);
524 requestContext
= request
->context
;
526 pthread_mutex_unlock(&a_requests_lock
);
528 if (request
!= NULL
) {
529 (callback
)(resultType
, replyDomain
, flags
, requestContext
);
536 kern_return_t internal_DNSServiceBrowserReply_rpc
540 DNSCString replyName
,
541 DNSCString replyType
,
542 DNSCString replyDomain
,
543 DNSServiceDiscoveryReplyFlags flags
546 struct a_requests
*request
;
547 void *requestContext
= NULL
;
548 DNSServiceBrowserReply callback
= NULL
;
550 pthread_mutex_lock(&a_requests_lock
);
551 request
= a_requests
;
553 if (request
->client_port
== reply
) {
556 request
= request
->next
;
558 if (request
!= NULL
) {
559 callback
= (*request
->callout
.browserCallback
);
560 requestContext
= request
->context
;
563 pthread_mutex_unlock(&a_requests_lock
);
565 if (request
!= NULL
) {
566 (callback
)(resultType
, replyName
, replyType
, replyDomain
, flags
, requestContext
);
573 kern_return_t internal_DNSServiceRegistrationReply_rpc
579 struct a_requests
*request
;
580 void *requestContext
= NULL
;
581 DNSServiceRegistrationReply callback
= NULL
;
583 pthread_mutex_lock(&a_requests_lock
);
584 request
= a_requests
;
586 if (request
->client_port
== reply
) {
589 request
= request
->next
;
591 if (request
!= NULL
) {
592 callback
= (*request
->callout
.regCallback
);
593 requestContext
= request
->context
;
596 pthread_mutex_unlock(&a_requests_lock
);
597 if (request
!= NULL
) {
598 (callback
)(resultType
, requestContext
);
604 kern_return_t internal_DNSServiceResolverReply_rpc
607 sockaddr_t interface
,
609 DNSCString txtRecord
,
610 DNSServiceDiscoveryReplyFlags flags
613 struct sockaddr
*interface_storage
= NULL
;
614 struct sockaddr
*address_storage
= NULL
;
615 struct a_requests
*request
;
616 void *requestContext
= NULL
;
617 DNSServiceResolverReply callback
= NULL
;
620 int len
= ((struct sockaddr
*)interface
)->sa_len
;
621 interface_storage
= (struct sockaddr
*)malloc(len
);
622 bcopy(interface
, interface_storage
,len
);
626 int len
= ((struct sockaddr
*)address
)->sa_len
;
627 address_storage
= (struct sockaddr
*)malloc(len
);
628 bcopy(address
, address_storage
, len
);
631 pthread_mutex_lock(&a_requests_lock
);
632 request
= a_requests
;
634 if (request
->client_port
== reply
) {
637 request
= request
->next
;
640 if (request
!= NULL
) {
641 callback
= (*request
->callout
.resolveCallback
);
642 requestContext
= request
->context
;
644 pthread_mutex_unlock(&a_requests_lock
);
646 if (request
!= NULL
) {
647 (callback
)(interface_storage
, address_storage
, txtRecord
, flags
, requestContext
);
651 free(interface_storage
);
654 free(address_storage
);