]> git.saurik.com Git - apple/mdnsresponder.git/blame - mDNSMacOSX/helper-main.c
mDNSResponder-1310.80.1.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / helper-main.c
CommitLineData
f0cc3e7b
A
1/*
2 * Copyright (c) 2007-2019 Apple Inc. All rights reserved.
67c8f8a1
A
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
83fb1e36 7 *
67c8f8a1 8 * http://www.apache.org/licenses/LICENSE-2.0
83fb1e36 9 *
67c8f8a1
A
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
67c8f8a1
A
15 */
16
67c8f8a1
A
17#include <CoreFoundation/CoreFoundation.h>
18#include <sys/cdefs.h>
f0cc3e7b 19#include <sys/socket.h>
67c8f8a1
A
20#include <sys/time.h>
21#include <sys/types.h>
22#include <mach/mach.h>
23#include <mach/mach_error.h>
24#include <servers/bootstrap.h>
67c8f8a1
A
25#include <launch.h>
26#include <pwd.h>
27#include <pthread.h>
28#include <stdarg.h>
29#include <stdbool.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <time.h>
33#include <unistd.h>
34#include <Security/Security.h>
35#include "helper.h"
36#include "helper-server.h"
9f221bca 37#include <xpc/private.h>
67c8f8a1 38
f0cc3e7b 39#if TARGET_OS_IPHONE
67c8f8a1
A
40#define NO_SECURITYFRAMEWORK 1
41#endif
42
43#ifndef LAUNCH_JOBKEY_MACHSERVICES
44#define LAUNCH_JOBKEY_MACHSERVICES "MachServices"
45#define LAUNCH_DATA_MACHPORT 10
46#define launch_data_get_machport launch_data_get_fd
47#endif
48
32bb7e43 49
9f221bca
A
50int mDNSHelperLogEnabled = 0;
51os_log_t log_handle = NULL;
52
53static dispatch_queue_t xpc_queue = NULL;
67c8f8a1
A
54static int opt_debug;
55static pthread_t idletimer_thread;
56
32bb7e43 57unsigned long maxidle = 15;
67c8f8a1
A
58unsigned long actualidle = 3600;
59
60CFRunLoopRef gRunLoop = NULL;
61CFRunLoopTimerRef gTimer = NULL;
62
32bb7e43
A
63
64static void handle_sigterm(int sig)
83fb1e36 65{
9f221bca 66 // os_log_debug(log_handle,"entry sig=%d", sig); Can't use syslog from within a signal handler
83fb1e36 67 assert(sig == SIGTERM);
9f221bca 68 helper_exit();
83fb1e36 69}
67c8f8a1
A
70
71static void initialize_logging(void)
83fb1e36 72{
9f221bca
A
73 log_handle = os_log_create("com.apple.mDNSResponderHelper", "INFO");
74
75 if (!log_handle)
76 {
77 // OS_LOG_DEFAULT is the default logging object, if you are not creating a custom subsystem/category
78 os_log_error(OS_LOG_DEFAULT, "Could NOT create log handle in mDNSResponderHelper");
79 }
80
83fb1e36 81}
67c8f8a1
A
82
83static void initialize_id(void)
83fb1e36
A
84{
85 static char login[] = "_mdnsresponder";
86 struct passwd hardcode;
87 struct passwd *pwd = &hardcode; // getpwnam(login);
88 hardcode.pw_uid = 65;
89 hardcode.pw_gid = 65;
90
9f221bca
A
91 if (!pwd)
92 {
93 os_log(log_handle, "Could not find account name `%s'. I will only help root.", login);
94 return;
95 }
83fb1e36
A
96 mDNSResponderUID = pwd->pw_uid;
97 mDNSResponderGID = pwd->pw_gid;
98}
67c8f8a1
A
99
100static void diediedie(CFRunLoopTimerRef timer, void *context)
83fb1e36 101{
9f221bca
A
102 os_log_info(log_handle, "entry %p %p %lu", timer, context, actualidle);
103
83fb1e36 104 assert(gTimer == timer);
9f221bca
A
105 os_log_info(log_handle, "mDNSResponderHelper exiting after [%lu] seconds", actualidle);
106
107 if (actualidle)
108 helper_exit();
83fb1e36 109}
67c8f8a1
A
110
111void pause_idle_timer(void)
83fb1e36 112{
9f221bca 113 os_log_debug(log_handle,"entry");
83fb1e36
A
114 assert(gTimer);
115 assert(gRunLoop);
116 CFRunLoopRemoveTimer(gRunLoop, gTimer, kCFRunLoopDefaultMode);
117}
67c8f8a1
A
118
119void unpause_idle_timer(void)
83fb1e36 120{
9f221bca 121 os_log_debug(log_handle,"entry");
83fb1e36
A
122 assert(gRunLoop);
123 assert(gTimer);
124 CFRunLoopAddTimer(gRunLoop, gTimer, kCFRunLoopDefaultMode);
125}
67c8f8a1
A
126
127void update_idle_timer(void)
83fb1e36 128{
9f221bca 129 os_log_debug(log_handle,"entry");
83fb1e36
A
130 assert(gTimer);
131 CFRunLoopTimerSetNextFireDate(gTimer, CFAbsoluteTimeGetCurrent() + actualidle);
132}
67c8f8a1
A
133
134static void *idletimer(void *context)
83fb1e36 135{
9f221bca
A
136 os_log_debug(log_handle,"entry context=%p", context);
137 gRunLoop = CFRunLoopGetMain();
83fb1e36
A
138
139 unpause_idle_timer();
140
141 for (;;)
142 {
9f221bca 143 // os_log_debug(log_handle,"Running CFRunLoop");
83fb1e36
A
144 CFRunLoopRun();
145 sleep(1);
146 }
147
148 return NULL;
149}
67c8f8a1 150
32bb7e43 151static int initialize_timer()
83fb1e36
A
152{
153 gTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + actualidle, actualidle, 0, 0, diediedie, NULL);
154 int err = 0;
9f221bca 155 os_log_info(log_handle, "mDNSResponderHelper initialize_timer() started");
67c8f8a1 156
83fb1e36 157 if (0 != (err = pthread_create(&idletimer_thread, NULL, idletimer, NULL)))
9f221bca 158 os_log(log_handle, "Could not start idletimer thread: %s", strerror(err));
32bb7e43 159
83fb1e36
A
160 return err;
161}
67c8f8a1 162
9f221bca
A
163/*
164 Reads the user's program arguments for mDNSResponderHelper
165 For now we have only one option: mDNSHelperDebugLogging which is used to turn on mDNSResponderHelperLogging
166
167 To turn ON mDNSResponderHelper Verbose Logging,
168 1] sudo defaults write /Library/Preferences/com.apple.mDNSResponderHelper.plist mDNSHelperDebugLogging -bool YES
169 2] sudo reboot
170
171 To turn OFF mDNSResponderHelper Logging,
172 1] sudo defaults delete /Library/Preferences/com.apple.mDNSResponderHelper.plist
173
174 To view the current options set,
175 1] plutil -p /Library/Preferences/com.apple.mDNSResponderHelper.plist
176 OR
177 1] sudo defaults read /Library/Preferences/com.apple.mDNSResponderHelper.plist
178*/
179
180static mDNSBool HelperPrefsGetValueBool(CFStringRef key, mDNSBool defaultVal)
83fb1e36 181{
9f221bca
A
182 CFBooleanRef boolean;
183 mDNSBool result = defaultVal;
184
185 boolean = CFPreferencesCopyAppValue(key, kmDNSHelperProgramArgs);
f0cc3e7b 186 if (boolean != NULL)
9f221bca
A
187 {
188 if (CFGetTypeID(boolean) == CFBooleanGetTypeID())
189 result = CFBooleanGetValue(boolean) ? mDNStrue : mDNSfalse;
190 CFRelease(boolean);
191 }
192
193 return result;
194}
195
83fb1e36 196
9f221bca
A
197// Verify Client's Entitlement
198static mDNSBool check_entitlement(xpc_connection_t conn, const char *password)
199{
200 mDNSBool entitled = mDNSfalse;
201 xpc_object_t ent = xpc_connection_copy_entitlement_value(conn, password);
202
203 if (ent)
204 {
205 if (xpc_get_type(ent) == XPC_TYPE_BOOL && xpc_bool_get_value(ent))
206 {
207 entitled = mDNStrue;
208 }
209 xpc_release(ent);
210 }
211 else
83fb1e36 212 {
9f221bca 213 os_log(log_handle, "client entitlement is NULL");
83fb1e36 214 }
51601d48 215
9f221bca
A
216 if (!entitled)
217 os_log(log_handle, "entitlement check failed -> client is missing entitlement!");
218
219 return entitled;
220}
221
222
223static void handle_request(xpc_object_t req)
224{
225 mDNSu32 helper_mode = 0;
226 int error_code = 0;
227
228 xpc_connection_t remote_conn = xpc_dictionary_get_remote_connection(req);
229 xpc_object_t response = xpc_dictionary_create_reply(req);
230
231 // switch here based on dictionary to handle different requests from mDNSResponder
232 if ((xpc_dictionary_get_uint64(req, kHelperMode)))
51601d48 233 {
9f221bca
A
234 os_log_info(log_handle, "Getting mDNSResponder request mode");
235 helper_mode = (mDNSu32)(xpc_dictionary_get_uint64(req, kHelperMode));
51601d48 236 }
9f221bca
A
237
238 switch (helper_mode)
239 {
240 case bpf_request:
241 {
242 os_log_info(log_handle, "Calling new RequestBPF()");
243 RequestBPF();
244 break;
245 }
246
247 case set_name:
248 {
249 const char *old_name;
250 const char *new_name;
251 int pref_key = 0;
252
253 pref_key = (int)(xpc_dictionary_get_uint64(req, kPrefsNameKey));
254 old_name = xpc_dictionary_get_string(req, kPrefsOldName);
255 new_name = xpc_dictionary_get_string(req, kPrefsNewName);
256
257 os_log_info(log_handle, "Calling new SetName() oldname: %s newname: %s key:%d", old_name, new_name, pref_key);
258 PreferencesSetName(pref_key, old_name, new_name);
259 break;
260 }
261
262 case p2p_packetfilter:
263 {
f0cc3e7b 264 size_t count = 0;
9f221bca
A
265 pfArray_t pfports;
266 pfArray_t pfprotocols;
267 const char *if_name;
268 uint32_t cmd;
f0cc3e7b
A
269 xpc_object_t xpc_obj_port_array;
270 size_t port_array_count = 0;
271 xpc_object_t xpc_obj_protocol_array;
272 size_t protocol_array_count = 0;
9f221bca
A
273
274 cmd = xpc_dictionary_get_uint64(req, "pf_opcode");
275 if_name = xpc_dictionary_get_string(req, "pf_ifname");
f0cc3e7b
A
276 xpc_obj_port_array = xpc_dictionary_get_value(req, "xpc_obj_array_port");
277 if ((void *)xpc_obj_port_array != NULL)
278 port_array_count = xpc_array_get_count(xpc_obj_port_array);
279 xpc_obj_protocol_array = xpc_dictionary_get_value(req, "xpc_obj_array_protocol");
280 if ((void *)xpc_obj_protocol_array != NULL)
281 protocol_array_count = xpc_array_get_count(xpc_obj_protocol_array);
282 if (port_array_count != protocol_array_count)
283 break;
284 if (port_array_count > PFPortArraySize)
285 break;
286 count = port_array_count;
287
288 for (size_t i = 0; i < count; i++) {
289 pfports[i] = (uint16_t)xpc_array_get_uint64(xpc_obj_port_array, i);
290 pfprotocols[i] = (uint16_t)xpc_array_get_uint64(xpc_obj_protocol_array, i);
291 }
292
9f221bca
A
293 os_log_info(log_handle,"Calling new PacketFilterControl()");
294 PacketFilterControl(cmd, if_name, count, pfports, pfprotocols);
295 break;
296 }
297
298 case user_notify:
299 {
300 const char *title;
301 const char *msg;
302 title = xpc_dictionary_get_string(req, "notify_title");
303 msg = xpc_dictionary_get_string(req, "notify_msg");
304
305 os_log_info(log_handle,"Calling new UserNotify() title:%s msg:%s", title, msg);
306 UserNotify(title, msg);
307 break;
308 }
309
310 case power_req:
311 {
312 int key, interval;
313 key = xpc_dictionary_get_uint64(req, "powerreq_key");
314 interval = xpc_dictionary_get_uint64(req, "powerreq_interval");
315
316 os_log_info(log_handle,"Calling new PowerRequest() key[%d] interval[%d]", key, interval);
317 PowerRequest(key, interval, &error_code);
318 break;
319 }
320
321 case send_wakepkt:
322 {
323 const char *ether_addr;
324 const char *ip_addr;
325 int iteration;
326 unsigned int if_id;
327
328 if_id = (unsigned int)xpc_dictionary_get_uint64(req, "interface_index");
329 ether_addr = xpc_dictionary_get_string(req, "ethernet_address");
330 ip_addr = xpc_dictionary_get_string(req, "ip_address");
331 iteration = (int)xpc_dictionary_get_uint64(req, "swp_iteration");
332
333 os_log_info(log_handle, "Calling new SendWakeupPacket() ether_addr[%s] ip_addr[%s] if_id[%d] iteration[%d]",
334 ether_addr, ip_addr, if_id, iteration);
335 SendWakeupPacket(if_id, ether_addr, ip_addr, iteration);
336 break;
337 }
338
339 case set_localaddr_cacheentry:
340 {
341 int if_index, family;
f0cc3e7b
A
342 size_t ip_len, eth_len;
343
9f221bca
A
344 if_index = xpc_dictionary_get_uint64(req, "slace_ifindex");
345 family = xpc_dictionary_get_uint64(req, "slace_family");
9f221bca 346
f0cc3e7b
A
347 const uint8_t * const ip = (const uint8_t *)xpc_dictionary_get_data(req, "slace_ip", &ip_len);
348 if (ip_len != sizeof(v6addr_t))
9f221bca 349 {
f0cc3e7b
A
350 error_code = kHelperErr_ParamErr;
351 break;
9f221bca
A
352 }
353
f0cc3e7b
A
354 const uint8_t * const eth = (const uint8_t *)xpc_dictionary_get_data(req, "slace_eth", &eth_len);
355 if (eth_len != sizeof(ethaddr_t))
9f221bca 356 {
f0cc3e7b
A
357 error_code = kHelperErr_ParamErr;
358 break;
9f221bca 359 }
f0cc3e7b
A
360
361 os_log_info(log_handle, "Calling new SetLocalAddressCacheEntry() if_index[%d] family[%d] ", if_index, family);
362
363 SetLocalAddressCacheEntry(if_index, family, ip, eth, &error_code);
9f221bca
A
364 break;
365 }
366
367 case send_keepalive:
368 {
369 uint16_t lport, rport, win;
370 uint32_t seq, ack;
f0cc3e7b 371 size_t sadd6_len, dadd6_len;
9f221bca
A
372
373 lport = xpc_dictionary_get_uint64(req, "send_keepalive_lport");
374 rport = xpc_dictionary_get_uint64(req, "send_keepalive_rport");
375 seq = xpc_dictionary_get_uint64(req, "send_keepalive_seq");
376 ack = xpc_dictionary_get_uint64(req, "send_keepalive_ack");
377 win = xpc_dictionary_get_uint64(req, "send_keepalive_win");
378
f0cc3e7b
A
379 const uint8_t * const sadd6 = (const uint8_t *)xpc_dictionary_get_data(req, "send_keepalive_sadd", &sadd6_len);
380 const uint8_t * const dadd6 = (const uint8_t *)xpc_dictionary_get_data(req, "send_keepalive_dadd", &dadd6_len);
381 if ((sadd6_len != sizeof(v6addr_t)) || (dadd6_len != sizeof(v6addr_t)))
382 {
383 error_code = kHelperErr_ParamErr;
384 break;
385 }
386
9f221bca
A
387 os_log_info(log_handle, "helper-main: handle_request: send_keepalive: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]",
388 lport, rport, seq, ack, win);
389
390 SendKeepalive(sadd6, dadd6, lport, rport, seq, ack, win);
391 break;
392 }
393
394 case retreive_tcpinfo:
395 {
396 uint16_t lport, rport;
397 int family;
398 uint32_t seq, ack;
399 uint16_t win;
400 int32_t intfid;
f0cc3e7b 401 size_t laddr_len, raddr_len;
9f221bca
A
402
403 lport = xpc_dictionary_get_uint64(req, "retreive_tcpinfo_lport");
404 rport = xpc_dictionary_get_uint64(req, "retreive_tcpinfo_rport");
405 family = xpc_dictionary_get_uint64(req, "retreive_tcpinfo_family");
f0cc3e7b
A
406
407 const uint8_t * const laddr = (const uint8_t *)xpc_dictionary_get_data(req, "retreive_tcpinfo_laddr", &laddr_len);
408 const uint8_t * const raddr = (const uint8_t *)xpc_dictionary_get_data(req, "retreive_tcpinfo_raddr", &raddr_len);
409 if ((laddr_len != sizeof(v6addr_t)) || (raddr_len != sizeof(v6addr_t)))
410 {
411 error_code = kHelperErr_ParamErr;
412 break;
413 }
414
9f221bca
A
415 os_log_info(log_handle, "helper-main: handle_request: retreive_tcpinfo: lport is[%d] rport is[%d] family is [%d]",
416 lport, rport, family);
417
418 RetrieveTCPInfo(family, laddr, lport, raddr, rport, &seq, &ack, &win, &intfid, &error_code);
419
420 if (response)
421 {
422 xpc_dictionary_set_uint64(response, "retreive_tcpinfo_seq", seq);
423 xpc_dictionary_set_uint64(response, "retreive_tcpinfo_ack", ack);
424 xpc_dictionary_set_uint64(response, "retreive_tcpinfo_win", win);
425 xpc_dictionary_set_uint64(response, "retreive_tcpinfo_ifid", intfid);
426 }
427
428 os_log_info(log_handle, "helper-main: handle_request: retreive_tcpinfo: seq is[%d] ack is[%d] win is [%d] intfid is [%d]",
429 seq, ack, win, intfid);
83fb1e36 430
9f221bca
A
431 break;
432 }
433
9f221bca
A
434 case keychain_getsecrets:
435 {
436 unsigned int num_sec = 0;
437 unsigned long secrets = 0;
438 unsigned int sec_cnt = 0;
439
440 os_log_info(log_handle,"Calling new KeyChainGetSecrets()");
441
442 KeychainGetSecrets(&num_sec, &secrets, &sec_cnt, &error_code);
443
444 if (response)
445 {
f0cc3e7b 446 xpc_dictionary_set_uint64(response, "keychain_num_secrets", num_sec);
9f221bca 447 xpc_dictionary_set_data(response, "keychain_secrets", (void *)secrets, sec_cnt);
9f221bca
A
448 }
449
f0cc3e7b
A
450 os_log_info(log_handle,"helper-main: handle_request: keychain_getsecrets: num_secrets is %u, secrets is %lu, secrets_Cnt is %u",
451 num_sec, secrets, sec_cnt);
9f221bca
A
452
453 if (secrets)
454 vm_deallocate(mach_task_self(), secrets, sec_cnt);
455
456 break;
457 }
458
459 default:
460 {
461 os_log(log_handle, "handle_request: Unrecognized mode!");
462 error_code = kHelperErr_UndefinedMode;
463 break;
464 }
465 }
466
467 // Return Response Status back to the client (essentially ACKing the request)
468 if (response)
469 {
470 xpc_dictionary_set_uint64(response, kHelperReplyStatus, kHelperReply_ACK);
471 xpc_dictionary_set_int64(response, kHelperErrCode, error_code);
472 xpc_connection_send_message(remote_conn, response);
473 xpc_release(response);
474 }
475 else
476 {
477 os_log(log_handle, "handle_requests: Response Dictionary could not be created!");
478 return;
479 }
480
83fb1e36 481}
67c8f8a1 482
9f221bca
A
483static void accept_client(xpc_connection_t conn)
484{
485 int c_pid = xpc_connection_get_pid(conn);
486
487 if (!(check_entitlement(conn, kHelperService)))
488 {
489 os_log(log_handle, "accept_client: Helper Client PID[%d] is missing Entitlement. Cancelling connection", c_pid);
490 xpc_connection_cancel(conn);
491 return;
492 }
493
494 xpc_retain(conn);
495 xpc_connection_set_target_queue(conn, xpc_queue);
496 xpc_connection_set_event_handler(conn, ^(xpc_object_t req_msg)
497 {
498 xpc_type_t type = xpc_get_type(req_msg);
499
500 if (type == XPC_TYPE_DICTIONARY)
501 {
502 os_log_info(log_handle,"accept_client:conn:[%p] client[%d](mDNSResponder) requesting service", (void *) conn, c_pid);
503 handle_request(req_msg);
504 }
505 else // We hit this case ONLY if Client Terminated Connection OR Crashed
506 {
507 os_log(log_handle, "accept_client:conn:[%p] client[%d](mDNSResponder) teared down the connection (OR Crashed)", (void *) conn, c_pid);
508 // handle_termination();
509 xpc_release(conn);
510 }
511 });
512
513 xpc_connection_resume(conn);
514}
515
516
517static void init_helper_service(const char *service_name)
518{
519
520 xpc_connection_t xpc_listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
521 if (!xpc_listener || xpc_get_type(xpc_listener) != XPC_TYPE_CONNECTION)
522 {
523 os_log(log_handle, "init_helper_service: Error Creating XPC Listener for mDNSResponderHelperService !!");
524 return;
525 }
526
527 os_log_info(log_handle,"init_helper_service: XPC Listener for mDNSResponderHelperService Listening");
528
529 xpc_queue = dispatch_queue_create("com.apple.mDNSHelper.service_queue", NULL);
530
531 xpc_connection_set_event_handler(xpc_listener, ^(xpc_object_t eventmsg)
532 {
533 xpc_type_t type = xpc_get_type(eventmsg);
534
535 if (type == XPC_TYPE_CONNECTION)
536 {
537 os_log_info(log_handle,"init_helper_service: new mDNSResponderHelper Client %p", eventmsg);
538 accept_client(eventmsg);
539 }
540 else if (type == XPC_TYPE_ERROR) // Ideally, we would never hit these cases below
541 {
542 os_log(log_handle, "init_helper_service: XPCError: %s", xpc_dictionary_get_string(eventmsg, XPC_ERROR_KEY_DESCRIPTION));
543 return;
544 }
545 else
546 {
547 os_log(log_handle, "init_helper_service: Unknown EventMsg type");
548 return;
549 }
550 });
551
552 xpc_connection_resume(xpc_listener);
553}
554
555
67c8f8a1 556int main(int ac, char *av[])
83fb1e36
A
557{
558 char *p = NULL;
83fb1e36
A
559 long n;
560 int ch;
83fb1e36
A
561
562 while ((ch = getopt(ac, av, "dt:")) != -1)
9f221bca 563 {
83fb1e36
A
564 switch (ch)
565 {
9f221bca
A
566 case 'd':
567 opt_debug = 1;
568 break;
569 case 't':
570 n = strtol(optarg, &p, 0);
571 if ('\0' == optarg[0] || '\0' != *p || n > LONG_MAX || n < 0)
572 {
573 fprintf(stderr, "Invalid idle timeout: %s\n", optarg);
574 exit(EXIT_FAILURE);
575 }
576 maxidle = n;
577 break;
578 case '?':
579 default:
580 fprintf(stderr, "Usage: mDNSResponderHelper [-d] [-t maxidle]\n");
581 exit(EXIT_FAILURE);
83fb1e36 582 }
9f221bca 583 }
83fb1e36
A
584 ac -= optind;
585 av += optind;
9f221bca
A
586 (void)ac; // Unused
587 (void)av; // Unused
83fb1e36
A
588
589 initialize_logging();
83fb1e36 590 initialize_id();
67c8f8a1 591
9f221bca
A
592 mDNSHelperLogEnabled = HelperPrefsGetValueBool(kPreferencesKey_mDNSHelperLog, mDNSHelperLogEnabled);
593
594// Currently on Fuji/Whitetail releases we are keeping the logging always enabled.
595// Hence mDNSHelperLogEnabled is set to true below by default.
596 mDNSHelperLogEnabled = 1;
597
598 os_log_info(log_handle,"mDNSResponderHelper Starting to run");
599
67c8f8a1 600#ifndef NO_SECURITYFRAMEWORK
83fb1e36
A
601 // We should normally be running as a system daemon. However, that might not be the case in some scenarios (e.g. debugging).
602 // Explicitly ensure that our Keychain operations utilize the system domain.
9f221bca
A
603 if (opt_debug)
604 SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
67c8f8a1 605#endif
83fb1e36 606
9f221bca
A
607 if (maxidle)
608 actualidle = maxidle;
83fb1e36
A
609
610 signal(SIGTERM, handle_sigterm);
611
9f221bca
A
612 if (initialize_timer())
613 exit(EXIT_FAILURE);
614 for (n=0; n<100000; n++)
615 if (!gRunLoop)
616 usleep(100);
617
83fb1e36
A
618 if (!gRunLoop)
619 {
9f221bca 620 os_log(log_handle, "gRunLoop not set after waiting");
83fb1e36
A
621 exit(EXIT_FAILURE);
622 }
623
9f221bca
A
624 init_helper_service(kHelperService);
625 os_log_info(log_handle,"mDNSResponderHelper is now running");
626 dispatch_main();
627
83fb1e36 628}
67c8f8a1
A
629
630// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
631// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
632// To expand "version" to its value before making the string, use STRINGIFY(version) instead
83fb1e36 633#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
67c8f8a1
A
634#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
635
636// For convenience when using the "strings" command, this is the last thing in the file
637// The "@(#) " pattern is a special prefix the "what" command looks for
638const char VersionString_SCCS[] = "@(#) mDNSResponderHelper " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
639
32bb7e43 640#if _BUILDING_XCODE_PROJECT_
67c8f8a1
A
641// If the process crashes, then this string will be magically included in the automatically-generated crash log
642const char *__crashreporter_info__ = VersionString_SCCS + 5;
83fb1e36 643asm (".desc ___crashreporter_info__, 0x10");
32bb7e43 644#endif