summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-01-30 13:52:13 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-01-30 16:23:04 +0100
commit9449f151d0ccf3ac755d5f2bd9b4057ae2b03157 (patch)
treeada21dc6aa0b146c62a7561a08fb51fe4a8922ee /mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c
parentDHCPCD(8): Add MASTER_ONLY option (diff)
downloadrtems-libbsd-9449f151d0ccf3ac755d5f2bd9b4057ae2b03157.tar.bz2
mDNS: Import
The sources can be obtained via: http://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-544.tar.gz
Diffstat (limited to 'mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c')
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c674
1 files changed, 674 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c
new file mode 100644
index 00000000..717efca2
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c
@@ -0,0 +1,674 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Suppress "warning: 'DNSServiceDiscoveryMachPort' is deprecated" messages -- we already know this code is building the deprecated API
+// Since we compile with all warnings treated as errors, we have to turn off the warnings here or the project won't compile
+#include <AvailabilityMacros.h>
+#undef AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED
+#define AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED
+#undef AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3
+#define AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3
+
+#include "../mDNSMacOSX/DNSServiceDiscovery.h"
+#include "DNSServiceDiscoveryDefines.h"
+#include "DNSServiceDiscoveryReplyServer.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <servers/bootstrap.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <pthread.h>
+
+#include <netinet/in.h>
+
+extern boolean_t DNSServiceDiscoveryReply_server(
+ mach_msg_header_t *InHeadP,
+ mach_msg_header_t *OutHeadP);
+
+extern
+kern_return_t DNSServiceBrowserCreate_rpc
+(
+ mach_port_t server,
+ mach_port_t client,
+ DNSCString regtype,
+ DNSCString domain
+);
+
+extern
+kern_return_t DNSServiceDomainEnumerationCreate_rpc
+(
+ mach_port_t server,
+ mach_port_t client,
+ int registrationDomains
+);
+
+extern
+kern_return_t DNSServiceRegistrationCreate_rpc
+(
+ mach_port_t server,
+ mach_port_t client,
+ DNSCString name,
+ DNSCString regtype,
+ DNSCString domain,
+ IPPort port,
+ DNSCString txtRecord
+);
+
+extern
+kern_return_t DNSServiceResolverResolve_rpc
+(
+ mach_port_t server,
+ mach_port_t client,
+ DNSCString name,
+ DNSCString regtype,
+ DNSCString domain
+);
+
+extern
+kern_return_t DNSServiceRegistrationAddRecord_rpc
+(
+ mach_port_t server,
+ mach_port_t client,
+ int type,
+ record_data_t data,
+ mach_msg_type_number_t record_dataCnt,
+ uint32_t ttl,
+ natural_t *reference
+);
+
+extern
+int DNSServiceRegistrationUpdateRecord_rpc
+(
+ mach_port_t server,
+ mach_port_t client,
+ natural_t reference,
+ record_data_t data,
+ mach_msg_type_number_t record_dataCnt,
+ uint32_t ttl
+);
+
+extern
+kern_return_t DNSServiceRegistrationRemoveRecord_rpc
+(
+ mach_port_t server,
+ mach_port_t client,
+ natural_t reference
+);
+
+struct a_requests {
+ struct a_requests *next;
+ mach_port_t client_port;
+ union {
+ DNSServiceBrowserReply browserCallback;
+ DNSServiceDomainEnumerationReply enumCallback;
+ DNSServiceRegistrationReply regCallback;
+ DNSServiceResolverReply resolveCallback;
+ } callout;
+ void *context;
+};
+
+static struct a_requests *a_requests = NULL;
+static pthread_mutex_t a_requests_lock = PTHREAD_MUTEX_INITIALIZER;
+
+typedef struct _dns_service_discovery_t {
+ mach_port_t port;
+} dns_service_discovery_t;
+
+static mach_port_t DNSServiceDiscoveryLookupServer(void)
+{
+ static mach_port_t sndPort = MACH_PORT_NULL;
+ kern_return_t result;
+
+ if (sndPort != MACH_PORT_NULL) {
+ return sndPort;
+ }
+
+ result = bootstrap_look_up(bootstrap_port, DNS_SERVICE_DISCOVERY_SERVER, &sndPort);
+ if (result != KERN_SUCCESS) {
+ printf("%s(): {%s:%d} bootstrap_look_up() failed: $%x\n", __FUNCTION__, __FILE__, __LINE__, (int) result);
+ sndPort = MACH_PORT_NULL;
+ }
+
+
+ return sndPort;
+}
+
+static void _increaseQueueLengthOnPort(mach_port_t port)
+{
+ mach_port_limits_t qlimits;
+ kern_return_t result;
+
+ qlimits.mpl_qlimit = 16;
+ result = mach_port_set_attributes(mach_task_self(), port, MACH_PORT_LIMITS_INFO, (mach_port_info_t)&qlimits, MACH_PORT_LIMITS_INFO_COUNT);
+
+ if (result != KERN_SUCCESS) {
+ printf("%s(): {%s:%d} mach_port_set_attributes() failed: $%x %s\n", __FUNCTION__, __FILE__, __LINE__, (int) result, mach_error_string(result));
+ }
+}
+
+dns_service_discovery_ref DNSServiceBrowserCreate (const char *regtype, const char *domain, DNSServiceBrowserReply callBack,void *context)
+{
+ mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+ mach_port_t clientPort;
+ kern_return_t result;
+ dns_service_discovery_ref return_t;
+ struct a_requests *request;
+
+ if (!serverPort) {
+ return NULL;
+ }
+
+ result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
+ if (result != KERN_SUCCESS) {
+ printf("Mach port receive creation failed, %s\n", mach_error_string(result));
+ return NULL;
+ }
+ result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
+ if (result != KERN_SUCCESS) {
+ printf("Mach port send creation failed, %s\n", mach_error_string(result));
+ mach_port_destroy(mach_task_self(), clientPort);
+ return NULL;
+ }
+ _increaseQueueLengthOnPort(clientPort);
+
+ return_t = malloc(sizeof(dns_service_discovery_t));
+ return_t->port = clientPort;
+
+ request = malloc(sizeof(struct a_requests));
+ request->client_port = clientPort;
+ request->context = context;
+ request->callout.browserCallback = callBack;
+
+ result = DNSServiceBrowserCreate_rpc(serverPort, clientPort, (char *)regtype, (char *)domain);
+
+ if (result != KERN_SUCCESS) {
+ printf("There was an error creating a browser, %s\n", mach_error_string(result));
+ free(request);
+ return NULL;
+ }
+
+ pthread_mutex_lock(&a_requests_lock);
+ request->next = a_requests;
+ a_requests = request;
+ pthread_mutex_unlock(&a_requests_lock);
+
+ return return_t;
+}
+
+/* Service Enumeration */
+
+dns_service_discovery_ref DNSServiceDomainEnumerationCreate (int registrationDomains, DNSServiceDomainEnumerationReply callBack, void *context)
+{
+ mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+ mach_port_t clientPort;
+ kern_return_t result;
+ dns_service_discovery_ref return_t;
+ struct a_requests *request;
+
+ if (!serverPort) {
+ return NULL;
+ }
+
+ result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
+ if (result != KERN_SUCCESS) {
+ printf("Mach port receive creation failed, %s\n", mach_error_string(result));
+ return NULL;
+ }
+ result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
+ if (result != KERN_SUCCESS) {
+ printf("Mach port send creation failed, %s\n", mach_error_string(result));
+ mach_port_destroy(mach_task_self(), clientPort);
+ return NULL;
+ }
+ _increaseQueueLengthOnPort(clientPort);
+
+ return_t = malloc(sizeof(dns_service_discovery_t));
+ return_t->port = clientPort;
+
+ request = malloc(sizeof(struct a_requests));
+ request->client_port = clientPort;
+ request->context = context;
+ request->callout.enumCallback = callBack;
+
+ result = DNSServiceDomainEnumerationCreate_rpc(serverPort, clientPort, registrationDomains);
+
+ if (result != KERN_SUCCESS) {
+ printf("There was an error creating an enumerator, %s\n", mach_error_string(result));
+ free(request);
+ return NULL;
+ }
+
+ pthread_mutex_lock(&a_requests_lock);
+ request->next = a_requests;
+ a_requests = request;
+ pthread_mutex_unlock(&a_requests_lock);
+
+ return return_t;
+}
+
+
+/* Service Registration */
+
+dns_service_discovery_ref DNSServiceRegistrationCreate
+ (const char *name, const char *regtype, const char *domain, uint16_t port, const char *txtRecord, DNSServiceRegistrationReply callBack, void *context)
+{
+ mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+ mach_port_t clientPort;
+ kern_return_t result;
+ dns_service_discovery_ref return_t;
+ struct a_requests *request;
+ IPPort IpPort;
+ char *portptr = (char *)&port;
+
+ if (!serverPort) {
+ return NULL;
+ }
+
+ if (!txtRecord) {
+ txtRecord = "";
+ }
+
+ result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
+ if (result != KERN_SUCCESS) {
+ printf("Mach port receive creation failed, %s\n", mach_error_string(result));
+ return NULL;
+ }
+ result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
+ if (result != KERN_SUCCESS) {
+ printf("Mach port send creation failed, %s\n", mach_error_string(result));
+ mach_port_destroy(mach_task_self(), clientPort);
+ return NULL;
+ }
+ _increaseQueueLengthOnPort(clientPort);
+
+ return_t = malloc(sizeof(dns_service_discovery_t));
+ return_t->port = clientPort;
+
+ request = malloc(sizeof(struct a_requests));
+ request->client_port = clientPort;
+ request->context = context;
+ request->callout.regCallback = callBack;
+
+ // older versions of this code passed the port via mach IPC as an int.
+ // we continue to pass it as 4 bytes to maintain binary compatibility,
+ // but now ensure that the network byte order is preserved by using a struct
+ IpPort.bytes[0] = 0;
+ IpPort.bytes[1] = 0;
+ IpPort.bytes[2] = portptr[0];
+ IpPort.bytes[3] = portptr[1];
+
+ result = DNSServiceRegistrationCreate_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain, IpPort, (char *)txtRecord);
+
+ if (result != KERN_SUCCESS) {
+ printf("There was an error creating a resolve, %s\n", mach_error_string(result));
+ free(request);
+ return NULL;
+ }
+
+ pthread_mutex_lock(&a_requests_lock);
+ request->next = a_requests;
+ a_requests = request;
+ pthread_mutex_unlock(&a_requests_lock);
+
+ return return_t;
+}
+
+/* Resolver requests */
+
+dns_service_discovery_ref DNSServiceResolverResolve(const char *name, const char *regtype, const char *domain, DNSServiceResolverReply callBack, void *context)
+{
+ mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+ mach_port_t clientPort;
+ kern_return_t result;
+ dns_service_discovery_ref return_t;
+ struct a_requests *request;
+
+ if (!serverPort) {
+ return NULL;
+ }
+
+ result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
+ if (result != KERN_SUCCESS) {
+ printf("Mach port receive creation failed, %s\n", mach_error_string(result));
+ return NULL;
+ }
+ result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
+ if (result != KERN_SUCCESS) {
+ printf("Mach port send creation failed, %s\n", mach_error_string(result));
+ mach_port_destroy(mach_task_self(), clientPort);
+ return NULL;
+ }
+ _increaseQueueLengthOnPort(clientPort);
+
+ return_t = malloc(sizeof(dns_service_discovery_t));
+ return_t->port = clientPort;
+
+ request = malloc(sizeof(struct a_requests));
+ request->client_port = clientPort;
+ request->context = context;
+ request->callout.resolveCallback = callBack;
+
+ DNSServiceResolverResolve_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain);
+
+ pthread_mutex_lock(&a_requests_lock);
+ request->next = a_requests;
+ a_requests = request;
+ pthread_mutex_unlock(&a_requests_lock);
+
+ return return_t;
+}
+
+DNSRecordReference DNSServiceRegistrationAddRecord(dns_service_discovery_ref ref, uint16_t rrtype, uint16_t rdlen, const char *rdata, uint32_t ttl)
+{
+ mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+ mach_port_t clientPort;
+ natural_t reference = 0;
+ kern_return_t result = KERN_SUCCESS;
+
+ if (!serverPort) {
+ return kDNSServiceDiscoveryUnknownErr;
+ }
+
+ clientPort = DNSServiceDiscoveryMachPort(ref);
+
+ if (!clientPort) {
+ return kDNSServiceDiscoveryUnknownErr;
+ }
+
+ result = DNSServiceRegistrationAddRecord_rpc(serverPort, clientPort, rrtype, (record_data_t)rdata, rdlen, ttl, &reference);
+
+ if (result != KERN_SUCCESS) {
+ printf("The result of the registration was not successful. Error %d, result %s\n", result, mach_error_string(result));
+ }
+
+ return reference;
+}
+
+DNSServiceRegistrationReplyErrorType DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref, DNSRecordReference reference, uint16_t rdlen, const char *rdata, uint32_t ttl)
+{
+ mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+ mach_port_t clientPort;
+ kern_return_t result = KERN_SUCCESS;
+
+ if (!serverPort) {
+ return kDNSServiceDiscoveryUnknownErr;
+ }
+
+ clientPort = DNSServiceDiscoveryMachPort(ref);
+
+ if (!clientPort) {
+ return kDNSServiceDiscoveryUnknownErr;
+ }
+
+ result = DNSServiceRegistrationUpdateRecord_rpc(serverPort, clientPort, (natural_t)reference, (record_data_t)rdata, rdlen, ttl);
+ if (result != KERN_SUCCESS) {
+ printf("The result of the registration was not successful. Error %d, result %s\n", result, mach_error_string(result));
+ return result;
+ }
+
+ return kDNSServiceDiscoveryNoError;
+}
+
+
+DNSServiceRegistrationReplyErrorType DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref, DNSRecordReference reference)
+{
+ mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+ mach_port_t clientPort;
+ kern_return_t result = KERN_SUCCESS;
+
+ if (!serverPort) {
+ return kDNSServiceDiscoveryUnknownErr;
+ }
+
+ clientPort = DNSServiceDiscoveryMachPort(ref);
+
+ if (!clientPort) {
+ return kDNSServiceDiscoveryUnknownErr;
+ }
+
+ result = DNSServiceRegistrationRemoveRecord_rpc(serverPort, clientPort, (natural_t)reference);
+
+ if (result != KERN_SUCCESS) {
+ printf("The result of the registration was not successful. Error %d, result %s\n", result, mach_error_string(result));
+ return result;
+ }
+
+ return kDNSServiceDiscoveryNoError;
+}
+
+void DNSServiceDiscovery_handleReply(void *replyMsg)
+{
+ unsigned long result = 0xFFFFFFFF;
+ mach_msg_header_t * msgSendBufPtr;
+ mach_msg_header_t * receivedMessage;
+ unsigned msgSendBufLength;
+
+ msgSendBufLength = internal_DNSServiceDiscoveryReply_subsystem.maxsize;
+ msgSendBufPtr = (mach_msg_header_t *) malloc(msgSendBufLength);
+
+
+ receivedMessage = ( mach_msg_header_t * ) replyMsg;
+
+ // Call DNSServiceDiscoveryReply_server to change mig-generated message into a
+ // genuine mach message. It will then cause the callback to get called.
+ result = DNSServiceDiscoveryReply_server ( receivedMessage, msgSendBufPtr );
+ ( void ) mach_msg_send ( msgSendBufPtr );
+ free(msgSendBufPtr);
+}
+
+mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery)
+{
+ return dnsServiceDiscovery->port;
+}
+
+void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery)
+{
+ struct a_requests *request0, *request;
+ mach_port_t reply = dnsServiceDiscovery->port;
+
+ if (dnsServiceDiscovery->port) {
+ pthread_mutex_lock(&a_requests_lock);
+ request0 = NULL;
+ request = a_requests;
+ while (request) {
+ if (request->client_port == reply) {
+ /* request info found, remove from list */
+ if (request0) {
+ request0->next = request->next;
+ } else {
+ a_requests = request->next;
+ }
+ break;
+ } else {
+ /* not info for this request, skip to next */
+ request0 = request;
+ request = request->next;
+ }
+
+ }
+ pthread_mutex_unlock(&a_requests_lock);
+
+ free(request);
+
+ mach_port_destroy(mach_task_self(), dnsServiceDiscovery->port);
+
+ free(dnsServiceDiscovery);
+ }
+ return;
+}
+
+// reply functions, calls the users setup callbacks with function pointers
+
+kern_return_t internal_DNSServiceDomainEnumerationReply_rpc
+(
+ mach_port_t reply,
+ int resultType,
+ DNSCString replyDomain,
+ int flags
+)
+{
+ struct a_requests *request;
+ void *requestContext = NULL;
+ DNSServiceDomainEnumerationReply callback = NULL;
+
+ pthread_mutex_lock(&a_requests_lock);
+ request = a_requests;
+ while (request) {
+ if (request->client_port == reply) {
+ break;
+ }
+ request = request->next;
+ }
+
+ if (request != NULL) {
+ callback = (*request->callout.enumCallback);
+ requestContext = request->context;
+ }
+ pthread_mutex_unlock(&a_requests_lock);
+
+ if (request != NULL) {
+ (callback)(resultType, replyDomain, flags, requestContext);
+ }
+
+ return KERN_SUCCESS;
+
+}
+
+kern_return_t internal_DNSServiceBrowserReply_rpc
+(
+ mach_port_t reply,
+ int resultType,
+ DNSCString replyName,
+ DNSCString replyType,
+ DNSCString replyDomain,
+ int flags
+)
+{
+ struct a_requests *request;
+ void *requestContext = NULL;
+ DNSServiceBrowserReply callback = NULL;
+
+ pthread_mutex_lock(&a_requests_lock);
+ request = a_requests;
+ while (request) {
+ if (request->client_port == reply) {
+ break;
+ }
+ request = request->next;
+ }
+ if (request != NULL) {
+ callback = (*request->callout.browserCallback);
+ requestContext = request->context;
+ }
+
+ pthread_mutex_unlock(&a_requests_lock);
+
+ if (request != NULL) {
+ (callback)(resultType, replyName, replyType, replyDomain, flags, requestContext);
+ }
+
+ return KERN_SUCCESS;
+}
+
+
+kern_return_t internal_DNSServiceRegistrationReply_rpc
+(
+ mach_port_t reply,
+ int resultType
+)
+{
+ struct a_requests *request;
+ void *requestContext = NULL;
+ DNSServiceRegistrationReply callback = NULL;
+
+ pthread_mutex_lock(&a_requests_lock);
+ request = a_requests;
+ while (request) {
+ if (request->client_port == reply) {
+ break;
+ }
+ request = request->next;
+ }
+ if (request != NULL) {
+ callback = (*request->callout.regCallback);
+ requestContext = request->context;
+ }
+
+ pthread_mutex_unlock(&a_requests_lock);
+ if (request != NULL) {
+ (callback)(resultType, requestContext);
+ }
+ return KERN_SUCCESS;
+}
+
+
+kern_return_t internal_DNSServiceResolverReply_rpc
+(
+ mach_port_t reply,
+ sockaddr_t interface,
+ sockaddr_t address,
+ DNSCString txtRecord,
+ int flags
+)
+{
+ struct sockaddr *interface_storage = NULL;
+ struct sockaddr *address_storage = NULL;
+ struct a_requests *request;
+ void *requestContext = NULL;
+ DNSServiceResolverReply callback = NULL;
+
+ if (interface) {
+ int len = ((struct sockaddr *)interface)->sa_len;
+ interface_storage = (struct sockaddr *)malloc(len);
+ memcpy(interface_storage, interface, len);
+ }
+
+ if (address) {
+ int len = ((struct sockaddr *)address)->sa_len;
+ address_storage = (struct sockaddr *)malloc(len);
+ memcpy(address_storage, address, len);
+ }
+
+ pthread_mutex_lock(&a_requests_lock);
+ request = a_requests;
+ while (request) {
+ if (request->client_port == reply) {
+ break;
+ }
+ request = request->next;
+ }
+
+ if (request != NULL) {
+ callback = (*request->callout.resolveCallback);
+ requestContext = request->context;
+ }
+ pthread_mutex_unlock(&a_requests_lock);
+
+ if (request != NULL) {
+ (callback)(interface_storage, address_storage, txtRecord, flags, requestContext);
+ }
+
+ if (interface) {
+ free(interface_storage);
+ }
+ if (address) {
+ free(address_storage);
+ }
+
+ return KERN_SUCCESS;
+}