summaryrefslogtreecommitdiff
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.c245
1 files changed, 141 insertions, 104 deletions
diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_services.c b/mDNSResponder/mDNSMacOSX/Private/dns_services.c
index 1df3b21d..794e2526 100644
--- a/mDNSResponder/mDNSMacOSX/Private/dns_services.c
+++ b/mDNSResponder/mDNSMacOSX/Private/dns_services.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
- * Copyright (c) 2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2012-2015 Apple Inc. All rights reserved.
*
* PRIVATE DNSX CLIENT LIBRARY --FOR Apple Platforms ONLY OSX/iOS--
* Resides in /usr/lib/libdns_services.dylib
@@ -10,10 +10,10 @@
#include "dns_xpc.h"
#include <xpc/xpc.h>
#include <Block.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <syslog.h>
+#define LOG_NOW LOG_INFO
+
//*************************************************************************************************************
// Globals
@@ -22,7 +22,7 @@
struct _DNSXConnRef_t
{
connection_t conn_ref; // xpc_connection between client and daemon
- dispatch_queue_t lib_q; // internal queue created in library itself
+ 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
};
@@ -37,11 +37,11 @@ static bool LogDebugEnabled()
static void LogDebug(const char *prefix, xpc_object_t o)
{
- if (!LogDebugEnabled())
+ if (!LogDebugEnabled())
return;
char *desc = xpc_copy_description(o);
- syslog(LOG_INFO, "%s: %s", prefix, desc);
+ syslog(LOG_NOW, "%s: %s", prefix, desc);
free(desc);
}
@@ -49,164 +49,201 @@ static void LogDebug(const char *prefix, xpc_object_t o)
void DNSXRefDeAlloc(DNSXConnRef connRef)
{
- if (!connRef)
+ if (connRef == NULL)
{
- syslog(LOG_WARNING, "dns_services: DNSXRefDeAlloc called with NULL DNSXConnRef");
+ syslog(LOG_WARNING, "dns_services DD: DNSXRefDeAlloc called with NULL DNSXConnRef");
return;
}
-
+
// Schedule this work on the internal library queue
dispatch_sync(connRef->lib_q, ^{
-
+ xpc_connection_set_event_handler((connRef)->conn_ref, ^(__unused xpc_object_t event){}); // ignore any more events
xpc_release(connRef->conn_ref);
+ connRef->conn_ref = NULL;
+ dispatch_release(connRef->lib_q);
+ connRef->lib_q = NULL;
connRef->AppCallBack = NULL;
- dispatch_release(connRef->client_q);
-
+ syslog(LOG_NOW, "dns_services DD: DNSXRefDeAlloc successfully DeAllocated conn_ref & lib_q");
+
+ dispatch_async((connRef)->client_q, ^{
+ dispatch_release(connRef->client_q);
+ connRef->client_q = NULL;
+ free(connRef);
+ syslog(LOG_NOW, "dns_services DD: DNSXRefDeAlloc successfully DeAllocated client_q & freed connRef");
+ });
});
-
- dispatch_release(connRef->lib_q);
- free(connRef);
-
- syslog(LOG_INFO, "dns_services: DNSXRefDeAlloc successfully DeAllocated connRef");
-
+
+ // DO NOT reference connRef after this comment, as it may have been freed
+ syslog(LOG_NOW, "dns_services DD: DNSXRefDeAlloc successfully DeAllocated connRef");
+
}
-// Sends the Msg(Dictionary) to the Server
-static DNSXErrorType SendMsgToServer(DNSXConnRef *connRef, xpc_object_t msg, bool old_conn)
+// Sends the Msg(Dictionary) to the Server Daemon
+static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg)
{
DNSXErrorType errx = kDNSX_NoError;
-
- LogDebug("dns_services: SendMsgToServer", msg);
- xpc_connection_set_event_handler((*connRef)->conn_ref, ^(xpc_object_t recv_msg)
+ LogDebug("dns_services DD: SendMsgToServer Sending msg to Daemon", msg);
+
+ xpc_connection_send_message_with_reply((connRef)->conn_ref, msg, (connRef)->lib_q, ^(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");
+ LogDebug("dns_services DD: SendMsgToServer Received reply msg from Daemon", recv_msg);
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;
- }
-
+
+ if (connRef == NULL || connRef->client_q == NULL || connRef->AppCallBack == NULL)
+ {
+ // If connRef is bad, do not schedule any callbacks to the client
+ syslog(LOG_WARNING, "dns_services DD: SendMsgToServer: connRef is BAD Daemon status code [%llu]", daemon_status);
+ }
+ else
+ {
+ switch (daemon_status)
+ {
+ case kDNSMsg_NoError:
+ dispatch_async((connRef)->client_q, ^{
+ if (connRef->AppCallBack != NULL)
+ ((DNSXEnableProxyReply)connRef->AppCallBack)(connRef, kDNSX_NoError);
+ });
+ break;
+
+ case kDNSMsg_BadArg:
+ dispatch_async((connRef)->client_q, ^{
+ if (connRef->AppCallBack != NULL)
+ ((DNSXEnableProxyReply)connRef->AppCallBack)(connRef, kDNSX_BadParam);
+ });
+ break;
+
+ default:
+ dispatch_async((connRef)->client_q, ^{
+ if (connRef->AppCallBack != NULL)
+ ((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);
- });
+ syslog(LOG_WARNING, "dns_services DD: SendMsgToServer Received unexpected reply from daemon [%s]",
+ xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION));
+ LogDebug("dns_services DD: SendMsgToServer Unexpected Reply contents", recv_msg);
}
});
- // 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)
+// Creates a new DNSX Connection Reference(DNSXConnRef)
+static DNSXErrorType InitConnection(DNSXConnRef *connRefOut, const char *servname, dispatch_queue_t clientq, void *AppCallBack)
{
- if (!connRef)
+ if (connRefOut == NULL)
+ return kDNSX_BadParam;
+
+ // Use a DNSXConnRef on the stack to be captured in the blocks below, rather than capturing the DNSXConnRef* owned by the client
+ DNSXConnRef connRef = malloc(sizeof(struct _DNSXConnRef_t));
+ if (connRef == NULL)
{
- syslog(LOG_WARNING, "dns_services: InitConnection() called with NULL DNSXConnRef");
- return kDNSX_BadParam;
+ syslog(LOG_WARNING, "dns_services DD: InitConnection() No memory to allocate!");
+ return kDNSX_NoMem;
}
-
- *connRef = malloc(sizeof(struct _DNSXConnRef_t));
- if (!(*connRef))
+
+ // 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", DISPATCH_QUEUE_SERIAL);
+ connRef->conn_ref = xpc_connection_create_mach_service(servname, connRef->lib_q, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
+
+ if (connRef->conn_ref == NULL || connRef->lib_q == NULL)
{
- syslog(LOG_WARNING, "dns_services: InitConnection() No memory to allocate");
+ syslog(LOG_WARNING, "dns_services DD: InitConnection() conn_ref/lib_q is NULL");
+ if (connRef != NULL)
+ free(connRef);
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");
+
+ xpc_connection_set_event_handler(connRef->conn_ref, ^(xpc_object_t event)
+ {
+ if (connRef == NULL || connRef->client_q == NULL || connRef->AppCallBack == NULL)
+ {
+ // If connRef is bad, do not schedule any callbacks to the client
+ syslog(LOG_WARNING, "dns_services DD: InitConnection: connRef is BAD Unexpected Connection Error [%s]",
+ xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
+ }
+ else
+ {
+ syslog(LOG_WARNING, "dns_services DD: InitConnection: Unexpected Connection Error [%s] Ping the client",
+ xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
+ dispatch_async(connRef->client_q, ^{
+ if (connRef->AppCallBack != NULL)
+ ((DNSXEnableProxyReply)connRef->AppCallBack)(connRef, kDNSX_DaemonNotRunning);
+ });
+ }
+
+ });
+ xpc_connection_resume(connRef->conn_ref);
+
+ *connRefOut = connRef;
+
return kDNSX_NoError;
}
-DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxyparam, IfIndex inIfindexArr[MaxInputIf],
- IfIndex outIfindex, dispatch_queue_t clientq, DNSXEnableProxyReply callBack)
+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)
+ if (connRef == NULL || callBack == NULL || clientq == NULL)
{
- syslog(LOG_WARNING, "dns_services: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter");
+ syslog(LOG_WARNING, "dns_services DD: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter");
return kDNSX_BadParam;
- }
-
- // If no connRef, get it from InitConnection()
- if (!*connRef)
+ }
+
+ // Get connRef from InitConnection()
+ if (*connRef == NULL)
{
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);
+ syslog(LOG_WARNING, "dns_services DD: Since InitConnection() returned %d error returning w/o sending msg", errx);
return errx;
}
}
- else // Client already has a valid connRef
+ else // Client already has a connRef and this is not valid use for this SPI
{
- old_conn = true;
+ syslog(LOG_WARNING, "dns_services DD: Client already has a valid connRef! This is incorrect usage from the client");
+ return kDNSX_BadParam;
}
-
+
// Create Dictionary To Send
- xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
- if (!dict)
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ if (dict == NULL)
{
- syslog(LOG_WARNING, "dns_services: DNSXEnableProxy could not create the Msg Dict To Send!");
+ syslog(LOG_WARNING, "dns_services DD: DNSXEnableProxy could not create the Msg Dict To Send!");
DNSXRefDeAlloc(*connRef);
- return kDNSX_DictError;
+ return kDNSX_NoMem;
}
-
+
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, 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);
+
+ errx = SendMsgToServer(*connRef, dict);
xpc_release(dict);
-
- return errx;
+ dict = NULL;
+
+ return errx;
}