]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/Private/dnsctl_server.c
mDNSResponder-878.250.4.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / Private / dnsctl_server.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 *
5 * dnsctl_server.c
6 * mDNSResponder
7 *
8 * XPC as an IPC mechanism to communicate with dnsctl. Open only to Apple OSX/iOS clients
9 */
10
11 #include "xpc_services.h"
12 #include "dns_xpc.h"
13
14 #include "mDNSMacOSX.h" // KQueueLock/KQueueUnlock
15 #include "helper.h" // mDNSResponderHelper tests
16 #include <xpc/xpc.h>
17
18 // ***************************************************************************
19 // Globals
20 extern mDNS mDNSStorage;
21 static dispatch_queue_t dnsctlserver_queue = NULL;
22 // ***************************************************************************
23
24 mDNSlocal void handle_logging(mDNSu32 log_level)
25 {
26 KQueueLock();
27
28 switch (log_level)
29 {
30 case log_level1:
31 mDNS_LoggingEnabled = mDNS_PacketLoggingEnabled = 0;
32 LogMsg("USR1 Logging:[%s] USR2 Logging:[%s]", mDNS_LoggingEnabled ? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
33 break;
34
35 case log_level2:
36 mDNS_LoggingEnabled = 1;
37 LogMsg("USR1 Logging %s", mDNS_LoggingEnabled ? "Enabled" : "Disabled");
38 break;
39
40 case log_level3:
41 mDNS_PacketLoggingEnabled = 1;
42 LogMsg("USR2 Logging %s", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
43 break;
44
45 case log_level4:
46 mDNS_LoggingEnabled = 1 ;
47 mDNS_PacketLoggingEnabled = 1;
48 LogMsg("USR1 Logging:%s USR2 Logging:%s", mDNS_LoggingEnabled ? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
49 break;
50
51 default:
52 mDNS_LoggingEnabled = 0 ;
53 mDNS_PacketLoggingEnabled = 0;
54 break;
55 }
56 UpdateDebugState();
57
58 KQueueUnlock("LogLevel changed");
59 }
60
61 mDNSlocal void handle_stateinfo(mDNSu32 state_level)
62 {
63 KQueueLock();
64
65 switch (state_level)
66 {
67 case full_state:
68 INFOCallback();
69 break;
70
71 default:
72 INFOCallback();
73 break;
74 }
75
76 KQueueUnlock("StateInfo dumped");
77 }
78
79
80 mDNSlocal void handle_test_mode(mDNSu32 test_mode)
81 {
82 KQueueLock();
83
84 switch (test_mode)
85 {
86 case test_helper_ipc:
87 mDNSNotify("mDNSResponderHelperTest", "This is just a test message to mDNSResponderHelper. This is NOT an actual alert");
88 break;
89
90 case test_mDNS_log:
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");
95 break;
96
97 default:
98 LogMsg("Unidentified Test mode: Please add this test");
99 break;
100 }
101
102 KQueueUnlock("Test Msg to mDNSResponderHelper");
103 }
104
105 mDNSlocal void handle_terminate()
106 {
107
108 LogInfo("handle_terminate: Client terminated connection.");
109
110 }
111
112 mDNSlocal void handle_requests(xpc_object_t req)
113 {
114 mDNSu32 log_level, state_level, test_mode;
115 xpc_connection_t remote_conn = xpc_dictionary_get_remote_connection(req);
116
117 LogInfo("handle_requests: Handler for dnsctl requests");
118
119 xpc_object_t response = xpc_dictionary_create_reply(req);
120
121 // Return Success Status to the client (essentially ACKing the request)
122 if (response)
123 {
124 xpc_dictionary_set_uint64(response, kDNSDaemonReply, kDNSMsg_NoError);
125 xpc_connection_send_message(remote_conn, response);
126 xpc_release(response);
127 }
128 else
129 {
130 LogMsg("handle_requests: Response Dictionary could not be created");
131 return;
132 }
133
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)))
137 {
138 log_level = (mDNSu32)(xpc_dictionary_get_uint64(req, kDNSLogLevel));
139 handle_logging(log_level);
140 }
141 else if ((xpc_dictionary_get_uint64(req, kDNSStateInfo)))
142 {
143 state_level = (mDNSu32)(xpc_dictionary_get_uint64(req, kDNSStateInfo));
144 handle_stateinfo(state_level);
145 }
146 else if ((xpc_dictionary_get_uint64(req, kmDNSResponderTests)))
147 {
148 test_mode = (mDNSu32)(xpc_dictionary_get_uint64(req, kmDNSResponderTests));
149 handle_test_mode(test_mode);
150 }
151 }
152
153 mDNSlocal void accept_client(xpc_connection_t conn)
154 {
155 uid_t c_euid;
156 int c_pid;
157 c_euid = xpc_connection_get_euid(conn);
158 c_pid = xpc_connection_get_pid(conn);
159
160 if (c_euid != 0 || !IsEntitled(conn, kDNSCTLService))
161 {
162 LogMsg("accept_client: Client PID[%d] is missing Entitlement or is NOT running as root!", c_pid);
163 xpc_connection_cancel(conn);
164 return;
165 }
166
167 xpc_retain(conn);
168 xpc_connection_set_target_queue(conn, dnsctlserver_queue);
169 xpc_connection_set_event_handler(conn, ^(xpc_object_t req_msg)
170 {
171 xpc_type_t type = xpc_get_type(req_msg);
172
173 if (type == XPC_TYPE_DICTIONARY)
174 {
175 handle_requests(req_msg);
176 }
177 else // We hit this case ONLY if Client Terminated Connection OR Crashed
178 {
179 LogInfo("accept_client: Client %p teared down the connection", (void *) conn);
180 handle_terminate();
181 xpc_release(conn);
182 }
183 });
184
185 xpc_connection_resume(conn);
186
187 }
188
189 mDNSexport void init_dnsctl_service(void)
190 {
191
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)
194 {
195 LogMsg("init_dnsctl_service: Error Creating XPC Listener for DNSCTL Server!");
196 return;
197 }
198
199 dnsctlserver_queue = dispatch_queue_create("com.apple.mDNSResponder.dnsctlserver_queue", NULL);
200
201 xpc_connection_set_event_handler(dnsctl_listener, ^(xpc_object_t eventmsg)
202 {
203 xpc_type_t type = xpc_get_type(eventmsg);
204
205 if (type == XPC_TYPE_CONNECTION)
206 {
207 LogInfo("init_dnsctl_service: New DNSCTL Client %p", eventmsg);
208 accept_client(eventmsg);
209 }
210 else if (type == XPC_TYPE_ERROR) // Ideally, we would never hit these cases
211 {
212 LogMsg("init_dnsctl_service: XPCError: %s", xpc_dictionary_get_string(eventmsg, XPC_ERROR_KEY_DESCRIPTION));
213 }
214 else
215 {
216 LogMsg("init_dnsctl_service: Unknown EventMsg type");
217 }
218 });
219
220 xpc_connection_resume(dnsctl_listener);
221 }
222
223
224