]> git.saurik.com Git - apple/configd.git/blobdiff - Plugins/IPMonitor/set-hostname.c
configd-699.1.5.tar.gz
[apple/configd.git] / Plugins / IPMonitor / set-hostname.c
index b9ff91321d0808a5e83da185d46ef49ca401ab66..5003bd15a511d1c6f3678c2261922a7577a25881 100644 (file)
@@ -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 <ctype.h>
 #include <SystemConfiguration/SCPrivate.h>
 
 #include <notify.h>
+
+#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("<getnameinfo_async_start reply MP> {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();