static mach_port_t register_service(const char *service_name) { mach_port_t port = MACH_PORT_NULL; kern_return_t kr; if (KERN_SUCCESS == (kr = bootstrap_check_in(bootstrap_port, (char *)service_name, &port))) { if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); else return port; } if (KERN_SUCCESS != (kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port))) { helplog(ASL_LEVEL_ERR, "mach_port_allocate: %s", mach_error_string(kr)); goto error; } if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); goto error; } // XXX bootstrap_register does not modify its second argument, but the prototype does not include const. if (KERN_SUCCESS != (kr = bootstrap_register(bootstrap_port, (char *)service_name, port))) { helplog(ASL_LEVEL_ERR, "bootstrap_register failed: %s", mach_error_string(kr)); goto error; } return port; error: if (MACH_PORT_NULL != port) mach_port_deallocate(mach_task_self(), port); return MACH_PORT_NULL; }
static void diediedie(CFRunLoopTimerRef timer, void *context) { debug("entry %p %p %d", timer, context, actualidle); assert(gTimer == timer); helplog(ASL_LEVEL_INFO, "mDNSResponder exiting after %d seconds", actualidle); if (actualidle) (void)proxy_mDNSExit(gPort); }
static mach_port_t checkin(char *service_name) { kern_return_t kr = KERN_SUCCESS; mach_port_t port = MACH_PORT_NULL; launch_data_t msg = NULL, reply = NULL, datum = NULL; if (NULL == (msg = launch_data_new_string(LAUNCH_KEY_CHECKIN))) { helplog(ASL_LEVEL_ERR, "Could not create checkin message for launchd."); goto fin; } if (NULL == (reply = launch_msg(msg))) { helplog(ASL_LEVEL_ERR, "Could not message launchd."); goto fin; } if (LAUNCH_DATA_ERRNO == launch_data_get_type(reply)) { if (launch_data_get_errno(reply) == EACCES) { launch_data_free(msg); launch_data_free(reply); return(MACH_PORT_NULL); } helplog(ASL_LEVEL_ERR, "Launchd checkin failed: %s.", strerror(launch_data_get_errno(reply))); goto fin; } if (NULL == (datum = launch_data_dict_lookup(reply, LAUNCH_JOBKEY_MACHSERVICES)) || LAUNCH_DATA_DICTIONARY != launch_data_get_type(datum)) { helplog(ASL_LEVEL_ERR, "Launchd reply does not contain %s dictionary.", LAUNCH_JOBKEY_MACHSERVICES); goto fin; } if (NULL == (datum = launch_data_dict_lookup(datum, service_name)) || LAUNCH_DATA_MACHPORT != launch_data_get_type(datum)) { helplog(ASL_LEVEL_ERR, "Launchd reply does not contain %s Mach port.", service_name); goto fin; } if (MACH_PORT_NULL == (port = launch_data_get_machport(datum))) { helplog(ASL_LEVEL_ERR, "Launchd gave me a null Mach port."); goto fin; } if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); goto fin; } fin: if (NULL != msg) launch_data_free(msg); if (NULL != reply) launch_data_free(reply); if (MACH_PORT_NULL == port) exit(EXIT_FAILURE); return port; }
// for safe_vproc void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *fmt, ...) { (void)logLevel; va_list ap; va_start(ap, fmt); // safe_vproc only calls LogMsg, so assume logLevel maps to ASL_LEVEL_ERR helplog(ASL_LEVEL_ERR, fmt, ap); va_end(ap); }
kern_return_t do_LKDCHelperExit (__unused mach_port_t port, audit_token_t token) { if (!authorized(token)) goto fin; helplog(ASL_LEVEL_NOTICE, "Idle exit"); exit(0); fin: return KERN_SUCCESS; }
static mach_port_t register_service(const char *service_name) { mach_port_t port = MACH_PORT_NULL; kern_return_t kr; if (KERN_SUCCESS != (kr = bootstrap_check_in(bootstrap_port, (char *)service_name, &port))) { helplog(ASL_LEVEL_ERR, "bootstrap_check_in: %d %X %s", kr, kr, mach_error_string(kr)); return MACH_PORT_NULL; } if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %d %X %s", kr, kr, mach_error_string(kr)); mach_port_deallocate(mach_task_self(), port); return MACH_PORT_NULL; } return port; }
static int initialize_timer() { gTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + actualidle, actualidle, 0, 0, diediedie, NULL); int err = 0; debug("entry"); if (0 != (err = pthread_create(&idletimer_thread, NULL, idletimer, NULL))) helplog(ASL_LEVEL_ERR, "Could not start idletimer thread: %s", strerror(err)); return err; }
static void initialize_id(void) { static char login[] = "_mdnsresponder"; struct passwd hardcode; struct passwd *pwd = &hardcode; // getpwnam(login); hardcode.pw_uid = 65; hardcode.pw_gid = 65; if (!pwd) { helplog(ASL_LEVEL_ERR, "Could not find account name `%s'. I will only help root.", login); return; } mDNSResponderUID = pwd->pw_uid; mDNSResponderGID = pwd->pw_gid; }
int main(int ac, char *av[]) { char *p = NULL; kern_return_t kr = KERN_FAILURE; long n; int ch; mach_msg_header_t hdr; while ((ch = getopt(ac, av, "dt:")) != -1) switch (ch) { case 'd': opt_debug = 1; break; case 't': n = strtol(optarg, &p, 0); if ('\0' == optarg[0] || '\0' != *p || n > LONG_MAX || n < 0) { fprintf(stderr, "Invalid idle timeout: %s\n", optarg); exit(EXIT_FAILURE); } maxidle = n; break; case '?': default: fprintf(stderr, "Usage: mDNSResponderHelper [-d] [-t maxidle]\n"); exit(EXIT_FAILURE); } ac -= optind; av += optind; (void)ac; // Unused (void)av; // Unused initialize_logging(); helplog(ASL_LEVEL_INFO, "Starting"); initialize_id(); #ifndef NO_SECURITYFRAMEWORK // We should normally be running as a system daemon. However, that might not be the case in some scenarios (e.g. debugging). // Explicitly ensure that our Keychain operations utilize the system domain. if (opt_debug) SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); #endif gPort = register_service(kmDNSHelperServiceName); if (!gPort) exit(EXIT_FAILURE); if (maxidle) actualidle = maxidle; signal(SIGTERM, handle_sigterm); if (initialize_timer()) exit(EXIT_FAILURE); for (n=0; n<100000; n++) if (!gRunLoop) usleep(100); if (!gRunLoop) { helplog(ASL_LEVEL_ERR, "gRunLoop not set after waiting"); exit(EXIT_FAILURE); } for(;;) { hdr.msgh_bits = 0; hdr.msgh_local_port = gPort; hdr.msgh_remote_port = MACH_PORT_NULL; hdr.msgh_size = sizeof(hdr); hdr.msgh_id = 0; kr = mach_msg(&hdr, MACH_RCV_LARGE | MACH_RCV_MSG, 0, hdr.msgh_size, gPort, 0, 0); if (MACH_RCV_TOO_LARGE != kr) helplog(ASL_LEVEL_ERR, "main MACH_RCV_MSG error: %d %X %s", kr, kr, mach_error_string(kr)); kr = mach_msg_server_once(helper_server, MAX_MSG_SIZE, gPort, MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)); if (KERN_SUCCESS != kr) { helplog(ASL_LEVEL_ERR, "mach_msg_server: %d %X %s", kr, kr, mach_error_string(kr)); exit(EXIT_FAILURE); } } exit(EXIT_SUCCESS); }