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
;
282 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
283 if (result
!= KERN_SUCCESS
) {
284 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
287 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
288 if (result
!= KERN_SUCCESS
) {
289 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
290 mach_port_destroy(mach_task_self(), clientPort
);
293 _increaseQueueLengthOnPort(clientPort
);
295 return_t
= malloc(sizeof(dns_service_discovery_t
));
296 return_t
->port
= clientPort
;
298 request
= malloc(sizeof(struct a_requests
));
299 request
->client_port
= clientPort
;
300 request
->context
= context
;
301 request
->callout
.regCallback
= callBack
;
303 result
= DNSServiceRegistrationCreate_rpc(serverPort
, clientPort
, (char *)name
, (char *)regtype
, (char *)domain
, port
, (char *)txtRecord
);
305 if (result
!= KERN_SUCCESS
) {
306 printf("There was an error creating a resolve, %s\n", mach_error_string(result
));
311 pthread_mutex_lock(&a_requests_lock
);
312 request
->next
= a_requests
;
313 a_requests
= request
;
314 pthread_mutex_unlock(&a_requests_lock
);
319 /* Resolver requests */
321 dns_service_discovery_ref
DNSServiceResolverResolve(const char *name
, const char *regtype
, const char *domain
, DNSServiceResolverReply callBack
, void *context
)
323 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
324 mach_port_t clientPort
;
325 kern_return_t result
;
326 dns_service_discovery_ref return_t
;
327 struct a_requests
*request
;
333 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &clientPort
);
334 if (result
!= KERN_SUCCESS
) {
335 printf("Mach port receive creation failed, %s\n", mach_error_string(result
));
338 result
= mach_port_insert_right(mach_task_self(), clientPort
, clientPort
, MACH_MSG_TYPE_MAKE_SEND
);
339 if (result
!= KERN_SUCCESS
) {
340 printf("Mach port send creation failed, %s\n", mach_error_string(result
));
341 mach_port_destroy(mach_task_self(), clientPort
);
344 _increaseQueueLengthOnPort(clientPort
);
346 return_t
= malloc(sizeof(dns_service_discovery_t
));
347 return_t
->port
= clientPort
;
349 request
= malloc(sizeof(struct a_requests
));
350 request
->client_port
= clientPort
;
351 request
->context
= context
;
352 request
->callout
.resolveCallback
= callBack
;
354 DNSServiceResolverResolve_rpc(serverPort
, clientPort
, (char *)name
, (char *)regtype
, (char *)domain
);
356 pthread_mutex_lock(&a_requests_lock
);
357 request
->next
= a_requests
;
358 a_requests
= request
;
359 pthread_mutex_unlock(&a_requests_lock
);
364 DNSRecordReference
DNSServiceRegistrationAddRecord(dns_service_discovery_ref ref
, uint16_t rrtype
, uint16_t rdlen
, const char *rdata
, uint32_t ttl
)
366 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
367 mach_port_t clientPort
;
368 natural_t reference
= 0;
369 kern_return_t result
= KERN_SUCCESS
;
372 return kDNSServiceDiscoveryUnknownErr
;
375 clientPort
= DNSServiceDiscoveryMachPort(ref
);
378 return kDNSServiceDiscoveryUnknownErr
;
381 result
= DNSServiceRegistrationAddRecord_rpc(serverPort
, clientPort
, rrtype
, (record_data_t
)rdata
, rdlen
, ttl
, &reference
);
383 if (result
!= KERN_SUCCESS
) {
384 printf("The result of the registration was not successful. Error %d, result %s\n", result
, mach_error_string(result
));
390 DNSServiceRegistrationReplyErrorType
DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref
, DNSRecordReference reference
, uint16_t rdlen
, const char *rdata
, uint32_t ttl
)
392 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
393 mach_port_t clientPort
;
394 kern_return_t result
= KERN_SUCCESS
;
397 return kDNSServiceDiscoveryUnknownErr
;
400 clientPort
= DNSServiceDiscoveryMachPort(ref
);
403 return kDNSServiceDiscoveryUnknownErr
;
406 result
= DNSServiceRegistrationUpdateRecord_rpc(serverPort
, clientPort
, (natural_t
)reference
, (record_data_t
)rdata
, rdlen
, ttl
);
407 if (result
!= KERN_SUCCESS
) {
408 printf("The result of the registration was not successful. Error %d, result %s\n", result
, mach_error_string(result
));
412 return kDNSServiceDiscoveryNoError
;
416 DNSServiceRegistrationReplyErrorType
DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref
, DNSRecordReference reference
)
418 mach_port_t serverPort
= DNSServiceDiscoveryLookupServer();
419 mach_port_t clientPort
;
420 kern_return_t result
= KERN_SUCCESS
;
423 return kDNSServiceDiscoveryUnknownErr
;
426 clientPort
= DNSServiceDiscoveryMachPort(ref
);
429 return kDNSServiceDiscoveryUnknownErr
;
432 result
= DNSServiceRegistrationRemoveRecord_rpc(serverPort
, clientPort
, (natural_t
)reference
);
434 if (result
!= KERN_SUCCESS
) {
435 printf("The result of the registration was not successful. Error %d, result %s\n", result
, mach_error_string(result
));
439 return kDNSServiceDiscoveryNoError
;
442 void DNSServiceDiscovery_handleReply(void *replyMsg
)
444 unsigned long result
= 0xFFFFFFFF;
445 mach_msg_header_t
* msgSendBufPtr
;
446 mach_msg_header_t
* receivedMessage
;
447 unsigned msgSendBufLength
;
449 msgSendBufLength
= internal_DNSServiceDiscoveryReply_subsystem
.maxsize
;
450 msgSendBufPtr
= (mach_msg_header_t
*) malloc(msgSendBufLength
);
453 receivedMessage
= ( mach_msg_header_t
* ) replyMsg
;
455 // Call DNSServiceDiscoveryReply_server to change mig-generated message into a
456 // genuine mach message. It will then cause the callback to get called.
457 result
= DNSServiceDiscoveryReply_server ( receivedMessage
, msgSendBufPtr
);
458 ( void ) mach_msg_send ( msgSendBufPtr
);
462 mach_port_t
DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery
)
464 return dnsServiceDiscovery
->port
;
467 void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery
)
469 struct a_requests
*request0
, *request
;
470 mach_port_t reply
= dnsServiceDiscovery
->port
;
472 if (dnsServiceDiscovery
->port
) {
473 pthread_mutex_lock(&a_requests_lock
);
475 request
= a_requests
;
477 if (request
->client_port
== reply
) {
478 /* request info found, remove from list */
480 request0
->next
= request
->next
;
482 a_requests
= request
->next
;
486 /* not info for this request, skip to next */
488 request
= request
->next
;
492 pthread_mutex_unlock(&a_requests_lock
);
496 mach_port_destroy(mach_task_self(), dnsServiceDiscovery
->port
);
498 free(dnsServiceDiscovery
);
503 // reply functions, calls the users setup callbacks with function pointers
505 kern_return_t internal_DNSServiceDomainEnumerationReply_rpc
509 DNSCString replyDomain
,
510 DNSServiceDiscoveryReplyFlags flags
513 struct a_requests
*request
;
514 void *requestContext
= NULL
;
515 DNSServiceDomainEnumerationReply callback
= NULL
;
517 pthread_mutex_lock(&a_requests_lock
);
518 request
= a_requests
;
520 if (request
->client_port
== reply
) {
523 request
= request
->next
;
526 if (request
!= NULL
) {
527 callback
= (*request
->callout
.enumCallback
);
528 requestContext
= request
->context
;
530 pthread_mutex_unlock(&a_requests_lock
);
532 if (request
!= NULL
) {
533 (callback
)(resultType
, replyDomain
, flags
, requestContext
);
540 kern_return_t internal_DNSServiceBrowserReply_rpc
544 DNSCString replyName
,
545 DNSCString replyType
,
546 DNSCString replyDomain
,
547 DNSServiceDiscoveryReplyFlags flags
550 struct a_requests
*request
;
551 void *requestContext
= NULL
;
552 DNSServiceBrowserReply callback
= NULL
;
554 pthread_mutex_lock(&a_requests_lock
);
555 request
= a_requests
;
557 if (request
->client_port
== reply
) {
560 request
= request
->next
;
562 if (request
!= NULL
) {
563 callback
= (*request
->callout
.browserCallback
);
564 requestContext
= request
->context
;
567 pthread_mutex_unlock(&a_requests_lock
);
569 if (request
!= NULL
) {
570 (callback
)(resultType
, replyName
, replyType
, replyDomain
, flags
, requestContext
);
577 kern_return_t internal_DNSServiceRegistrationReply_rpc
583 struct a_requests
*request
;
584 void *requestContext
= NULL
;
585 DNSServiceRegistrationReply callback
= NULL
;
587 pthread_mutex_lock(&a_requests_lock
);
588 request
= a_requests
;
590 if (request
->client_port
== reply
) {
593 request
= request
->next
;
595 if (request
!= NULL
) {
596 callback
= (*request
->callout
.regCallback
);
597 requestContext
= request
->context
;
600 pthread_mutex_unlock(&a_requests_lock
);
601 if (request
!= NULL
) {
602 (callback
)(resultType
, requestContext
);
608 kern_return_t internal_DNSServiceResolverReply_rpc
611 sockaddr_t interface
,
613 DNSCString txtRecord
,
614 DNSServiceDiscoveryReplyFlags flags
617 struct sockaddr
*interface_storage
= NULL
;
618 struct sockaddr
*address_storage
= NULL
;
619 struct a_requests
*request
;
620 void *requestContext
= NULL
;
621 DNSServiceResolverReply callback
= NULL
;
624 int len
= ((struct sockaddr
*)interface
)->sa_len
;
625 interface_storage
= (struct sockaddr
*)malloc(len
);
626 bcopy(interface
, interface_storage
,len
);
630 int len
= ((struct sockaddr
*)address
)->sa_len
;
631 address_storage
= (struct sockaddr
*)malloc(len
);
632 bcopy(address
, address_storage
, len
);
635 pthread_mutex_lock(&a_requests_lock
);
636 request
= a_requests
;
638 if (request
->client_port
== reply
) {
641 request
= request
->next
;
644 if (request
!= NULL
) {
645 callback
= (*request
->callout
.resolveCallback
);
646 requestContext
= request
->context
;
648 pthread_mutex_unlock(&a_requests_lock
);
650 if (request
!= NULL
) {
651 (callback
)(interface_storage
, address_storage
, txtRecord
, flags
, requestContext
);
655 free(interface_storage
);
658 free(address_storage
);