]> git.saurik.com Git - apple/mdnsresponder.git/blob - Clients/dnsctl.c
mDNSResponder-878.270.2.tar.gz
[apple/mdnsresponder.git] / Clients / dnsctl.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2012-2015 Apple Inc. All rights reserved.
4 *
5 * dnsctl.c
6 * Command-line tool using libdns_services.dylib
7 *
8 * To build only this tool, copy and paste the following on the command line:
9 * On Apple 64bit Platforms ONLY OSX/iOS:
10 * clang -Wall dnsctl.c /usr/lib/libdns_services.dylib -o dnsctl
11 *
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/time.h>
18 #include <net/if.h> // if_nametoindex()
19
20 #include "dns_services.h"
21 #include <xpc/xpc.h>
22 #include "dns_xpc.h"
23
24 //*************************************************************************************************************
25 // Globals:
26 //*************************************************************************************************************
27
28 static const char kFilePathSep = '/';
29
30 static DNSXConnRef ClientRef = NULL;
31
32 static xpc_connection_t dnsctl_conn = NULL;
33
34 //*************************************************************************************************************
35 // Utility Funcs:
36 //*************************************************************************************************************
37
38 static void printtimestamp(void)
39 {
40 struct tm tm;
41 int ms;
42 static char date[16];
43 static char new_date[16];
44 struct timeval tv;
45 gettimeofday(&tv, NULL);
46 localtime_r((time_t*)&tv.tv_sec, &tm);
47 ms = tv.tv_usec/1000;
48 strftime(new_date, sizeof(new_date), "%a %d %b %Y", &tm);
49 //display date only if it has changed
50 if (strncmp(date, new_date, sizeof(new_date)))
51 {
52 printf("DATE: ---%s---\n", new_date);
53 strlcpy(date, new_date, sizeof(date));
54 }
55 printf("%2d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms);
56 }
57
58 static void print_usage(const char *arg0)
59 {
60 fprintf(stderr, "%s USAGE: \n", arg0);
61 fprintf(stderr, "%s -DP Enable DNS Proxy with Default Parameters \n", arg0);
62 fprintf(stderr, "%s -DP [-o <output interface>] [-i <input interface(s)>] Enable DNS Proxy \n", arg0);
63 fprintf(stderr, "%s -L [1/2/3/4] Change mDNSResponder Logging Level \n", arg0);
64 fprintf(stderr, "%s -I Print mDNSResponder STATE INFO \n", arg0);
65 }
66
67
68 static bool DebugEnabled()
69 {
70 return true; // keep this true to debug the XPC msgs
71 }
72
73 static void DebugLog(const char *prefix, xpc_object_t o)
74 {
75 if (!DebugEnabled())
76 return;
77
78 char *desc = xpc_copy_description(o);
79 printf("%s: %s \n", prefix, desc);
80 free(desc);
81 }
82
83 //*************************************************************************************************************
84 // CallBack Funcs:
85 //*************************************************************************************************************
86
87
88 // DNSXEnableProxy Callback from the Daemon
89 static void dnsproxy_reply(DNSXConnRef connRef, DNSXErrorType errCode)
90 {
91 (void) connRef;
92 printtimestamp();
93 switch (errCode)
94 {
95 case kDNSX_NoError : printf(" SUCCESS \n");
96 break;
97 case kDNSX_DaemonNotRunning : printf(" NO DAEMON \n");
98 DNSXRefDeAlloc(ClientRef); break;
99 case kDNSX_BadParam : printf(" BAD PARAMETER \n");
100 DNSXRefDeAlloc(ClientRef); break;
101 case kDNSX_Busy : printf(" BUSY \n");
102 DNSXRefDeAlloc(ClientRef); break;
103 case kDNSX_UnknownErr :
104 default : printf(" UNKNOWN ERR \n");
105 DNSXRefDeAlloc(ClientRef); break;
106 }
107 fflush(NULL);
108
109 }
110
111 //*************************************************************************************************************
112 // XPC Funcs:
113 //*************************************************************************************************************
114
115 static void Init_Connection(const char *servname)
116 {
117 dnsctl_conn = xpc_connection_create_mach_service(servname, dispatch_get_main_queue(), XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
118
119 xpc_connection_set_event_handler(dnsctl_conn, ^(xpc_object_t event)
120 {
121 printf("InitConnection: [%s] \n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
122 });
123
124 xpc_connection_resume(dnsctl_conn);
125 }
126
127 static void SendDictToServer(xpc_object_t msg)
128 {
129
130 DebugLog("SendDictToServer Sending msg to Daemon", msg);
131
132 xpc_connection_send_message_with_reply(dnsctl_conn, msg, dispatch_get_main_queue(), ^(xpc_object_t recv_msg)
133 {
134 xpc_type_t type = xpc_get_type(recv_msg);
135
136 if (type == XPC_TYPE_DICTIONARY)
137 {
138 DebugLog("SendDictToServer Received reply msg from Daemon", recv_msg);
139 /*
140 // If we ever want to do something based on the reply of the daemon
141 switch (daemon_status)
142 {
143 default:
144 break;
145 }
146 */
147 }
148 else
149 {
150 printf("SendDictToServer Received unexpected reply from daemon [%s]",
151 xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION));
152 DebugLog("SendDictToServer Unexpected Reply contents", recv_msg);
153 }
154 exit(1);
155 });
156 }
157
158 //*************************************************************************************************************
159
160 int main(int argc, char **argv)
161 {
162 // Extract program name from argv[0], which by convention contains the path to this executable
163 const char *a0 = strrchr(argv[0], kFilePathSep) + 1;
164 if (a0 == (const char *)1)
165 a0 = argv[0];
166
167 // Must run as root
168 if (0 != geteuid())
169 {
170 fprintf(stderr, "%s MUST run as root!!\n", a0);
171 exit(-1);
172 }
173 if ((sizeof(argv) == 8))
174 printf("dnsctl running in 64-bit mode\n");
175 else if ((sizeof(argv) == 4))
176 printf("dnsctl running in 32-bit mode\n");
177
178 // expects atleast one argument
179 if (argc < 2)
180 goto Usage;
181
182 printtimestamp();
183 if (!strcasecmp(argv[1], "-DP"))
184 {
185 DNSXErrorType err;
186 // Default i/p intf is lo0 and o/p intf is primary interface
187 IfIndex Ipintfs[MaxInputIf] = {1, 0, 0, 0, 0};
188 IfIndex Opintf = kDNSIfindexAny;
189
190 if (argc == 2)
191 {
192 dispatch_queue_t my_Q = dispatch_queue_create("com.apple.dnsctl.callback_queue", NULL);
193 err = DNSXEnableProxy(&ClientRef, kDNSProxyEnable, Ipintfs, Opintf, my_Q, dnsproxy_reply);
194 if (err)
195 fprintf(stderr, "DNSXEnableProxy returned %d\n", err);
196 }
197 else if (argc > 2)
198 {
199 argc--;
200 argv++;
201 if (!strcmp(argv[1], "-o"))
202 {
203 Opintf = if_nametoindex(argv[2]);
204 if (!Opintf)
205 Opintf = atoi(argv[2]);
206 if (!Opintf)
207 {
208 fprintf(stderr, "Could not parse o/p interface [%s]: Passing default primary \n", argv[2]);
209 Opintf = kDNSIfindexAny;
210 }
211 argc -= 2;
212 argv += 2;
213 }
214 if (argc > 2 && !strcmp(argv[1], "-i"))
215 {
216 int i;
217 argc--;
218 argv++;
219 for (i = 0; i < MaxInputIf && argc > 1; i++)
220 {
221 Ipintfs[i] = if_nametoindex(argv[1]);
222 if (!Ipintfs[i])
223 Ipintfs[i] = atoi(argv[1]);
224 if (!Ipintfs[i])
225 {
226 fprintf(stderr, "Could not parse i/p interface [%s]: Passing default lo0 \n", argv[2]);
227 Ipintfs[i] = 1;
228 }
229 argc--;
230 argv++;
231 }
232 }
233 printf("Enabling DNSProxy on mDNSResponder \n");
234 dispatch_queue_t my_Q = dispatch_queue_create("com.apple.dnsctl.callback_queue", NULL);
235 err = DNSXEnableProxy(&ClientRef, kDNSProxyEnable, Ipintfs, Opintf, my_Q, dnsproxy_reply);
236 if (err)
237 fprintf(stderr, "DNSXEnableProxy returned %d\n", err);
238 }
239 }
240 else if (!strcasecmp(argv[1], "-l"))
241 {
242 printf("Changing loglevel of mDNSResponder \n");
243 Init_Connection(kDNSCTLService);
244
245 // Create Dictionary To Send
246 xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
247
248 if (argc == 2)
249 {
250 xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level1);
251
252 SendDictToServer(dict);
253 xpc_release(dict);
254 dict = NULL;
255 }
256 else if (argc > 2)
257 {
258 argc--;
259 argv++;
260 switch (atoi(argv[1]))
261 {
262 case log_level1:
263 xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level1);
264 break;
265
266 case log_level2:
267 xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level2);
268 break;
269
270 case log_level3:
271 xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level3);
272 break;
273
274 case log_level4:
275 xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level4);
276 break;
277
278 default:
279 xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level1);
280 break;
281 }
282 SendDictToServer(dict);
283 xpc_release(dict);
284 dict = NULL;
285 }
286 }
287 else if(!strcasecmp(argv[1], "-i"))
288 {
289 printf("Get STATE INFO of mDNSResponder \n");
290 Init_Connection(kDNSCTLService);
291
292 // Create Dictionary To Send
293 xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
294 xpc_dictionary_set_uint64(dict, kDNSStateInfo, full_state);
295 SendDictToServer(dict);
296 xpc_release(dict);
297 dict = NULL;
298 }
299 else if(!strcasecmp(argv[1], "-th"))
300 {
301 printf("Sending Test message to mDNSResponder to forward to mDNSResponderHelper\n");
302 Init_Connection(kDNSCTLService);
303
304 // Create Dictionary To Send
305 xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
306 xpc_dictionary_set_uint64(dict, kmDNSResponderTests, test_helper_ipc);
307 SendDictToServer(dict);
308 xpc_release(dict);
309 dict = NULL;
310 }
311 else if(!strcasecmp(argv[1], "-tl"))
312 {
313 printf("Testing mDNSResponder Logging\n");
314 Init_Connection(kDNSCTLService);
315
316 // Create Dictionary To Send
317 xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
318 xpc_dictionary_set_uint64(dict, kmDNSResponderTests, test_mDNS_log);
319 SendDictToServer(dict);
320 xpc_release(dict);
321 dict = NULL;
322 }
323 else
324 {
325 goto Usage;
326 }
327
328 dispatch_main();
329
330 Usage:
331 print_usage(a0);
332 return 0;
333 }
334
335 /*
336
337 #include <getopt.h>
338
339 static int operation;
340
341 static int getfirstoption(int argc, char **argv, const char *optstr, int *pOptInd)
342 {
343 // Return the recognized option in optstr and the option index of the next arg.
344 int o = getopt(argc, (char *const *)argv, optstr);
345 *pOptInd = optind;
346 return o;
347 }
348
349 int opindex;
350 operation = getfirstoption(argc, argv, "lLDdPp", &opindex);
351 if (operation == -1)
352 goto Usage;
353
354
355
356 switch (operation)
357 {
358 case 'L':
359 case 'l':
360 {
361 printtimestamp();
362 printf("Change Verbosity Level of mDNSResponder\n");
363
364 Init_Connection(kDNSCTLService);
365
366 // Create Dictionary To Send
367 xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
368 if (dict == NULL)
369 printf("could not create the Msg Dict To Send! \n");
370 xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level2);
371
372 SendDictToServer(dict);
373
374 xpc_release(dict);
375 dict = NULL;
376 break;
377 }
378 // exit(1);
379
380 }
381
382 */
383