]> git.saurik.com Git - apple/configd.git/blobdiff - SystemConfiguration.fproj/reachability/SCNetworkReachabilityServer_server.c
configd-801.1.1.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / reachability / SCNetworkReachabilityServer_server.c
diff --git a/SystemConfiguration.fproj/reachability/SCNetworkReachabilityServer_server.c b/SystemConfiguration.fproj/reachability/SCNetworkReachabilityServer_server.c
deleted file mode 100644 (file)
index 50f090c..0000000
+++ /dev/null
@@ -1,2125 +0,0 @@
-/*
- * Copyright (c) 2011-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,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * 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 <CoreFoundation/CoreFoundation.h>
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-#include "SCNetworkReachabilityInternal.h"
-
-#include <fcntl.h>
-#include <paths.h>
-#include <CommonCrypto/CommonDigest.h>
-#include <dispatch/dispatch.h>
-#include <dispatch/private.h>
-#include <xpc/xpc.h>
-#include <xpc/private.h>
-#include <sys/rbtree.h>
-
-
-#pragma mark -
-#pragma mark Globals
-
-
-/*
- * S_debug
- *   A boolean that enables additional logging.
- */
-static boolean_t       S_debug         = FALSE;
-
-
-#pragma mark -
-#pragma mark Support functions
-
-
-static void
-log_xpc_object(const char *msg, xpc_object_t obj)
-{
-       char            *desc;
-
-       desc = xpc_copy_description(obj);
-       SCLog(S_debug, LOG_INFO, CFSTR("%s = %s"), msg, desc);
-       free(desc);
-}
-
-
-static __inline__ void
-my_CFDictionaryApplyFunction(CFDictionaryRef                   theDict,
-                            CFDictionaryApplierFunction        applier,
-                            void                               *context)
-{
-       CFAllocatorRef  myAllocator;
-       CFDictionaryRef myDict;
-
-       myAllocator = CFGetAllocator(theDict);
-       myDict      = CFDictionaryCreateCopy(myAllocator, theDict);
-       CFDictionaryApplyFunction(myDict, applier, context);
-       CFRelease(myDict);
-       return;
-}
-
-
-#pragma mark -
-#pragma mark SCNetworkReachability target support
-
-
-static CFMutableDictionaryRef  reach_digest_map;
-
-
-static dispatch_queue_t
-_server_concurrent_queue()
-{
-       static dispatch_once_t  once;
-       static dispatch_queue_t q;
-
-       dispatch_once(&once, ^{
-               q = dispatch_queue_create(REACH_SERVICE_NAME ".concurrent",
-                                         DISPATCH_QUEUE_CONCURRENT);
-       });
-
-       return q;
-}
-
-
-static dispatch_queue_t
-_server_digest_queue()
-{
-       static dispatch_once_t  once;
-       static dispatch_queue_t q;
-
-       dispatch_once(&once, ^{
-               q = dispatch_queue_create(REACH_SERVICE_NAME ".digest", NULL);
-       });
-
-       return q;
-}
-
-
-static dispatch_group_t
-_target_group(SCNetworkReachabilityRef target)
-{
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       return targetPrivate->serverGroup;
-}
-
-
-static dispatch_queue_t
-_target_queue(SCNetworkReachabilityRef target)
-{
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       return targetPrivate->serverQueue;
-}
-
-
-#pragma mark -
-
-
-/*
- * _target_reference_add
- *
- * Note: use dispatch_sync(_server_digest_queue(), ^{ ... });
- */
-static void
-_target_reference_add(SCNetworkReachabilityRef target, CFDataRef digest, xpc_connection_t connection)
-{
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       // take a reference to the target
-       CFRetain(target);
-
-       // ensure that we have a dispatch group
-       if (targetPrivate->serverGroup == NULL) {
-               targetPrivate->serverGroup = dispatch_group_create();
-       }
-
-       // ensure that we have a dispatch queue
-       if (targetPrivate->serverQueue == NULL) {
-               char    qname[256];
-
-               snprintf(qname, sizeof(qname), "com.apple.SCNetworkReachability.%p.server", target);
-               targetPrivate->serverQueue = dispatch_queue_create(qname, NULL);
-       }
-
-       // bump the reference count
-       if (_SC_ATOMIC_INC(&targetPrivate->serverReferences) == 0) {
-               // and maintain a digest-->target mapping
-               targetPrivate->serverDigest = CFRetain(digest);
-               CFDictionarySetValue(reach_digest_map, digest, target);
-       }
-
-       if (S_debug) {
-               CFStringRef     str;
-
-               str = _SCNetworkReachabilityCopyTargetDescription(target);
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("<%p>   target %p: reference added (%@, %d)"),
-                     connection,
-                     target,
-                     str,
-                     targetPrivate->serverReferences);
-               CFRelease(str);
-       }
-
-       return;
-}
-
-
-/*
- * _target_reference_remove
- *
- * Note: use dispatch_sync(_server_digest_queue(), ^{ ... });
- */
-static void
-_target_reference_remove(SCNetworkReachabilityRef target, xpc_connection_t connection)
-{
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       // drop the reference count
-       if (_SC_ATOMIC_DEC(&targetPrivate->serverReferences) == 0) {
-               /*
-                * if that was the last reference, we no longer need to
-                * keep the digest-->target mapping
-                */
-               CFDictionaryRemoveValue(reach_digest_map, targetPrivate->serverDigest);
-               CFRelease(targetPrivate->serverDigest);
-               targetPrivate->serverDigest = NULL;
-       }
-
-       if (S_debug) {
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("<%p>   target %p: reference removed (%d)"),
-                     connection,
-                     target,
-                     targetPrivate->serverReferences);
-       }
-
-       // release a reference to the target
-       CFRelease(target);
-
-       return;
-}
-
-
-#pragma mark -
-
-
-#define        MUTEX_LOCK(m) {                                                 \
-       int _lock_ = (pthread_mutex_lock(m) == 0);                      \
-       assert(_lock_);                                                 \
-}
-
-#define        MUTEX_UNLOCK(m) {                                               \
-       int _unlock_ = (pthread_mutex_unlock(m) == 0);                  \
-       assert(_unlock_);                                               \
-}
-
-
-static void
-_target_reply_add_reachability(SCNetworkReachabilityRef target,
-                              xpc_object_t             reply)
-{
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       MUTEX_LOCK(&targetPrivate->lock);
-
-       xpc_dictionary_set_uint64(reply,
-                                 REACH_STATUS_CYCLE,
-                                 targetPrivate->info.cycle);
-       xpc_dictionary_set_uint64(reply,
-                                 REACH_STATUS_FLAGS,
-                                 targetPrivate->info.flags);
-       xpc_dictionary_set_uint64(reply,
-                                 REACH_STATUS_IF_INDEX,
-                                 targetPrivate->info.if_index);
-       xpc_dictionary_set_data  (reply,
-                                 REACH_STATUS_IF_NAME,
-                                 targetPrivate->info.if_name,
-                                 sizeof(targetPrivate->info.if_name));
-       xpc_dictionary_set_bool  (reply,
-                                 REACH_STATUS_SLEEPING,
-                                 targetPrivate->info.sleeping);
-       if (isReachabilityTypeName(targetPrivate->type)) {
-               if (isA_CFArray(targetPrivate->resolvedAddresses)) {
-                       xpc_object_t    addresses;
-                       CFIndex         i;
-                       CFIndex         n;
-
-                       addresses = xpc_array_create(NULL, 0);
-
-                       n = CFArrayGetCount(targetPrivate->resolvedAddresses);
-                       for (i = 0; i < n; i++) {
-                               if (targetPrivate->type == reachabilityTypeName) {
-                                       CFDataRef       address;
-
-                                       address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddresses, i);
-                                       xpc_array_set_data(addresses,
-                                                          XPC_ARRAY_APPEND,
-                                                          CFDataGetBytePtr(address),
-                                                          CFDataGetLength(address));
-                               } else if (targetPrivate->type == reachabilityTypePTR) {
-                                       CFStringRef     name;
-                                       char            str[MAXHOSTNAMELEN];
-
-                                       name = CFArrayGetValueAtIndex(targetPrivate->resolvedAddresses, i);
-                                       _SC_cfstring_to_cstring(name, str, sizeof(str), kCFStringEncodingUTF8);
-                                       xpc_array_set_string(addresses, XPC_ARRAY_APPEND, str);
-                               }
-                       }
-
-                       xpc_dictionary_set_value(reply,
-                                                REACH_STATUS_RESOLVED_ADDRESSES,
-                                                addresses);
-                       xpc_release(addresses);
-               }
-               xpc_dictionary_set_int64(reply,
-                                        REACH_STATUS_RESOLVED_ERROR,
-                                        targetPrivate->resolvedError);
-               xpc_dictionary_set_uint64(reply,
-                                         REACH_STATUS_DNS_FLAGS,
-                                         targetPrivate->dnsFlags);
-
-       }
-
-       MUTEX_UNLOCK(&targetPrivate->lock);
-
-       return;
-}
-
-
-#pragma mark -
-
-
-typedef struct {
-       xpc_connection_t        connection;
-       uint64_t                target_id;
-} reach_watcher_key_t;
-
-typedef struct {
-       unsigned int            n_changes;
-} reach_watcher_val_t;
-
-
-static CFDataRef
-_target_watcher_key_create(xpc_connection_t    connection,
-                          uint64_t             target_id)
-{
-       CFDataRef               key;
-       reach_watcher_key_t     watcher_key;
-
-       watcher_key.connection = connection;
-       watcher_key.target_id  = target_id;
-
-       key = CFDataCreate(NULL, (UInt8 *)&watcher_key, sizeof(watcher_key));
-       return key;
-}
-
-
-static Boolean
-_target_watcher_add(SCNetworkReachabilityRef   target,
-                   xpc_connection_t            connection,
-                   uint64_t                    target_id)
-{
-       __block Boolean         ok      = TRUE;
-       dispatch_queue_t        q;
-
-       q = _target_queue(target);
-       dispatch_sync(q, ^{
-               CFDataRef                       key;
-               SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-               if (targetPrivate->serverWatchers == NULL) {
-                       ok = SCNetworkReachabilitySetDispatchQueue(target, q);
-                       if (!ok) {
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("<%p> target %p: _watcher_add SCNetworkReachabilitySetDispatchQueue() failed: %s"),
-                                     connection,
-                                     target,
-                                     SCErrorString(SCError()));
-                               return;
-                       }
-
-                       targetPrivate->serverWatchers = CFDictionaryCreateMutable(NULL,
-                                                                                 0,
-                                                                                 &kCFTypeDictionaryKeyCallBacks,
-                                                                                 &kCFTypeDictionaryValueCallBacks);
-               }
-
-               xpc_retain(connection);
-
-               key = _target_watcher_key_create(connection, target_id);
-               if (CFDictionaryContainsKey(targetPrivate->serverWatchers, key)) {
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("<%p>   target %p: watcher not added, c=0x%0llx, \"serverWatchers\" key exists"),
-                             connection,
-                             target,
-                             target_id);
-               } else {
-                       CFDataRef                               val;
-                       static const reach_watcher_val_t        watcher_val0    = { 0 };
-
-                       val = CFDataCreate(NULL, (UInt8 *)&watcher_val0, sizeof(watcher_val0));
-                       CFDictionaryAddValue(targetPrivate->serverWatchers, key, val);
-                       CFRelease(val);
-
-                       if (S_debug) {
-                               SCLog(TRUE, LOG_INFO,
-                                     CFSTR("<%p>   target %p: watcher added, c=0x%0llx, n=%ld"),
-                                     connection,
-                                     target,
-                                     target_id,
-                                     CFDictionaryGetCount(targetPrivate->serverWatchers));
-                       }
-               }
-               CFRelease(key);
-       });
-
-       return ok;
-}
-
-
-static Boolean
-_target_watcher_checkin(SCNetworkReachabilityRef       target,
-                       xpc_connection_t                connection,
-                       uint64_t                        target_id)
-{
-       __block Boolean         scheduled       = FALSE;
-
-       dispatch_sync(_target_queue(target), ^{
-               CFDataRef                       key;
-               unsigned int                    n;
-               SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-               CFDataRef                       val;
-               reach_watcher_val_t             *watcher_val;
-
-               if (targetPrivate->serverWatchers == NULL) {
-                       // if no watchers
-                       return;
-               }
-
-               key = _target_watcher_key_create(connection, target_id);
-               val = CFDictionaryGetValue(targetPrivate->serverWatchers, key);
-               CFRelease(key);
-               if (val == NULL) {
-                       // if the target [for this client] was not scheduled
-                       return;
-               }
-
-               // indicate that the target was scheduled
-               scheduled = TRUE;
-
-               /*
-                * and note that the reachability flags for this target have
-                * been picked up by the client
-                */
-               /* ALIGN: CF aligns to at least >8 byte boundries */
-               watcher_val = (reach_watcher_val_t *)(void *)CFDataGetBytePtr(val);
-               n = _SC_ATOMIC_ZERO(&watcher_val->n_changes);
-               if (S_debug && (n > 0)) {
-                       SCLog(TRUE, LOG_INFO,
-                             CFSTR("<%p> target %p: SCNetworkReachabilityGetFlags() after %d notification%s"),
-                             connection,
-                             target,
-                             n,
-                             (n == 1) ? "" : "s");
-               }
-       });
-
-       return scheduled;
-}
-
-
-static Boolean
-_target_watcher_remove(SCNetworkReachabilityRef        target,
-                      xpc_connection_t         connection,
-                      uint64_t                 target_id)
-{
-       __block Boolean         ok      = TRUE;
-
-       dispatch_sync(_target_queue(target), ^{
-               CFDataRef                       key;
-               CFIndex                         n;
-               SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-               if (targetPrivate->serverWatchers == NULL) {
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("<%p>   target %p: watcher not removed, c=0x%0llx, no \"serverWatchers\""),
-                             connection,
-                             target,
-                             target_id);
-                       ok = FALSE;
-                       return;
-               }
-
-               key = _target_watcher_key_create(connection, target_id);
-               if (!CFDictionaryContainsKey(targetPrivate->serverWatchers, key)) {
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("<%p>   target %p: watcher not removed, c=0x%0llx, no \"serverWatchers\" key"),
-                             connection,
-                             target,
-                             target_id);
-                       CFRelease(key);
-                       ok = FALSE;
-                       return;
-               }
-
-               CFDictionaryRemoveValue(targetPrivate->serverWatchers, key);
-               CFRelease(key);
-
-               n = CFDictionaryGetCount(targetPrivate->serverWatchers);
-
-               if (S_debug) {
-                       SCLog(TRUE, LOG_INFO,
-                             CFSTR("<%p>   target %p: watcher removed, c=0x%0llx, n=%ld"),
-                             connection,
-                             target,           // server
-                             target_id,        // client
-                             n);
-               }
-
-               if (n == 0) {
-                       CFRelease(targetPrivate->serverWatchers);
-                       targetPrivate->serverWatchers = NULL;
-
-                       ok = SCNetworkReachabilitySetDispatchQueue(target, NULL);
-                       if (!ok) {
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("<%p> target %p: _watcher_remove SCNetworkReachabilitySetDispatchQueue() failed: %s"),
-                                     connection,
-                                     target,
-                                     SCErrorString(SCError()));
-                               return;
-                       }
-
-                       // no more watchers, flags are no longer valid
-                       if (_SC_ATOMIC_CMPXCHG(&targetPrivate->serverInfoValid, TRUE, FALSE)) {
-                               if (S_debug) {
-                                       SCLog(TRUE, LOG_INFO, CFSTR("%s  flags are no longer \"valid\""),
-                                             targetPrivate->log_prefix);
-                               }
-                       }
-               }
-
-               xpc_release(connection);
-       });
-
-       return ok;
-}
-
-
-#pragma mark -
-#pragma mark Reachability [RBT] client support
-
-
-typedef struct {
-       rb_node_t               rbn;
-       xpc_connection_t        connection;
-       pid_t                   pid;
-       const char              *proc_name;
-       CFMutableDictionaryRef  targets;        // target_id --> SCNetworkReachabilityRef
-} reach_client_t;
-
-
-static int
-_rbt_compare_transaction_nodes(void *context, const void *n1, const void *n2)
-{
-       uint64_t        a = (uintptr_t)((reach_client_t *)n1)->connection;
-       uint64_t        b = (uintptr_t)((reach_client_t *)n2)->connection;
-
-       if (a == b) {
-               return 0;
-       } else if (a < b) {
-               return -1;
-       } else {
-               return 1;
-       }
-}
-
-
-static int
-_rbt_compare_transaction_key(void *context, const void *n1, const void *key)
-{
-       uint64_t        a = (uintptr_t)((reach_client_t *)n1)->connection;
-       uint64_t        b = *(uintptr_t *)key;
-
-       if (a == b) {
-               return 0;
-       } else if (a < b) {
-               return -1;
-       } else {
-               return 1;
-       }
-}
-
-
-static rb_tree_t *
-_reach_clients_rbt()
-{
-       static dispatch_once_t          once;
-       static const rb_tree_ops_t      ops = {
-               .rbto_compare_nodes     = _rbt_compare_transaction_nodes,
-               .rbto_compare_key       = _rbt_compare_transaction_key,
-               .rbto_node_offset       = offsetof(reach_client_t, rbn),
-               .rbto_context           = NULL
-       };
-       static rb_tree_t                rbt;
-
-       dispatch_once(&once, ^{
-               rb_tree_init(&rbt, &ops);
-       });
-
-       return &rbt;
-}
-
-
-static dispatch_queue_t
-_reach_clients_rbt_queue()
-{
-       static dispatch_once_t  once;
-       static dispatch_queue_t q;
-
-       dispatch_once(&once, ^{
-               q = dispatch_queue_create(REACH_SERVICE_NAME ".clients.rbt", NULL);
-       });
-
-       return q;
-}
-
-
-static reach_client_t *
-_reach_client_create(xpc_connection_t connection)
-{
-       reach_client_t  *client;
-
-       client = calloc(1, sizeof(*client));
-       client->connection = connection;
-       client->pid = xpc_connection_get_pid(connection);
-       client->proc_name = NULL;
-       client->targets = CFDictionaryCreateMutable(NULL,
-                                                   0,
-                                                   &kCFTypeDictionaryKeyCallBacks,
-                                                   &kCFTypeDictionaryValueCallBacks);
-
-       return client;
-}
-
-
-static void
-_reach_client_release(reach_client_t *client)
-{
-       if (client->proc_name != NULL) {
-               free((void *)client->proc_name);
-       }
-       CFRelease(client->targets);
-       free(client);
-       return;
-}
-
-
-static void
-_reach_client_remove_target(const void *key, const void *value, void *context)
-{
-       xpc_connection_t                connection      = (xpc_connection_t)context;
-       SCNetworkReachabilityRef        target          = (SCNetworkReachabilityRef)value;
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       // check if we have anyone watching this target
-       if (targetPrivate->serverWatchers != NULL) {
-               CFIndex         n;
-
-               n = CFDictionaryGetCount(targetPrivate->serverWatchers);
-               if (n > 0) {
-                       CFIndex         i;
-                       CFDictionaryRef serverWatchers;
-                       const void *    watchers_q[32];
-                       const void **   watchers        = watchers_q;
-
-                       serverWatchers = CFDictionaryCreateCopy(NULL, targetPrivate->serverWatchers);
-
-                       if (n > sizeof(watchers_q)/sizeof(watchers[0])) {
-                               watchers = CFAllocatorAllocate(NULL, n * sizeof(CFDataRef), 0);
-                       }
-                       CFDictionaryGetKeysAndValues(serverWatchers, watchers, NULL);
-
-                       for (i = 0; i < n; i++) {
-                               CFDataRef               key;
-                               reach_watcher_key_t     *watcher_key;
-
-                               key = (CFDataRef)watchers[i];
-                               /* ALIGN: CF aligns to >8 byte boundries */
-                               watcher_key = (reach_watcher_key_t *)(void *)CFDataGetBytePtr(key);
-                               if (watcher_key->connection == connection) {
-                                       // remove watcher references for THIS connection
-                                       _target_watcher_remove(target,
-                                                              watcher_key->connection,
-                                                              watcher_key->target_id);
-                               }
-                       }
-
-                       if (watchers != watchers_q) {
-                               CFAllocatorDeallocate(NULL, watchers);
-                       }
-
-                       CFRelease(serverWatchers);
-               }
-       }
-
-       // remove our reference to this target
-       dispatch_sync(_server_digest_queue(), ^{
-               _target_reference_remove(target, connection);
-       });
-
-       return;
-}
-
-
-static void
-_reach_client_remove(xpc_connection_t connection)
-{
-       uint64_t        connection_id   = (uintptr_t)connection;
-
-       dispatch_sync(_reach_clients_rbt_queue(), ^{
-               reach_client_t  *client;
-               rb_tree_t       *rbt    = _reach_clients_rbt();
-
-               client = rb_tree_find_node(rbt, &connection_id);
-               if (client != NULL) {
-                       // remove any remaining target references (for this client)
-                       my_CFDictionaryApplyFunction(client->targets,
-                                                    _reach_client_remove_target,
-                                                    (void *)connection);
-
-                       rb_tree_remove_node(rbt, client);
-                       _reach_client_release(client);
-               } else {
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("<%p> _reach_client_remove: unexpected client"),
-                             connection);
-               }
-       });
-
-       return;
-}
-
-
-static __inline__ CFDataRef
-_client_target_key_create(uint64_t target_id)
-{
-       CFDataRef       target_key;
-
-       target_key = CFDataCreate(NULL, (UInt8 *)&target_id, sizeof(target_id));
-       return target_key;
-}
-
-
-static SCNetworkReachabilityRef
-_client_target_copy(reach_client_t *client, uint64_t target_id)
-{
-       SCNetworkReachabilityRef        target;
-       CFDataRef                       target_key;
-
-       target_key = _client_target_key_create(target_id);
-       target = CFDictionaryGetValue(client->targets, target_key);
-       CFRelease(target_key);
-
-       if (target != NULL) {
-               CFRetain(target);
-       }
-
-       return target;
-}
-
-
-static Boolean
-_client_target_set(reach_client_t *client, uint64_t target_id, SCNetworkReachabilityRef target)
-{
-       Boolean         added;
-       CFDataRef       target_key;
-
-       target_key = _client_target_key_create(target_id);
-       added = !CFDictionaryContainsKey(client->targets, target_key);
-       if (added) {
-               CFDictionarySetValue(client->targets, target_key, target);
-       }
-       CFRelease(target_key);
-
-       return added;
-}
-
-
-static void
-_client_target_remove(reach_client_t *client, uint64_t target_id)
-{
-       CFDataRef       target_key;
-
-       target_key = _client_target_key_create(target_id);
-       CFDictionaryRemoveValue(client->targets, target_key);
-       CFRelease(target_key);
-
-       return;
-}
-
-
-#pragma mark -
-#pragma mark Reachability [XPC] server functions
-
-
-static dispatch_queue_t
-_reach_server_queue()
-{
-       static dispatch_once_t  once;
-       static dispatch_queue_t q;
-
-       dispatch_once(&once, ^{
-               q = dispatch_queue_create(REACH_SERVICE_NAME, NULL);
-       });
-
-       return q;
-}
-
-
-/*
- * _reach_changed
- *
- * Note: should be exec'd on the target queue
- */
-static void
-_reach_changed(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
-{
-       CFIndex                         i;
-       CFIndex                         n;
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-       const void *                    watcher_keys_q[32];
-       const void **                   watcher_keys    = watcher_keys_q;
-       const void *                    watcher_vals_q[32];
-       const void **                   watcher_vals    = watcher_vals_q;
-
-       if (S_debug) {
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("%sprocess reachability changed, flags = 0x%08x"),
-                     targetPrivate->log_prefix,
-                     flags);
-       }
-
-       if (targetPrivate->serverWatchers == NULL) {
-               // if no watchers
-               return;
-       }
-
-       n = CFDictionaryGetCount(targetPrivate->serverWatchers);
-       if (n == 0) {
-               // if no watchers
-               return;
-       }
-
-       if (!isReachabilityTypeName(targetPrivate->type) || !targetPrivate->dnsNoAddressesSinceLastTimeout) {
-               /*
-                * Because we are actively watching for additional changes
-                * we mark the flags as "valid"
-                */
-               if (_SC_ATOMIC_CMPXCHG(&targetPrivate->serverInfoValid, FALSE, TRUE)) {
-                       if (S_debug) {
-                               SCLog(TRUE, LOG_INFO, CFSTR("%s  flags are now \"valid\""),
-                                     targetPrivate->log_prefix);
-                       }
-               }
-       }
-
-       // notify all of the watchers
-       if (n > sizeof(watcher_keys_q)/sizeof(watcher_keys[0])) {
-               watcher_keys = CFAllocatorAllocate(NULL, n * sizeof(CFDataRef), 0);
-               watcher_vals = CFAllocatorAllocate(NULL, n * sizeof(CFDataRef), 0);
-       }
-
-       CFDictionaryGetKeysAndValues(targetPrivate->serverWatchers,
-                                    watcher_keys,
-                                    watcher_vals);
-
-       for (i = 0; i < n; i++) {
-               xpc_connection_t        connection;
-               CFDataRef               key;
-               uint64_t                target_id;
-               CFDataRef               val;
-               reach_watcher_key_t     *watcher_key;
-               reach_watcher_val_t     *watcher_val;
-
-               val = (CFDataRef)watcher_vals[i];
-               /* ALIGN: CF aligns to >8 byte boundries */
-               watcher_val = (reach_watcher_val_t *)(void *)CFDataGetBytePtr(val);
-
-               if (_SC_ATOMIC_INC(&watcher_val->n_changes) > 0) {
-                       // if we've already sent a notification
-                       continue;
-               }
-
-               key = (CFDataRef)watcher_keys[i];
-               /* ALIGN: CF aligns to >8 byte boundries */
-               watcher_key = (reach_watcher_key_t *)(void *)CFDataGetBytePtr(key);
-
-               connection = xpc_retain(watcher_key->connection);
-               target_id  = watcher_key->target_id;
-               dispatch_async(_reach_server_queue(), ^{
-                       xpc_object_t    reply;
-
-                       // create our [async] notification
-                       reply = xpc_dictionary_create(NULL, NULL, 0);
-
-                       // set notification
-                       xpc_dictionary_set_int64(reply,
-                                                MESSAGE_NOTIFY,
-                                                MESSAGE_REACHABILITY_STATUS);
-
-                       // set target ID
-                       xpc_dictionary_set_uint64(reply,
-                                                 REACH_CLIENT_TARGET_ID,
-                                                 target_id);
-
-                       log_xpc_object("  reply [async]", reply);
-                       xpc_connection_send_message(connection, reply);
-
-                       xpc_release(reply);
-                       xpc_release(connection);
-               });
-       }
-
-       if (n > sizeof(watcher_keys_q)/sizeof(watcher_keys[0])) {
-               CFAllocatorDeallocate(NULL, watcher_keys);
-               CFAllocatorDeallocate(NULL, watcher_vals);
-       }
-
-       return;
-}
-
-
-static void
-sanitize_address(const struct sockaddr *from, struct sockaddr *to)
-{
-       switch (from->sa_family) {
-               case AF_INET : {
-                       /* ALIGN: cast okay, alignment not assumed. */
-                       struct sockaddr_in *from4       = (struct sockaddr_in *)(void *)from;
-                       struct sockaddr_in *to4         = (struct sockaddr_in *)(void *)to;
-
-                       bzero(to4, sizeof(*to4));
-                       to4->sin_len = sizeof(*to4);
-                       to4->sin_family = AF_INET;
-                       bcopy(&from4->sin_addr, &to4->sin_addr, sizeof(to4->sin_addr));
-                       break;
-               }
-
-               case AF_INET6 : {
-                       /* ALIGN: cast okay, alignment not assumed. */
-                       struct sockaddr_in6 *from6      = (struct sockaddr_in6 *)(void *)from;
-                       struct sockaddr_in6 *to6        = (struct sockaddr_in6 *)(void *)to;
-
-                       bzero(to6, sizeof(*to6));
-                       to6->sin6_len = sizeof(*to6);
-                       to6->sin6_family = AF_INET6;
-                       bcopy(&from6->sin6_addr, &to6->sin6_addr, sizeof(to6->sin6_addr));
-                       to6->sin6_scope_id = from6->sin6_scope_id;
-                       break;
-               }
-
-               default:
-                       bcopy(from, to, from->sa_len);
-                       break;
-       }
-
-       return;
-}
-
-
-static void
-target_add(reach_client_t *client, xpc_object_t request)
-{
-       const char                              *name;
-       const struct sockaddr                   *localAddress;
-       struct sockaddr_storage                 localAddress0;
-       const struct sockaddr                   *remoteAddress;
-       struct sockaddr_storage                 remoteAddress0;
-       const struct sockaddr                   *ptrAddress;
-       struct sockaddr_storage                 ptrAddress0;
-       int64_t                                 if_index;
-       const char                              *if_name        = NULL;
-       bool                                    onDemandBypass  = FALSE;
-       bool                                    resolverBypass  = FALSE;
-       uint64_t                                target_id;
-       uid_t                                   uid             = 0;
-
-
-       unsigned char                           bytes[CC_SHA1_DIGEST_LENGTH];
-       CC_SHA1_CTX                             ctx;
-       CFDataRef                               digest          = NULL;
-       size_t                                  len;
-       xpc_connection_t                        remote;
-       xpc_object_t                            reply;
-       uint64_t                                status          = REACH_REQUEST_REPLY_FAILED;
-
-       Boolean                                 added;
-       __block Boolean                         ok              = TRUE;
-       __block SCNetworkReachabilityRef        target          = NULL;
-
-       if (S_debug) {
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("<%p> create reachability target"),
-                     client->connection);
-//             log_xpc_object("  create", request);
-       }
-
-       remote = xpc_dictionary_get_remote_connection(request);
-       reply = xpc_dictionary_create_reply(request);
-       if (reply == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("<%p> target_add: xpc_dictionary_create_reply: failed"),
-                     client->connection);
-               return;
-       }
-
-       target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
-       if (target_id == 0) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "no target ID");
-               goto done;
-       }
-
-       // create a "digest" of the [new] target
-
-       CC_SHA1_Init(&ctx);
-
-       name = xpc_dictionary_get_string(request, REACH_TARGET_NAME);
-       if (name != NULL) {
-               CC_SHA1_Update(&ctx, REACH_TARGET_NAME, sizeof(REACH_TARGET_NAME));
-               CC_SHA1_Update(&ctx, name, (CC_LONG)strlen(name));
-       }
-
-       localAddress = xpc_dictionary_get_data(request, REACH_TARGET_LOCAL_ADDR, &len);
-       if (localAddress != NULL) {
-               if ((len == localAddress->sa_len) && (len <= sizeof(struct sockaddr_storage))) {
-                       sanitize_address(localAddress, (struct sockaddr *)&localAddress0);
-                       CC_SHA1_Update(&ctx, REACH_TARGET_LOCAL_ADDR, sizeof(REACH_TARGET_LOCAL_ADDR));
-                       CC_SHA1_Update(&ctx, &localAddress0, (CC_LONG)len);
-               } else {
-                       xpc_dictionary_set_string(reply,
-                                                 REACH_REQUEST_REPLY_DETAIL,
-                                                 "local address: size error");
-                       goto done;
-               }
-       }
-
-       remoteAddress = xpc_dictionary_get_data(request, REACH_TARGET_REMOTE_ADDR, &len);
-       if (remoteAddress != NULL) {
-               if ((len == remoteAddress->sa_len) && (len <= sizeof(struct sockaddr_storage))) {
-                       sanitize_address(remoteAddress, (struct sockaddr *)&remoteAddress0);
-                       CC_SHA1_Update(&ctx, REACH_TARGET_REMOTE_ADDR, sizeof(REACH_TARGET_REMOTE_ADDR));
-                       CC_SHA1_Update(&ctx, &remoteAddress0, (CC_LONG)len);
-               } else {
-                       xpc_dictionary_set_string(reply,
-                                                 REACH_REQUEST_REPLY_DETAIL,
-                                                 "remote address: size error");
-                       goto done;
-               }
-       }
-
-       ptrAddress = xpc_dictionary_get_data(request, REACH_TARGET_PTR_ADDR, &len);
-       if (ptrAddress != NULL) {
-               if ((len == ptrAddress->sa_len) && (len <= sizeof(struct sockaddr_storage))) {
-                       sanitize_address(ptrAddress, (struct sockaddr *)&ptrAddress0);
-                       CC_SHA1_Update(&ctx, REACH_TARGET_PTR_ADDR, sizeof(REACH_TARGET_PTR_ADDR));
-                       CC_SHA1_Update(&ctx, &ptrAddress0, (CC_LONG)len);
-               } else {
-                       xpc_dictionary_set_string(reply,
-                                                 REACH_REQUEST_REPLY_DETAIL,
-                                                 "ptr address: size error");
-                       goto done;
-               }
-       }
-
-       if_index = xpc_dictionary_get_int64(request, REACH_TARGET_IF_INDEX);
-       if (if_index != 0) {
-               if_name = xpc_dictionary_get_string(request, REACH_TARGET_IF_NAME);
-               if (if_name != NULL) {
-                       CC_SHA1_Update(&ctx, REACH_TARGET_IF_NAME, sizeof(REACH_TARGET_IF_NAME));
-                       CC_SHA1_Update(&ctx, if_name, (CC_LONG)strlen(if_name));
-               }
-       }
-
-
-       onDemandBypass = xpc_dictionary_get_bool(request, REACH_TARGET_ONDEMAND_BYPASS);
-       if (onDemandBypass) {
-               CC_SHA1_Update(&ctx, REACH_TARGET_ONDEMAND_BYPASS, sizeof(REACH_TARGET_ONDEMAND_BYPASS));
-               CC_SHA1_Update(&ctx, &onDemandBypass, sizeof(onDemandBypass));
-       }
-
-       resolverBypass = xpc_dictionary_get_bool(request, REACH_TARGET_RESOLVER_BYPASS);
-       if (resolverBypass) {
-               CC_SHA1_Update(&ctx, REACH_TARGET_RESOLVER_BYPASS, sizeof(REACH_TARGET_RESOLVER_BYPASS));
-               CC_SHA1_Update(&ctx, &resolverBypass, sizeof(resolverBypass));
-       }
-
-       // Grab UID from XPC connection
-       uid = xpc_connection_get_euid(remote);
-       CC_SHA1_Update(&ctx, &uid, sizeof(uid));
-
-
-       CC_SHA1_Final(bytes, &ctx);
-       digest = CFDataCreate(NULL, bytes, sizeof(bytes));
-
-       /*
-        * Check to see if we already have a SCNetworkReachability object
-        * for this digest. If so, we'll share the existing target. If not,
-        * create a new [shared] target.
-        */
-       dispatch_sync(_server_digest_queue(), ^{
-               target = CFDictionaryGetValue(reach_digest_map, digest);
-               if (target != NULL) {
-                       CFRetain(target);
-               } else {
-                       CFDataRef                       data;
-                       CFMutableDictionaryRef          options;
-                       CFStringRef                     str;
-
-                       options = CFDictionaryCreateMutable(NULL,
-                                                           0,
-                                                           &kCFTypeDictionaryKeyCallBacks,
-                                                           &kCFTypeDictionaryValueCallBacks);
-                       if (name != NULL) {
-                               str = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
-                               CFRelease(str);
-                       }
-                       if (localAddress != NULL) {
-                               data = CFDataCreate(NULL, (const UInt8 *)&localAddress0, localAddress0.ss_len);
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionLocalAddress, data);
-                               CFRelease(data);
-                       }
-                       if (remoteAddress != NULL) {
-                               data = CFDataCreate(NULL, (const UInt8 *)&remoteAddress0, remoteAddress0.ss_len);
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
-                               CFRelease(data);
-                       }
-                       if (ptrAddress != NULL) {
-                               data = CFDataCreate(NULL, (const UInt8 *)&ptrAddress0, ptrAddress0.ss_len);
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionPTRAddress, data);
-                               CFRelease(data);
-                       }
-                       if (onDemandBypass) {
-                               CFDictionarySetValue(options,
-                                                    kSCNetworkReachabilityOptionConnectionOnDemandBypass,
-                                                    kCFBooleanTrue);
-                       }
-                       if (resolverBypass) {
-                               CFDictionarySetValue(options,
-                                                    kSCNetworkReachabilityOptionResolverBypass,
-                                                    kCFBooleanTrue);
-                       }
-                       CFDictionarySetValue(options,
-                                            kSCNetworkReachabilityOptionServerBypass,
-                                            kCFBooleanTrue);
-                       target = SCNetworkReachabilityCreateWithOptions(NULL, options);
-                       CFRelease(options);
-                       if (target == NULL) {
-                               xpc_dictionary_set_string(reply,
-                                                         REACH_REQUEST_REPLY_DETAIL,
-                                                         "SCNetworkReachabilityCreateWithOptions failed");
-                               ok = FALSE;
-                               return;
-                       }
-
-                       // Set the UID on the target
-                       ((SCNetworkReachabilityPrivateRef)target)->uid = uid;
-
-                       // because the interface name may not (no longer) be valid we set
-                       // this after we've created the SCNetworkReachability object
-                       if ((if_index != 0) && (if_name != NULL)) {
-                               SCNetworkReachabilityPrivateRef targetPrivate;
-
-                               targetPrivate = (SCNetworkReachabilityPrivateRef)target;
-                               targetPrivate->if_index = (unsigned int)if_index;
-                               strlcpy(targetPrivate->if_name, if_name, sizeof(targetPrivate->if_name));
-                       }
-
-
-                       ok = SCNetworkReachabilitySetCallback(target, _reach_changed, NULL);
-                       if (!ok) {
-                               xpc_dictionary_set_string(reply,
-                                                         REACH_REQUEST_REPLY_DETAIL,
-                                                         "SCNetworkReachabilitySetCallback failed");
-                               CFRelease(target);
-                               target = NULL;
-                               return;
-                       }
-               }
-
-               // bump the number of references to this target
-               _target_reference_add(target, digest, client->connection);
-       });
-
-       if (!ok) {
-               goto done;
-       }
-
-       /*
-        * add an association for the client's target_id to the [shared]
-        * SCNetworkReachability object.
-        */
-       added = _client_target_set(client, target_id, target);
-       if (!added) {
-               // if we already had a reference to the target (e.g. reconnect)
-               dispatch_sync(_server_digest_queue(), ^{
-                       _target_reference_remove(target, client->connection);
-               });
-       }
-
-       status = REACH_REQUEST_REPLY_OK;
-
-    done :
-
-       xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
-//     log_xpc_object("  reply", reply);
-       xpc_connection_send_message(remote, reply);
-       xpc_release(reply);
-
-       if (digest != NULL) CFRelease(digest);
-       if (target != NULL) CFRelease(target);
-       return;
-}
-
-
-static void
-target_remove(reach_client_t *client, xpc_object_t request)
-{
-       xpc_connection_t                remote;
-       xpc_object_t                    reply;
-       uint64_t                        status          = REACH_REQUEST_REPLY_FAILED;
-       SCNetworkReachabilityRef        target          = NULL;
-       uint64_t                        target_id;
-
-       if (S_debug) {
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("<%p> remove reachability target"),
-                     client->connection);
-//             log_xpc_object("  remove", request);
-       }
-
-       remote = xpc_dictionary_get_remote_connection(request);
-       reply = xpc_dictionary_create_reply(request);
-       if (reply == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("<%p> target_remove: xpc_dictionary_create_reply: failed"),
-                     client->connection);
-               return;
-       }
-
-       target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
-       if (target_id == 0) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "no target ID");
-               goto done;
-       }
-
-       target = _client_target_copy(client, target_id);
-       if (target == NULL) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "no target");
-               status = REACH_REQUEST_REPLY_UNKNOWN;
-               goto done;
-       }
-
-       /*
-        * remove the association from the client's target_id to the [shared]
-        * SCNetworkReachability object.
-        */
-       _client_target_remove(client, target_id);
-
-       // drop the number of references to this target
-       dispatch_sync(_server_digest_queue(), ^{
-               _target_reference_remove(target, client->connection);
-       });
-
-       status = REACH_REQUEST_REPLY_OK;
-
-    done :
-
-       xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
-//     log_xpc_object("  reply", reply);
-       xpc_connection_send_message(remote, reply);
-       xpc_release(reply);
-
-       if (target != NULL) CFRelease(target);
-       return;
-}
-
-
-static void
-target_schedule(reach_client_t *client, xpc_object_t request)
-{
-       Boolean                         ok;
-       xpc_connection_t                remote;
-       xpc_object_t                    reply;
-       uint64_t                        status          = REACH_REQUEST_REPLY_FAILED;
-       SCNetworkReachabilityRef        target          = NULL;
-       uint64_t                        target_id;
-
-       if (S_debug) {
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("<%p> schedule reachability target"),
-                     client->connection);
-//             log_xpc_object("  schedule", request);
-       }
-
-       remote = xpc_dictionary_get_remote_connection(request);
-       reply = xpc_dictionary_create_reply(request);
-       if (reply == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("<%p> target_schedule: xpc_dictionary_create_reply: failed"),
-                     client->connection);
-               return;
-       }
-
-       target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
-       if (target_id == 0) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "no target ID");
-               goto done;
-       }
-
-       target = _client_target_copy(client, target_id);
-       if (target == NULL) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "no target");
-               status = REACH_REQUEST_REPLY_UNKNOWN;
-               goto done;
-       }
-
-       // enable monitoring
-       ok = _target_watcher_add(target, client->connection, target_id);
-       if (!ok) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "could not add watcher");
-               goto done;
-       }
-
-       status = REACH_REQUEST_REPLY_OK;
-
-    done :
-
-       xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
-//     log_xpc_object("  reply", reply);
-       xpc_connection_send_message(remote, reply);
-       xpc_release(reply);
-
-       if (target != NULL) CFRelease(target);
-       return;
-}
-
-
-static void
-target_status(reach_client_t *client, xpc_object_t request)
-{
-       xpc_connection_t                remote;
-       xpc_object_t                    reply;
-       __block Boolean                 reply_now       = TRUE;
-       Boolean                         scheduled;
-       uint64_t                        status          = REACH_REQUEST_REPLY_FAILED;
-       SCNetworkReachabilityRef        target          = NULL;
-       uint64_t                        target_id;
-
-       if(S_debug) {
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("<%p> get status of reachability target"),
-                     client->connection);
-//             log_xpc_object("  status", request);
-       }
-
-       remote = xpc_dictionary_get_remote_connection(request);
-       reply = xpc_dictionary_create_reply(request);
-       if (reply == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("<%p> target_status: xpc_dictionary_create_reply: failed"),
-                     client->connection);
-               return;
-       }
-
-       target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
-       if (target_id == 0) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("<%p>   target_status: no target"),
-                     client->connection);
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "no target ID");
-               goto done;
-       }
-
-       target = _client_target_copy(client, target_id);
-       if (target == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("<%p>   target_status: no target (0x%0llx)"),
-                     client->connection,
-                     target_id);
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "no target");
-               status = REACH_REQUEST_REPLY_UNKNOWN;
-               goto done;
-       }
-
-       /*
-        * Check to see if the target [for this client] had been "scheduled".
-        *
-        * If so, also mark that we've picked up the current reachability
-        * flags and that any pending notifications have been processed.
-        */
-       scheduled = _target_watcher_checkin(target, client->connection, target_id);
-
-       /*
-        * return current reachability information to the caller
-        */
-       dispatch_sync(_target_queue(target), ^{
-               SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-               if (scheduled) {
-                       /*
-                        * The client "scheduled" this target.  As such, we
-                        * know that this is an async query and that we only
-                        * need to return the "last known" flags.
-                        */
-                       _target_reply_add_reachability(target, reply);
-//                     log_xpc_object("  reply [scheduled]", reply);
-
-                       /*
-                        * ... and if it's not a "name" query then we can mark the
-                        * flags as valid.
-                        */
-                       if (!isReachabilityTypeName(targetPrivate->type)) {
-                               if (_SC_ATOMIC_CMPXCHG(&targetPrivate->serverInfoValid, FALSE, TRUE)) {
-                                       if (S_debug) {
-                                               SCLog(TRUE, LOG_INFO, CFSTR("%s  flags are now \"valid\"."),
-                                                     targetPrivate->log_prefix);
-                                       }
-                               }
-                       }
-
-                       if (S_debug) {
-                               CFStringRef     str;
-
-                               str = _SCNetworkReachabilityCopyTargetFlags(target);
-                               SCLog(TRUE, LOG_INFO,
-                                     CFSTR("<%p>   reply [scheduled%s], %@"),
-                                     client->connection,
-                                     targetPrivate->serverInfoValid ? "/valid" : "",
-                                     str);
-                               CFRelease(str);
-                       }
-               } else {
-                       /*
-                        * The client has NOT "scheduled" this target.  As
-                        * such, we know that this is a sync query and that
-                        * we must return "current" flags.
-                        */
-                       if (targetPrivate->scheduled && targetPrivate->serverInfoValid) {
-                               /*
-                                * The server target has been "scheduled" and we
-                                * have flags that are "current".
-                                */
-                               _target_reply_add_reachability(target, reply);
-//                             log_xpc_object("  reply [scheduled/valid]", reply);
-
-                               if (S_debug) {
-                                       CFStringRef     str;
-
-                                       str = _SCNetworkReachabilityCopyTargetFlags(target);
-                                       SCLog(TRUE, LOG_INFO,
-                                             CFSTR("<%p>   reply [scheduled/valid], %@"),
-                                             client->connection,
-                                             str);
-                                       CFRelease(str);
-                               }
-                       } else {
-                               dispatch_group_t        group;
-
-                               /*
-                                * The server target has NOT been "scheduled" or
-                                * we do not have "current" flags.  This means that
-                                * we must query for the current information and
-                                * return the flags to the client when they are
-                                * available.
-                                */
-
-                               reply_now = FALSE;
-
-                               group = _target_group(target);
-                               if (_SC_ATOMIC_INC(&targetPrivate->serverSyncQueryActive) == 0) {
-                                       CFRetain(target);
-                                       dispatch_group_async(group, _server_concurrent_queue(), ^{
-                                               SCNetworkReachabilityFlags      flags;
-                                               unsigned int                    n;
-                                               Boolean                         ok;
-
-                                               // query for the flags
-                                               ok = SCNetworkReachabilityGetFlags(target, &flags);
-                                               flags = targetPrivate->info.flags;      // get the "raw" flags
-                                               if (!ok) {
-                                                       SCLog(TRUE, LOG_ERR,
-                                                             CFSTR("SCNetworkReachabilityGetFlags() [sync query] failed"
-                                                                   "\n  target = %@"
-                                                                   "\n  status = %s"),
-                                                             target,
-                                                             SCErrorString(SCError()));
-                                               }
-
-                                               /*
-                                                * if we have current flags, if the target has since been
-                                                * scheduled, and this is not a "name" query, then mark as
-                                                * valid.
-                                                */
-                                               if (ok &&
-                                                   targetPrivate->scheduled &&
-                                                   !isReachabilityTypeName(targetPrivate->type)) {
-                                                       if (_SC_ATOMIC_CMPXCHG(&targetPrivate->serverInfoValid, FALSE, TRUE)) {
-                                                               if (S_debug) {
-                                                                       SCLog(TRUE, LOG_INFO, CFSTR("%s  flags are now \"valid\"!"),
-                                                                             targetPrivate->log_prefix);
-                                                               }
-                                                       }
-                                               }
-
-                                               // sync query complete
-                                               n = _SC_ATOMIC_ZERO(&targetPrivate->serverSyncQueryActive);
-                                               if (S_debug) {
-                                                       SCLog(TRUE, LOG_INFO,
-                                                             CFSTR("%sSCNetworkReachabilityGetFlags() [sync query] complete, n = %d"),
-                                                             targetPrivate->log_prefix,
-                                                             n);
-                                               }
-
-                                               CFRelease(target);
-                                       });
-                               }
-
-                               CFRetain(target);
-                               dispatch_group_notify(group, _target_queue(target), ^{
-                                       // flags are now available
-                                       _target_reply_add_reachability(target, reply);
-                                       xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, REACH_REQUEST_REPLY_OK);
-//                                     log_xpc_object("  reply [delayed]", reply);
-
-                                       if (S_debug) {
-                                               CFStringRef     str;
-
-                                               str = _SCNetworkReachabilityCopyTargetFlags(target);
-                                               SCLog(TRUE, LOG_INFO,
-                                                     CFSTR("<%p>   reply [delayed], %@"),
-                                                     client->connection,
-                                                     str);
-                                               CFRelease(str);
-                                       }
-
-                                       xpc_connection_send_message(remote, reply);
-                                       xpc_release(reply);
-
-                                       CFRelease(target);
-                               });
-                       }
-               }
-       });
-
-       status = REACH_REQUEST_REPLY_OK;
-
-    done :
-
-       if (reply_now) {
-               xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
-
-               if (status != REACH_REQUEST_REPLY_OK) {
-//                     log_xpc_object("  reply [!]", reply);
-
-                       if (S_debug) {
-                               SCLog(TRUE, LOG_INFO,
-                                     CFSTR("<%p>   reply [!]"),
-                                     client->connection);
-                       }
-               }
-
-               xpc_connection_send_message(remote, reply);
-               xpc_release(reply);
-       } else if (S_debug) {
-               CFStringRef     str;
-
-               str = _SCNetworkReachabilityCopyTargetFlags(target);
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("<%p>   no reply [yet], %@"),
-                     client->connection,
-                     str);
-               CFRelease(str);
-       }
-
-       if (target != NULL) CFRelease(target);
-       return;
-}
-
-
-static void
-target_unschedule(reach_client_t *client, xpc_object_t request)
-{
-       xpc_connection_t                remote;
-       xpc_object_t                    reply;
-       uint64_t                        status          = REACH_REQUEST_REPLY_FAILED;
-       SCNetworkReachabilityRef        target          = NULL;
-       uint64_t                        target_id;
-
-       if (S_debug) {
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("<%p> unschedule reachability target"),
-                     client->connection);
-//             log_xpc_object("  unschedule", request);
-       }
-
-       remote = xpc_dictionary_get_remote_connection(request);
-       reply = xpc_dictionary_create_reply(request);
-       if (reply == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("<%p> target_unschedule: xpc_dictionary_create_reply: failed"),
-                     client->connection);
-               return;
-       }
-
-       target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
-       if (target_id == 0) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "no target ID");
-               goto done;
-       }
-
-       target = _client_target_copy(client, target_id);
-       if (target == NULL) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "no target");
-               status = REACH_REQUEST_REPLY_UNKNOWN;
-               goto done;
-       }
-
-       // disable monitoring
-       _target_watcher_remove(target, client->connection, target_id);
-
-       status = REACH_REQUEST_REPLY_OK;
-
-    done :
-
-       xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
-//     log_xpc_object("  reply", reply);
-       xpc_connection_send_message(remote, reply);
-       xpc_release(reply);
-
-       if (target != NULL) CFRelease(target);
-       return;
-}
-
-
-#define        SNAPSHOT_PATH_STATE     _PATH_VARTMP "configd-reachability"
-
-
-static void
-_snapshot_digest_watcher(const void *key, const void *value, void *context)
-{
-       __block reach_client_t  *client         = NULL;
-       FILE                    *f              = (FILE *)context;
-       static reach_client_t   no_client       = {
-               .pid = 0,
-               .proc_name = "?",
-       };
-       reach_watcher_key_t     *watcher_key;
-       reach_watcher_val_t     *watcher_val;
-
-       /* ALIGN: CF aligns to >8 byte boundries */
-       watcher_key = (reach_watcher_key_t *)(void *)CFDataGetBytePtr(key);
-       watcher_val = (reach_watcher_val_t *)(void *)CFDataGetBytePtr(value);
-
-       dispatch_sync(_reach_clients_rbt_queue(), ^{
-               uint64_t        connection_id   = (uintptr_t)watcher_key->connection;
-               rb_tree_t       *rbt            = _reach_clients_rbt();
-
-               client = rb_tree_find_node(rbt, &connection_id);
-               if (client == NULL) {
-                       client = &no_client;
-               }
-       });
-
-       SCPrint(TRUE, f,
-               CFSTR("      connection = %p, target(c) = 0x%0llx, command = %s, pid = %d, changes = %u\n"),
-               watcher_key->connection,
-               watcher_key->target_id,
-               client->proc_name,
-               client->pid,
-               watcher_val->n_changes);
-
-       return;
-}
-
-
-static void
-_snapshot_digest(const void *key, const void *value, void *context)
-{
-       FILE                            *f              = (FILE *)context;
-       CFStringRef                     digest          = (CFStringRef)key;
-       dispatch_queue_t                q;
-       SCNetworkReachabilityRef        target          = (SCNetworkReachabilityRef)value;
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       q = _target_queue(target);
-       dispatch_sync(q, ^{
-               CFIndex         nWatchers       = 0;
-
-               if (targetPrivate->serverWatchers != NULL) {
-                       nWatchers = CFDictionaryGetCount(targetPrivate->serverWatchers);
-               }
-
-               SCPrint(TRUE, f, CFSTR("\n  digest : %@\n"), digest);
-               SCPrint(TRUE, f, CFSTR("    %@\n"), target);
-               SCPrint(TRUE, f, CFSTR("    valid = %s, async watchers = %ld, sync queries = %u, refs = %u\n"),
-                       targetPrivate->serverInfoValid ? "Y" : "N",
-                       nWatchers,
-                       targetPrivate->serverSyncQueryActive,
-                       targetPrivate->serverReferences);
-
-               SCPrint(TRUE, f, CFSTR("    network %ld.%3.3d"),
-                       targetPrivate->last_network.tv_sec,
-                       targetPrivate->last_network.tv_usec / 1000);
-#if    !TARGET_OS_IPHONE
-               SCPrint(TRUE, f, CFSTR(", power %ld.%3.3d"),
-                       targetPrivate->last_power.tv_sec,
-                       targetPrivate->last_power.tv_usec / 1000);
-#endif // !TARGET_OS_IPHONE
-               if (isReachabilityTypeName(targetPrivate->type)) {
-                       SCPrint(TRUE, f, CFSTR(", DNS %ld.%3.3d"),
-                               targetPrivate->last_dns.tv_sec,
-                               targetPrivate->last_dns.tv_usec / 1000);
-                       if (timerisset(&targetPrivate->dnsQueryEnd)) {
-                               struct timeval  dnsQueryElapsed;
-
-                               timersub(&targetPrivate->dnsQueryEnd,
-                                        &targetPrivate->dnsQueryStart,
-                                        &dnsQueryElapsed);
-                               SCPrint(TRUE, f, CFSTR(" (query %ld.%3.3d / reply %ld.%3.3d)"),
-                                       targetPrivate->dnsQueryStart.tv_sec,
-                                       targetPrivate->dnsQueryStart.tv_usec / 1000,
-                                       dnsQueryElapsed.tv_sec,
-                                       dnsQueryElapsed.tv_usec / 1000);
-                       }
-               }
-               if (timerisset(&targetPrivate->last_push)) {
-                       SCPrint(TRUE, f, CFSTR(", last notify %ld.%3.3d"),
-                               targetPrivate->last_push.tv_sec,
-                               targetPrivate->last_push.tv_usec / 1000);
-               }
-               SCPrint(TRUE, f, CFSTR(", uid %d"),
-                       targetPrivate->uid);
-               SCPrint(TRUE, f, CFSTR("\n"));
-
-               if (nWatchers > 0) {
-                       CFDictionaryApplyFunction(targetPrivate->serverWatchers,
-                                                 _snapshot_digest_watcher,
-                                                 f);
-               }
-       });
-
-       return;
-}
-
-
-static void
-_snapshot_target(const void *key, const void *value, void *context)
-{
-       FILE                            *f              = (FILE *)context;
-       SCNetworkReachabilityRef        target          = (SCNetworkReachabilityRef)value;
-       uint64_t                        target_id;
-       CFDataRef                       target_key      = (CFDataRef)key;
-
-       /* ALIGN: CF aligns > 8 byte boundries */
-       target_id = *(uint64_t *)(void *)CFDataGetBytePtr(target_key);
-
-       SCPrint(TRUE, f,
-               CFSTR("    target(c) = 0x%0llx, target(s) = %@\n"),
-               target_id,
-               target);
-
-       return;
-}
-
-
-static void
-_snapshot(reach_client_t *client, xpc_object_t request)
-{
-       uid_t                   euid;
-       FILE                    *f;
-       int                     fd;
-       Boolean                 ok      = FALSE;
-       xpc_connection_t        remote;
-       xpc_object_t            reply;
-
-       if (S_debug) {
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR("<%p> snapshot"),
-                     client->connection);
-//             log_xpc_object("  create", request);
-       }
-
-       remote = xpc_dictionary_get_remote_connection(request);
-       reply = xpc_dictionary_create_reply(request);
-       if (reply == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("<%p> _snapshot: xpc_dictionary_create_reply: failed"),
-                     client->connection);
-               return;
-       }
-
-       euid = xpc_connection_get_euid(remote);
-       if (euid != 0) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "Permission denied.");
-               goto done;
-       }
-
-       // Save a snapshot of the SCNetworkReachability server "state"
-
-       (void) unlink(SNAPSHOT_PATH_STATE);
-       fd = open(SNAPSHOT_PATH_STATE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
-       if (fd == -1) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "open: failed");
-               goto done;
-       }
-       f = fdopen(fd, "w");
-       if (f == NULL) {
-               xpc_dictionary_set_string(reply,
-                                         REACH_REQUEST_REPLY_DETAIL,
-                                         "fdopen: failed");
-               goto done;
-       }
-
-       // provide connection/client info
-
-       dispatch_sync(_reach_clients_rbt_queue(), ^{
-               rb_tree_t       *rbt    = _reach_clients_rbt();
-
-               SCPrint(TRUE, f, CFSTR("Clients :\n"));
-
-               if (rb_tree_count(rbt) > 0) {
-                       reach_client_t  *client;
-
-                       RB_TREE_FOREACH(client, rbt) {
-                               SCPrint(TRUE, f,
-                                       CFSTR("\n  connection = %p, client = %p, command = %s, pid = %d\n"),
-                                       client->connection,
-                                       client,
-                                       client->proc_name != NULL ? client->proc_name : "?",
-                                       client->pid);
-                               my_CFDictionaryApplyFunction(client->targets,
-                                                            _snapshot_target,
-                                                            f);
-                       }
-               } else {
-                       SCPrint(TRUE, f, CFSTR("  None.\n"));
-               }
-
-               SCPrint(TRUE, f, CFSTR("\n"));
-       });
-
-       // provide "digest" info
-
-       SCPrint(TRUE, f, CFSTR("Digests :\n"));
-       dispatch_sync(_server_digest_queue(), ^{
-               if (reach_digest_map != NULL) {
-                       CFDictionaryApplyFunction(reach_digest_map,
-                                                 _snapshot_digest,
-                                                 f);
-               }
-       });
-
-       (void) fclose(f);
-
-       ok = TRUE;
-
-    done :
-
-       xpc_dictionary_set_int64(reply,
-                                REACH_REQUEST_REPLY,
-                                ok ? REACH_REQUEST_REPLY_OK : REACH_REQUEST_REPLY_FAILED);
-//     log_xpc_object("  reply", reply);
-       xpc_connection_send_message(remote, reply);
-       xpc_release(reply);
-
-       return;
-}
-
-
-static __inline__ void
-_extract_client_info(reach_client_t *client, xpc_object_t request)
-{
-       // if available/needed, save the process name
-       if (client->proc_name == NULL) {
-               const char      *proc_name;
-
-               proc_name = xpc_dictionary_get_string(request, REACH_CLIENT_PROC_NAME);
-               if (proc_name != NULL) {
-                       client->proc_name = strdup(proc_name);
-               }
-       }
-
-       return;
-}
-
-
-static void
-process_request(reach_client_t *client, xpc_object_t request)
-{
-       int64_t         op;
-
-       op = xpc_dictionary_get_int64(request, REACH_REQUEST);
-       switch (op) {
-               case REACH_REQUEST_CREATE :
-                       _extract_client_info(client, request);
-                       target_add(client, request);
-                       break;
-               case REACH_REQUEST_REMOVE :
-                       target_remove(client, request);
-                       break;
-               case REACH_REQUEST_STATUS :
-                       target_status(client, request);
-                       break;
-               case REACH_REQUEST_SCHEDULE :
-                       target_schedule(client, request);
-                       break;
-               case REACH_REQUEST_UNSCHEDULE :
-                       target_unschedule(client, request);
-                       break;
-               case REACH_REQUEST_SNAPSHOT :
-                       _extract_client_info(client, request);
-                       _snapshot(client, request);
-                       break;
-               default :
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("<%p> unknown request : %lld"),
-                             client->connection,
-                             op);
-                       break;
-       }
-
-       return;
-}
-
-
-static void
-process_new_connection(xpc_connection_t connection)
-{
-       reach_client_t  *client;
-
-       if (S_debug) {
-               SCLog(TRUE, LOG_INFO, CFSTR("<%p> new reach client, pid=%d"),
-                     connection,
-                     xpc_connection_get_pid(connection));
-       }
-
-       client = _reach_client_create(connection);
-       assert(client != NULL);
-
-       dispatch_sync(_reach_clients_rbt_queue(), ^{
-               rb_tree_t       *rbt    = _reach_clients_rbt();
-
-               rb_tree_insert_node(rbt, client);
-       });
-
-       xpc_connection_set_target_queue(connection, _reach_server_queue());
-
-       xpc_connection_set_event_handler(connection, ^(xpc_object_t xobj) {
-               xpc_type_t      type;
-
-               type = xpc_get_type(xobj);
-               if (type == XPC_TYPE_DICTIONARY) {
-                       __block reach_client_t  *client = NULL;
-
-                       dispatch_sync(_reach_clients_rbt_queue(), ^{
-                               uint64_t        connection_id   = (uintptr_t)connection;
-                               rb_tree_t       *rbt            = _reach_clients_rbt();
-
-                               client = rb_tree_find_node(rbt, &connection_id);
-                       });
-
-                       if (client != NULL) {
-                               // process the request
-                               process_request(client, xobj);
-                       } else {
-                               char            *desc;
-
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("<%p:%d> unexpected SCNetworkReachability request"),
-                                     connection,
-                                     xpc_connection_get_pid(connection));
-
-                               desc = xpc_copy_description(xobj);
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("  request = %s"),
-                                     desc);
-                               free(desc);
-
-                               xpc_connection_cancel(connection);
-                       }
-
-               } else if (type == XPC_TYPE_ERROR) {
-                       const char      *desc;
-
-                       desc = xpc_dictionary_get_string(xobj, XPC_ERROR_KEY_DESCRIPTION);
-                       if (xobj == XPC_ERROR_CONNECTION_INVALID) {
-                               if (S_debug) {
-                                       SCLog(TRUE, LOG_INFO,
-                                             CFSTR("<%p:%d> %s"),
-                                             connection,
-                                             xpc_connection_get_pid(connection),
-                                             desc);
-                               }
-
-                               _reach_client_remove(connection);
-
-                       } else if (xobj == XPC_ERROR_CONNECTION_INTERRUPTED) {
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("<%p:%d> %s"),
-                                     connection,
-                                     xpc_connection_get_pid(connection),
-                                     desc);
-
-                       } else {
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("<%p:%d> Connection error: %p : %s"),
-                                     connection,
-                                     xpc_connection_get_pid(connection),
-                                     xobj,
-                                     desc);
-                       }
-
-               }  else {
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("<%p:%d> unknown event type : %p"),
-                             connection,
-                             xpc_connection_get_pid(connection),
-                             type);
-               }
-       });
-
-       xpc_connection_resume(connection);
-
-       return;
-}
-
-
-#pragma mark -
-#pragma mark Reachability server "main"
-
-
-__private_extern__
-void
-load_SCNetworkReachability(CFBundleRef bundle, Boolean bundleVerbose)
-{
-       xpc_connection_t        connection;
-       const char              *name;
-
-       S_debug = bundleVerbose;
-
-       /*
-        * create a dictionary mapping SCNetworkReachability [CFData] digests
-        * to SCNetworkReachability objects.
-        */
-       reach_digest_map = CFDictionaryCreateMutable(NULL,
-                                                    0,
-                                                    &kCFTypeDictionaryKeyCallBacks,
-                                                    &kCFTypeDictionaryValueCallBacks);
-
-       // create XPC listener
-       name = getenv("REACH_SERVER");
-       if (name == NULL) {
-               name = REACH_SERVICE_NAME;
-       }
-       connection = xpc_connection_create_mach_service(name,
-                                                       _reach_server_queue(),
-                                                       XPC_CONNECTION_MACH_SERVICE_LISTENER);
-
-       xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
-               xpc_type_t      type;
-
-               type = xpc_get_type(event);
-               if (type == XPC_TYPE_CONNECTION) {
-                       process_new_connection(event);
-
-               } else if (type == XPC_TYPE_ERROR) {
-                       const char      *desc;
-
-                       desc = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION);
-                       if (event == XPC_ERROR_CONNECTION_INVALID) {
-                               SCLog(TRUE, LOG_ERR, CFSTR("reach server: %s"), desc);
-                               xpc_release(connection);
-                       } else if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
-                               SCLog(TRUE, LOG_ERR, CFSTR("reach server: %s"), desc);
-                       } else {
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("reach server: Connection error: %p : %s"),
-                                     event,
-                                     desc);
-                       }
-
-               } else {
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("reach server: unknown event type : %p"),
-                             type);
-               }
-       });
-       xpc_connection_resume(connection);
-
-       return;
-}
-
-#ifdef  MAIN
-
-int
-main(int argc, char **argv)
-{
-//     _sc_log     = FALSE;
-       _sc_verbose = (argc > 1) ? TRUE : FALSE;
-       _sc_debug   = TRUE;
-
-       load_SCNetworkReachability(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
-       CFRunLoopRun();
-       /* not reached */
-       exit(0);
-       return 0;
-}
-
-#endif  /* MAIN */