diff options
Diffstat (limited to 'mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c')
-rw-r--r-- | mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c b/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c new file mode 100644 index 00000000..9b3885e6 --- /dev/null +++ b/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c @@ -0,0 +1,224 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2015 Apple Inc. All rights reserved. + * + * dnsctl_server.c + * mDNSResponder + * + * XPC as an IPC mechanism to communicate with dnsctl. Open only to Apple OSX/iOS clients + */ + +#include "xpc_services.h" +#include "dns_xpc.h" + +#include "mDNSMacOSX.h" // KQueueLock/KQueueUnlock +#include "helper.h" // mDNSResponderHelper tests +#include <xpc/xpc.h> + +// *************************************************************************** +// Globals +extern mDNS mDNSStorage; +static dispatch_queue_t dnsctlserver_queue = NULL; +// *************************************************************************** + +mDNSlocal void handle_logging(mDNSu32 log_level) +{ + KQueueLock(&mDNSStorage); + + switch (log_level) + { + case log_level1: + mDNS_LoggingEnabled = mDNS_PacketLoggingEnabled = 0; + LogMsg("USR1 Logging:[%s] USR2 Logging:[%s]", mDNS_LoggingEnabled ? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled"); + break; + + case log_level2: + mDNS_LoggingEnabled = 1; + LogMsg("USR1 Logging %s", mDNS_LoggingEnabled ? "Enabled" : "Disabled"); + break; + + case log_level3: + mDNS_PacketLoggingEnabled = 1; + LogMsg("USR2 Logging %s", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled"); + break; + + case log_level4: + mDNS_LoggingEnabled = 1 ; + mDNS_PacketLoggingEnabled = 1; + LogMsg("USR1 Logging:%s USR2 Logging:%s", mDNS_LoggingEnabled ? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled"); + break; + + default: + mDNS_LoggingEnabled = 0 ; + mDNS_PacketLoggingEnabled = 0; + break; + } + UpdateDebugState(); + + KQueueUnlock(&mDNSStorage, "LogLevel changed"); +} + +mDNSlocal void handle_stateinfo(mDNSu32 state_level) +{ + KQueueLock(&mDNSStorage); + + switch (state_level) + { + case full_state: + INFOCallback(); + break; + + default: + INFOCallback(); + break; + } + + KQueueUnlock(&mDNSStorage, "StateInfo dumped"); +} + + +mDNSlocal void handle_test_mode(mDNSu32 test_mode) +{ + KQueueLock(&mDNSStorage); + + switch (test_mode) + { + case test_helper_ipc: + mDNSNotify("mDNSResponderHelperTest", "This is just a test message to mDNSResponderHelper. This is NOT an actual alert"); + break; + + case test_mDNS_log: + LogInfo("LogInfo: Should be logged at INFO level"); + LogOperation("LogOperation: Should be logged at INFO level"); + LogMsg("LogMsg: Should be logged at DEFAULT level"); + LogSPS("LogSPS: Should be logged at INFO level"); + break; + + default: + LogMsg("Unidentified Test mode: Please add this test"); + break; + } + + KQueueUnlock(&mDNSStorage, "Test Msg to mDNSResponderHelper"); +} + +mDNSlocal void handle_terminate() +{ + + LogInfo("handle_terminate: Client terminated connection."); + +} + +mDNSlocal void handle_requests(xpc_object_t req) +{ + mDNSu32 log_level, state_level, test_mode; + xpc_connection_t remote_conn = xpc_dictionary_get_remote_connection(req); + + LogInfo("handle_requests: Handler for dnsctl requests"); + + xpc_object_t response = xpc_dictionary_create_reply(req); + + // Return Success Status to the client (essentially ACKing the request) + if (response) + { + xpc_dictionary_set_uint64(response, kDNSDaemonReply, kDNSMsg_NoError); + xpc_connection_send_message(remote_conn, response); + xpc_release(response); + } + else + { + LogMsg("handle_requests: Response Dictionary could not be created"); + return; + } + + // switch here based on dictionary + // to handle various different requests like logging, INFO snapshot, etc.. + if ((xpc_dictionary_get_uint64(req, kDNSLogLevel))) + { + log_level = (mDNSu32)(xpc_dictionary_get_uint64(req, kDNSLogLevel)); + handle_logging(log_level); + } + else if ((xpc_dictionary_get_uint64(req, kDNSStateInfo))) + { + state_level = (mDNSu32)(xpc_dictionary_get_uint64(req, kDNSStateInfo)); + handle_stateinfo(state_level); + } + else if ((xpc_dictionary_get_uint64(req, kmDNSResponderTests))) + { + test_mode = (mDNSu32)(xpc_dictionary_get_uint64(req, kmDNSResponderTests)); + handle_test_mode(test_mode); + } +} + +mDNSlocal void accept_client(xpc_connection_t conn) +{ + uid_t c_euid; + int c_pid; + c_euid = xpc_connection_get_euid(conn); + c_pid = xpc_connection_get_pid(conn); + + if (c_euid != 0 || !IsEntitled(conn, kDNSCTLService)) + { + LogMsg("accept_client: Client PID[%d] is missing Entitlement or is NOT running as root!", c_pid); + xpc_connection_cancel(conn); + return; + } + + xpc_retain(conn); + xpc_connection_set_target_queue(conn, dnsctlserver_queue); + xpc_connection_set_event_handler(conn, ^(xpc_object_t req_msg) + { + xpc_type_t type = xpc_get_type(req_msg); + + if (type == XPC_TYPE_DICTIONARY) + { + handle_requests(req_msg); + } + else // We hit this case ONLY if Client Terminated Connection OR Crashed + { + LogInfo("accept_client: Client %p teared down the connection", (void *) conn); + handle_terminate(); + xpc_release(conn); + } + }); + + xpc_connection_resume(conn); + +} + +mDNSexport void init_dnsctl_service(void) +{ + + xpc_connection_t dnsctl_listener = xpc_connection_create_mach_service(kDNSCTLService, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + if (!dnsctl_listener || xpc_get_type(dnsctl_listener) != XPC_TYPE_CONNECTION) + { + LogMsg("init_dnsctl_service: Error Creating XPC Listener for DNSCTL Server!"); + return; + } + + dnsctlserver_queue = dispatch_queue_create("com.apple.mDNSResponder.dnsctlserver_queue", NULL); + + xpc_connection_set_event_handler(dnsctl_listener, ^(xpc_object_t eventmsg) + { + xpc_type_t type = xpc_get_type(eventmsg); + + if (type == XPC_TYPE_CONNECTION) + { + LogInfo("init_dnsctl_service: New DNSCTL Client %p", eventmsg); + accept_client(eventmsg); + } + else if (type == XPC_TYPE_ERROR) // Ideally, we would never hit these cases + { + LogMsg("init_dnsctl_service: XPCError: %s", xpc_dictionary_get_string(eventmsg, XPC_ERROR_KEY_DESCRIPTION)); + } + else + { + LogMsg("init_dnsctl_service: Unknown EventMsg type"); + } + }); + + xpc_connection_resume(dnsctl_listener); +} + + + |