]> git.saurik.com Git - apple/configd.git/blobdiff - scutil.tproj/tests.c
configd-802.20.7.tar.gz
[apple/configd.git] / scutil.tproj / tests.c
index bc9160eb2502c3e8e7fbde9a0311e2fb98e08ff1..a243962365ad1e3fd33e67d4c13706f7a0267f60 100644 (file)
@@ -1,15 +1,15 @@
 /*
- * Copyright (c) 2000, 2001, 2003-2005, 2007-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2015 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 "scutil.h"
+#include "prefs.h"
 #include "tests.h"
 
 #include <netdb.h>
 #include <netdb_async.h>
+#include <notify.h>
 #include <sys/time.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#define my_log(__level, fmt, ...)      SCPrint(TRUE, stdout, CFSTR(fmt "\n"), ## __VA_ARGS__)
+
 #include <dnsinfo.h>
+#include "dnsinfo_internal.h"
 #include <network_information.h>
+#include "network_information_priv.h"
 #include "SCNetworkReachabilityInternal.h"
+#include <CommonCrypto/CommonDigest.h>
+
 
 static Boolean resolver_bypass;
 
+
 static CF_RETURNS_RETAINED CFMutableDictionaryRef
 _setupReachabilityOptions(int argc, char **argv, const char *interface)
 {
+       int                     i;
        CFMutableDictionaryRef  options;
 
        options = CFDictionaryCreateMutable(NULL,
@@ -62,103 +72,60 @@ _setupReachabilityOptions(int argc, char **argv, const char *interface)
                                            &kCFTypeDictionaryKeyCallBacks,
                                            &kCFTypeDictionaryValueCallBacks);
 
-       if (argc > 2) {
-               struct addrinfo         hints   = { 0 };
-               int                     n_hints = 0;
-               int                     i;
-
-               for (i = 2; i < argc; i++) {
-                       if (strcasecmp(argv[i], "interface") == 0) {
-                               if (++i >= argc) {
-                                       SCPrint(TRUE, stderr, CFSTR("No interface\n"));
-                                       CFRelease(options);
-                                       exit(1);
-                               }
-
-                               interface = argv[i];
-                               continue;
+       for (i = 0; i < argc; i++) {
+               if (strcasecmp(argv[i], "interface") == 0) {
+                       if (++i >= argc) {
+                               SCPrint(TRUE, stderr, CFSTR("No interface\n"));
+                               CFRelease(options);
+                               exit(1);
                        }
 
+                       interface = argv[i];
+                       continue;
+               }
 
-                       if (strcasecmp(argv[i], "llq") == 0) {
-                               CFDictionarySetValue(options,
-                                                    kSCNetworkReachabilityOptionLongLivedQueryBypass,
-                                                    kCFBooleanFalse);
-                               continue;
-                       } else if (strcasecmp(argv[i], "no-llq") == 0) {
-                               CFDictionarySetValue(options,
-                                                    kSCNetworkReachabilityOptionLongLivedQueryBypass,
-                                                    kCFBooleanTrue);
-                               continue;
-                       }
 
-                       if (strcasecmp(argv[i], "server") == 0) {
-                               CFDictionarySetValue(options,
-                                                    kSCNetworkReachabilityOptionServerBypass,
-                                                    kCFBooleanFalse);
-                               continue;
-                       } else if (strcasecmp(argv[i], "no-server") == 0) {
-                               CFDictionarySetValue(options,
-                                                    kSCNetworkReachabilityOptionServerBypass,
-                                                    kCFBooleanTrue);
-                               continue;
-                       }
+               if (strcasecmp(argv[i], "server") == 0) {
+                       CFDictionarySetValue(options,
+                                            kSCNetworkReachabilityOptionServerBypass,
+                                            kCFBooleanFalse);
+                       continue;
+               } else if (strcasecmp(argv[i], "no-server") == 0) {
+                       CFDictionarySetValue(options,
+                                            kSCNetworkReachabilityOptionServerBypass,
+                                            kCFBooleanTrue);
+                       continue;
+               }
 
-                       if (strcasecmp(argv[i], "no-resolve") == 0) {
-                               CFDictionarySetValue(options,
-                                                    kSCNetworkReachabilityOptionResolverBypass,
-                                                    kCFBooleanTrue);
-                               resolver_bypass = TRUE;
-                               continue;
-                       }
+               if (strcasecmp(argv[i], "no-connection-on-demand") == 0) {
+                       CFDictionarySetValue(options,
+                                            kSCNetworkReachabilityOptionConnectionOnDemandBypass,
+                                            kCFBooleanTrue);
+                       continue;
+               }
 
-                       if (strcasecmp(argv[i], "AI_ADDRCONFIG") == 0) {
-                               hints.ai_flags |= AI_ADDRCONFIG;
-                       } else if (strcasecmp(argv[i], "AI_ALL") == 0) {
-                               hints.ai_flags |= AI_ALL;
-                       } else if (strcasecmp(argv[i], "AI_V4MAPPED") == 0) {
-                               hints.ai_flags |= AI_V4MAPPED;
-                       } else if (strcasecmp(argv[i], "AI_V4MAPPED_CFG") == 0) {
-                               hints.ai_flags |= AI_V4MAPPED_CFG;
-                       } else if (strcasecmp(argv[i], "AI_ADDRCONFIG") == 0) {
-                               hints.ai_flags |= AI_ADDRCONFIG;
-                       } else if (strcasecmp(argv[i], "AI_V4MAPPED") == 0) {
-                               hints.ai_flags |= AI_V4MAPPED;
-                       } else if (strcasecmp(argv[i], "AI_DEFAULT") == 0) {
-                               hints.ai_flags |= AI_DEFAULT;
-#ifdef AI_PARALLEL
-                       } else if (strcasecmp(argv[i], "AI_PARALLEL") == 0) {
-                               hints.ai_flags |= AI_PARALLEL;
-#endif // AI_PARALLEL
-                       } else if (strcasecmp(argv[i], "PF_INET") == 0) {
-                               hints.ai_family = PF_INET;
-                       } else if (strcasecmp(argv[i], "PF_INET6") == 0) {
-                               hints.ai_family = PF_INET6;
-                       } else if (strcasecmp(argv[i], "SOCK_STREAM") == 0) {
-                               hints.ai_socktype = SOCK_STREAM;
-                       } else if (strcasecmp(argv[i], "SOCK_DGRAM") == 0) {
-                               hints.ai_socktype = SOCK_DGRAM;
-                       } else if (strcasecmp(argv[i], "SOCK_RAW") == 0) {
-                               hints.ai_socktype = SOCK_RAW;
-                       } else if (strcasecmp(argv[i], "IPPROTO_TCP") == 0) {
-                               hints.ai_protocol = IPPROTO_TCP;
-                       } else if (strcasecmp(argv[i], "IPPROTO_UDP") == 0) {
-                               hints.ai_protocol = IPPROTO_UDP;
-                       } else {
-                               SCPrint(TRUE, stderr, CFSTR("Unrecognized hint: %s\n"), argv[i]);
-                               CFRelease(options);
-                               exit(1);
-                       }
-                       n_hints++;
+               if (strcasecmp(argv[i], "no-resolve") == 0) {
+                       CFDictionarySetValue(options,
+                                            kSCNetworkReachabilityOptionResolverBypass,
+                                            kCFBooleanTrue);
+                       resolver_bypass = TRUE;
+                       continue;
                }
 
-               if (n_hints > 0) {
-                       CFDataRef       data;
+               if (strcasecmp(argv[i], "ptr") == 0) {
+                       CFDictionarySetValue(options,
+                                            kSCNetworkReachabilityOptionPTRAddress,
+                                            kCFBooleanTrue);
+                       continue;
+               }
 
-                       data = CFDataCreate(NULL, (const UInt8 *)&hints, sizeof(hints));
-                       CFDictionarySetValue(options, kSCNetworkReachabilityOptionHints, data);
-                       CFRelease(data);
+               if (strlen(argv[i]) == 0) {
+                       continue;
                }
+
+               SCPrint(TRUE, stderr, CFSTR("Unrecognized option: %s\n"), argv[i]);
+               CFRelease(options);
+               exit(1);
        }
 
        if (interface != NULL) {
@@ -186,9 +153,13 @@ _setupReachabilityOptions(int argc, char **argv, const char *interface)
 static SCNetworkReachabilityRef
 _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
 {
-       char                            *ip_address     = argv[0];
+       const char                      *ip_address     = argv[0];
+       char                            *ip_addressN    = NULL;
        const char                      *interface;
        CFMutableDictionaryRef          options         = NULL;
+       const char                      *remote_address = NULL;
+       char                            *remote_addressN= NULL;
+       const char                      *remote_interface;
        struct sockaddr_in              sin;
        struct sockaddr_in6             sin6;
        SCNetworkReachabilityRef        target          = NULL;
@@ -201,17 +172,41 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
        sin6.sin6_len    = sizeof(sin6);
        sin6.sin6_family = AF_INET6;
 
-       interface = strchr(argv[0], '%');
+       interface = strchr(ip_address, '%');
        if (interface != NULL) {
-               ip_address = strdup(argv[0]);
-               ip_address[interface - argv[0]] = '\0';
+               ip_addressN = strdup(ip_address);
+               ip_addressN[interface - ip_address] = '\0';
+               ip_address = ip_addressN;
                interface++;
        }
 
+       if ((argc > 1) && (strlen(argv[1]) > 0)) {
+               remote_address = argv[1];
+
+               remote_interface = strchr(remote_address, '%');
+               if (remote_interface != NULL) {
+                       remote_addressN = strdup(remote_address);
+                       remote_addressN[remote_interface - remote_address] = '\0';
+                       remote_address = remote_addressN;
+                       remote_interface++;
+               }
+       }
+
        if (inet_aton(ip_address, &sin.sin_addr) == 1) {
-               if ((argc == 1) ||
-                   ((argc > 1) && (strlen(argv[1]) == 0))) {
-                       options = _setupReachabilityOptions(argc, argv, interface);
+               struct sockaddr_in      r_sin;
+
+               if (argc > 1) {
+                       bzero(&r_sin, sizeof(r_sin));
+                       r_sin.sin_len    = sizeof(r_sin);
+                       r_sin.sin_family = AF_INET;
+               }
+
+               if ((argc == 1)
+                   || (remote_address == NULL)
+                   || (inet_aton(remote_address, &r_sin.sin_addr) == 0)) {
+                       if (argc > 2) {
+                               options = _setupReachabilityOptions(argc - 2, argv + 2, interface);
+                       }
                        if (options == NULL) {
                                target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin);
                                if (context != NULL) {
@@ -238,40 +233,19 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
                                }
                        }
                } else {
-                       char                    *remote_address = argv[1];
-                       const char              *interface2;
-                       struct sockaddr_in      r_sin;
-
-                       interface2 = strchr(argv[1], '%');
-                       if (interface2 != NULL) {
-                               remote_address = strdup(argv[1]);
-                               remote_address[interface2 - argv[1]] = '\0';
-                               interface2++;
-
-                               if ((interface != NULL) && (strcmp(interface, interface2) != 0)) {
+                       if (remote_interface != NULL) {
+                               if ((interface != NULL) && (strcmp(interface, remote_interface) != 0)) {
                                        SCPrint(TRUE, stderr,
                                                CFSTR("Interface mismatch \"%s\" != \"%s\"\n"),
                                                interface,
-                                               interface2);
+                                               remote_interface);
                                        exit(1);
                                }
 
-                               interface = interface2;
-                       }
-
-                       bzero(&r_sin, sizeof(r_sin));
-                       r_sin.sin_len    = sizeof(r_sin);
-                       r_sin.sin_family = AF_INET;
-                       if (inet_aton(remote_address, &r_sin.sin_addr) == 0) {
-                               SCPrint(TRUE, stderr, CFSTR("Could not interpret address \"%s\"\n"), remote_address);
-                               exit(1);
-                       }
-
-                       if (remote_address != argv[1]) {
-                               free(remote_address);
+                               interface = remote_interface;
                        }
 
-                       options = _setupReachabilityOptions(argc, argv, interface);
+                       options = _setupReachabilityOptions(argc - 2, argv + 2, interface);
                        if (options == NULL) {
                                target = SCNetworkReachabilityCreateWithAddressPair(NULL,
                                                                                    (struct sockaddr *)&sin,
@@ -303,14 +277,25 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
                                }
                        }
                }
-       } else if (inet_pton(AF_INET6, argv[0], &sin6.sin6_addr) == 1) {
+       } else if (inet_pton(AF_INET6, ip_address, &sin6.sin6_addr) == 1) {
+               struct sockaddr_in6     r_sin6;
+
                if (interface != NULL) {
                        sin6.sin6_scope_id = if_nametoindex(interface);
                }
 
-               if ((argc == 1) ||
-                   ((argc > 1) && (strlen(argv[1]) == 0))) {
-                       options = _setupReachabilityOptions(argc, argv, NULL);
+               if (argc > 1) {
+                       bzero(&r_sin6, sizeof(r_sin6));
+                       r_sin6.sin6_len    = sizeof(r_sin6);
+                       r_sin6.sin6_family = AF_INET6;
+               }
+
+               if ((argc == 1)
+                   || (remote_address == NULL)
+                   || (inet_pton(AF_INET6, remote_address, &r_sin6.sin6_addr) == 0)) {
+                       if (argc > 2) {
+                               options = _setupReachabilityOptions(argc - 2, argv + 2, NULL);
+                       }
                        if (options == NULL) {
                                target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin6);
                                if (context != NULL) {
@@ -328,22 +313,19 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
                                }
                        }
                } else {
-                       struct sockaddr_in6     r_sin6;
-
-                       bzero(&r_sin6, sizeof(r_sin6));
-                       r_sin6.sin6_len         = sizeof(r_sin6);
-                       r_sin6.sin6_family      = AF_INET6;
-                       if (inet_pton(AF_INET6, argv[1], &r_sin6.sin6_addr) == 0) {
-                               SCPrint(TRUE, stderr, CFSTR("Could not interpret address \"%s\"\n"), argv[1]);
-                               exit(1);
-                       }
+                       if (remote_interface != NULL) {
+                               r_sin6.sin6_scope_id = if_nametoindex(remote_interface);
 
-                       interface = strchr(argv[1], '%');
-                       if (interface != NULL) {
-                               r_sin6.sin6_scope_id = if_nametoindex(interface);
+                               if ((interface != NULL) && (strcmp(interface, remote_interface) != 0)) {
+                                       SCPrint(TRUE, stderr,
+                                               CFSTR("Interface mismatch \"%s\" != \"%s\"\n"),
+                                               interface,
+                                               remote_interface);
+                                       exit(1);
+                               }
                        }
 
-                       options = _setupReachabilityOptions(argc, argv, NULL);
+                       options = _setupReachabilityOptions(argc - 2, argv + 2, NULL);
                        if (options == NULL) {
                                target = SCNetworkReachabilityCreateWithAddressPair(NULL,
                                                                                    (struct sockaddr *)&sin6,
@@ -367,18 +349,21 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
                        }
                }
        } else {
-               CFStringRef     str;
-
-               options = _setupReachabilityOptions(argc, argv, NULL);
-
-               if (((argc == 1) && (strlen(argv[0]) > 0)) ||
-                   ((argc > 1) && (strlen(argv[0]) > 0) && (strlen(argv[1]) == 0))) {
+               if (argc == 1) {
+                       target = SCNetworkReachabilityCreateWithName(NULL, argv[0]);
+                       if (context != NULL) {
+                               context->info = "by name";
+                       }
+               } else {
+                       options = _setupReachabilityOptions(argc - 1, argv + 1, NULL);
                        if (options == NULL) {
                                target = SCNetworkReachabilityCreateWithName(NULL, argv[0]);
                                if (context != NULL) {
                                        context->info = "by name";
                                }
                        } else {
+                               CFStringRef     str;
+
                                str  = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
                                CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
                                CFRelease(str);
@@ -387,49 +372,47 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
                                        context->info = "by name w/options";
                                }
                        }
-               } else {
-                       CFIndex         n_options;
+               }
+       }
 
-                       if (options == NULL) {
-                               options = CFDictionaryCreateMutable(NULL,
-                                                                   0,
-                                                                   &kCFTypeDictionaryKeyCallBacks,
-                                                                   &kCFTypeDictionaryValueCallBacks);
-                       }
-                       n_options = CFDictionaryGetCount(options);
+       if (ip_addressN != NULL) {
+               free(ip_addressN);
+       }
 
-                       if (strlen(argv[0]) > 0) {
-                               str  = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
-                               CFRelease(str);
-                       }
-                       if (strlen(argv[1]) > 0) {
-                               str  = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionServName, str);
-                               CFRelease(str);
-                       }
+       if (remote_addressN != NULL) {
+               free(remote_addressN);
+       }
 
-                       if (CFDictionaryGetCount(options) > n_options) {
-                               if (context != NULL) {
-                                       if (n_options == 0) {
-                                               context->info = "by (node and/or serv) name";
+       if ((target == NULL) && (options != NULL)) {
+               if (CFDictionaryContainsKey(options, kSCNetworkReachabilityOptionPTRAddress)) {
+                       CFDataRef       address;
+
+                       address = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionRemoteAddress);
+                       if (address == NULL) {
+                               SCPrint(TRUE, stderr, CFSTR("No address\n"));
+                               exit(1);
+                       }
+                       CFDictionarySetValue(options, kSCNetworkReachabilityOptionPTRAddress, address);
+                       CFDictionaryRemoveValue(options, kSCNetworkReachabilityOptionRemoteAddress);
+
+                       if (context != NULL) {
+                               CFIndex n       = CFDictionaryGetCount(options);
+
+                               if (n == 1) {
+                                       context->info = "by PTR";
+                               } else if (CFDictionaryContainsKey(options,
+                                                                  kSCNetworkReachabilityOptionInterface)) {
+                                       if (n == 2) {
+                                               context->info = "by PTR w/scope";
                                        } else {
-                                               context->info = "by (node and/or serv) name w/options";
+                                               context->info = "by PTR w/scope and options";
                                        }
+                               } else {
+                                       context->info = "by PTR w/options";
                                }
-                       } else {
-                               SCPrint(TRUE, stderr, CFSTR("Must specify nodename or servname\n"));
-                               CFRelease(options);
-                               exit(1);
                        }
                }
-       }
 
-       if (ip_address != argv[0]) {
-               free(ip_address);
-       }
-
-       if ((target == NULL) && (options != NULL)) {
                target = SCNetworkReachabilityCreateWithOptions(NULL, options);
                CFRelease(options);
        }
@@ -437,90 +420,30 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
        return target;
 }
 
-static void
-_printReachabilityFlags(SCNetworkReachabilityFlags flags)
-{
-       if (flags != 0) {
-               if (flags & kSCNetworkReachabilityFlagsReachable) {
-                       SCPrint(TRUE, stdout, CFSTR("Reachable"));
-                       flags &= ~kSCNetworkReachabilityFlagsReachable;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-               if (flags & kSCNetworkReachabilityFlagsTransientConnection) {
-                       SCPrint(TRUE, stdout, CFSTR("Transient Connection"));
-                       flags &= ~kSCNetworkReachabilityFlagsTransientConnection;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-               if (flags & kSCNetworkReachabilityFlagsConnectionRequired) {
-                       SCPrint(TRUE, stdout, CFSTR("Connection Required"));
-                       flags &= ~kSCNetworkReachabilityFlagsConnectionRequired;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-               if (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) {
-                       SCPrint(TRUE, stdout, CFSTR("Automatic Connection On Traffic"));
-                       flags &= ~kSCNetworkReachabilityFlagsConnectionOnTraffic;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-               if (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) {
-                       SCPrint(TRUE, stdout, CFSTR("Automatic Connection On Demand"));
-                       flags &= ~kSCNetworkReachabilityFlagsConnectionOnDemand;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-               if (flags & kSCNetworkReachabilityFlagsInterventionRequired) {
-                       SCPrint(TRUE, stdout, CFSTR("Intervention Required"));
-                       flags &= ~kSCNetworkReachabilityFlagsInterventionRequired;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-               if (flags & kSCNetworkReachabilityFlagsIsLocalAddress) {
-                       SCPrint(TRUE, stdout, CFSTR("Local Address"));
-                       flags &= ~kSCNetworkReachabilityFlagsIsLocalAddress;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-               if (flags & kSCNetworkReachabilityFlagsIsDirect) {
-                       SCPrint(TRUE, stdout, CFSTR("Directly Reachable Address"));
-                       flags &= ~kSCNetworkReachabilityFlagsIsDirect;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-#if    TARGET_OS_IPHONE
-               if (flags & kSCNetworkReachabilityFlagsIsWWAN) {
-                       SCPrint(TRUE, stdout, CFSTR("WWAN"));
-                       flags &= ~kSCNetworkReachabilityFlagsIsWWAN;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-#endif // TARGET_OS_IPHONE
-               if (flags != 0) {
-                       SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
-               }
-       } else {
-               SCPrint(TRUE, stdout, CFSTR("Not Reachable"));
-       }
-
-       return;
-}
 
 static void
 _printReachability(SCNetworkReachabilityRef target)
 {
        SCNetworkReachabilityFlags      flags;
        Boolean                         ok;
+       CFStringRef                     str;
 
        ok = SCNetworkReachabilityGetFlags(target, &flags);
        if (!ok) {
-               printf("    could not determine reachability, %s\n", SCErrorString(SCError()));
+               SCPrint(TRUE, stderr, CFSTR("    could not determine reachability, %s\n"), SCErrorString(SCError()));
                return;
        }
 
-       SCPrint(_sc_debug, stdout, CFSTR("flags = 0x%08x ("), flags);
-       _printReachabilityFlags(flags);
-       SCPrint(_sc_debug, stdout, CFSTR(")"));
+       str = __SCNetworkReachabilityCopyFlags(flags, CFSTR("flags = "), _sc_debug);
+       SCPrint(TRUE, stdout, CFSTR("%@\n"), str);
+       CFRelease(str);
 
-       if (resolver_bypass) {
-               int if_index =
-                       SCNetworkReachabilityGetInterfaceIndex(target);
-               SCPrint(_sc_debug, stdout, CFSTR("interface index = %d"), if_index);
-       }
+       if (resolver_bypass && _sc_debug) {
+               int     if_index;
 
-       SCPrint(TRUE, stdout, CFSTR("\n"));
+               if_index = SCNetworkReachabilityGetInterfaceIndex(target);
+               SCPrint(TRUE, stdout, CFSTR("interface index = %d\n"), if_index);
+       }
 
        return;
 }
@@ -547,6 +470,7 @@ do_checkReachability(int argc, char **argv)
 static void
 _printNWIFlags(nwi_ifstate_flags flags)
 {
+       flags &= NWI_IFSTATE_FLAGS_MASK;
        if (flags == 0) {
                return;
        }
@@ -567,8 +491,23 @@ _printNWIFlags(nwi_ifstate_flags flags)
                flags &= ~NWI_IFSTATE_FLAGS_HAS_DNS;
                SCPrint(flags != 0, stdout, CFSTR(","));
        }
+       if (flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST) {
+               SCPrint(TRUE, stdout, CFSTR("NOT-IN-LIST"));
+               flags &= ~NWI_IFSTATE_FLAGS_NOT_IN_LIST;
+               SCPrint(flags != 0, stdout, CFSTR(","));
+       }
+       if (flags & NWI_IFSTATE_FLAGS_HAS_SIGNATURE) {
+               SCPrint(TRUE, stdout, CFSTR("SIGNATURE"));
+               flags &= ~NWI_IFSTATE_FLAGS_HAS_SIGNATURE;
+               SCPrint(flags != 0, stdout, CFSTR(","));
+       }
+       if (flags & NWI_IFSTATE_FLAGS_NOT_IN_IFLIST) {
+               SCPrint(TRUE, stdout, CFSTR("NOT-IN-IFLIST"));
+               flags &= ~NWI_IFSTATE_FLAGS_NOT_IN_IFLIST;
+               SCPrint(flags != 0, stdout, CFSTR(","));
+       }
        if (flags != 0) {
-               SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
+               SCPrint(TRUE, stdout, CFSTR("%p"), (void *)flags);
        }
        SCPrint(TRUE, stdout, CFSTR(")"));
 
@@ -576,79 +515,210 @@ _printNWIFlags(nwi_ifstate_flags flags)
 }
 
 
-__private_extern__
-void
-do_nwi(int argc, char **argv)
+static void
+_printNWIInfo(nwi_ifstate_t ifstate)
+{
+       nwi_ifstate_flags               ifstate_flags;
+       SCNetworkReachabilityFlags      reach_flags = nwi_ifstate_get_reachability_flags(ifstate);
+       const uint8_t                   *signature;
+       int                             signature_length;
+       CFStringRef                     str;
+       const struct sockaddr           *vpn_addr = nwi_ifstate_get_vpn_server(ifstate);
+
+       ifstate_flags = nwi_ifstate_get_flags(ifstate);
+       if (_sc_debug) {
+               ifstate_flags |= ifstate->flags;
+       }
+
+       SCPrint(TRUE, stdout,
+               CFSTR(" %7s : flags %p"),
+               nwi_ifstate_get_ifname(ifstate),
+               (void *)ifstate_flags);
+       _printNWIFlags(ifstate_flags);
+
+       str = __SCNetworkReachabilityCopyFlags(reach_flags, CFSTR("           reach "), TRUE);
+       SCPrint(TRUE, stdout, CFSTR("\n%@"), str);
+       CFRelease(str);
+
+       if (vpn_addr != NULL) {
+               char vpn_ntopbuf[INET6_ADDRSTRLEN];
+
+               _SC_sockaddr_to_string(vpn_addr, vpn_ntopbuf, sizeof(vpn_ntopbuf));
+               SCPrint(TRUE, stdout, CFSTR("\n           VPN server: %s"), vpn_ntopbuf);
+       }
+
+       signature = nwi_ifstate_get_signature(ifstate, AF_UNSPEC, &signature_length);
+       if (signature != NULL) {
+               CFDataRef       digest  = NULL;
+
+               digest = CFDataCreate(NULL, signature, CC_SHA1_DIGEST_LENGTH);
+               SCPrint(TRUE, stdout, CFSTR("\n           Signature Hash: %@"), digest);
+               CFRelease(digest);
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("\n           Signature Hash: <empty>"));
+       }
+
+       SCPrint(TRUE, stdout, CFSTR("\n           generation %llu\n"),
+               nwi_ifstate_get_generation(ifstate));
+
+       return;
+}
+
+
+static void
+_printNWIReachInfo(nwi_state_t state, int af)
+{
+       uint32_t        reach_flags;
+       CFStringRef     str;
+
+       reach_flags = nwi_state_get_reachability_flags(state, af);
+
+       str = __SCNetworkReachabilityCopyFlags(reach_flags, CFSTR("   REACH : flags "), TRUE);
+       SCPrint(TRUE, stdout, CFSTR("\n%@\n"), str);
+       CFRelease(str);
+
+       return;
+}
+
+
+static void
+do_printNWI(int argc, char **argv, nwi_state_t state)
 {
+       unsigned int    count;
        nwi_ifstate_t   ifstate;
-       nwi_state_t     state   = nwi_state_copy();
 
        if (state == NULL) {
                SCPrint(TRUE, stdout, CFSTR("No network information\n"));
-               exit(1);
+               return;
        }
 
        if (argc > 0) {
                ifstate = nwi_state_get_ifstate(state, argv[0]);
                if (ifstate != NULL) {
-                       nwi_ifstate_flags       flags   = nwi_ifstate_get_flags(ifstate);
-
-                       SCPrint(TRUE, stdout, CFSTR("Network interface information\n"), argv[0]);
-                       SCPrint(TRUE, stdout,
-                               CFSTR(" %7s : flags %p"),
-                               nwi_ifstate_get_ifname(ifstate),
-                               flags);
-                       _printNWIFlags(flags);
-                       SCPrint(TRUE, stdout, CFSTR("\n"));
+                       nwi_ifstate_t   alias;
+
+                       _printNWIInfo(ifstate);
+
+                       alias = nwi_ifstate_get_alias(ifstate,
+                                                     ifstate->af == AF_INET ? AF_INET6 : AF_INET);
+                       if (alias != NULL) {
+                               SCPrint(TRUE, stdout, CFSTR("\n"));
+                               _printNWIInfo(alias);
+                       }
                } else {
                        SCPrint(TRUE, stdout, CFSTR("No network information (for %s)\n"), argv[0]);
                }
-
-               goto done;
+               return;
        }
 
-       SCPrint(TRUE, stdout, CFSTR("Network information\n"));
+       SCPrint(TRUE, stdout, CFSTR("Network information (generation %llu)"),
+               nwi_state_get_generation(state));
+
        SCPrint(TRUE, stdout, CFSTR("\nIPv4 network interface information\n"));
+
        ifstate = nwi_state_get_first_ifstate(state, AF_INET);
+       if (ifstate == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("   No IPv4 states found\n"));
+       } else {
+               while (ifstate != NULL) {
+                       _printNWIInfo(ifstate);
+                       ifstate = nwi_ifstate_get_next(ifstate, AF_INET);
+               }
+       }
+       _printNWIReachInfo(state, AF_INET);
 
+       SCPrint(TRUE, stdout, CFSTR("\nIPv6 network interface information\n"));
+
+       ifstate = nwi_state_get_first_ifstate(state, AF_INET6);
        if (ifstate == NULL) {
-               SCPrint(TRUE, stdout, CFSTR(" No IPv4 states found\n"));
+               SCPrint(TRUE, stdout, CFSTR("   No IPv6 states found\n"));
+       } else {
+               while (ifstate != NULL) {
+                       _printNWIInfo(ifstate);
+                       ifstate = nwi_ifstate_get_next(ifstate, AF_INET6);
+               }
        }
+       _printNWIReachInfo(state, AF_INET6);
 
-       while (ifstate != NULL) {
-               nwi_ifstate_flags       flags   = nwi_ifstate_get_flags(ifstate);
+       count = nwi_state_get_interface_names(state, NULL, 0);
+       if (count > 0) {
+               const char *    names[count];
 
-               SCPrint(TRUE, stdout,
-                       CFSTR(" %7s : flags %p"),
-                       nwi_ifstate_get_ifname(ifstate),
-                       flags);
-               _printNWIFlags(flags);
-               SCPrint(TRUE, stdout, CFSTR("\n"));
-               ifstate = nwi_ifstate_get_next(ifstate, AF_INET);
+               count = nwi_state_get_interface_names(state, names, count);
+               if (count > 0) {
+                       int i;
+
+                       printf("\nNetwork interfaces:");
+                       for (i = 0; i < count; i++) {
+                               printf(" %s", names[i]);
+                       }
+                       printf("\n");
+               }
        }
+       return;
+}
 
-       SCPrint(TRUE, stdout, CFSTR("\nIPv6 network interface information\n"));
-       ifstate = nwi_state_get_first_ifstate(state, AF_INET6);
 
-       if (ifstate == NULL) {
-               SCPrint(TRUE, stdout, CFSTR(" No IPv6 states found\n"));
+__private_extern__
+void
+do_showNWI(int argc, char **argv)
+{
+       nwi_state_t     state;
+
+       state = nwi_state_copy();
+       do_printNWI(argc, argv, state);
+       if (state != NULL) {
+               nwi_state_release(state);
+       } else {
+               exit(1);
        }
 
-       while (ifstate != NULL) {
-               nwi_ifstate_flags       flags   = nwi_ifstate_get_flags(ifstate);
+       exit(0);
+}
+
 
-               SCPrint(TRUE, stdout,
-                       CFSTR(" %7s : flags %p"),
-                       nwi_ifstate_get_ifname(ifstate),
-                       flags);
-               _printNWIFlags(flags);
-               SCPrint(TRUE, stdout, CFSTR("\n"));
-               ifstate = nwi_ifstate_get_next(ifstate, AF_INET6);
+__private_extern__
+void
+do_watchNWI(int argc, char **argv)
+{
+       nwi_state_t     state;
+       int             status;
+       int             token;
+
+       state = nwi_state_copy();
+       do_printNWI(argc, argv, state);
+       if (state != NULL) {
+               nwi_state_release(state);
        }
 
-    done :
+       status = notify_register_dispatch(nwi_state_get_notify_key(),
+                                         &token,
+                                         dispatch_get_main_queue(),
+                                         ^(int token){
+                                                 nwi_state_t           state;
+                                                 struct tm             tm_now;
+                                                 struct timeval        tv_now;
+
+                                                 (void)gettimeofday(&tv_now, NULL);
+                                                 (void)localtime_r(&tv_now.tv_sec, &tm_now);
+                                                 SCPrint(TRUE, stdout, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
+                                                         tm_now.tm_hour,
+                                                         tm_now.tm_min,
+                                                         tm_now.tm_sec,
+                                                         tv_now.tv_usec / 1000);
+
+                                                 state = nwi_state_copy();
+                                                 do_printNWI(argc, argv, state);
+                                                 if (state != NULL) {
+                                                         nwi_state_release(state);
+                                                 }
+                                         });
+       if (status != NOTIFY_STATUS_OK) {
+               SC_log(LOG_INFO, "notify_register_dispatch() failed for nwi changes, status=%u", status);
+               exit(1);
+       }
 
-       nwi_state_release(state);
+       CFRunLoopRun();
        exit(0);
 }
 
@@ -726,7 +796,7 @@ do_watchReachability(int argc, char **argv)
        }
 
        if (doDispatch) {
-               if (!SCNetworkReachabilitySetDispatchQueue(target_async, dispatch_get_current_queue())) {
+               if (!SCNetworkReachabilitySetDispatchQueue(target_async, dispatch_get_main_queue())) {
                        printf("SCNetworkReachabilitySetDispatchQueue() failed: %s\n", SCErrorString(SCError()));
                        exit(1);
                }
@@ -750,87 +820,22 @@ do_watchReachability(int argc, char **argv)
 
 
 static void
-showResolver(dns_resolver_t *resolver, int index)
+do_printDNSConfiguration(int argc, char **argv, dns_config_t *dns_config)
 {
-       int     i;
-
-       SCPrint(TRUE, stdout, CFSTR("\nresolver #%d\n"), index);
-
-       if (resolver->domain != NULL) {
-               SCPrint(TRUE, stdout, CFSTR("  domain   : %s\n"), resolver->domain);
-       }
-
-       for (i = 0; i < resolver->n_search; i++) {
-               SCPrint(TRUE, stdout, CFSTR("  search domain[%d] : %s\n"), i, resolver->search[i]);
-       }
-
-       for (i = 0; i < resolver->n_nameserver; i++) {
-               char    buf[128];
-
-               _SC_sockaddr_to_string(resolver->nameserver[i], buf, sizeof(buf));
-               SCPrint(TRUE, stdout, CFSTR("  nameserver[%d] : %s\n"), i, buf);
-       }
-
-       for (i = 0; i < resolver->n_sortaddr; i++) {
-               char    abuf[32];
-               char    mbuf[32];
-
-               (void)inet_ntop(AF_INET, &resolver->sortaddr[i]->address, abuf, sizeof(abuf));
-               (void)inet_ntop(AF_INET, &resolver->sortaddr[i]->mask,    mbuf, sizeof(mbuf));
-               SCPrint(TRUE, stdout, CFSTR("  sortaddr[%d] : %s/%s\n"), i, abuf, mbuf);
-       }
-
-       if (resolver->options != NULL) {
-               SCPrint(TRUE, stdout, CFSTR("  options  : %s\n"), resolver->options);
-       }
-
-       if (resolver->port != 0) {
-               SCPrint(TRUE, stdout, CFSTR("  port     : %hd\n"), resolver->port);
-       }
-
-       if (resolver->timeout != 0) {
-               SCPrint(TRUE, stdout, CFSTR("  timeout  : %d\n"), resolver->timeout);
-       }
+       int     _sc_log_save;
 
-       if (resolver->if_index != 0) {
-               char    buf[IFNAMSIZ];
-               char    *if_name;
-
-               if_name = if_indextoname(resolver->if_index, buf);
-               SCPrint(TRUE, stdout, CFSTR("  if_index : %d (%s)\n"),
-                       resolver->if_index,
-                       (if_name != NULL) ? if_name : "?");
-       }
-
-       if (resolver->flags != 0) {
-               uint32_t        flags   = resolver->flags;
-
-               SCPrint(TRUE, stdout, CFSTR("  flags    : "));
-               SCPrint(_sc_debug, stdout, CFSTR("0x%08x ("), flags);
-               if (flags & DNS_RESOLVER_FLAGS_SCOPED) {
-                       SCPrint(TRUE, stdout, CFSTR("Scoped"));
-                       flags &= ~DNS_RESOLVER_FLAGS_SCOPED;
-                       SCPrint(flags != 0, stdout, CFSTR(","));
-               }
-               if (flags != 0) {
-                       SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
-               }
-               SCPrint(_sc_debug, stdout, CFSTR(")"));
-               SCPrint(TRUE, stdout, CFSTR("\n"));
+       if (dns_config == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
+               return;
        }
 
-       if (resolver->reach_flags != 0) {
-               uint32_t        flags   = resolver->reach_flags;
-
-               SCPrint(TRUE, stdout, CFSTR("  reach    : "));
-               SCPrint(_sc_debug, stdout, CFSTR("0x%08x ("), flags);
-               _printReachabilityFlags(flags);
-               SCPrint(_sc_debug, stdout, CFSTR(")"));
-               SCPrint(TRUE, stdout, CFSTR("\n"));
-       }
+       _sc_log_save = _sc_log;
+       _sc_log = FALSE;
+       _dns_configuration_log(dns_config, _sc_debug);
+       _sc_log = _sc_log_save;
 
-       if (resolver->search_order != 0) {
-               SCPrint(TRUE, stdout, CFSTR("  order    : %d\n"), resolver->search_order);
+       if (_sc_debug) {
+               SCPrint(TRUE, stdout, CFSTR("\ngeneration = %llu\n"), dns_config->generation);
        }
 
        return;
@@ -841,78 +846,62 @@ __private_extern__
 void
 do_showDNSConfiguration(int argc, char **argv)
 {
-       dns_config_t                    *dns_config;
-       SCNetworkReachabilityRef        target;
+       dns_config_t    *dns_config;
 
        dns_config = dns_configuration_copy();
-
-       if (dns_config == NULL) {
-               SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
+       do_printDNSConfiguration(argc, argv, dns_config);
+       if (dns_config != NULL) {
+               dns_configuration_free(dns_config);
+       } else {
                exit(1);
        }
 
-       if (argc > 1) {
-               int                             dns_config_index        = -1;
-               SCNetworkReachabilityFlags      flags                   = 0;
-               Boolean                         haveDNS                 = FALSE;
-               Boolean                         ok                      = FALSE;
-               dns_resolver_t                  *resolver;
-               uint32_t                        resolver_if_index;
-               SCNetworkReachabilityPrivateRef targetPrivate;
-
-               target = _setupReachability(argc, argv, NULL);
-
-               targetPrivate = (SCNetworkReachabilityPrivateRef)target;
-
-               if (targetPrivate->type != reachabilityTypeName) {
-                       SCPrint(TRUE, stdout, CFSTR("\"%s\" is not a hostname.\n"), argv[0]);
-                       exit(1);
-               }
-
-               ok = __SC_checkResolverReachabilityInternal(&store, &flags,
-                                                           &haveDNS, targetPrivate->name, NULL,
-                                                           &resolver_if_index, &dns_config_index);
-
-               if (!ok) {
-                       SCPrint(TRUE, stdout, CFSTR("No DNS configuration available.\n" ));
-                       exit(1);
-               }
-
-               SCPrint(TRUE, stdout, CFSTR("DNS configuration for %s\n"),
-                       targetPrivate->name);
-
-               if (targetPrivate->if_index == 0) {
-                       resolver = dns_config->resolver[dns_config_index];
-               } else {
-                       resolver = dns_config->scoped_resolver[dns_config_index];
-               }
-
-               showResolver(resolver, dns_config_index + 1);
-
-               if (target != NULL) CFRelease(target);
-       } else {
-               int     i;
-
-               SCPrint(TRUE, stdout, CFSTR("DNS configuration\n"));
-
-               for (i = 0; i < dns_config->n_resolver; i++) {
-                       dns_resolver_t  *resolver       = dns_config->resolver[i];
+       exit(0);
+}
 
-                       showResolver(resolver, i + 1);
-               }
 
-               if ((dns_config->n_scoped_resolver > 0) && (dns_config->scoped_resolver != NULL)) {
-                       SCPrint(TRUE, stdout, CFSTR("\nDNS configuration (for scoped queries)\n"));
+__private_extern__
+void
+do_watchDNSConfiguration(int argc, char **argv)
+{
+       dns_config_t    *dns_config;
+       int             status;
+       int             token;
 
-                       for (i = 0; i < dns_config->n_scoped_resolver; i++) {
-                               dns_resolver_t  *resolver       = dns_config->scoped_resolver[i];
+       dns_config = dns_configuration_copy();
+       do_printDNSConfiguration(argc, argv, dns_config);
+       if (dns_config != NULL) {
+               dns_configuration_free(dns_config);
+       }
 
-                               showResolver(resolver, i + 1);
-                       }
-               }
+       status = notify_register_dispatch(dns_configuration_notify_key(),
+                                         &token,
+                                         dispatch_get_main_queue(),
+                                         ^(int token){
+                                                 dns_config_t          *dns_config;
+                                                 struct tm             tm_now;
+                                                 struct timeval        tv_now;
+
+                                                 (void)gettimeofday(&tv_now, NULL);
+                                                 (void)localtime_r(&tv_now.tv_sec, &tm_now);
+                                                 SCPrint(TRUE, stdout, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
+                                                         tm_now.tm_hour,
+                                                         tm_now.tm_min,
+                                                         tm_now.tm_sec,
+                                                         tv_now.tv_usec / 1000);
+
+                                                 dns_config = dns_configuration_copy();
+                                                 do_printDNSConfiguration(argc, argv, dns_config);
+                                                 if (dns_config != NULL) {
+                                                         dns_configuration_free(dns_config);
+                                                 }
+                                         });
+       if (status != NOTIFY_STATUS_OK) {
+               SC_log(LOG_INFO, "notify_register_dispatch() failed for DNS configuration changes, status=%u", status);
+               exit(1);
        }
 
-       dns_configuration_free(dns_config);
+       CFRunLoopRun();
        exit(0);
 }
 
@@ -924,8 +913,9 @@ showProxy(CFDictionaryRef proxy)
 
        if (!_sc_debug) {
                cleaned = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
-               CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesSupplemental);
                CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesScoped);
+               CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesServices);
+               CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesSupplemental);
                proxy = cleaned;
        }
 
@@ -939,9 +929,22 @@ __private_extern__
 void
 do_showProxyConfiguration(int argc, char **argv)
 {
-       CFDictionaryRef proxies;
+       CFMutableDictionaryRef  options = NULL;
+       CFDictionaryRef         proxies;
+
+       if (getenv("BYPASS_GLOBAL_PROXY") != NULL) {
+               options = CFDictionaryCreateMutable(NULL, 0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+               CFDictionaryAddValue(options, kSCProxiesNoGlobal, kCFBooleanTrue);
+       }
+
+       proxies = SCDynamicStoreCopyProxiesWithOptions(NULL, options);
+
+       if (options != NULL) {
+               CFRelease(options);
+       }
 
-       proxies = SCDynamicStoreCopyProxies(NULL);
        if (proxies != NULL) {
                CFStringRef     interface       = NULL;
                CFStringRef     server          = NULL;
@@ -1005,7 +1008,7 @@ do_showProxyConfiguration(int argc, char **argv)
                                        CFDictionaryRef proxy;
 
                                        proxy = CFArrayGetValueAtIndex(matching, i);
-                                       SCPrint(TRUE, stdout, CFSTR("\nproxy #%d\n"), i + 1);
+                                       SCPrint(TRUE, stdout, CFSTR("\nproxy #%ld\n"), i + 1);
                                        showProxy(proxy);
                                }
 
@@ -1036,14 +1039,121 @@ do_snapshot(int argc, char **argv)
                SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
        }
 
-#ifdef HAVE_REACHABILITY_SERVER
-       (void) _SCNetworkReachabilityServer_snapshot();
-#endif // HAVE_REACHABILITY_SERVER
-
        return;
 }
 
 
+__private_extern__
+void
+do_renew(char *if_name)
+{
+       CFArrayRef      services;
+       Boolean         ok      = FALSE;
+
+       if ((if_name == NULL) || (strlen(if_name) == 0)) {
+               SCPrint(TRUE, stderr, CFSTR("No interface name\n"));
+               exit(1);
+       }
+
+       if (getenv("ATTEMPT_DHCP_RENEW_WITH_SCDYNAMICSTORE") != NULL) {
+               CFArrayRef      interfaces;
+
+               interfaces = SCNetworkInterfaceCopyAll();
+               if (interfaces != NULL) {
+                       CFIndex         i;
+                       CFStringRef     match_name;
+                       CFIndex         n;
+
+                       match_name = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII);
+                       assert(match_name != NULL);
+
+                       n = CFArrayGetCount(interfaces);
+                       for (i = 0; i < n; i++) {
+                               CFStringRef             bsd_name;
+                               SCNetworkInterfaceRef   interface;
+
+                               interface = CFArrayGetValueAtIndex(interfaces, i);
+                               bsd_name = SCNetworkInterfaceGetBSDName(interface);
+                               if (_SC_CFEqual(bsd_name, match_name)) {
+                                       // if match
+                                       ok = SCNetworkInterfaceForceConfigurationRefresh(interface);
+                                       if (!ok) {
+                                               int     status;
+
+                                               status = SCError();
+                                               if (status != kSCStatusAccessError) {
+                                                       SCPrint(TRUE, stderr, CFSTR("%s\n"), SCErrorString(status));
+                                                       exit(1);
+                                               }
+
+                                               // ... and if can't write the SCDynamicStore, try w/prefs
+                                       }
+
+                                       break;
+                               }
+                       }
+
+                       CFRelease(match_name);
+                       CFRelease(interfaces);
+               }
+
+               if (ok) {
+                       exit(0);
+               }
+       }
+
+       do_prefs_init();        /* initialization */
+       do_prefs_open(0, NULL); /* open default prefs */
+
+       services = SCNetworkServiceCopyAll(prefs);
+       if (services != NULL) {
+               CFIndex         i;
+               CFStringRef     match_name;
+               CFIndex         n;
+
+               match_name = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII);
+               assert(match_name != NULL);
+
+               n = CFArrayGetCount(services);
+               for (i = 0; i < n; i++) {
+                       CFStringRef             bsd_name;
+                       SCNetworkInterfaceRef   interface;
+                       SCNetworkServiceRef     service;
+
+                       service = CFArrayGetValueAtIndex(services, i);
+                       interface = SCNetworkServiceGetInterface(service);
+                       if (interface == NULL) {
+                               // if no interface
+                               continue;
+                       }
+
+                       bsd_name = SCNetworkInterfaceGetBSDName(interface);
+                       if (_SC_CFEqual(bsd_name, match_name)) {
+                               // if match
+                               ok = SCNetworkInterfaceForceConfigurationRefresh(interface);
+                               if (!ok) {
+                                       SCPrint(TRUE, stderr, CFSTR("%s\n"), SCErrorString(SCError()));
+                                       exit(1);
+                               }
+
+                               break;
+                       }
+               }
+
+               CFRelease(match_name);
+               CFRelease(services);
+       }
+
+       if (!ok) {
+               SCPrint(TRUE, stderr, CFSTR("No interface\n"));
+               exit(1);
+       }
+
+       _prefs_close();
+       exit(0);
+}
+
+
 static void
 waitKeyFound()
 {
@@ -1116,8 +1226,9 @@ do_wait(char *waitKey, int timeout)
        CFRunLoopRun();
 }
 
-#ifdef TEST_DNS_CONFIGURATION_COPY
+#ifdef TEST_DNS_CONFIGURATION
 
+Boolean                        doDispatch      = FALSE;
 CFRunLoopSourceRef     notifyRls       = NULL;
 SCDynamicStoreRef      store           = NULL;
 CFPropertyListRef      value           = NULL;
@@ -1125,8 +1236,26 @@ CFPropertyListRef        value           = NULL;
 int
 main(int argc, char **argv)
 {
+       dns_config_t    *dns_config;
+
+fprintf(stdout, "copy configuration\n");
+       dns_config = dns_configuration_copy();
+       if (dns_config != NULL) {
+
+fprintf(stdout, "sleeping for 120 seconds\n");
+sleep(120);
+
+fprintf(stdout, "sending ack\n");
+               _dns_configuration_ack(dns_config, "TEST_DNS_CONFIGURATION");
+
+fprintf(stdout, "sleeping for 120 seconds\n");
+sleep(120);
+
+               dns_configuration_free(dns_config);
+       }
+
        do_showDNSConfiguration(argc, argv);
        exit(0);
 }
 
-#endif // TEST_DNS_CONFIGURATION_COPY
+#endif // TEST_DNS_CONFIGURATION