X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/6f870c060efc60e067aebc5814c89f110eec9777..78403150fdf95618c483be7dbe6bca9459b92a9f:/Plugins/IPMonitor/set-hostname.c diff --git a/Plugins/IPMonitor/set-hostname.c b/Plugins/IPMonitor/set-hostname.c index b9ff913..5003bd1 100644 --- a/Plugins/IPMonitor/set-hostname.c +++ b/Plugins/IPMonitor/set-hostname.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2004-2012 Apple Inc. All rights reserved. + * Copyright (c) 2004-2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ #include @@ -40,14 +40,18 @@ #include #include + +#ifdef MAIN +#define my_log(__level, fmt, ...) SCPrint(TRUE, stdout, CFSTR(fmt "\n"), ## __VA_ARGS__) +#else // MAIN #include "ip_plugin.h" +#endif // MAIN static SCDynamicStoreRef store = NULL; static CFRunLoopSourceRef rls = NULL; -static Boolean dnsActive = FALSE; -static CFMachPortRef dnsPort = NULL; -static struct timeval dnsQueryStart; +static struct timeval ptrQueryStart; +static SCNetworkReachabilityRef ptrTarget = NULL; static Boolean _verbose = FALSE; @@ -79,7 +83,7 @@ set_hostname(CFStringRef hostname) old_name[sizeof(old_name)-1] = '\0'; new_name[sizeof(new_name)-1] = '\0'; if (strcmp(old_name, new_name) != 0) { - if (sethostname(new_name, strlen(new_name)) == 0) { + if (sethostname(new_name, (int)strlen(new_name)) == 0) { uint32_t status; my_log(LOG_NOTICE, @@ -89,12 +93,12 @@ set_hostname(CFStringRef hostname) status = notify_post(HOSTNAME_NOTIFY_KEY); if (status != NOTIFY_STATUS_OK) { my_log(LOG_ERR, - "notify_post(" HOSTNAME_NOTIFY_KEY ") failed: error=%lu", + "notify_post(" HOSTNAME_NOTIFY_KEY ") failed: error=%u", status); } } else { my_log(LOG_ERR, - "sethostname(%s, %d) failed: %s", + "sethostname(%s, %ld) failed: %s", new_name, strlen(new_name), strerror(errno)); @@ -106,116 +110,6 @@ set_hostname(CFStringRef hostname) } -#define HOSTCONFIG "/etc/hostconfig" -#define HOSTNAME_KEY "HOSTNAME=" -#define AUTOMATIC "-AUTOMATIC-" - -#define HOSTNAME_KEY_LEN (sizeof(HOSTNAME_KEY) - 1) - -static CFStringRef -copy_static_name() -{ - FILE * f; - char buf[256]; - CFStringRef name = NULL; - - f = fopen(HOSTCONFIG, "r"); - if (f == NULL) { - return NULL; - } - - while (fgets(buf, sizeof(buf), f) != NULL) { - char * bp; - int n; - char * np; - Boolean str_escape; - Boolean str_quote; - - n = strlen(buf); - if (buf[n-1] == '\n') { - /* the entire line fit in the buffer, remove the newline */ - buf[n-1] = '\0'; - } else { - /* eat the remainder of the line */ - do { - n = fgetc(f); - } while ((n != '\n') && (n != EOF)); - } - - // skip leading white space - bp = &buf[0]; - while (isspace(*bp)) { - bp++; - } - - // find "HOSTNAME=" key - if (strncmp(bp, HOSTNAME_KEY, HOSTNAME_KEY_LEN) != 0) { - continue; // if not - } - - // get the hostname string - bp += HOSTNAME_KEY_LEN; - str_escape = FALSE; - str_quote = FALSE; - - np = &buf[0]; - while (*bp != '\0') { - char ch = *bp; - - switch (ch) { - case '\\' : - if (!str_escape) { - str_escape = TRUE; - bp++; - continue; - } - break; - case '"' : - if (!str_escape) { - str_quote = !str_quote; - bp++; - continue; - } - break; - default : - break; - } - - if (str_escape) { - str_escape = FALSE; - } else if (!str_quote && (isspace(ch) || (ch == '#'))) { - break; - } - - *np++ = ch; - bp++; - } - - *np = '\0'; - - if (name != NULL) { - CFRelease(name); - name = NULL; - } - - if (str_quote) { - // the shell won't parse this file so neither will we - break; - } - - if (strcmp(buf, AUTOMATIC) == 0) { - // skip "-AUTOMATIC-" - continue; - } - - name = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); - } - - (void) fclose(f); - return name; -} - - static CFStringRef copy_prefs_hostname(SCDynamicStoreRef store) { @@ -310,55 +204,62 @@ copy_primary_ip(SCDynamicStoreRef store, CFStringRef serviceID) return address; } + static void -reverseDNSComplete(int32_t status, char *host, char *serv, void *context) +ptr_query_stop() { - struct timeval dnsQueryComplete; - struct timeval dnsQueryElapsed; - CFStringRef hostname; - SCDynamicStoreRef store = (SCDynamicStoreRef)context; + if (ptrTarget == NULL) { + return; + } + + SCNetworkReachabilitySetCallback(ptrTarget, NULL, NULL); + SCNetworkReachabilityUnscheduleFromRunLoop(ptrTarget, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + CFRelease(ptrTarget); + ptrTarget = NULL; - (void) gettimeofday(&dnsQueryComplete, NULL); - timersub(&dnsQueryComplete, &dnsQueryStart, &dnsQueryElapsed); + return; +} + + +static void +ptr_query_callback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) +{ + CFStringRef hostname = NULL; + struct timeval ptrQueryComplete; + struct timeval ptrQueryElapsed; + + (void) gettimeofday(&ptrQueryComplete, NULL); + timersub(&ptrQueryComplete, &ptrQueryStart, &ptrQueryElapsed); if (_verbose) { - my_log(LOG_INFO, "async DNS complete%s (query time = %d.%3.3d)", - ((status == 0) && (host != NULL)) ? "" : ", host not found", - dnsQueryElapsed.tv_sec, - dnsQueryElapsed.tv_usec / 1000); + my_log(LOG_DEBUG, "ptr query complete%s (query time = %ld.%3.3d)", + (flags & kSCNetworkReachabilityFlagsReachable) ? "" : ", host not found", + ptrQueryElapsed.tv_sec, + ptrQueryElapsed.tv_usec / 1000); } // use reverse DNS name, if available - switch (status) { - case 0 : - /* - * if [reverse] DNS query was successful - */ - if (host != NULL) { - hostname = CFStringCreateWithCString(NULL, host, kCFStringEncodingUTF8); - if (hostname != NULL) { - my_log(LOG_INFO, "hostname (reverse DNS query) = %@", hostname); - set_hostname(hostname); - CFRelease(hostname); - goto done; - } + if (flags & kSCNetworkReachabilityFlagsReachable) { + int error_num; + CFArrayRef hosts; + + /* + * if [reverse] DNS query was successful + */ + hosts = SCNetworkReachabilityCopyResolvedAddress(target, &error_num); + if (hosts != NULL) { + if (CFArrayGetCount(hosts) > 0) { + + hostname = CFArrayGetValueAtIndex(hosts, 0); + my_log(LOG_DEBUG, "hostname (reverse DNS query) = %@", hostname); + set_hostname(hostname); + } + CFRelease(hosts); + + if (hostname != NULL) { + goto done; } - break; - - case EAI_NONAME : -#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) - case EAI_NODATA: -#endif - /* - * if no name available - */ - break; - - default : - /* - * Hmmmm... - */ - my_log(LOG_ERR, "getnameinfo() failed: %s", gai_strerror(status)); + } } // get local (multicast DNS) name, if available @@ -367,7 +268,7 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context) if (hostname != NULL) { CFMutableStringRef localName; - my_log(LOG_INFO, "hostname (multicast DNS) = %@", hostname); + my_log(LOG_DEBUG, "hostname (multicast DNS) = %@", hostname); localName = CFStringCreateMutableCopy(NULL, 0, hostname); assert(localName != NULL); CFStringAppend(localName, CFSTR(".local")); @@ -383,142 +284,56 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context) done : - if (host != NULL) free(host); - if (serv != NULL) free(serv); - dnsActive = FALSE; - return; -} - - -static CFStringRef -replyMPCopyDescription(const void *info) -{ - SCDynamicStoreRef store = (SCDynamicStoreRef)info; - - return CFStringCreateWithFormat(NULL, - NULL, - CFSTR(" {store = %p}"), - store); -} - - -static void -getnameinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info) -{ - mach_port_t mp = MACH_PORT_NULL; - int32_t status; - - if (port != dnsPort) { - // we've received a callback on the async DNS port but since the - // associated CFMachPort doesn't match than the request must have - // already been cancelled. - my_log(LOG_ERR, "getnameinfo_async_handleCFReply(): port != dnsPort"); - return; - } + ptr_query_stop(); - mp = CFMachPortGetPort(port); - CFMachPortInvalidate(dnsPort); - CFRelease(dnsPort); - dnsPort = NULL; - __MACH_PORT_DEBUG(mp != MACH_PORT_NULL, "*** set-hostname (after unscheduling)", mp); - - status = getnameinfo_async_handle_reply(msg); - __MACH_PORT_DEBUG(mp != MACH_PORT_NULL, "*** set-hostname (after getnameinfo_async_handle_reply)", mp); - if ((status == 0) && dnsActive && (mp != MACH_PORT_NULL)) { - CFMachPortContext context = { 0 - , (void *)store - , CFRetain - , CFRelease - , replyMPCopyDescription - }; - CFRunLoopSourceRef rls; - - // if request has been re-queued - dnsPort = _SC_CFMachPortCreateWithPort("IPMonitor/set-hostname/re-queue", - mp, - getnameinfo_async_handleCFReply, - &context); - rls = CFMachPortCreateRunLoopSource(NULL, dnsPort, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); - CFRelease(rls); - __MACH_PORT_DEBUG(mp != MACH_PORT_NULL, "*** set-hostname (after rescheduling)", mp); - } +#ifdef MAIN + CFRunLoopStop(CFRunLoopGetCurrent()); +#endif // MAIN return; } -static void -start_dns_query(SCDynamicStoreRef store, CFStringRef address) +static Boolean +ptr_query_start(CFStringRef address) { union { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; } addr; char buf[64]; - SCNetworkReachabilityFlags flags; - Boolean haveDNS; - Boolean ok; + CFDataRef data; + CFMutableDictionaryRef options; if (_SC_cfstring_to_cstring(address, buf, sizeof(buf), kCFStringEncodingASCII) == NULL) { - my_log(LOG_ERR, "could not convert [primary] address"); - return; + my_log(LOG_ERR, "could not convert [primary] address string"); + return FALSE; } if (_SC_string_to_sockaddr(buf, AF_UNSPEC, (void *)&addr, sizeof(addr)) == NULL) { - /* if not an IP[v6] address */ - my_log(LOG_ERR, "could not parse [primary] address"); - return; - } - - ok = _SC_checkResolverReachabilityByAddress(&store, &flags, &haveDNS, &addr.sa); - if (ok) { - if (!(flags & kSCNetworkReachabilityFlagsReachable) || - (flags & kSCNetworkReachabilityFlagsConnectionRequired)) { - // if not reachable *OR* connection required - ok = FALSE; - } + my_log(LOG_ERR, "could not convert [primary] address"); + return FALSE; } - if (ok) { - CFMachPortContext context = { 0 - , (void *)store - , CFRetain - , CFRelease - , replyMPCopyDescription - }; - int32_t error; - mach_port_t mp; - CFRunLoopSourceRef rls; - - (void) gettimeofday(&dnsQueryStart, NULL); - - error = getnameinfo_async_start(&mp, - &addr.sa, - addr.sa.sa_len, - NI_NAMEREQD, // flags - reverseDNSComplete, - NULL); - if (error != 0) { - goto done; - } - __MACH_PORT_DEBUG(TRUE, "*** set-hostname (after getnameinfo_async_start)", mp); - - dnsActive = TRUE; - dnsPort = _SC_CFMachPortCreateWithPort("IPMonitor/set-hostname", - mp, - getnameinfo_async_handleCFReply, - &context); - rls = CFMachPortCreateRunLoopSource(NULL, dnsPort, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); - CFRelease(rls); - __MACH_PORT_DEBUG(TRUE, "*** set-hostname (after scheduling)", mp); + options = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + data = CFDataCreate(NULL, (const UInt8 *)&addr.sa, addr.sa.sa_len); + CFDictionarySetValue(options, kSCNetworkReachabilityOptionPTRAddress, data); + CFRelease(data); + ptrTarget = SCNetworkReachabilityCreateWithOptions(NULL, options); + CFRelease(options); + if (ptrTarget == NULL) { + my_log(LOG_ERR, "could not resolve [primary] address"); + return FALSE; } - done : + (void) SCNetworkReachabilitySetCallback(ptrTarget, ptr_query_callback, NULL); + (void) SCNetworkReachabilityScheduleWithRunLoop(ptrTarget, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - return; + return TRUE; } @@ -531,31 +346,15 @@ update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) // if active, cancel any in-progress attempt to resolve the primary IP address - if (dnsPort != NULL) { - mach_port_t mp = CFMachPortGetPort(dnsPort); - - /* cancel the outstanding DNS query */ - CFMachPortInvalidate(dnsPort); - CFRelease(dnsPort); - dnsPort = NULL; - - getnameinfo_async_cancel(mp); - } - - // get static hostname, if available - - hostname = copy_static_name(); - if (hostname != NULL) { - my_log(LOG_INFO, "hostname (static) = %@", hostname); - set_hostname(hostname); - goto done; + if (ptrTarget != NULL) { + ptr_query_stop(); } // get [prefs] hostname, if available hostname = copy_prefs_hostname(store); if (hostname != NULL) { - my_log(LOG_INFO, "hostname (prefs) = %@", hostname); + my_log(LOG_DEBUG, "hostname (prefs) = %@", hostname); set_hostname(hostname); goto done; } @@ -571,7 +370,7 @@ update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) hostname = copy_dhcp_hostname(serviceID); if (hostname != NULL) { - my_log(LOG_INFO, "hostname (DHCP) = %@", hostname); + my_log(LOG_DEBUG, "hostname (DHCP) = %@", hostname); set_hostname(hostname); goto done; } @@ -580,9 +379,14 @@ update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) address = copy_primary_ip(store, serviceID); if (address != NULL) { + Boolean ok; + // start reverse DNS query using primary IP address - (void) start_dns_query(store, address); - goto done; + ok = ptr_query_start(address); + if (ok) { + // if query started + goto done; + } } mDNS : @@ -593,7 +397,7 @@ update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) if (hostname != NULL) { CFMutableStringRef localName; - my_log(LOG_INFO, "hostname (multicast DNS) = %@", hostname); + my_log(LOG_DEBUG, "hostname (multicast DNS) = %@", hostname); localName = CFStringCreateMutableCopy(NULL, 0, hostname); assert(localName != NULL); CFStringAppend(localName, CFSTR(".local")); @@ -715,6 +519,7 @@ main(int argc, char **argv) _sc_log = FALSE; if ((argc > 1) && (strcmp(argv[1], "-d") == 0)) { _sc_verbose = TRUE; + _verbose = TRUE; argv++; argc--; } @@ -732,17 +537,18 @@ main(int argc, char **argv) exit(1); } - // get static hostname - hostname = copy_static_name(); + // get [prefs] hostname, if available + hostname = copy_prefs_hostname(store); if (hostname != NULL) { - SCPrint(TRUE, stdout, CFSTR("hostname (static) = %@\n"), hostname); + SCPrint(TRUE, stdout, CFSTR("hostname (prefs) = %@\n"), hostname); CFRelease(hostname); } - // get [prefs] hostname, if available - hostname = copy_prefs_hostname(store); + // get local (multicast DNS) name, if available + + hostname = SCDynamicStoreCopyLocalHostName(store); if (hostname != NULL) { - SCPrint(TRUE, stdout, CFSTR("hostname (prefs) = %@\n"), hostname); + SCPrint(TRUE, stdout, CFSTR("hostname (multicast DNS) = %@\n"), hostname); CFRelease(hostname); } @@ -752,7 +558,6 @@ main(int argc, char **argv) SCPrint(TRUE, stdout, CFSTR("primary service ID = %@\n"), serviceID); } else { SCPrint(TRUE, stdout, CFSTR("No primary service\n")); - goto mDNS; } if ((argc == (2+1)) && (argv[1][0] == 's')) { @@ -761,49 +566,33 @@ main(int argc, char **argv) SCPrint(TRUE, stdout, CFSTR("alternate service ID = %@\n"), serviceID); } - // get DHCP provided name - hostname = copy_dhcp_name(store, serviceID); - if (hostname != NULL) { - SCPrint(TRUE, stdout, CFSTR("hostname (DHCP) = %@\n"), hostname); - CFRelease(hostname); - } - - // get primary IP address - address = copy_primary_ip(store, serviceID); - if (address != NULL) { - SCPrint(TRUE, stdout, CFSTR("primary address = %@\n"), address); - - if ((argc == (2+1)) && (argv[1][0] == 'a')) { - if (address != NULL) CFRelease(address); - address = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8); - SCPrint(TRUE, stdout, CFSTR("alternate primary address = %@\n"), address); + if (serviceID != NULL) { + // get DHCP provided name + hostname = copy_dhcp_hostname(serviceID); + if (hostname != NULL) { + SCPrint(TRUE, stdout, CFSTR("hostname (DHCP) = %@\n"), hostname); + CFRelease(hostname); } - // start reverse DNS query using primary IP address - start_dns_query(store, address); - CFRelease(address); - } - - CFRelease(serviceID); - - mDNS : + // get primary IP address + address = copy_primary_ip(store, serviceID); + if (address != NULL) { + SCPrint(TRUE, stdout, CFSTR("primary address = %@\n"), address); - // get local (multicast DNS) name, if available + if ((argc == (2+1)) && (argv[1][0] == 'a')) { + if (address != NULL) CFRelease(address); + address = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8); + SCPrint(TRUE, stdout, CFSTR("alternate primary address = %@\n"), address); + } - hostname = SCDynamicStoreCopyLocalHostName(store); - if (hostname != NULL) { - CFMutableStringRef localName; + // start reverse DNS query using primary IP address + (void) ptr_query_start(address); + CFRelease(address); + } - SCPrint(TRUE, stdout, CFSTR("hostname (multicast DNS) = %@\n"), hostname); - localName = CFStringCreateMutableCopy(NULL, 0, hostname); - CFStringAppend(localName, CFSTR(".local")); - CFRelease(localName); + CFRelease(serviceID); } - if (hostname != NULL) CFRelease(hostname); - - update_hostname(store, NULL, NULL); - CFRelease(store); CFRunLoopRun();