1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2015 Apple Inc. All rights reserved.
8 * XPC as an IPC mechanism to communicate with dnsctl. Open only to Apple OSX/iOS clients
11 #include "xpc_services.h"
14 #include "mDNSMacOSX.h" // KQueueLock/KQueueUnlock
15 #include "helper.h" // mDNSResponderHelper tests
18 // ***************************************************************************
20 extern mDNS mDNSStorage
;
21 static dispatch_queue_t dnsctlserver_queue
= NULL
;
22 // ***************************************************************************
24 mDNSlocal
void handle_logging(mDNSu32 log_level
)
26 KQueueLock(&mDNSStorage
);
31 mDNS_LoggingEnabled
= mDNS_PacketLoggingEnabled
= 0;
32 LogMsg("USR1 Logging:[%s] USR2 Logging:[%s]", mDNS_LoggingEnabled
? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled
? "Enabled" : "Disabled");
36 mDNS_LoggingEnabled
= 1;
37 LogMsg("USR1 Logging %s", mDNS_LoggingEnabled
? "Enabled" : "Disabled");
41 mDNS_PacketLoggingEnabled
= 1;
42 LogMsg("USR2 Logging %s", mDNS_PacketLoggingEnabled
? "Enabled" : "Disabled");
46 mDNS_LoggingEnabled
= 1 ;
47 mDNS_PacketLoggingEnabled
= 1;
48 LogMsg("USR1 Logging:%s USR2 Logging:%s", mDNS_LoggingEnabled
? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled
? "Enabled" : "Disabled");
52 mDNS_LoggingEnabled
= 0 ;
53 mDNS_PacketLoggingEnabled
= 0;
58 KQueueUnlock(&mDNSStorage
, "LogLevel changed");
61 mDNSlocal
void handle_stateinfo(mDNSu32 state_level
)
63 KQueueLock(&mDNSStorage
);
76 KQueueUnlock(&mDNSStorage
, "StateInfo dumped");
80 mDNSlocal
void handle_test_mode(mDNSu32 test_mode
)
82 KQueueLock(&mDNSStorage
);
87 mDNSNotify("mDNSResponderHelperTest", "This is just a test message to mDNSResponderHelper. This is NOT an actual alert");
91 LogInfo("LogInfo: Should be logged at INFO level");
92 LogOperation("LogOperation: Should be logged at INFO level");
93 LogMsg("LogMsg: Should be logged at DEFAULT level");
94 LogSPS("LogSPS: Should be logged at INFO level");
98 LogMsg("Unidentified Test mode: Please add this test");
102 KQueueUnlock(&mDNSStorage
, "Test Msg to mDNSResponderHelper");
105 mDNSlocal
void handle_terminate()
108 LogInfo("handle_terminate: Client terminated connection.");
112 mDNSlocal
void handle_requests(xpc_object_t req
)
114 mDNSu32 log_level
, state_level
, test_mode
;
115 xpc_connection_t remote_conn
= xpc_dictionary_get_remote_connection(req
);
117 LogInfo("handle_requests: Handler for dnsctl requests");
119 xpc_object_t response
= xpc_dictionary_create_reply(req
);
121 // Return Success Status to the client (essentially ACKing the request)
124 xpc_dictionary_set_uint64(response
, kDNSDaemonReply
, kDNSMsg_NoError
);
125 xpc_connection_send_message(remote_conn
, response
);
126 xpc_release(response
);
130 LogMsg("handle_requests: Response Dictionary could not be created");
134 // switch here based on dictionary
135 // to handle various different requests like logging, INFO snapshot, etc..
136 if ((xpc_dictionary_get_uint64(req
, kDNSLogLevel
)))
138 log_level
= (mDNSu32
)(xpc_dictionary_get_uint64(req
, kDNSLogLevel
));
139 handle_logging(log_level
);
141 else if ((xpc_dictionary_get_uint64(req
, kDNSStateInfo
)))
143 state_level
= (mDNSu32
)(xpc_dictionary_get_uint64(req
, kDNSStateInfo
));
144 handle_stateinfo(state_level
);
146 else if ((xpc_dictionary_get_uint64(req
, kmDNSResponderTests
)))
148 test_mode
= (mDNSu32
)(xpc_dictionary_get_uint64(req
, kmDNSResponderTests
));
149 handle_test_mode(test_mode
);
153 mDNSlocal
void accept_client(xpc_connection_t conn
)
157 c_euid
= xpc_connection_get_euid(conn
);
158 c_pid
= xpc_connection_get_pid(conn
);
160 if (c_euid
!= 0 || !IsEntitled(conn
, kDNSCTLService
))
162 LogMsg("accept_client: Client PID[%d] is missing Entitlement or is NOT running as root!", c_pid
);
163 xpc_connection_cancel(conn
);
168 xpc_connection_set_target_queue(conn
, dnsctlserver_queue
);
169 xpc_connection_set_event_handler(conn
, ^(xpc_object_t req_msg
)
171 xpc_type_t type
= xpc_get_type(req_msg
);
173 if (type
== XPC_TYPE_DICTIONARY
)
175 handle_requests(req_msg
);
177 else // We hit this case ONLY if Client Terminated Connection OR Crashed
179 LogInfo("accept_client: Client %p teared down the connection", (void *) conn
);
185 xpc_connection_resume(conn
);
189 mDNSexport
void init_dnsctl_service(void)
192 xpc_connection_t dnsctl_listener
= xpc_connection_create_mach_service(kDNSCTLService
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
193 if (!dnsctl_listener
|| xpc_get_type(dnsctl_listener
) != XPC_TYPE_CONNECTION
)
195 LogMsg("init_dnsctl_service: Error Creating XPC Listener for DNSCTL Server!");
199 dnsctlserver_queue
= dispatch_queue_create("com.apple.mDNSResponder.dnsctlserver_queue", NULL
);
201 xpc_connection_set_event_handler(dnsctl_listener
, ^(xpc_object_t eventmsg
)
203 xpc_type_t type
= xpc_get_type(eventmsg
);
205 if (type
== XPC_TYPE_CONNECTION
)
207 LogInfo("init_dnsctl_service: New DNSCTL Client %p", eventmsg
);
208 accept_client(eventmsg
);
210 else if (type
== XPC_TYPE_ERROR
) // Ideally, we would never hit these cases
212 LogMsg("init_dnsctl_service: XPCError: %s", xpc_dictionary_get_string(eventmsg
, XPC_ERROR_KEY_DESCRIPTION
));
216 LogMsg("init_dnsctl_service: Unknown EventMsg type");
220 xpc_connection_resume(dnsctl_listener
);