summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSMacOSX/Private/dns_services.c
diff options
context:
space:
mode:
Diffstat (limited to 'mDNSResponder/mDNSMacOSX/Private/dns_services.c')
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/dns_services.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_services.c b/mDNSResponder/mDNSMacOSX/Private/dns_services.c
new file mode 100644
index 00000000..d0e9e6ca
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/Private/dns_services.c
@@ -0,0 +1,212 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2012 Apple Inc. All rights reserved.
+ *
+ * PRIVATE DNSX CLIENT LIBRARY --FOR Apple Platforms ONLY OSX/iOS--
+ * Resides in /usr/lib/libdns_services.dylib
+ */
+
+#include "dns_services.h"
+#include "dns_xpc.h"
+#include <xpc/xpc.h>
+#include <Block.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+//*************************************************************************************************************
+// Globals
+
+#define connection_t xpc_connection_t
+
+struct _DNSXConnRef_t
+{
+ connection_t conn_ref; // xpc_connection between client and daemon
+ dispatch_queue_t lib_q; // internal queue created in library itself
+ void *AppCallBack; // Callback function ptr for Client
+ dispatch_queue_t client_q; // Queue specified by client for scheduling its Callback
+};
+
+//*************************************************************************************************************
+// Utility Functions
+
+static bool LogDebugEnabled()
+{
+ return false;
+}
+
+static void LogDebug(const char *prefix, xpc_object_t o)
+{
+ if (!LogDebugEnabled())
+ return;
+
+ char *desc = xpc_copy_description(o);
+ syslog(LOG_INFO, "%s: %s", prefix, desc);
+ free(desc);
+}
+
+//**************************************************************************************************************
+
+void DNSXRefDeAlloc(DNSXConnRef connRef)
+{
+ if (!connRef)
+ {
+ syslog(LOG_WARNING, "dns_services: DNSXRefDeAlloc called with NULL DNSXConnRef");
+ return;
+ }
+
+ // Schedule this work on the internal library queue
+ dispatch_sync(connRef->lib_q, ^{
+
+ xpc_release(connRef->conn_ref);
+ connRef->AppCallBack = NULL;
+ dispatch_release(connRef->client_q);
+
+ });
+
+ dispatch_release(connRef->lib_q);
+ free(connRef);
+
+ syslog(LOG_INFO, "dns_services: DNSXRefDeAlloc successfully DeAllocated connRef");
+
+}
+
+// Sends the Msg(Dictionary) to the Server
+static DNSXErrorType SendMsgToServer(DNSXConnRef *connRef, xpc_object_t msg, bool old_conn)
+{
+ DNSXErrorType errx = kDNSX_NoError;
+
+ LogDebug("dns_services: SendMsgToServer", msg);
+
+ xpc_connection_set_event_handler((*connRef)->conn_ref, ^(xpc_object_t recv_msg)
+ {
+ xpc_type_t type = xpc_get_type(recv_msg);
+
+ if (type == XPC_TYPE_DICTIONARY)
+ {
+ LogDebug("dns_services: SendMsgToServer SUCCESS CALLBACK FROM SERVER", recv_msg);
+ syslog(LOG_INFO, "dns_services: Successfully Sent Msg to the Daemon");
+ uint64_t daemon_status = xpc_dictionary_get_uint64(recv_msg, kDNSDaemonReply);
+
+ // Schedule the AppCallBacks on the Client Specified Queue
+ switch (daemon_status)
+ {
+ case kDNSDaemonEngaged:
+ dispatch_async((*connRef)->client_q, ^{
+ ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_Engaged);
+ });
+ break;
+ case kDNSMsgReceived:
+ dispatch_async((*connRef)->client_q, ^{
+ ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_NoError);
+ });
+ break;
+ default:
+ dispatch_async((*connRef)->client_q, ^{
+ ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_UnknownErr);
+ });
+ break;
+ }
+
+ }
+ else
+ {
+ LogDebug("dns_services: SendMsgToServer UNEXPECTED CALLBACK FROM SERVER", recv_msg);
+ syslog(LOG_WARNING, "dns_services: Connection failed since NO privileges to access service OR Daemon NOT Running");
+ dispatch_async((*connRef)->client_q, ^{
+ ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_DaemonNotRunning);
+ });
+ }
+ });
+
+ // To prevent Over-Resume of a connection
+ if (!old_conn)
+ xpc_connection_resume((*connRef)->conn_ref);
+ xpc_connection_send_message((*connRef)->conn_ref, msg);
+ if (!errx)
+ syslog(LOG_INFO, "dns_services: SendMSgToServer sent Msg Dict successfully to Daemon");
+ return errx;
+}
+
+// Creates a new DNSX Connection Reference(DNSXConnRef).
+// If DNSXConnRef exists, you may want to use that depending on the use case
+static DNSXErrorType InitConnection(DNSXConnRef *connRef, const char *servname, dispatch_queue_t clientq, void *AppCallBack)
+{
+ if (!connRef)
+ {
+ syslog(LOG_WARNING, "dns_services: InitConnection() called with NULL DNSXConnRef");
+ return kDNSX_BadParam;
+ }
+
+ *connRef = malloc(sizeof(struct _DNSXConnRef_t));
+ if (!(*connRef))
+ {
+ syslog(LOG_WARNING, "dns_services: InitConnection() No memory to allocate");
+ return kDNSX_NoMem;
+ }
+
+ // Initialize the DNSXConnRef
+ dispatch_retain(clientq);
+ (*connRef)->client_q = clientq;
+ (*connRef)->AppCallBack = AppCallBack;
+ (*connRef)->lib_q = dispatch_queue_create("com.apple.mDNSResponder.libdns_services.q", NULL);
+ (*connRef)->conn_ref = xpc_connection_create_mach_service(servname, (*connRef)->lib_q, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
+
+ syslog(LOG_INFO, "dns_services: InitConnection() successfully create a new DNSXConnRef");
+ return kDNSX_NoError;
+}
+
+DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxyparam, IfIndex inIfindexArr[MaxInputIf],
+ IfIndex outIfindex, dispatch_queue_t clientq, DNSXEnableProxyReply callBack)
+{
+
+ DNSXErrorType errx = kDNSX_NoError;
+ bool old_conn = false;
+
+ // Sanity Checks
+ if (!connRef || !callBack || !clientq)
+ {
+ syslog(LOG_WARNING, "dns_services: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter");
+ return kDNSX_BadParam;
+ }
+
+ // If no connRef, get it from InitConnection()
+ if (!*connRef)
+ {
+ errx = InitConnection(connRef, kDNSProxyService, clientq, callBack);
+ if (errx) // On error InitConnection() leaves *connRef set to NULL
+ {
+ syslog(LOG_WARNING, "dns_services: Since InitConnection() returned %d error returning w/o sending msg", errx);
+ return errx;
+ }
+ }
+ else // Client already has a valid connRef
+ {
+ old_conn = true;
+ }
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ if (!dict)
+ {
+ syslog(LOG_WARNING, "dns_services: DNSXEnableProxy could not create the Msg Dict To Send!");
+ DNSXRefDeAlloc(*connRef);
+ return kDNSX_DictError;
+ }
+
+ xpc_dictionary_set_uint64(dict, kDNSProxyParameters, proxyparam);
+
+ xpc_dictionary_set_uint64(dict, kDNSInIfindex0, inIfindexArr[0]);
+ xpc_dictionary_set_uint64(dict, kDNSInIfindex1, inIfindexArr[1]);
+ xpc_dictionary_set_uint64(dict, kDNSInIfindex2, inIfindexArr[2]);
+ xpc_dictionary_set_uint64(dict, kDNSInIfindex3, inIfindexArr[3]);
+ xpc_dictionary_set_uint64(dict, kDNSInIfindex4, inIfindexArr[4]);
+
+ xpc_dictionary_set_uint64(dict, kDNSOutIfindex, outIfindex);
+
+ errx = SendMsgToServer(connRef, dict, old_conn);
+ xpc_release(dict);
+
+ return errx;
+}
+